mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 04:22:13 +00:00
Compare commits
64 Commits
vercel@23.
...
vercel-plu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32664cd13b | ||
|
|
db468c489a | ||
|
|
edd9bb506c | ||
|
|
a72549a290 | ||
|
|
4aa6a13912 | ||
|
|
81ea0082f1 | ||
|
|
6dff0875f5 | ||
|
|
30aa392c0a | ||
|
|
c4fc060030 | ||
|
|
3fa08bf64f | ||
|
|
43056bde1f | ||
|
|
a49966b9b4 | ||
|
|
7f55de71bb | ||
|
|
db8e36e04c | ||
|
|
82924bb5c4 | ||
|
|
18b5fac93e | ||
|
|
a6012e600b | ||
|
|
c3abf73f58 | ||
|
|
4873b8b379 | ||
|
|
6248139281 | ||
|
|
507a5de3cd | ||
|
|
be1c78e72f | ||
|
|
c277c649c6 | ||
|
|
ed1dacd276 | ||
|
|
144e890bfa | ||
|
|
af097c2c06 | ||
|
|
873a582986 | ||
|
|
986b4c0b1a | ||
|
|
14071819ac | ||
|
|
2a8588a0c5 | ||
|
|
0f7e89f76c | ||
|
|
e68ed33a88 | ||
|
|
d3e98cdb73 | ||
|
|
bf4e77110f | ||
|
|
5b5197d2c5 | ||
|
|
a6ccf6c180 | ||
|
|
8d848ebe8b | ||
|
|
6ef2c16d63 | ||
|
|
6c71ceaaeb | ||
|
|
1dcb6dfc6f | ||
|
|
4fd24575e5 | ||
|
|
8714f1905e | ||
|
|
2e69f2513d | ||
|
|
979e4b674a | ||
|
|
07fa47bcfb | ||
|
|
307c4fc377 | ||
|
|
44868d79b6 | ||
|
|
df9a4afa5c | ||
|
|
8a6869bae2 | ||
|
|
a3fc3c1ca7 | ||
|
|
44037c58be | ||
|
|
1a9419b690 | ||
|
|
93d0e5966c | ||
|
|
306f3a1312 | ||
|
|
9c67e8115e | ||
|
|
b890ac1e44 | ||
|
|
28e71ff109 | ||
|
|
2bf060c708 | ||
|
|
c8ef1d71d1 | ||
|
|
3d2efc7dcd | ||
|
|
cd7185a872 | ||
|
|
981a76fbe2 | ||
|
|
c35c05446b | ||
|
|
b88e65c4ad |
@@ -1,11 +1,10 @@
|
||||
node_modules
|
||||
dist
|
||||
examples
|
||||
packages/build-utils/test/fixtures
|
||||
packages/*/test/fixtures
|
||||
packages/cli/@types
|
||||
packages/cli/download
|
||||
packages/cli/dist
|
||||
packages/cli/test/fixtures
|
||||
packages/cli/test/dev/fixtures
|
||||
packages/cli/bin
|
||||
packages/cli/link
|
||||
@@ -13,6 +12,6 @@ packages/cli/src/util/dev/templates/*.ts
|
||||
packages/client/tests/fixtures
|
||||
packages/client/lib
|
||||
packages/node/src/bridge.ts
|
||||
packages/node/test/fixtures
|
||||
packages/node-bridge/bridge.js
|
||||
packages/node-bridge/launcher.js
|
||||
packages/middleware/src/entries.js
|
||||
|
||||
2
.github/workflows/test-integration-dev.yml
vendored
2
.github/workflows/test-integration-dev.yml
vendored
@@ -11,7 +11,7 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
name: Dev
|
||||
timeout-minutes: 60
|
||||
timeout-minutes: 75
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ test/lib/deployment/failed-page.txt
|
||||
/public
|
||||
__pycache__
|
||||
.vercel
|
||||
.output
|
||||
|
||||
@@ -14,8 +14,6 @@ const frameworks = (_frameworks as Framework[])
|
||||
sort: undefined,
|
||||
dependency: undefined,
|
||||
defaultRoutes: undefined,
|
||||
devCommand: undefined,
|
||||
buildCommand: undefined,
|
||||
};
|
||||
|
||||
if (framework.logo) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "11.1.2",
|
||||
"next": "12.0.1",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
|
||||
@@ -43,7 +43,14 @@
|
||||
core-js-pure "^3.16.0"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@7.15.3", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2":
|
||||
"@babel/runtime@7.15.4":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
|
||||
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2":
|
||||
version "7.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
|
||||
integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
|
||||
@@ -112,10 +119,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c"
|
||||
integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==
|
||||
|
||||
"@next/env@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-11.1.2.tgz#27996efbbc54c5f949f5e8c0a156e3aa48369b99"
|
||||
integrity sha512-+fteyVdQ7C/OoulfcF6vd1Yk0FEli4453gr8kSFbU8sKseNSizYq6df5MKz/AjwLptsxrUeIkgBdAzbziyJ3mA==
|
||||
"@next/env@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.1.tgz#d57141ef1fe844f6f7c18cdaf29a712788c18ca4"
|
||||
integrity sha512-+eJ8mQbAcV/ZILRAgIx9xwDg6hrqm6m/7QLfEvsf2BPnsh+fwU4Xf1zgcbyqD2V4ja4OTWG6ow+Hiukgap3mZQ==
|
||||
|
||||
"@next/eslint-plugin-next@11.1.0":
|
||||
version "11.1.0"
|
||||
@@ -124,15 +131,15 @@
|
||||
dependencies:
|
||||
glob "7.1.7"
|
||||
|
||||
"@next/polyfill-module@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-11.1.2.tgz#1fe92c364fdc81add775a16c678f5057c6aace98"
|
||||
integrity sha512-xZmixqADM3xxtqBV0TpAwSFzWJP0MOQzRfzItHXf1LdQHWb0yofHHC+7eOrPFic8+ZGz5y7BdPkkgR1S25OymA==
|
||||
"@next/polyfill-module@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-12.0.1.tgz#d20abf06f686ee7a8bd0d9056accfd0662f19e87"
|
||||
integrity sha512-fTrndwGuvrQO+4myVGcPtsYI4/tmZBhHHJId7MSHWz+9gW4NFgsmDlr8OI9Th2ZXpqk5WHLsTYQ+dLiQp1zV4g==
|
||||
|
||||
"@next/react-dev-overlay@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-11.1.2.tgz#73795dc5454b7af168bac93df7099965ebb603be"
|
||||
integrity sha512-rDF/mGY2NC69mMg2vDqzVpCOlWqnwPUXB2zkARhvknUHyS6QJphPYv9ozoPJuoT/QBs49JJd9KWaAzVBvq920A==
|
||||
"@next/react-dev-overlay@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-12.0.1.tgz#134299ae44fad5a59448d5e671518074f37cba95"
|
||||
integrity sha512-dLv1to40bvadbr0VO8pBsbr9ddgktCLilfejOpEFQkOOrdQBUuIfegqqEDiCL9THkAO3QGYY4t/ZPfv9wrxLZQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "7.12.11"
|
||||
anser "1.4.9"
|
||||
@@ -144,32 +151,67 @@
|
||||
shell-quote "1.7.2"
|
||||
source-map "0.8.0-beta.0"
|
||||
stacktrace-parser "0.1.10"
|
||||
strip-ansi "6.0.0"
|
||||
strip-ansi "6.0.1"
|
||||
|
||||
"@next/react-refresh-utils@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-11.1.2.tgz#44ea40d8e773e4b77bad85e24f6ac041d5e4b4a5"
|
||||
integrity sha512-hsoJmPfhVqjZ8w4IFzoo8SyECVnN+8WMnImTbTKrRUHOVJcYMmKLL7xf7T0ft00tWwAl/3f3Q3poWIN2Ueql/Q==
|
||||
"@next/react-refresh-utils@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-12.0.1.tgz#219be7a81696a7bd1e2d4ee397ca100eb8262f23"
|
||||
integrity sha512-CjTBR9a6ai+2fUT8KFya9AiTaCnfDY34H6pDmtdJdkD+vY08AwtPpv10kzsgNEhsL06210yVzH59IsEQLBIllA==
|
||||
|
||||
"@next/swc-darwin-arm64@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-11.1.2.tgz#93226c38db488c4b62b30a53b530e87c969b8251"
|
||||
integrity sha512-hZuwOlGOwBZADA8EyDYyjx3+4JGIGjSHDHWrmpI7g5rFmQNltjlbaefAbiU5Kk7j3BUSDwt30quJRFv3nyJQ0w==
|
||||
"@next/swc-android-arm64@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.0.1.tgz#c776853e0911c12fcc69a69cd7ab111dff29f8d2"
|
||||
integrity sha512-zI/6zsZuO2igknzHzfaQep0PeD3d4/qdjXUcQLwLHJQtGdhPvZFMke1z3BBWZqePHVsR1JPjE4QTii7udF5qsQ==
|
||||
|
||||
"@next/swc-darwin-x64@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-11.1.2.tgz#792003989f560c00677b5daeff360b35b510db83"
|
||||
integrity sha512-PGOp0E1GisU+EJJlsmJVGE+aPYD0Uh7zqgsrpD3F/Y3766Ptfbe1lEPPWnRDl+OzSSrSrX1lkyM/Jlmh5OwNvA==
|
||||
"@next/swc-darwin-arm64@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.1.tgz#bee9c5932511c993ab384ef9aedb86c02532d41e"
|
||||
integrity sha512-vRfHz7rEt9+TTfwi3uY9ObUSLhzMmgVZ96b+yOSmZ6Kxs/V46IXHOLawCnoldXylpskZ/+HTWcrB1D3aimGeZA==
|
||||
|
||||
"@next/swc-linux-x64-gnu@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-11.1.2.tgz#8216b2ae1f21f0112958735c39dd861088108f37"
|
||||
integrity sha512-YcDHTJjn/8RqvyJVB6pvEKXihDcdrOwga3GfMv/QtVeLphTouY4BIcEUfrG5+26Nf37MP1ywN3RRl1TxpurAsQ==
|
||||
"@next/swc-darwin-x64@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.1.tgz#a0bdcbcf11b8b62190ec8e0406cecbbcc810b7fc"
|
||||
integrity sha512-mM7QLIqRUqR8I74gbZ4Uq+dY8k3Whrs98wK+vPurmDTBhXhaVnAYblEkEwe0DJGqlmjD4w6faYfCydmFI69jqw==
|
||||
|
||||
"@next/swc-win32-x64-msvc@11.1.2":
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-11.1.2.tgz#e15824405df137129918205e43cb5e9339589745"
|
||||
integrity sha512-e/pIKVdB+tGQYa1cW3sAeHm8gzEri/HYLZHT4WZojrUxgWXqx8pk7S7Xs47uBcFTqBDRvK3EcQpPLf3XdVsDdg==
|
||||
"@next/swc-linux-arm-gnueabihf@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.1.tgz#d0132637288f452ad5c6a6161e42aebcd4355f82"
|
||||
integrity sha512-QF5LVyAWTah5i1p/yG4a8nTGRXerHoDkS3kWYCdjcwlALOiAJ9m0GUTks/O47izNokBAbZnL7URUdvtGFjP0Ng==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.1.tgz#6b310344b9bac7700eaff8f4c536540b1226e378"
|
||||
integrity sha512-ETFUh373WsjUJJr32GHSDlVSgwFwS+EJUJuSH40Pr4xB6250YxuRk8ccF6QR5LHqTL4tbbVEEfCD8sZVnccP8w==
|
||||
|
||||
"@next/swc-linux-arm64-musl@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.1.tgz#8ab1fc81d18bbb70bb15bcc4250382257bba6298"
|
||||
integrity sha512-pfnXNjKywXyp2DJsjFhkfOlvcNu9xa8HgEhCUKXm1OZ4pGnpeb1+UD4t5Pn9b9ggiWPzauZK1abR/9nShvbSzw==
|
||||
|
||||
"@next/swc-linux-x64-gnu@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.1.tgz#a664268aedec402da5df34efac1b337d9b0e492e"
|
||||
integrity sha512-d9cXS27Ar7TTtA3BJ8gxosDDdVNSFy4MQiwsszKlEiqfGrnINeXKdVgeiOa+xxq+JxNvPzonp4sbX6k8InIocg==
|
||||
|
||||
"@next/swc-linux-x64-musl@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.1.tgz#4b7e5fee5a62adb6d9c9aad1a4aa00a6a09b53dc"
|
||||
integrity sha512-4SAmi7riavU6TFGX7wQFioFi/vx8uJ2/Cx7ZfrYiZzzKmmuu2eM8onW1kcKu+aQD777x/kvzW4+2pWkM2gyPOA==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.1.tgz#9ff0c2a2f00f41d40bd44d6da195bdf649d807c6"
|
||||
integrity sha512-JRad3QyXvs5zDkeEmc6z5tEvm/ZZnjnsBY921zWw7OIcIZR5wAs+1AnRVjIxHTEHSExxOvBgPyEMpgVkB8OyxQ==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.1.tgz#5a927ec832b184ce2e35f8ec668daa34175e47d0"
|
||||
integrity sha512-ierQmzVWPi6a7PqrdgfI6nrQ/SWJ9W5jllByyQeFIOKhOzZiz030Tw+U6V7NqE3gGNeRwpj56Iya8nUb3hlM1g==
|
||||
|
||||
"@next/swc-win32-x64-msvc@12.0.1":
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.1.tgz#fe145cf7baf79564159a87a545e430f96c835578"
|
||||
integrity sha512-li3CCXpdMX0+wJlQpy0xZmHCgHMebaBf5X2BIAJrv8cQXYc6dejeojttXLFNCF0dNAo3UzlbP6h7N+8p6Wbakw==
|
||||
|
||||
"@node-rs/helper@1.2.1":
|
||||
version "1.2.1"
|
||||
@@ -258,6 +300,16 @@ acorn-jsx@^5.3.1:
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
acorn@8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
|
||||
integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
|
||||
|
||||
acorn@^6.2.1:
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
|
||||
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
|
||||
|
||||
acorn@^7.4.0:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
@@ -298,6 +350,11 @@ ansi-regex@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
||||
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||
@@ -390,24 +447,11 @@ assert@2.0.0:
|
||||
object-is "^1.0.1"
|
||||
util "^0.12.0"
|
||||
|
||||
assert@^1.1.1:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
|
||||
integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
util "0.10.3"
|
||||
|
||||
ast-types-flow@^0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
|
||||
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
|
||||
|
||||
ast-types@0.13.2:
|
||||
version "0.13.2"
|
||||
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48"
|
||||
integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==
|
||||
|
||||
astral-regex@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
||||
@@ -532,7 +576,7 @@ browserify-sign@^4.0.0:
|
||||
readable-stream "^3.6.0"
|
||||
safe-buffer "^5.2.0"
|
||||
|
||||
browserify-zlib@0.2.0, browserify-zlib@^0.2.0:
|
||||
browserify-zlib@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
|
||||
integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
|
||||
@@ -563,15 +607,6 @@ buffer@5.6.0:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^4.3.0:
|
||||
version "4.9.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
|
||||
integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
|
||||
dependencies:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
isarray "^1.0.0"
|
||||
|
||||
builtin-status-codes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
@@ -692,12 +727,7 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
console-browserify@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
||||
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
|
||||
|
||||
constants-browserify@1.0.0, constants-browserify@^1.0.0:
|
||||
constants-browserify@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
||||
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
|
||||
@@ -714,11 +744,6 @@ core-js-pure@^3.16.0:
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.16.1.tgz#b997df2669c957a5b29f06e95813a171f993592e"
|
||||
integrity sha512-TyofCdMzx0KMhi84mVRS8rL1XsRk2SPUNz2azmth53iRN0/08Uim9fdhQTaZTG1LqaXHYVci4RDHka6WrXfnvg==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
create-ecdh@^4.0.0:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
|
||||
@@ -759,7 +784,7 @@ cross-spawn@^7.0.2:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypto-browserify@3.12.0, crypto-browserify@^3.11.0:
|
||||
crypto-browserify@3.12.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
|
||||
integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
|
||||
@@ -886,11 +911,6 @@ domain-browser@4.19.0:
|
||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1"
|
||||
integrity sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ==
|
||||
|
||||
domain-browser@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
|
||||
|
||||
electron-to-chromium@^1.3.723:
|
||||
version "1.3.802"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.802.tgz#0afa989321de3e904ac653ee79e0d642883731a1"
|
||||
@@ -1219,7 +1239,7 @@ etag@1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
events@^3.0.0:
|
||||
events@3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
|
||||
@@ -1486,7 +1506,7 @@ http-errors@1.7.3:
|
||||
statuses ">= 1.5.0 < 2"
|
||||
toidentifier "1.0.0"
|
||||
|
||||
https-browserify@1.0.0, https-browserify@^1.0.0:
|
||||
https-browserify@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
@@ -1548,21 +1568,11 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
inherits@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
|
||||
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
|
||||
|
||||
inherits@2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
internal-slot@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
|
||||
@@ -1706,11 +1716,6 @@ is-typed-array@^1.1.3, is-typed-array@^1.1.6:
|
||||
foreach "^2.0.5"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
isarray@^1.0.0, isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
@@ -1952,32 +1957,30 @@ nanoid@^3.1.23:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
|
||||
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
|
||||
|
||||
native-url@0.3.4:
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.3.4.tgz#29c943172aed86c63cee62c8c04db7f5756661f8"
|
||||
integrity sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA==
|
||||
dependencies:
|
||||
querystring "^0.2.0"
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
next@11.1.2:
|
||||
version "11.1.2"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-11.1.2.tgz#527475787a9a362f1bc916962b0c0655cc05bc91"
|
||||
integrity sha512-azEYL0L+wFjv8lstLru3bgvrzPvK0P7/bz6B/4EJ9sYkXeW8r5Bjh78D/Ol7VOg0EIPz0CXoe72hzAlSAXo9hw==
|
||||
neo-async@^2.6.1:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
next@12.0.1:
|
||||
version "12.0.1"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.0.1.tgz#7b82a73bc185bfda7372e7e8309f9b38e6be9cb0"
|
||||
integrity sha512-4MNXAbD9+Tmtejg0TOKbaP52Cgu4mIn2ejKMLHWV0acxWGkkcE7QvdZwvg5pkg3fQBMrgucOxxtmw4D7yWaZvg==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.15.3"
|
||||
"@babel/runtime" "7.15.4"
|
||||
"@hapi/accept" "5.0.2"
|
||||
"@next/env" "11.1.2"
|
||||
"@next/polyfill-module" "11.1.2"
|
||||
"@next/react-dev-overlay" "11.1.2"
|
||||
"@next/react-refresh-utils" "11.1.2"
|
||||
"@next/env" "12.0.1"
|
||||
"@next/polyfill-module" "12.0.1"
|
||||
"@next/react-dev-overlay" "12.0.1"
|
||||
"@next/react-refresh-utils" "12.0.1"
|
||||
"@node-rs/helper" "1.2.1"
|
||||
acorn "8.5.0"
|
||||
assert "2.0.0"
|
||||
ast-types "0.13.2"
|
||||
browserify-zlib "0.2.0"
|
||||
browserslist "4.16.6"
|
||||
buffer "5.6.0"
|
||||
@@ -1990,40 +1993,48 @@ next@11.1.2:
|
||||
domain-browser "4.19.0"
|
||||
encoding "0.1.13"
|
||||
etag "1.8.1"
|
||||
events "3.3.0"
|
||||
find-cache-dir "3.3.1"
|
||||
get-orientation "1.1.2"
|
||||
https-browserify "1.0.0"
|
||||
image-size "1.0.0"
|
||||
jest-worker "27.0.0-next.5"
|
||||
native-url "0.3.4"
|
||||
node-fetch "2.6.1"
|
||||
node-html-parser "1.4.9"
|
||||
node-libs-browser "^2.2.1"
|
||||
os-browserify "0.3.0"
|
||||
p-limit "3.1.0"
|
||||
path-browserify "1.0.1"
|
||||
pnp-webpack-plugin "1.6.4"
|
||||
postcss "8.2.15"
|
||||
process "0.11.10"
|
||||
querystring-es3 "0.2.1"
|
||||
raw-body "2.4.1"
|
||||
react-is "17.0.2"
|
||||
react-refresh "0.8.3"
|
||||
react-server-dom-webpack "0.0.0-experimental-3c4c1c470-20211021"
|
||||
regenerator-runtime "0.13.4"
|
||||
stream-browserify "3.0.0"
|
||||
stream-http "3.1.1"
|
||||
string_decoder "1.3.0"
|
||||
styled-jsx "4.0.1"
|
||||
styled-jsx "5.0.0-beta.3"
|
||||
timers-browserify "2.0.12"
|
||||
tty-browserify "0.0.1"
|
||||
use-subscription "1.5.1"
|
||||
util "0.12.4"
|
||||
vm-browserify "1.1.2"
|
||||
watchpack "2.1.1"
|
||||
web-streams-polyfill "3.0.3"
|
||||
optionalDependencies:
|
||||
"@next/swc-darwin-arm64" "11.1.2"
|
||||
"@next/swc-darwin-x64" "11.1.2"
|
||||
"@next/swc-linux-x64-gnu" "11.1.2"
|
||||
"@next/swc-win32-x64-msvc" "11.1.2"
|
||||
"@next/swc-android-arm64" "12.0.1"
|
||||
"@next/swc-darwin-arm64" "12.0.1"
|
||||
"@next/swc-darwin-x64" "12.0.1"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.0.1"
|
||||
"@next/swc-linux-arm64-gnu" "12.0.1"
|
||||
"@next/swc-linux-arm64-musl" "12.0.1"
|
||||
"@next/swc-linux-x64-gnu" "12.0.1"
|
||||
"@next/swc-linux-x64-musl" "12.0.1"
|
||||
"@next/swc-win32-arm64-msvc" "12.0.1"
|
||||
"@next/swc-win32-ia32-msvc" "12.0.1"
|
||||
"@next/swc-win32-x64-msvc" "12.0.1"
|
||||
|
||||
node-fetch@2.6.1:
|
||||
version "2.6.1"
|
||||
@@ -2037,35 +2048,6 @@ node-html-parser@1.4.9:
|
||||
dependencies:
|
||||
he "1.2.0"
|
||||
|
||||
node-libs-browser@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
|
||||
integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
|
||||
dependencies:
|
||||
assert "^1.1.1"
|
||||
browserify-zlib "^0.2.0"
|
||||
buffer "^4.3.0"
|
||||
console-browserify "^1.1.0"
|
||||
constants-browserify "^1.0.0"
|
||||
crypto-browserify "^3.11.0"
|
||||
domain-browser "^1.1.1"
|
||||
events "^3.0.0"
|
||||
https-browserify "^1.0.0"
|
||||
os-browserify "^0.3.0"
|
||||
path-browserify "0.0.1"
|
||||
process "^0.11.10"
|
||||
punycode "^1.2.4"
|
||||
querystring-es3 "^0.2.0"
|
||||
readable-stream "^2.3.3"
|
||||
stream-browserify "^2.0.1"
|
||||
stream-http "^2.7.2"
|
||||
string_decoder "^1.0.0"
|
||||
timers-browserify "^2.0.4"
|
||||
tty-browserify "0.0.0"
|
||||
url "^0.11.0"
|
||||
util "^0.11.0"
|
||||
vm-browserify "^1.0.1"
|
||||
|
||||
node-releases@^1.1.71:
|
||||
version "1.1.74"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e"
|
||||
@@ -2166,7 +2148,7 @@ optionator@^0.9.1:
|
||||
type-check "^0.4.0"
|
||||
word-wrap "^1.2.3"
|
||||
|
||||
os-browserify@0.3.0, os-browserify@^0.3.0:
|
||||
os-browserify@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
|
||||
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
|
||||
@@ -2247,11 +2229,6 @@ parse-json@^4.0.0:
|
||||
error-ex "^1.3.1"
|
||||
json-parse-better-errors "^1.0.1"
|
||||
|
||||
path-browserify@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
|
||||
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
|
||||
|
||||
path-browserify@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
|
||||
@@ -2341,13 +2318,6 @@ platform@1.3.6:
|
||||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
|
||||
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
|
||||
|
||||
pnp-webpack-plugin@1.6.4:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
|
||||
integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==
|
||||
dependencies:
|
||||
ts-pnp "^1.1.6"
|
||||
|
||||
postcss@8.2.15:
|
||||
version "8.2.15"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65"
|
||||
@@ -2362,12 +2332,7 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
process@0.11.10, process@^0.11.10:
|
||||
process@0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
@@ -2398,36 +2363,16 @@ public-encrypt@^4.0.0:
|
||||
randombytes "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
punycode@1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
||||
|
||||
punycode@^1.2.4:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
querystring-es3@0.2.1, querystring-es3@^0.2.0:
|
||||
querystring-es3@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||
integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
|
||||
|
||||
querystring@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
|
||||
|
||||
querystring@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
|
||||
integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@@ -2489,6 +2434,16 @@ react-refresh@0.8.3:
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
|
||||
|
||||
react-server-dom-webpack@0.0.0-experimental-3c4c1c470-20211021:
|
||||
version "0.0.0-experimental-3c4c1c470-20211021"
|
||||
resolved "https://registry.yarnpkg.com/react-server-dom-webpack/-/react-server-dom-webpack-0.0.0-experimental-3c4c1c470-20211021.tgz#cdcaa2f19c8d820c1f4d31252319fb05e2de0e88"
|
||||
integrity sha512-YyRlED5kR0C2aQ3IJ/8BR2TELt51RcDZhnUDKz+m/HU+Gb/qak0CZkG0A8Zxffom9VI6HFkUj1dRFZqm0Lh9Pg==
|
||||
dependencies:
|
||||
acorn "^6.2.1"
|
||||
loose-envify "^1.1.0"
|
||||
neo-async "^2.6.1"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
react@17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
@@ -2514,19 +2469,6 @@ read-pkg@^3.0.0:
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^3.0.0"
|
||||
|
||||
readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.5.0, readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
@@ -2543,6 +2485,11 @@ readdirp@~3.5.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
regenerator-runtime@0.13.4:
|
||||
version "0.13.4"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz#e96bf612a3362d12bb69f7e8f74ffeab25c7ac91"
|
||||
integrity sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==
|
||||
|
||||
regenerator-runtime@^0.13.4:
|
||||
version "0.13.9"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
|
||||
@@ -2619,7 +2566,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2,
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
@@ -2780,14 +2727,6 @@ stream-browserify@3.0.0:
|
||||
inherits "~2.0.4"
|
||||
readable-stream "^3.5.0"
|
||||
|
||||
stream-browserify@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
|
||||
integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
|
||||
dependencies:
|
||||
inherits "~2.0.1"
|
||||
readable-stream "^2.0.2"
|
||||
|
||||
stream-http@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564"
|
||||
@@ -2798,17 +2737,6 @@ stream-http@3.1.1:
|
||||
readable-stream "^3.6.0"
|
||||
xtend "^4.0.2"
|
||||
|
||||
stream-http@^2.7.2:
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc"
|
||||
integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==
|
||||
dependencies:
|
||||
builtin-status-codes "^3.0.0"
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.3.6"
|
||||
to-arraybuffer "^1.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
stream-parser@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
|
||||
@@ -2860,21 +2788,21 @@ string.prototype.trimstart@^1.0.4:
|
||||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
string_decoder@1.3.0, string_decoder@^1.0.0, string_decoder@^1.1.1:
|
||||
string_decoder@1.3.0, string_decoder@^1.1.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
strip-ansi@6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@6.0.0, strip-ansi@^6.0.0:
|
||||
strip-ansi@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
|
||||
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
|
||||
@@ -2891,10 +2819,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
styled-jsx@4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-4.0.1.tgz#ae3f716eacc0792f7050389de88add6d5245b9e9"
|
||||
integrity sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ==
|
||||
styled-jsx@5.0.0-beta.3:
|
||||
version "5.0.0-beta.3"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0-beta.3.tgz#400d16179b5dff10d5954ab8be27a9a1b7780dd2"
|
||||
integrity sha512-HtDDGSFPvmjHIqWf9n8Oo54tAoY/DTplvlyOH2+YOtD80Sp31Ap8ffSmxhgk5EkUoJ7xepdXMGT650mSffWuRA==
|
||||
dependencies:
|
||||
"@babel/plugin-syntax-jsx" "7.14.5"
|
||||
"@babel/types" "7.15.0"
|
||||
@@ -2953,18 +2881,13 @@ text-table@^0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
||||
|
||||
timers-browserify@2.0.12, timers-browserify@^2.0.4:
|
||||
timers-browserify@2.0.12:
|
||||
version "2.0.12"
|
||||
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee"
|
||||
integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==
|
||||
dependencies:
|
||||
setimmediate "^1.0.4"
|
||||
|
||||
to-arraybuffer@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
|
||||
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
@@ -2989,11 +2912,6 @@ tr46@^1.0.1:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
ts-pnp@^1.1.6:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
||||
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
||||
|
||||
tsconfig-paths@^3.9.0:
|
||||
version "3.10.1"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7"
|
||||
@@ -3015,11 +2933,6 @@ tsutils@^3.21.0:
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
tty-browserify@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
||||
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
|
||||
|
||||
tty-browserify@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811"
|
||||
@@ -3064,14 +2977,6 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
url@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
|
||||
integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
|
||||
dependencies:
|
||||
punycode "1.3.2"
|
||||
querystring "0.2.0"
|
||||
|
||||
use-subscription@1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
|
||||
@@ -3079,18 +2984,11 @@ use-subscription@1.5.1:
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
util@0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
||||
integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
|
||||
dependencies:
|
||||
inherits "2.0.1"
|
||||
|
||||
util@0.12.4, util@^0.12.0:
|
||||
version "0.12.4"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253"
|
||||
@@ -3103,13 +3001,6 @@ util@0.12.4, util@^0.12.0:
|
||||
safe-buffer "^5.1.2"
|
||||
which-typed-array "^1.1.2"
|
||||
|
||||
util@^0.11.0:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"
|
||||
integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==
|
||||
dependencies:
|
||||
inherits "2.0.3"
|
||||
|
||||
v8-compile-cache@^2.0.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
@@ -3123,7 +3014,7 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vm-browserify@1.1.2, vm-browserify@^1.0.1:
|
||||
vm-browserify@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
@@ -3136,6 +3027,11 @@ watchpack@2.1.1:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
web-streams-polyfill@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz#f49e487eedeca47a207c1aee41ee5578f884b42f"
|
||||
integrity sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
@@ -3190,7 +3086,7 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.2:
|
||||
xtend@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-plugin-jest": "24.3.6",
|
||||
"husky": "6.0.0",
|
||||
"jest": "27.0.6",
|
||||
"jest": "27.3.1",
|
||||
"json5": "2.1.1",
|
||||
"lint-staged": "9.2.5",
|
||||
"node-fetch": "2.6.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.12.3-canary.12",
|
||||
"version": "2.12.3-canary.19",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"@types/async-retry": "^1.2.1",
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"@types/end-of-stream": "^1.4.0",
|
||||
"@types/fs-extra": "^5.0.5",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/jest": "27.0.1",
|
||||
"@types/js-yaml": "3.12.1",
|
||||
@@ -30,7 +30,7 @@
|
||||
"@types/node-fetch": "^2.1.6",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/yazl": "^2.4.1",
|
||||
"@vercel/frameworks": "0.5.1-canary.8",
|
||||
"@vercel/frameworks": "0.5.1-canary.12",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"aggregate-error": "3.0.1",
|
||||
"async-retry": "1.2.3",
|
||||
@@ -38,7 +38,7 @@
|
||||
"boxen": "4.2.0",
|
||||
"cross-spawn": "6.0.5",
|
||||
"end-of-stream": "1.4.1",
|
||||
"fs-extra": "7.0.0",
|
||||
"fs-extra": "10.0.0",
|
||||
"glob": "7.1.3",
|
||||
"into-stream": "5.0.0",
|
||||
"js-yaml": "3.13.1",
|
||||
|
||||
171
packages/build-utils/src/convert-runtime-to-plugin.ts
Normal file
171
packages/build-utils/src/convert-runtime-to-plugin.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import fs from 'fs-extra';
|
||||
import { join, dirname, relative } from 'path';
|
||||
import glob from './fs/glob';
|
||||
import { normalizePath } from './fs/normalize-path';
|
||||
import { FILES_SYMBOL, getLambdaOptionsFromFunction, Lambda } from './lambda';
|
||||
import type FileBlob from './file-blob';
|
||||
import type { BuilderFunctions, BuildOptions, Files } from './types';
|
||||
import minimatch from 'minimatch';
|
||||
|
||||
/**
|
||||
* Convert legacy Runtime to a Plugin.
|
||||
* @param buildRuntime - a legacy build() function from a Runtime
|
||||
* @param ext - the file extension, for example `.py`
|
||||
*/
|
||||
export function convertRuntimeToPlugin(
|
||||
buildRuntime: (options: BuildOptions) => Promise<{ output: Lambda }>,
|
||||
ext: string
|
||||
) {
|
||||
return async function build({ workPath }: { workPath: string }) {
|
||||
const opts = { cwd: workPath };
|
||||
const files = await glob('**', opts);
|
||||
delete files['vercel.json']; // Builders/Runtimes didn't have vercel.json
|
||||
const entrypoints = await glob(`api/**/*${ext}`, opts);
|
||||
const pages: { [key: string]: any } = {};
|
||||
const { functions = {} } = await readVercelConfig(workPath);
|
||||
const traceDir = join(workPath, '.output', 'runtime-traced-files');
|
||||
await fs.ensureDir(traceDir);
|
||||
|
||||
for (const entrypoint of Object.keys(entrypoints)) {
|
||||
const key =
|
||||
Object.keys(functions).find(
|
||||
src => src === entrypoint || minimatch(entrypoint, src)
|
||||
) || '';
|
||||
const config = functions[key] || {};
|
||||
|
||||
const { output } = await buildRuntime({
|
||||
files,
|
||||
entrypoint,
|
||||
workPath,
|
||||
config: {
|
||||
zeroConfig: true,
|
||||
includeFiles: config.includeFiles,
|
||||
excludeFiles: config.excludeFiles,
|
||||
},
|
||||
});
|
||||
|
||||
pages[entrypoint] = {
|
||||
handler: output.handler,
|
||||
runtime: output.runtime,
|
||||
memory: output.memory,
|
||||
maxDuration: output.maxDuration,
|
||||
environment: output.environment,
|
||||
allowQuery: output.allowQuery,
|
||||
regions: output.regions,
|
||||
};
|
||||
|
||||
// @ts-ignore This symbol is a private API
|
||||
const lambdaFiles: Files = output[FILES_SYMBOL];
|
||||
|
||||
const entry = join(workPath, '.output', 'server', 'pages', entrypoint);
|
||||
await fs.ensureDir(dirname(entry));
|
||||
await linkOrCopy(files[entrypoint].fsPath, entry);
|
||||
|
||||
const tracedFiles: {
|
||||
absolutePath: string;
|
||||
relativePath: string;
|
||||
}[] = [];
|
||||
|
||||
Object.entries(lambdaFiles).forEach(async ([relPath, file]) => {
|
||||
const newPath = join(traceDir, relPath);
|
||||
tracedFiles.push({ absolutePath: newPath, relativePath: relPath });
|
||||
if (file.fsPath) {
|
||||
await linkOrCopy(file.fsPath, newPath);
|
||||
} else if (file.type === 'FileBlob') {
|
||||
const { data, mode } = file as FileBlob;
|
||||
await fs.writeFile(newPath, data, { mode });
|
||||
} else {
|
||||
throw new Error(`Unknown file type: ${file.type}`);
|
||||
}
|
||||
});
|
||||
|
||||
const nft = join(
|
||||
workPath,
|
||||
'.output',
|
||||
'server',
|
||||
'pages',
|
||||
`${entrypoint}.nft.json`
|
||||
);
|
||||
const json = JSON.stringify({
|
||||
version: 1,
|
||||
files: tracedFiles.map(f => ({
|
||||
input: normalizePath(relative(nft, f.absolutePath)),
|
||||
output: normalizePath(f.relativePath),
|
||||
})),
|
||||
});
|
||||
|
||||
await fs.ensureDir(dirname(nft));
|
||||
await fs.writeFile(nft, json);
|
||||
}
|
||||
|
||||
await updateFunctionsManifest({ workPath, pages });
|
||||
};
|
||||
}
|
||||
|
||||
async function linkOrCopy(existingPath: string, newPath: string) {
|
||||
try {
|
||||
await fs.createLink(existingPath, newPath);
|
||||
} catch (err: any) {
|
||||
if (err.code !== 'EEXIST') {
|
||||
await fs.copyFile(existingPath, newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function readJson(filePath: string): Promise<{ [key: string]: any }> {
|
||||
try {
|
||||
const str = await fs.readFile(filePath, 'utf8');
|
||||
return JSON.parse(str);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
return {};
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function readVercelConfig(
|
||||
workPath: string
|
||||
): Promise<{ functions?: BuilderFunctions; regions?: string[] }> {
|
||||
const vercelJsonPath = join(workPath, 'vercel.json');
|
||||
return readJson(vercelJsonPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `.output/functions-manifest.json` exists, append to the pages
|
||||
* property. Otherwise write a new file. This will also read `vercel.json`
|
||||
* and apply relevant `functions` property config.
|
||||
*/
|
||||
export async function updateFunctionsManifest({
|
||||
workPath,
|
||||
pages,
|
||||
}: {
|
||||
workPath: string;
|
||||
pages: { [key: string]: any };
|
||||
}) {
|
||||
const functionsManifestPath = join(
|
||||
workPath,
|
||||
'.output',
|
||||
'functions-manifest.json'
|
||||
);
|
||||
const vercelConfig = await readVercelConfig(workPath);
|
||||
const functionsManifest = await readJson(functionsManifestPath);
|
||||
|
||||
if (!functionsManifest.version) functionsManifest.version = 1;
|
||||
if (!functionsManifest.pages) functionsManifest.pages = {};
|
||||
|
||||
for (const [pageKey, pageConfig] of Object.entries(pages)) {
|
||||
const fnConfig = await getLambdaOptionsFromFunction({
|
||||
sourceFile: pageKey,
|
||||
config: vercelConfig,
|
||||
});
|
||||
functionsManifest.pages[pageKey] = {
|
||||
...pageConfig,
|
||||
memory: fnConfig.memory || pageConfig.memory,
|
||||
maxDuration: fnConfig.maxDuration || pageConfig.maxDuration,
|
||||
regions: vercelConfig.regions || pageConfig.regions,
|
||||
};
|
||||
}
|
||||
|
||||
await fs.writeFile(functionsManifestPath, JSON.stringify(functionsManifest));
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import assert from 'assert';
|
||||
import vanillaGlob_ from 'glob';
|
||||
import { promisify } from 'util';
|
||||
import { lstat, Stats } from 'fs-extra';
|
||||
import { normalizePath } from './normalize-path';
|
||||
import FileFsRef from '../file-fs-ref';
|
||||
|
||||
export type GlobOptions = vanillaGlob_.IOptions;
|
||||
@@ -45,7 +46,7 @@ export default async function glob(
|
||||
const files = await vanillaGlob(pattern, options);
|
||||
|
||||
for (const relativePath of files) {
|
||||
const fsPath = path.join(options.cwd!, relativePath).replace(/\\/g, '/');
|
||||
const fsPath = normalizePath(path.join(options.cwd!, relativePath));
|
||||
let stat: Stats = options.statCache![fsPath] as Stats;
|
||||
assert(
|
||||
stat,
|
||||
|
||||
8
packages/build-utils/src/fs/normalize-path.ts
Normal file
8
packages/build-utils/src/fs/normalize-path.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const isWin = process.platform === 'win32';
|
||||
|
||||
/**
|
||||
* Convert Windows separators to Unix separators.
|
||||
*/
|
||||
export function normalizePath(p: string): string {
|
||||
return isWin ? p.replace(/\\/g, '/') : p;
|
||||
}
|
||||
@@ -81,6 +81,11 @@ export {
|
||||
export { detectFramework } from './detect-framework';
|
||||
export { DetectorFilesystem } from './detectors/filesystem';
|
||||
export { readConfigFile } from './fs/read-config-file';
|
||||
export { normalizePath } from './fs/normalize-path';
|
||||
export {
|
||||
convertRuntimeToPlugin,
|
||||
updateFunctionsManifest,
|
||||
} from './convert-runtime-to-plugin';
|
||||
|
||||
export * from './schemas';
|
||||
export * from './types';
|
||||
|
||||
@@ -36,9 +36,11 @@ interface CreateLambdaOptions {
|
||||
|
||||
interface GetLambdaOptionsFromFunctionOptions {
|
||||
sourceFile: string;
|
||||
config?: Config;
|
||||
config?: Pick<Config, 'functions'>;
|
||||
}
|
||||
|
||||
export const FILES_SYMBOL = Symbol('files');
|
||||
|
||||
export class Lambda {
|
||||
public type: 'Lambda';
|
||||
public zipBuffer: Buffer;
|
||||
@@ -118,7 +120,7 @@ export async function createLambda({
|
||||
|
||||
try {
|
||||
const zipBuffer = await createZip(files);
|
||||
return new Lambda({
|
||||
const lambda = new Lambda({
|
||||
zipBuffer,
|
||||
handler,
|
||||
runtime,
|
||||
@@ -127,6 +129,9 @@ export async function createLambda({
|
||||
environment,
|
||||
regions,
|
||||
});
|
||||
// @ts-ignore This symbol is a private API
|
||||
lambda[FILES_SYMBOL] = files;
|
||||
return lambda;
|
||||
} finally {
|
||||
sema.release();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface File {
|
||||
mode: number;
|
||||
contentType?: string;
|
||||
toStream: () => NodeJS.ReadableStream;
|
||||
toStreamAsync?: () => Promise<NodeJS.ReadableStream>;
|
||||
/**
|
||||
* The absolute path to the file in the filesystem
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
||||
"probes": [{ "path": "/", "mustContain": "npm version: 7" }]
|
||||
"probes": [{ "path": "/", "mustContain": "npm version: 8" }]
|
||||
}
|
||||
|
||||
182
packages/build-utils/test/unit.convert-runtime-to-plugin.test.ts
vendored
Normal file
182
packages/build-utils/test/unit.convert-runtime-to-plugin.test.ts
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
import { join } from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { BuildOptions, createLambda } from '../src';
|
||||
import { convertRuntimeToPlugin } from '../src/convert-runtime-to-plugin';
|
||||
|
||||
async function fsToJson(dir: string, output: Record<string, any> = {}) {
|
||||
const files = await fs.readdir(dir);
|
||||
for (const file of files) {
|
||||
const fsPath = join(dir, file);
|
||||
const stat = await fs.stat(fsPath);
|
||||
if (stat.isDirectory()) {
|
||||
output[file] = {};
|
||||
await fsToJson(fsPath, output[file]);
|
||||
} else {
|
||||
output[file] = await fs.readFile(fsPath, 'utf8');
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
const workPath = join(__dirname, 'walk', 'python-api');
|
||||
|
||||
describe('convert-runtime-to-plugin', () => {
|
||||
afterEach(async () => {
|
||||
await fs.remove(join(workPath, '.output'));
|
||||
});
|
||||
|
||||
it('should create correct fileystem for python', async () => {
|
||||
const lambdaOptions = {
|
||||
handler: 'index.handler',
|
||||
runtime: 'python3.9',
|
||||
memory: 512,
|
||||
maxDuration: 5,
|
||||
environment: {},
|
||||
regions: ['sfo1'],
|
||||
};
|
||||
|
||||
const buildRuntime = async (opts: BuildOptions) => {
|
||||
const lambda = await createLambda({
|
||||
files: opts.files,
|
||||
...lambdaOptions,
|
||||
});
|
||||
return { output: lambda };
|
||||
};
|
||||
|
||||
const lambdaFiles = await fsToJson(workPath);
|
||||
delete lambdaFiles['vercel.json'];
|
||||
const build = await convertRuntimeToPlugin(buildRuntime, '.py');
|
||||
|
||||
await build({ workPath });
|
||||
|
||||
const output = await fsToJson(join(workPath, '.output'));
|
||||
expect(output).toMatchObject({
|
||||
'functions-manifest.json': expect.stringContaining('{'),
|
||||
'runtime-traced-files': lambdaFiles,
|
||||
server: {
|
||||
pages: {
|
||||
api: {
|
||||
'index.py': expect.stringContaining('index'),
|
||||
'index.py.nft.json': expect.stringContaining('{'),
|
||||
users: {
|
||||
'get.py': expect.stringContaining('get'),
|
||||
'get.py.nft.json': expect.stringContaining('{'),
|
||||
'post.py': expect.stringContaining('post'),
|
||||
'post.py.nft.json': expect.stringContaining('{'),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const funcManifest = JSON.parse(output['functions-manifest.json']);
|
||||
expect(funcManifest).toMatchObject({
|
||||
version: 1,
|
||||
pages: {
|
||||
'api/index.py': lambdaOptions,
|
||||
'api/users/get.py': lambdaOptions,
|
||||
'api/users/post.py': { ...lambdaOptions, memory: 3008 },
|
||||
},
|
||||
});
|
||||
|
||||
const indexJson = JSON.parse(output.server.pages.api['index.py.nft.json']);
|
||||
expect(indexJson).toMatchObject({
|
||||
version: 1,
|
||||
files: [
|
||||
{
|
||||
input: '../../../../runtime-traced-files/api/index.py',
|
||||
output: 'api/index.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../runtime-traced-files/api/users/get.py',
|
||||
output: 'api/users/get.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../runtime-traced-files/api/users/post.py',
|
||||
output: 'api/users/post.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../runtime-traced-files/file.txt',
|
||||
output: 'file.txt',
|
||||
},
|
||||
{
|
||||
input: '../../../../runtime-traced-files/util/date.py',
|
||||
output: 'util/date.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../runtime-traced-files/util/math.py',
|
||||
output: 'util/math.py',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const getJson = JSON.parse(
|
||||
output.server.pages.api.users['get.py.nft.json']
|
||||
);
|
||||
expect(getJson).toMatchObject({
|
||||
version: 1,
|
||||
files: [
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/index.py',
|
||||
output: 'api/index.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/users/get.py',
|
||||
output: 'api/users/get.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/users/post.py',
|
||||
output: 'api/users/post.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/file.txt',
|
||||
output: 'file.txt',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/util/date.py',
|
||||
output: 'util/date.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/util/math.py',
|
||||
output: 'util/math.py',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const postJson = JSON.parse(
|
||||
output.server.pages.api.users['post.py.nft.json']
|
||||
);
|
||||
expect(postJson).toMatchObject({
|
||||
version: 1,
|
||||
files: [
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/index.py',
|
||||
output: 'api/index.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/users/get.py',
|
||||
output: 'api/users/get.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/api/users/post.py',
|
||||
output: 'api/users/post.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/file.txt',
|
||||
output: 'file.txt',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/util/date.py',
|
||||
output: 'util/date.py',
|
||||
},
|
||||
{
|
||||
input: '../../../../../runtime-traced-files/util/math.py',
|
||||
output: 'util/math.py',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(output.server.pages['file.txt']).toBeUndefined();
|
||||
expect(output.server.pages.api['file.txt']).toBeUndefined();
|
||||
});
|
||||
});
|
||||
1
packages/build-utils/test/walk/python-api/api/index.py
Normal file
1
packages/build-utils/test/walk/python-api/api/index.py
Normal file
@@ -0,0 +1 @@
|
||||
# index
|
||||
@@ -0,0 +1 @@
|
||||
# get
|
||||
@@ -0,0 +1 @@
|
||||
# post
|
||||
1
packages/build-utils/test/walk/python-api/file.txt
Normal file
1
packages/build-utils/test/walk/python-api/file.txt
Normal file
@@ -0,0 +1 @@
|
||||
This file should also be included
|
||||
1
packages/build-utils/test/walk/python-api/util/date.py
Normal file
1
packages/build-utils/test/walk/python-api/util/date.py
Normal file
@@ -0,0 +1 @@
|
||||
# date
|
||||
1
packages/build-utils/test/walk/python-api/util/math.py
Normal file
1
packages/build-utils/test/walk/python-api/util/math.py
Normal file
@@ -0,0 +1 @@
|
||||
# math
|
||||
10
packages/build-utils/test/walk/python-api/vercel.json
Normal file
10
packages/build-utils/test/walk/python-api/vercel.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"functions": {
|
||||
"api/users/post.py": {
|
||||
"memory": 3008
|
||||
},
|
||||
"api/not-matching-anything.py": {
|
||||
"memory": 768
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "23.1.3-canary.14",
|
||||
"version": "23.1.3-canary.35",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -43,14 +43,17 @@
|
||||
"node": ">= 12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.12.3-canary.12",
|
||||
"@vercel/go": "1.2.4-canary.3",
|
||||
"@vercel/node": "1.12.2-canary.4",
|
||||
"@vercel/python": "2.0.6-canary.4",
|
||||
"@vercel/ruby": "1.2.8-canary.3",
|
||||
"update-notifier": "4.1.0"
|
||||
"@vercel/build-utils": "2.12.3-canary.19",
|
||||
"@vercel/go": "1.2.4-canary.4",
|
||||
"@vercel/node": "1.12.2-canary.6",
|
||||
"@vercel/python": "2.0.6-canary.6",
|
||||
"@vercel/ruby": "1.2.8-canary.4",
|
||||
"update-notifier": "4.1.0",
|
||||
"vercel-plugin-middleware": "0.0.0-canary.7",
|
||||
"vercel-plugin-node": "1.12.2-canary.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/env": "11.1.2",
|
||||
"@sentry/node": "5.5.0",
|
||||
"@sindresorhus/slugify": "0.11.0",
|
||||
"@tootallnate/once": "1.1.2",
|
||||
@@ -63,7 +66,7 @@
|
||||
"@types/dotenv": "6.1.1",
|
||||
"@types/escape-html": "0.0.20",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "5.0.5",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/glob": "7.1.1",
|
||||
"@types/http-proxy": "1.16.2",
|
||||
"@types/inquirer": "7.3.1",
|
||||
@@ -87,8 +90,9 @@
|
||||
"@types/update-notifier": "5.1.0",
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@vercel/frameworks": "0.5.1-canary.8",
|
||||
"@vercel/frameworks": "0.5.1-canary.12",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/nft": "0.17.0",
|
||||
"@zeit/fun": "0.11.2",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
"ajv": "6.12.2",
|
||||
@@ -120,7 +124,7 @@
|
||||
"execa": "3.2.0",
|
||||
"express": "4.17.1",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"fs-extra": "7.0.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"get-port": "5.1.1",
|
||||
"glob": "7.1.2",
|
||||
"http-proxy": "1.18.1",
|
||||
|
||||
791
packages/cli/src/commands/build.ts
Normal file
791
packages/cli/src/commands/build.ts
Normal file
@@ -0,0 +1,791 @@
|
||||
import { loadEnvConfig, processEnv } from '@next/env';
|
||||
import {
|
||||
execCommand,
|
||||
getScriptName,
|
||||
GlobOptions,
|
||||
scanParentDirs,
|
||||
spawnAsync,
|
||||
} from '@vercel/build-utils';
|
||||
import { nodeFileTrace } from '@vercel/nft';
|
||||
import Sema from 'async-sema';
|
||||
import chalk from 'chalk';
|
||||
import { SpawnOptions } from 'child_process';
|
||||
import { assert } from 'console';
|
||||
import { createHash } from 'crypto';
|
||||
import fs from 'fs-extra';
|
||||
import ogGlob from 'glob';
|
||||
import { isAbsolute, join, parse, relative, resolve } from 'path';
|
||||
import pluralize from 'pluralize';
|
||||
import Client from '../util/client';
|
||||
import { emoji, prependEmoji } from '../util/emoji';
|
||||
import getArgs from '../util/get-args';
|
||||
import handleError from '../util/handle-error';
|
||||
import confirm from '../util/input/confirm';
|
||||
import { isSettingValue } from '../util/is-setting-value';
|
||||
import cmd from '../util/output/cmd';
|
||||
import logo from '../util/output/logo';
|
||||
import param from '../util/output/param';
|
||||
import stamp from '../util/output/stamp';
|
||||
import { getCommandName, getPkgName } from '../util/pkg-name';
|
||||
import { loadCliPlugins } from '../util/plugins';
|
||||
import { findFramework } from '../util/projects/find-framework';
|
||||
import { VERCEL_DIR } from '../util/projects/link';
|
||||
import { readProjectSettings } from '../util/projects/project-settings';
|
||||
import pull from './pull';
|
||||
|
||||
const sema = new Sema(16, {
|
||||
capacity: 100,
|
||||
});
|
||||
|
||||
const help = () => {
|
||||
return console.log(`
|
||||
${chalk.bold(`${logo} ${getPkgName()} build`)}
|
||||
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
|
||||
'DIR'
|
||||
)} Path to the global ${'`.vercel`'} directory
|
||||
--cwd [path] The current working directory
|
||||
-d, --debug Debug mode [off]
|
||||
-y, --yes Skip the confirmation prompt
|
||||
|
||||
${chalk.dim('Examples:')}
|
||||
|
||||
${chalk.gray('–')} Build the project
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} build`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} build --cwd ./path-to-project`)}
|
||||
`);
|
||||
};
|
||||
|
||||
const OUTPUT_DIR = '.output';
|
||||
|
||||
export default async function main(client: Client) {
|
||||
if (process.env.__VERCEL_BUILD_RUNNING) {
|
||||
client.output.error(
|
||||
`${cmd(
|
||||
`${getPkgName()} build`
|
||||
)} must not recursively invoke itself. Check the Build Command in the Project Settings or the ${cmd(
|
||||
'build'
|
||||
)} script in ${cmd('package.json')}`
|
||||
);
|
||||
client.output.error(
|
||||
`Learn More: https://vercel.link/recursive-invocation-of-commands`
|
||||
);
|
||||
return 1;
|
||||
} else {
|
||||
process.env.__VERCEL_BUILD_RUNNING = '1';
|
||||
}
|
||||
|
||||
let argv;
|
||||
const buildStamp = stamp();
|
||||
try {
|
||||
argv = getArgs(client.argv.slice(2), {
|
||||
'--debug': Boolean,
|
||||
'--cwd': String,
|
||||
});
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argv['--help']) {
|
||||
help();
|
||||
return 2;
|
||||
}
|
||||
|
||||
let cwd = argv['--cwd'] || process.cwd();
|
||||
|
||||
let project = await readProjectSettings(join(cwd, VERCEL_DIR));
|
||||
// If there are no project settings, only then do we pull them down
|
||||
while (!project?.settings) {
|
||||
const confirmed = await confirm(
|
||||
`No Project Settings found locally. Run ${getCommandName(
|
||||
'pull'
|
||||
)} for retrieving them?`,
|
||||
true
|
||||
);
|
||||
if (!confirmed) {
|
||||
client.output.print(`Aborted. No Project Settings retrieved.\n`);
|
||||
return 0;
|
||||
}
|
||||
const result = await pull(client);
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
}
|
||||
project = await readProjectSettings(join(cwd, VERCEL_DIR));
|
||||
}
|
||||
|
||||
// If `rootDirectory` exists, then `baseDir` will be the repo's root directory.
|
||||
const baseDir = cwd;
|
||||
|
||||
cwd = project.settings.rootDirectory
|
||||
? join(cwd, project.settings.rootDirectory)
|
||||
: cwd;
|
||||
|
||||
// Load the environment
|
||||
const { combinedEnv, loadedEnvFiles } = loadEnvConfig(cwd, false, {
|
||||
info: () => ({}), // we don't want to log this yet.
|
||||
error: (...args: any[]) => client.output.error(args.join(' ')),
|
||||
});
|
||||
|
||||
// Set process.env with loaded environment variables
|
||||
await processEnv(loadedEnvFiles);
|
||||
|
||||
const spawnOpts = {
|
||||
env: { ...combinedEnv, VERCEL: '1' },
|
||||
};
|
||||
|
||||
process.chdir(cwd);
|
||||
|
||||
const framework = findFramework(project.settings.framework);
|
||||
// If this is undefined, we bail. If it is null, then findFramework should return "Other",
|
||||
// so this should really never happen, but just in case....
|
||||
if (framework === undefined) {
|
||||
client.output.error(
|
||||
`Framework detection failed or is malformed. Please run ${getCommandName(
|
||||
'pull'
|
||||
)} again.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const buildState = { ...project.settings };
|
||||
const formatSetting = (
|
||||
name: string,
|
||||
override: string | null | undefined,
|
||||
defaults: typeof framework.settings.outputDirectory
|
||||
) =>
|
||||
` - ${chalk.bold(`${name}:`)} ${`${
|
||||
override
|
||||
? override + ` (override)`
|
||||
: 'placeholder' in defaults
|
||||
? chalk.italic(`${defaults.placeholder}`)
|
||||
: defaults.value
|
||||
}`}`;
|
||||
console.log(`Retrieved Project Settings:`);
|
||||
console.log(
|
||||
chalk.dim(` - ${chalk.bold(`Framework Preset:`)} ${framework.name}`)
|
||||
);
|
||||
console.log(
|
||||
chalk.dim(
|
||||
formatSetting(
|
||||
'Build Command',
|
||||
project.settings.buildCommand,
|
||||
framework.settings.buildCommand
|
||||
)
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
chalk.dim(
|
||||
formatSetting(
|
||||
'Output Directory',
|
||||
project.settings.outputDirectory,
|
||||
framework.settings.outputDirectory
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
buildState.outputDirectory =
|
||||
project.settings.outputDirectory ||
|
||||
(isSettingValue(framework.settings.outputDirectory)
|
||||
? framework.settings.outputDirectory.value
|
||||
: null);
|
||||
buildState.rootDirectory = project.settings.rootDirectory;
|
||||
|
||||
if (loadedEnvFiles.length > 0) {
|
||||
console.log(
|
||||
`Loaded Environment Variables from ${loadedEnvFiles.length} ${pluralize(
|
||||
'file',
|
||||
loadedEnvFiles.length
|
||||
)}:`
|
||||
);
|
||||
for (let envFile of loadedEnvFiles) {
|
||||
console.log(chalk.dim(` - ${envFile.path}`));
|
||||
}
|
||||
}
|
||||
|
||||
// Load plugins
|
||||
const debug = argv['--debug'];
|
||||
let plugins;
|
||||
try {
|
||||
plugins = await loadCliPlugins(cwd, client.output);
|
||||
} catch (error) {
|
||||
client.output.error('Failed to load CLI Plugins');
|
||||
handleError(error, { debug });
|
||||
return 1;
|
||||
}
|
||||
|
||||
const origLog = console.log;
|
||||
const origErr = console.error;
|
||||
const prefixedLog = (
|
||||
prefix: string,
|
||||
args: any[],
|
||||
logger: (...args: any[]) => void
|
||||
) => {
|
||||
if (typeof args[0] === 'string') {
|
||||
args[0] = `${prefix} ${args[0]}`;
|
||||
} else {
|
||||
args.unshift(prefix);
|
||||
}
|
||||
return logger(...args);
|
||||
};
|
||||
|
||||
if (plugins?.pluginCount && plugins?.pluginCount > 0) {
|
||||
console.log(
|
||||
`Loaded ${plugins.pluginCount} CLI ${pluralize(
|
||||
'Plugin',
|
||||
plugins.pluginCount
|
||||
)}`
|
||||
);
|
||||
// preBuild Plugins
|
||||
if (plugins.preBuildPlugins.length > 0) {
|
||||
console.log(
|
||||
`Running ${plugins.pluginCount} CLI ${pluralize(
|
||||
'Plugin',
|
||||
plugins.pluginCount
|
||||
)} before Build Command:`
|
||||
);
|
||||
for (let item of plugins.preBuildPlugins) {
|
||||
const { name, plugin, color } = item;
|
||||
if (typeof plugin.preBuild === 'function') {
|
||||
const pluginStamp = stamp();
|
||||
const fullName = name + '.preBuild';
|
||||
const prefix = chalk.gray(' > ') + color(fullName + ':');
|
||||
client.output.debug(`Running ${fullName}:`);
|
||||
try {
|
||||
console.log = (...args: any[]) =>
|
||||
prefixedLog(prefix, args, origLog);
|
||||
console.error = (...args: any[]) =>
|
||||
prefixedLog(prefix, args, origErr);
|
||||
await plugin.preBuild();
|
||||
client.output.debug(
|
||||
`Completed ${fullName} ${chalk.dim(`${pluginStamp()}`)}`
|
||||
);
|
||||
} catch (error) {
|
||||
client.output.error(`${prefix} failed`);
|
||||
handleError(error, { debug });
|
||||
return 1;
|
||||
} finally {
|
||||
console.log = origLog;
|
||||
console.error = origErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean the output directory
|
||||
fs.removeSync(join(cwd, OUTPUT_DIR));
|
||||
|
||||
// Yarn v2 PnP mode may be activated, so force
|
||||
// "node-modules" linker style
|
||||
const env = {
|
||||
YARN_NODE_LINKER: 'node-modules',
|
||||
...spawnOpts.env,
|
||||
};
|
||||
|
||||
if (typeof buildState.buildCommand === 'string') {
|
||||
console.log(`Running Build Command: ${cmd(buildState.buildCommand)}`);
|
||||
await execCommand(buildState.buildCommand, {
|
||||
...spawnOpts,
|
||||
env,
|
||||
cwd,
|
||||
});
|
||||
} else if (fs.existsSync(join(cwd, 'package.json'))) {
|
||||
await runPackageJsonScript(
|
||||
client,
|
||||
cwd,
|
||||
['vercel-build', 'now-build', 'build'],
|
||||
spawnOpts
|
||||
);
|
||||
} else if (typeof framework.settings.buildCommand.value === 'string') {
|
||||
console.log(
|
||||
`Running Build Command: ${cmd(framework.settings.buildCommand.value)}`
|
||||
);
|
||||
await execCommand(framework.settings.buildCommand.value, {
|
||||
...spawnOpts,
|
||||
env,
|
||||
cwd,
|
||||
});
|
||||
}
|
||||
|
||||
if (!fs.existsSync(join(cwd, OUTPUT_DIR))) {
|
||||
let outputDir = join(OUTPUT_DIR, 'static');
|
||||
let distDir = await framework.getFsOutputDir(cwd);
|
||||
if (framework.slug === 'nextjs') {
|
||||
outputDir = OUTPUT_DIR;
|
||||
}
|
||||
const copyStamp = stamp();
|
||||
await fs.ensureDir(join(cwd, outputDir));
|
||||
const relativeDistDir = relative(cwd, distDir);
|
||||
client.output.spinner(
|
||||
`Copying files from ${param(distDir)} to ${param(outputDir)}`
|
||||
);
|
||||
const files = await glob(join(relativeDistDir, '**'), {
|
||||
ignore: [
|
||||
'node_modules/**',
|
||||
'.vercel/**',
|
||||
'.env',
|
||||
'.env.*',
|
||||
'.*ignore',
|
||||
'_middleware.ts',
|
||||
'_middleware.mts',
|
||||
'_middleware.cts',
|
||||
'_middleware.mjs',
|
||||
'_middleware.cjs',
|
||||
'_middleware.js',
|
||||
'api/**',
|
||||
'.git/**',
|
||||
'.next/cache/**',
|
||||
],
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
absolute: true,
|
||||
});
|
||||
await Promise.all(
|
||||
files.map(f =>
|
||||
smartCopy(
|
||||
client,
|
||||
f,
|
||||
distDir === '.'
|
||||
? join(cwd, outputDir, relative(cwd, f))
|
||||
: f.replace(distDir, outputDir)
|
||||
)
|
||||
)
|
||||
);
|
||||
client.output.stopSpinner();
|
||||
console.log(
|
||||
`Copied ${files.length.toLocaleString()} files from ${param(
|
||||
distDir
|
||||
)} to ${param(outputDir)} ${copyStamp()}`
|
||||
);
|
||||
|
||||
const buildManifestPath = join(cwd, OUTPUT_DIR, 'build-manifest.json');
|
||||
const routesManifestPath = join(cwd, OUTPUT_DIR, 'routes-manifest.json');
|
||||
|
||||
if (!fs.existsSync(buildManifestPath)) {
|
||||
client.output.debug(
|
||||
`Generating build manifest: ${param(buildManifestPath)}`
|
||||
);
|
||||
const buildManifest = {
|
||||
cache: framework.cachePattern ? [framework.cachePattern] : [],
|
||||
};
|
||||
await fs.writeJSON(buildManifestPath, buildManifest, { spaces: 2 });
|
||||
}
|
||||
|
||||
if (!fs.existsSync(routesManifestPath)) {
|
||||
client.output.debug(
|
||||
`Generating routes manifest: ${param(routesManifestPath)}`
|
||||
);
|
||||
const routesManifest = {
|
||||
version: 3,
|
||||
pages404: true,
|
||||
basePath: '',
|
||||
redirects: framework.defaultRedirects ?? [],
|
||||
headers: framework.defaultHeaders ?? [],
|
||||
dynamicRoutes: [],
|
||||
dataRoutes: [],
|
||||
rewrites: framework.defaultRewrites ?? [],
|
||||
};
|
||||
await fs.writeJSON(
|
||||
join(cwd, OUTPUT_DIR, 'routes-manifest.json'),
|
||||
routesManifest,
|
||||
{ spaces: 2 }
|
||||
);
|
||||
}
|
||||
|
||||
// Special Next.js processing.
|
||||
if (framework.slug === 'nextjs') {
|
||||
// The contents of `.output/static` should be placed inside of `.output/static/_next/static`
|
||||
const tempStatic = '___static';
|
||||
await fs.rename(
|
||||
join(cwd, OUTPUT_DIR, 'static'),
|
||||
join(cwd, OUTPUT_DIR, tempStatic)
|
||||
);
|
||||
await fs.mkdirp(join(cwd, OUTPUT_DIR, 'static', '_next', 'static'));
|
||||
await fs.rename(
|
||||
join(cwd, OUTPUT_DIR, tempStatic),
|
||||
join(cwd, OUTPUT_DIR, 'static', '_next', 'static')
|
||||
);
|
||||
|
||||
// Next.js might reference files from the `static` directory in `middleware-manifest.json`.
|
||||
// Since we move all files from `static` to `static/_next/static`, we'll need to change
|
||||
// those references as well and update the manifest file.
|
||||
const middlewareManifest = join(
|
||||
cwd,
|
||||
OUTPUT_DIR,
|
||||
'server',
|
||||
'middleware-manifest.json'
|
||||
);
|
||||
if (fs.existsSync(middlewareManifest)) {
|
||||
const manifest = await fs.readJSON(middlewareManifest);
|
||||
Object.keys(manifest.middleware).forEach(key => {
|
||||
const files = manifest.middleware[key].files.map((f: string) => {
|
||||
if (f.startsWith('static/')) {
|
||||
const next = f.replace(/^static\//gm, 'static/_next/static/');
|
||||
client.output.debug(
|
||||
`Replacing file in \`middleware-manifest.json\`: ${f} => ${next}`
|
||||
);
|
||||
return next;
|
||||
}
|
||||
|
||||
return f;
|
||||
});
|
||||
|
||||
manifest.middleware[key].files = files;
|
||||
});
|
||||
|
||||
await fs.writeJSON(middlewareManifest, manifest);
|
||||
}
|
||||
|
||||
// We want to pick up directories for user-provided static files into `.`output/static`.
|
||||
// More specifically, the static directory contents would then be mounted to `output/static/static`,
|
||||
// and the public directory contents would be mounted to `output/static`. Old Next.js versions
|
||||
// allow `static`, and newer ones allow both, but since there's nobody that actually uses both,
|
||||
// we can check for the existence of both and pick the first match that we find (first
|
||||
// `public`, then`static`). We can't read both at the same time because that would mean we'd
|
||||
// read public for old Next.js versions that don't support it, which might be breaking (and
|
||||
// we don't want to make vercel build specific framework versions).
|
||||
const publicFiles = await glob('public/**', {
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
absolute: true,
|
||||
});
|
||||
if (publicFiles.length > 0) {
|
||||
await Promise.all(
|
||||
publicFiles.map(f =>
|
||||
smartCopy(
|
||||
client,
|
||||
f,
|
||||
f.replace('public', join(OUTPUT_DIR, 'static'))
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const staticFiles = await glob('static/**', {
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
absolute: true,
|
||||
});
|
||||
await Promise.all(
|
||||
staticFiles.map(f =>
|
||||
smartCopy(
|
||||
client,
|
||||
f,
|
||||
f.replace('static', join(OUTPUT_DIR, 'static', 'static'))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Regardless of the Next.js version, we make sure that it is compatible with
|
||||
// the Filesystem API. We get there by moving all the files needed
|
||||
// into the outputs directory `inputs` folder. Next.js is > 12, we can
|
||||
// read the .nft.json files directly. If there aren't .nft.json files
|
||||
// we trace and create them. We then resolve the files in each nft file list
|
||||
// and move them into the "inputs" directory. We rename them with hashes to
|
||||
// prevent collisions and then update the related .nft files accordingly
|
||||
// to point to the newly named input files. Again, all of this is so that Next.js
|
||||
// works with the Filesystem API (and so .output contains all inputs
|
||||
// needed to run Next.js) and `vc --prebuilt`.
|
||||
const nftFiles = await glob(join(OUTPUT_DIR, '**', '*.nft.json'), {
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
// If there are no .nft.json files, we know that Next.js < 12. We then
|
||||
// execute the tracing on our own.
|
||||
if (nftFiles.length === 0) {
|
||||
const serverFiles = await glob(
|
||||
join(OUTPUT_DIR, 'server', 'pages', '**', '*.js'),
|
||||
{
|
||||
nodir: true,
|
||||
dot: true,
|
||||
cwd,
|
||||
ignore: ['webpack-runtime.js'],
|
||||
absolute: true,
|
||||
}
|
||||
);
|
||||
for (let f of serverFiles) {
|
||||
const { ext, dir } = parse(f);
|
||||
const { fileList } = await nodeFileTrace([f], {
|
||||
ignore: [
|
||||
relative(cwd, f),
|
||||
'node_modules/next/dist/pages/**/*',
|
||||
'node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
|
||||
'node_modules/react/**/*.development.js',
|
||||
'node_modules/react-dom/**/*.development.js',
|
||||
'node_modules/use-subscription/**/*.development.js',
|
||||
'node_modules/sharp/**/*',
|
||||
],
|
||||
});
|
||||
fileList.delete(relative(cwd, f));
|
||||
await resolveNftToOutput({
|
||||
client,
|
||||
baseDir,
|
||||
outputDir: OUTPUT_DIR,
|
||||
nftFileName: f.replace(ext, '.js.nft.json'),
|
||||
nft: {
|
||||
version: 1,
|
||||
files: Array.from(fileList).map(fileListEntry =>
|
||||
relative(dir, fileListEntry)
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (let f of nftFiles) {
|
||||
const json = await fs.readJson(f);
|
||||
await resolveNftToOutput({
|
||||
client,
|
||||
baseDir,
|
||||
outputDir: OUTPUT_DIR,
|
||||
nftFileName: f,
|
||||
nft: json,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const requiredServerFilesPath = join(
|
||||
OUTPUT_DIR,
|
||||
'required-server-files.json'
|
||||
);
|
||||
const requiredServerFilesJson = await fs.readJSON(
|
||||
requiredServerFilesPath
|
||||
);
|
||||
await fs.writeJSON(requiredServerFilesPath, {
|
||||
...requiredServerFilesJson,
|
||||
appDir: '.',
|
||||
files: requiredServerFilesJson.files.map((i: string) => {
|
||||
const absolutePath = join(cwd, i.replace('.next', '.output'));
|
||||
const output = relative(baseDir, absolutePath);
|
||||
|
||||
return {
|
||||
input: i.replace('.next', '.output'),
|
||||
output,
|
||||
};
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Build Plugins
|
||||
if (plugins?.buildPlugins && plugins.buildPlugins.length > 0) {
|
||||
console.log(
|
||||
`Running ${plugins.pluginCount} CLI ${pluralize(
|
||||
'Plugin',
|
||||
plugins.pluginCount
|
||||
)} after Build Command:`
|
||||
);
|
||||
for (let item of plugins.buildPlugins) {
|
||||
const { name, plugin, color } = item;
|
||||
if (typeof plugin.build === 'function') {
|
||||
const pluginStamp = stamp();
|
||||
const fullName = name + '.build';
|
||||
const prefix = chalk.gray(' > ') + color(fullName + ':');
|
||||
client.output.debug(`Running ${fullName}:`);
|
||||
try {
|
||||
console.log = (...args: any[]) => prefixedLog(prefix, args, origLog);
|
||||
console.error = (...args: any[]) =>
|
||||
prefixedLog(prefix, args, origErr);
|
||||
await plugin.build({
|
||||
workPath: cwd,
|
||||
});
|
||||
client.output.debug(
|
||||
`Completed ${fullName} ${chalk.dim(`${pluginStamp()}`)}`
|
||||
);
|
||||
} catch (error) {
|
||||
client.output.error(`${prefix} failed`);
|
||||
handleError(error, { debug });
|
||||
return 1;
|
||||
} finally {
|
||||
console.log = origLog;
|
||||
console.error = origLog;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`${prependEmoji(
|
||||
`Build Completed in ${chalk.bold(OUTPUT_DIR)} ${chalk.gray(
|
||||
buildStamp()
|
||||
)}`,
|
||||
emoji('success')
|
||||
)}`
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export async function runPackageJsonScript(
|
||||
client: Client,
|
||||
destPath: string,
|
||||
scriptNames: string | Iterable<string>,
|
||||
spawnOpts?: SpawnOptions
|
||||
) {
|
||||
assert(isAbsolute(destPath));
|
||||
|
||||
const { packageJson, cliType, lockfileVersion } = await scanParentDirs(
|
||||
destPath,
|
||||
true
|
||||
);
|
||||
const scriptName = getScriptName(
|
||||
packageJson,
|
||||
typeof scriptNames === 'string' ? [scriptNames] : scriptNames
|
||||
);
|
||||
if (!scriptName) return false;
|
||||
|
||||
client.output.debug('Running user script...');
|
||||
const runScriptTime = Date.now();
|
||||
|
||||
const opts: any = { cwd: destPath, ...spawnOpts };
|
||||
const env = (opts.env = { ...process.env, ...opts.env });
|
||||
|
||||
if (cliType === 'npm') {
|
||||
opts.prettyCommand = `npm run ${scriptName}`;
|
||||
|
||||
if (typeof lockfileVersion === 'number' && lockfileVersion >= 2) {
|
||||
// Ensure that npm 7 is at the beginning of the `$PATH`
|
||||
env.PATH = `/node16/bin-npm7:${env.PATH}`;
|
||||
}
|
||||
} else {
|
||||
opts.prettyCommand = `yarn run ${scriptName}`;
|
||||
|
||||
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||
if (!env.YARN_NODE_LINKER) {
|
||||
env.YARN_NODE_LINKER = 'node-modules';
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Running Build Command: ${cmd(opts.prettyCommand)}\n`);
|
||||
await spawnAsync(cliType, ['run', scriptName], opts);
|
||||
console.log(); // give it some room
|
||||
client.output.debug(`Script complete [${Date.now() - runScriptTime}ms]`);
|
||||
return true;
|
||||
}
|
||||
|
||||
async function linkOrCopy(existingPath: string, newPath: string) {
|
||||
try {
|
||||
if (
|
||||
newPath.endsWith('.nft.json') ||
|
||||
newPath.endsWith('middleware-manifest.json') ||
|
||||
newPath.endsWith('required-server-files.json')
|
||||
) {
|
||||
await fs.copy(existingPath, newPath, {
|
||||
overwrite: true,
|
||||
});
|
||||
} else {
|
||||
await fs.createSymlink(existingPath, newPath, 'file');
|
||||
}
|
||||
} catch (err: any) {
|
||||
// eslint-disable-line
|
||||
// If a symlink to the same file already exists
|
||||
// then trying to copy it will make an empty file from it.
|
||||
if (err['code'] === 'EEXIST') return;
|
||||
// In some VERY rare cases (1 in a thousand), symlink creation fails on Windows.
|
||||
// In that case, we just fall back to copying.
|
||||
// This issue is reproducible with "pnpm add @material-ui/icons@4.9.1"
|
||||
await fs.copy(existingPath, newPath, {
|
||||
overwrite: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function smartCopy(client: Client, from: string, to: string) {
|
||||
sema.acquire();
|
||||
try {
|
||||
client.output.debug(`Copying from ${from} to ${to}`);
|
||||
await linkOrCopy(from, to);
|
||||
} finally {
|
||||
sema.release();
|
||||
}
|
||||
}
|
||||
|
||||
async function glob(pattern: string, options: GlobOptions): Promise<string[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
ogGlob(pattern, options, (err, files) => {
|
||||
err ? reject(err) : resolve(files);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hash for the given buf.
|
||||
*
|
||||
* @param {Buffer} file data
|
||||
* @return {String} hex digest
|
||||
*/
|
||||
function hash(buf: Buffer): string {
|
||||
return createHash('sha1').update(buf).digest('hex');
|
||||
}
|
||||
|
||||
interface NftFile {
|
||||
version: number;
|
||||
files: (string | { input: string; output: string })[];
|
||||
}
|
||||
|
||||
// resolveNftToOutput takes nft file and moves all of its trace files
|
||||
// into the specified directory + `inputs`, (renaming them to their hash + ext) and
|
||||
// subsequently updating the original nft file accordingly. This is done
|
||||
// to make the `.output` directory be self-contained, so that it works
|
||||
// properly with `vc --prebuilt`.
|
||||
async function resolveNftToOutput({
|
||||
client,
|
||||
baseDir,
|
||||
outputDir,
|
||||
nftFileName,
|
||||
nft,
|
||||
}: {
|
||||
client: Client;
|
||||
baseDir: string;
|
||||
outputDir: string;
|
||||
nftFileName: string;
|
||||
nft: NftFile;
|
||||
}) {
|
||||
client.output.debug(`Processing and resolving ${nftFileName}`);
|
||||
await fs.ensureDir(join(outputDir, 'inputs'));
|
||||
const newFilesList: NftFile['files'] = [];
|
||||
for (let fileEntity of nft.files) {
|
||||
const relativeInput: string =
|
||||
typeof fileEntity === 'string' ? fileEntity : fileEntity.input;
|
||||
const fullInput = resolve(join(parse(nftFileName).dir, relativeInput));
|
||||
|
||||
// if the resolved path is NOT in the .output directory we move in it there
|
||||
if (!fullInput.includes(outputDir)) {
|
||||
const { ext } = parse(fullInput);
|
||||
const raw = await fs.readFile(fullInput);
|
||||
const newFilePath = join(outputDir, 'inputs', hash(raw) + ext);
|
||||
smartCopy(client, fullInput, newFilePath);
|
||||
|
||||
// We have to use `baseDir` instead of `cwd`, because we want to
|
||||
// mount everything from there (especially `node_modules`).
|
||||
// This is important for NPM Workspaces where `node_modules` is not
|
||||
// in the directory of the workspace.
|
||||
const output = relative(baseDir, fullInput).replace('.output', '.next');
|
||||
|
||||
newFilesList.push({
|
||||
input: relative(parse(nftFileName).dir, newFilePath),
|
||||
output,
|
||||
});
|
||||
} else {
|
||||
newFilesList.push(relativeInput);
|
||||
}
|
||||
}
|
||||
// Update the .nft.json with new input and output mapping
|
||||
await fs.writeJSON(nftFileName, {
|
||||
...nft,
|
||||
files: newFilesList,
|
||||
});
|
||||
}
|
||||
@@ -18,9 +18,10 @@ export const help = () => `
|
||||
init [example] Initialize an example project
|
||||
ls | list [app] Lists deployments
|
||||
inspect [id] Displays information related to a deployment
|
||||
link Link local directory to a Vercel Project
|
||||
link [path] Link local directory to a Vercel Project
|
||||
login [email] Logs into your account or creates a new one
|
||||
logout Logs out of your account
|
||||
pull [path] Pull your Project Settings from the cloud
|
||||
switch [scope] Switches between teams and your personal account
|
||||
help [cmd] Displays complete help for [cmd]
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import { getCommandName } from '../../util/pkg-name';
|
||||
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url';
|
||||
import { Output } from '../../util/output';
|
||||
import { help } from './args';
|
||||
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
|
||||
|
||||
export default async (client: Client) => {
|
||||
const { output } = client;
|
||||
@@ -78,6 +79,7 @@ export default async (client: Client) => {
|
||||
// This is not an array in favor of matching
|
||||
// the config property name.
|
||||
'--regions': String,
|
||||
'--prebuilt': Boolean,
|
||||
'--prod': Boolean,
|
||||
'--confirm': Boolean,
|
||||
'-f': '--force',
|
||||
@@ -444,6 +446,7 @@ export default async (client: Client) => {
|
||||
build: { env: deploymentBuildEnv },
|
||||
forceNew: argv['--force'],
|
||||
withCache: argv['--with-cache'],
|
||||
prebuilt: argv['--prebuilt'],
|
||||
quiet,
|
||||
wantsPublic: argv['--public'] || localConfig.public,
|
||||
isFile,
|
||||
@@ -527,6 +530,20 @@ export default async (client: Client) => {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (deployment.checksConclusion === 'failed') {
|
||||
const { checks } = await getDeploymentChecks(client, deployment.id);
|
||||
const counters = new Map<string, number>();
|
||||
checks.forEach(c => {
|
||||
counters.set(c.conclusion, (counters.get(c.conclusion) ?? 0) + 1);
|
||||
});
|
||||
|
||||
const counterList = Array.from(counters)
|
||||
.map(([name, no]) => `${no} ${name}`)
|
||||
.join(', ');
|
||||
output.error(`Running Checks: ${counterList}`);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const deploymentResponse = await getDeploymentByIdOrHost(
|
||||
client,
|
||||
contextName,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { ProjectEnvVariable } from '../../types';
|
||||
import Client from '../../util/client';
|
||||
import { getLinkedProject } from '../../util/projects/link';
|
||||
import { getFrameworks } from '../../util/get-frameworks';
|
||||
import { isSettingValue } from '../../util/is-setting-value';
|
||||
import { ProjectSettings } from '../../types';
|
||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||
import setupAndLink from '../../util/link/setup-and-link';
|
||||
@@ -71,9 +70,9 @@ export default async function dev(
|
||||
frameworkSlug = framework.slug;
|
||||
}
|
||||
|
||||
const defaults = framework.settings.devCommand;
|
||||
if (isSettingValue(defaults)) {
|
||||
devCommand = defaults.value;
|
||||
const defaults = framework.settings.devCommand.value;
|
||||
if (defaults) {
|
||||
devCommand = defaults;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,22 @@ const help = () => {
|
||||
};
|
||||
|
||||
export default async function main(client: Client) {
|
||||
if (process.env.__VERCEL_DEV_RUNNING) {
|
||||
client.output.error(
|
||||
`${cmd(
|
||||
`${getPkgName()} dev`
|
||||
)} must not recursively invoke itself. Check the Development Command in the Project Settings or the ${cmd(
|
||||
'dev'
|
||||
)} script in ${cmd('package.json')}`
|
||||
);
|
||||
client.output.error(
|
||||
`Learn More: https://vercel.link/recursive-invocation-of-commands`
|
||||
);
|
||||
return 1;
|
||||
} else {
|
||||
process.env.__VERCEL_DEV_RUNNING = '1';
|
||||
}
|
||||
|
||||
let argv;
|
||||
let args;
|
||||
const { output } = client;
|
||||
@@ -90,22 +106,21 @@ export default async function main(client: Client) {
|
||||
if (pkg) {
|
||||
const { scripts } = pkg as PackageJson;
|
||||
|
||||
if (scripts && scripts.dev && /\bnow\b\W+\bdev\b/.test(scripts.dev)) {
|
||||
output.error(
|
||||
`The ${cmd('dev')} script in ${cmd(
|
||||
'package.json'
|
||||
)} must not contain ${cmd('now dev')}`
|
||||
if (
|
||||
scripts &&
|
||||
scripts.dev &&
|
||||
/\b(now|vercel)\b\W+\bdev\b/.test(scripts.dev)
|
||||
) {
|
||||
client.output.error(
|
||||
`${cmd(
|
||||
`${getPkgName()} dev`
|
||||
)} must not recursively invoke itself. Check the Development Command in the Project Settings or the ${cmd(
|
||||
'dev'
|
||||
)} script in ${cmd('package.json')}`
|
||||
);
|
||||
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
|
||||
return 1;
|
||||
}
|
||||
if (scripts && scripts.dev && /\bvercel\b\W+\bdev\b/.test(scripts.dev)) {
|
||||
output.error(
|
||||
`The ${cmd('dev')} script in ${cmd(
|
||||
'package.json'
|
||||
)} must not contain ${cmd('vercel dev')}`
|
||||
client.output.error(
|
||||
`Learn More: https://vercel.link/recursive-invocation-of-commands`
|
||||
);
|
||||
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
21
packages/cli/src/commands/env/index.ts
vendored
21
packages/cli/src/commands/env/index.ts
vendored
@@ -1,18 +1,16 @@
|
||||
import chalk from 'chalk';
|
||||
|
||||
import getArgs from '../../util/get-args';
|
||||
import getSubcommand from '../../util/get-subcommand';
|
||||
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
||||
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
|
||||
import { getLinkedProject } from '../../util/projects/link';
|
||||
import Client from '../../util/client';
|
||||
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
|
||||
import getArgs from '../../util/get-args';
|
||||
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
||||
import getSubcommand from '../../util/get-subcommand';
|
||||
import handleError from '../../util/handle-error';
|
||||
import logo from '../../util/output/logo';
|
||||
import { getCommandName, getPkgName } from '../../util/pkg-name';
|
||||
|
||||
import { getLinkedProject } from '../../util/projects/link';
|
||||
import add from './add';
|
||||
import pull from './pull';
|
||||
import ls from './ls';
|
||||
import pull from './pull';
|
||||
import rm from './rm';
|
||||
|
||||
const help = () => {
|
||||
@@ -139,6 +137,13 @@ export default async function main(client: Client) {
|
||||
case 'rm':
|
||||
return rm(client, project, argv, args, output);
|
||||
case 'pull':
|
||||
output.warn(
|
||||
`${getCommandName(
|
||||
'env pull'
|
||||
)} is deprecated and will be removed in future releases. Run ${getCommandName(
|
||||
'pull'
|
||||
)} instead.`
|
||||
);
|
||||
return pull(client, project, argv, args, output);
|
||||
default:
|
||||
output.error(getInvalidSubcommand(COMMAND_CONFIG));
|
||||
|
||||
21
packages/cli/src/commands/env/pull.ts
vendored
21
packages/cli/src/commands/env/pull.ts
vendored
@@ -1,18 +1,18 @@
|
||||
import chalk from 'chalk';
|
||||
import { closeSync, openSync, promises, readSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { Project } from '../../types';
|
||||
import { Output } from '../../util/output';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import Client from '../../util/client';
|
||||
import stamp from '../../util/output/stamp';
|
||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||
import param from '../../util/output/param';
|
||||
import { join } from 'path';
|
||||
import { promises, openSync, closeSync, readSync } from 'fs';
|
||||
import exposeSystemEnvs from '../../util/dev/expose-system-envs';
|
||||
import { emoji, prependEmoji } from '../../util/emoji';
|
||||
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import { Output } from '../../util/output';
|
||||
import param from '../../util/output/param';
|
||||
import stamp from '../../util/output/stamp';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
const { writeFile } = promises;
|
||||
import exposeSystemEnvs from '../../util/dev/expose-system-envs';
|
||||
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
||||
|
||||
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
||||
|
||||
@@ -56,8 +56,9 @@ export default async function pull(
|
||||
return 1;
|
||||
}
|
||||
|
||||
// handle relative or absolute filename
|
||||
const [filename = '.env'] = args;
|
||||
const fullPath = join(process.cwd(), filename);
|
||||
const fullPath = resolve(filename);
|
||||
const skipConfirmation = opts['--yes'];
|
||||
|
||||
const head = tryReadHeadSync(fullPath, Buffer.byteLength(CONTENTS_PREFIX));
|
||||
|
||||
@@ -2,6 +2,7 @@ export default new Map([
|
||||
['alias', 'alias'],
|
||||
['aliases', 'alias'],
|
||||
['billing', 'billing'],
|
||||
['build', 'build'],
|
||||
['cc', 'billing'],
|
||||
['cert', 'certs'],
|
||||
['certs', 'certs'],
|
||||
@@ -24,6 +25,7 @@ export default new Map([
|
||||
['ls', 'list'],
|
||||
['project', 'projects'],
|
||||
['projects', 'projects'],
|
||||
['pull', 'pull'],
|
||||
['remove', 'remove'],
|
||||
['rm', 'remove'],
|
||||
['secret', 'secrets'],
|
||||
|
||||
116
packages/cli/src/commands/pull.ts
Normal file
116
packages/cli/src/commands/pull.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import chalk from 'chalk';
|
||||
import { join } from 'path';
|
||||
import Client from '../util/client';
|
||||
import { emoji, prependEmoji } from '../util/emoji';
|
||||
import getArgs from '../util/get-args';
|
||||
import handleError from '../util/handle-error';
|
||||
import setupAndLink from '../util/link/setup-and-link';
|
||||
import logo from '../util/output/logo';
|
||||
import stamp from '../util/output/stamp';
|
||||
import { getPkgName } from '../util/pkg-name';
|
||||
import {
|
||||
getLinkedProject,
|
||||
VERCEL_DIR,
|
||||
VERCEL_DIR_PROJECT,
|
||||
} from '../util/projects/link';
|
||||
import { writeProjectSettings } from '../util/projects/project-settings';
|
||||
import pull from './env/pull';
|
||||
|
||||
const help = () => {
|
||||
return console.log(`
|
||||
${chalk.bold(`${logo} ${getPkgName()} pull`)} [path]
|
||||
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
|
||||
'DIR'
|
||||
)} Path to the global ${'`.vercel`'} directory
|
||||
-d, --debug Debug mode [off]
|
||||
--env [filename] The file to write Development Environment Variables to [.env]
|
||||
-y, --yes Skip the confirmation prompt
|
||||
|
||||
${chalk.dim('Examples:')}
|
||||
|
||||
${chalk.gray('–')} Pull the latest Project Settings from the cloud
|
||||
|
||||
${chalk.cyan(`$ ${getPkgName()} pull`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} pull ./path-to-project`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} pull --env .env.local`)}
|
||||
${chalk.cyan(`$ ${getPkgName()} pull ./path-to-project --env .env.local`)}
|
||||
`);
|
||||
};
|
||||
export default async function main(client: Client) {
|
||||
let argv;
|
||||
try {
|
||||
argv = getArgs(client.argv.slice(2), {
|
||||
'--yes': Boolean,
|
||||
'--env': String,
|
||||
'--debug': Boolean,
|
||||
'-d': '--debug',
|
||||
'-y': '--yes',
|
||||
});
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argv['--help']) {
|
||||
help();
|
||||
return 2;
|
||||
}
|
||||
|
||||
const cwd = argv._[1] || process.cwd();
|
||||
const yes = argv['--yes'];
|
||||
const env = argv['--env'] ?? '.env';
|
||||
const settingsStamp = stamp();
|
||||
let link = await getLinkedProject(client, cwd);
|
||||
if (link.status === 'not_linked') {
|
||||
link = await setupAndLink(client, cwd, {
|
||||
autoConfirm: yes,
|
||||
successEmoji: 'link',
|
||||
setupMsg: 'Set up',
|
||||
});
|
||||
|
||||
if (link.status === 'not_linked') {
|
||||
// User aborted project linking questions
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
}
|
||||
|
||||
const { project, org } = link;
|
||||
|
||||
client.config.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||
|
||||
const result = await pull(
|
||||
client,
|
||||
project,
|
||||
argv,
|
||||
[join(cwd, env)],
|
||||
client.output
|
||||
);
|
||||
if (result !== 0) {
|
||||
// an error happened
|
||||
return result;
|
||||
}
|
||||
|
||||
await writeProjectSettings(cwd, project, org);
|
||||
|
||||
client.output.print(
|
||||
`${prependEmoji(
|
||||
`Downloaded project settings to ${chalk.bold(
|
||||
join(VERCEL_DIR, VERCEL_DIR_PROJECT)
|
||||
)} ${chalk.gray(settingsStamp())}`,
|
||||
emoji('success')
|
||||
)}\n`
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -160,18 +160,26 @@ const main = async () => {
|
||||
// * a path to deploy (as in: `vercel path/`)
|
||||
// * a subcommand (as in: `vercel ls`)
|
||||
const targetOrSubcommand = argv._[2];
|
||||
const isBuildOrDev =
|
||||
targetOrSubcommand === 'build' || targetOrSubcommand === 'dev';
|
||||
|
||||
output.print(
|
||||
`${chalk.grey(
|
||||
`${getTitleName()} CLI ${pkg.version}${
|
||||
targetOrSubcommand === 'dev' ? ' dev (beta)' : ''
|
||||
}${
|
||||
isCanary || targetOrSubcommand === 'dev'
|
||||
? ' — https://vercel.com/feedback'
|
||||
: ''
|
||||
}`
|
||||
)}\n`
|
||||
);
|
||||
if (isBuildOrDev) {
|
||||
console.log(
|
||||
`${chalk.grey(
|
||||
`${getTitleName()} CLI ${
|
||||
pkg.version
|
||||
} ${targetOrSubcommand} (beta) — https://vercel.com/feedback`
|
||||
)}`
|
||||
);
|
||||
} else {
|
||||
output.print(
|
||||
`${chalk.grey(
|
||||
`${getTitleName()} CLI ${pkg.version}${
|
||||
isCanary ? ' — https://vercel.com/feedback' : ''
|
||||
}`
|
||||
)}\n`
|
||||
);
|
||||
}
|
||||
|
||||
// Handle `--version` directly
|
||||
if (!targetOrSubcommand && argv['--version']) {
|
||||
@@ -286,7 +294,14 @@ const main = async () => {
|
||||
|
||||
let authConfig = null;
|
||||
|
||||
const subcommandsWithoutToken = ['login', 'logout', 'help', 'init', 'update'];
|
||||
const subcommandsWithoutToken = [
|
||||
'login',
|
||||
'logout',
|
||||
'help',
|
||||
'init',
|
||||
'update',
|
||||
'build',
|
||||
];
|
||||
|
||||
if (authConfigExists) {
|
||||
try {
|
||||
@@ -393,20 +408,33 @@ const main = async () => {
|
||||
} else if (commands.has(singular)) {
|
||||
alternative = singular;
|
||||
}
|
||||
console.error(
|
||||
error(
|
||||
`The supplied argument ${param(targetOrSubcommand)} is ambiguous.` +
|
||||
`\nIf you wish to deploy the ${fileType} ${param(
|
||||
targetOrSubcommand
|
||||
)}, first run "cd ${targetOrSubcommand}". ` +
|
||||
if (targetOrSubcommand === 'build') {
|
||||
output.note(
|
||||
`If you wish to deploy the ${fileType} ${param(
|
||||
targetOrSubcommand
|
||||
)}, run ${getCommandName('deploy build')}.` +
|
||||
(alternative
|
||||
? `\nIf you wish to use the subcommand ${param(
|
||||
targetOrSubcommand
|
||||
)}, use ${param(alternative)} instead.`
|
||||
: '')
|
||||
)
|
||||
);
|
||||
return 1;
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
error(
|
||||
`The supplied argument ${param(targetOrSubcommand)} is ambiguous.` +
|
||||
`\nIf you wish to deploy the ${fileType} ${param(
|
||||
targetOrSubcommand
|
||||
)}, first run "cd ${targetOrSubcommand}". ` +
|
||||
(alternative
|
||||
? `\nIf you wish to use the subcommand ${param(
|
||||
targetOrSubcommand
|
||||
)}, use ${param(alternative)} instead.`
|
||||
: '')
|
||||
)
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (subcommandExists) {
|
||||
@@ -601,6 +629,9 @@ const main = async () => {
|
||||
case 'billing':
|
||||
func = await import('./commands/billing');
|
||||
break;
|
||||
case 'build':
|
||||
func = await import('./commands/build');
|
||||
break;
|
||||
case 'certs':
|
||||
func = await import('./commands/certs');
|
||||
break;
|
||||
@@ -643,6 +674,9 @@ const main = async () => {
|
||||
case 'projects':
|
||||
func = await import('./commands/projects');
|
||||
break;
|
||||
case 'pull':
|
||||
func = await import('./commands/pull');
|
||||
break;
|
||||
case 'remove':
|
||||
func = await import('./commands/remove');
|
||||
break;
|
||||
|
||||
@@ -100,7 +100,7 @@ export default class Client extends EventEmitter {
|
||||
let body;
|
||||
if (isJSONObject(opts.body)) {
|
||||
body = JSON.stringify(opts.body);
|
||||
headers.set('content-type', 'application/json; charset=utf8');
|
||||
headers.set('content-type', 'application/json; charset=utf-8');
|
||||
} else {
|
||||
body = opts.body;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,8 @@ export const isDirectory = (path: string): boolean => {
|
||||
const getGlobalPathConfig = (): string => {
|
||||
let customPath: string | undefined;
|
||||
|
||||
try {
|
||||
const argv = getArgs(process.argv.slice(2), {});
|
||||
customPath = argv['--global-config'];
|
||||
} catch (_error) {
|
||||
// args are optional so consume error
|
||||
}
|
||||
const argv = getArgs(process.argv.slice(2), {}, { permissive: true });
|
||||
customPath = argv['--global-config'];
|
||||
|
||||
const vercelDirectories = XDGAppPaths('com.vercel.cli').dataDirs();
|
||||
|
||||
|
||||
@@ -7,12 +7,8 @@ import getArgs from '../../util/get-args';
|
||||
export default function getLocalPathConfig(prefix: string) {
|
||||
let customPath: string | undefined;
|
||||
|
||||
try {
|
||||
const argv = getArgs(process.argv.slice(2), {});
|
||||
customPath = argv['--local-config'];
|
||||
} catch (_error) {
|
||||
// args are optional so consume error
|
||||
}
|
||||
const argv = getArgs(process.argv.slice(2), {}, { permissive: true });
|
||||
customPath = argv['--local-config'];
|
||||
|
||||
// If `--local-config` flag was specified, then that takes priority
|
||||
if (customPath) {
|
||||
|
||||
37
packages/cli/src/util/deploy/get-deployment-checks.ts
Normal file
37
packages/cli/src/util/deploy/get-deployment-checks.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import Client from '../client';
|
||||
|
||||
type CheckStatus = 'registered' | 'running' | 'completed';
|
||||
type CheckConclusion =
|
||||
| 'canceled'
|
||||
| 'failed'
|
||||
| 'neutral'
|
||||
| 'succeeded'
|
||||
| 'skipped'
|
||||
| 'stale';
|
||||
|
||||
export interface DeploymentCheck {
|
||||
id: string;
|
||||
status: CheckStatus;
|
||||
conclusion: CheckConclusion;
|
||||
name: string;
|
||||
startedAt: number;
|
||||
completedAt: number;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
integrationId: string;
|
||||
rerequestable: boolean;
|
||||
}
|
||||
|
||||
export interface DeploymentChecksResponse {
|
||||
checks: DeploymentCheck[];
|
||||
}
|
||||
|
||||
export async function getDeploymentChecks(
|
||||
client: Client,
|
||||
deploymentId: string
|
||||
) {
|
||||
const checksResponse = await client.fetch<DeploymentChecksResponse>(
|
||||
`/v1/deployments/${encodeURIComponent(deploymentId)}/checks`
|
||||
);
|
||||
return checksResponse;
|
||||
}
|
||||
@@ -47,6 +47,7 @@ export default async function processDeployment({
|
||||
force?: boolean;
|
||||
withCache?: boolean;
|
||||
org: Org;
|
||||
prebuilt: boolean;
|
||||
projectName: string;
|
||||
isSettingUpProject: boolean;
|
||||
skipAutoDetectionConfirmation?: boolean;
|
||||
@@ -62,6 +63,7 @@ export default async function processDeployment({
|
||||
withCache,
|
||||
nowConfig,
|
||||
quiet,
|
||||
prebuilt,
|
||||
} = args;
|
||||
|
||||
const { debug } = output;
|
||||
@@ -83,6 +85,7 @@ export default async function processDeployment({
|
||||
path: paths[0],
|
||||
force,
|
||||
withCache,
|
||||
prebuilt,
|
||||
skipAutoDetectionConfirmation,
|
||||
};
|
||||
|
||||
@@ -179,10 +182,26 @@ export default async function processDeployment({
|
||||
return event.payload;
|
||||
}
|
||||
|
||||
if (event.type === 'ready') {
|
||||
// If `checksState` is present, we can only continue to "Completing" if the checks finished,
|
||||
// otherwise we might show "Completing" before "Running Checks".
|
||||
if (
|
||||
event.type === 'ready' &&
|
||||
(event.payload.checksState
|
||||
? event.payload.checksState === 'completed'
|
||||
: true)
|
||||
) {
|
||||
output.spinner('Completing', 0);
|
||||
}
|
||||
|
||||
if (event.type === 'checks-running') {
|
||||
output.spinner('Running Checks', 0);
|
||||
}
|
||||
|
||||
if (event.type === 'checks-conclusion-failed') {
|
||||
output.stopSpinner();
|
||||
return event.payload;
|
||||
}
|
||||
|
||||
// Handle error events
|
||||
if (event.type === 'error') {
|
||||
output.stopSpinner();
|
||||
|
||||
@@ -89,6 +89,7 @@ import {
|
||||
} from './types';
|
||||
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
||||
import exposeSystemEnvs from './expose-system-envs';
|
||||
import { loadCliPlugins } from '../plugins';
|
||||
|
||||
const frontendRuntimeSet = new Set(
|
||||
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
||||
@@ -1349,6 +1350,30 @@ export default class DevServer {
|
||||
return false;
|
||||
};
|
||||
|
||||
runDevMiddleware = async (
|
||||
req: http.IncomingMessage,
|
||||
res: http.ServerResponse
|
||||
) => {
|
||||
const { devMiddlewarePlugins } = await loadCliPlugins(
|
||||
this.cwd,
|
||||
this.output
|
||||
);
|
||||
try {
|
||||
for (let plugin of devMiddlewarePlugins) {
|
||||
const result = await plugin.plugin.runDevMiddleware(req, res, this.cwd);
|
||||
if (result.finished) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return { finished: false };
|
||||
} catch (e) {
|
||||
return {
|
||||
finished: true,
|
||||
error: e,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Serve project directory as a v2 deployment.
|
||||
*/
|
||||
@@ -1416,6 +1441,36 @@ export default class DevServer {
|
||||
let prevUrl = req.url;
|
||||
let prevHeaders: HttpHeadersConfig = {};
|
||||
|
||||
const middlewareResult = await this.runDevMiddleware(req, res);
|
||||
|
||||
if (middlewareResult) {
|
||||
if (middlewareResult.error) {
|
||||
this.sendError(
|
||||
req,
|
||||
res,
|
||||
requestId,
|
||||
'EDGE_FUNCTION_INVOCATION_FAILED',
|
||||
500
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (middlewareResult.finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (middlewareResult.pathname) {
|
||||
const origUrl = url.parse(req.url || '/', true);
|
||||
origUrl.pathname = middlewareResult.pathname;
|
||||
prevUrl = url.format(origUrl);
|
||||
}
|
||||
if (middlewareResult.query && prevUrl) {
|
||||
const origUrl = url.parse(req.url || '/', true);
|
||||
delete origUrl.search;
|
||||
Object.assign(origUrl.query, middlewareResult.query);
|
||||
prevUrl = url.format(origUrl);
|
||||
}
|
||||
}
|
||||
|
||||
for (const phase of phases) {
|
||||
statusCode = undefined;
|
||||
|
||||
@@ -2106,7 +2161,10 @@ export default class DevServer {
|
||||
process.stdout.write(data.replace(proxyPort, devPort));
|
||||
});
|
||||
|
||||
p.on('exit', () => {
|
||||
p.on('exit', (code: number) => {
|
||||
if (code > 0) {
|
||||
process.exit(code);
|
||||
}
|
||||
this.devProcessPort = undefined;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { Stats } from 'fs';
|
||||
import { sep, dirname, join, resolve } from 'path';
|
||||
import { readJSON, lstat, readlink, readFile, realpath } from 'fs-extra';
|
||||
import { lstat, readlink, readFile, realpath } from 'fs-extra';
|
||||
import { isCanary } from './is-canary';
|
||||
import { getPkgName } from './pkg-name';
|
||||
|
||||
// `npm` tacks a bunch of extra properties on the `package.json` file,
|
||||
// so check for one of them to determine yarn vs. npm.
|
||||
async function isYarn(): Promise<boolean> {
|
||||
let s: Stats;
|
||||
let binPath = process.argv[1];
|
||||
@@ -20,8 +18,12 @@ async function isYarn(): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
const pkgPath = join(dirname(binPath), '..', 'package.json');
|
||||
const pkg = await readJSON(pkgPath).catch(() => ({}));
|
||||
return !('_id' in pkg);
|
||||
/*
|
||||
* Generally, pkgPath looks like:
|
||||
* "/Users/username/.config/yarn/global/node_modules/vercel/package.json"
|
||||
* "/usr/local/share/.config/yarn/global/node_modules/vercel/package.json"
|
||||
*/
|
||||
return pkgPath.includes(join('yarn', 'global'));
|
||||
}
|
||||
|
||||
async function getConfigPrefix() {
|
||||
|
||||
@@ -36,6 +36,7 @@ export interface CreateOptions {
|
||||
name: string;
|
||||
project?: string;
|
||||
wantsPublic: boolean;
|
||||
prebuilt?: boolean;
|
||||
meta: Dictionary<string>;
|
||||
regions?: string[];
|
||||
quiet?: boolean;
|
||||
@@ -111,6 +112,7 @@ export default class Now extends EventEmitter {
|
||||
// Latest
|
||||
name,
|
||||
project,
|
||||
prebuilt = false,
|
||||
wantsPublic,
|
||||
meta,
|
||||
regions,
|
||||
@@ -165,6 +167,7 @@ export default class Now extends EventEmitter {
|
||||
isSettingUpProject,
|
||||
skipAutoDetectionConfirmation,
|
||||
cwd,
|
||||
prebuilt,
|
||||
});
|
||||
|
||||
if (deployment && deployment.warnings) {
|
||||
|
||||
24
packages/cli/src/util/output/color-name-cache.ts
Normal file
24
packages/cli/src/util/output/color-name-cache.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import chalk from 'chalk';
|
||||
|
||||
const colors = [
|
||||
chalk.cyan,
|
||||
chalk.magenta,
|
||||
chalk.green,
|
||||
chalk.yellow,
|
||||
chalk.blue,
|
||||
];
|
||||
|
||||
let childIndex = 0;
|
||||
const packageNameColorCache = new Map<string, chalk.Chalk>();
|
||||
|
||||
/** Return a consistent (gradient) color for a given package name */
|
||||
export function getColorForPkgName(pkgName: string) {
|
||||
let color = packageNameColorCache.get(pkgName);
|
||||
|
||||
if (!color) {
|
||||
color = colors[childIndex++ % colors.length];
|
||||
packageNameColorCache.set(pkgName, color);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
@@ -125,10 +125,14 @@ export class Output {
|
||||
this.debug(`Spinner invoked (${message}) with a ${delay}ms delay`);
|
||||
return;
|
||||
}
|
||||
if (this._spinner) {
|
||||
this._spinner.text = message;
|
||||
if (this.isTTY) {
|
||||
if (this._spinner) {
|
||||
this._spinner.text = message;
|
||||
} else {
|
||||
this._spinner = wait(message, delay);
|
||||
}
|
||||
} else {
|
||||
this._spinner = wait(message, delay);
|
||||
this.print(`${message}\n`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { relative as nativeRelative } from 'path';
|
||||
|
||||
const isWin = process.platform === 'win32';
|
||||
import { normalizePath } from '@vercel/build-utils';
|
||||
|
||||
export function relative(a: string, b: string): string {
|
||||
let p = nativeRelative(a, b);
|
||||
if (isWin) {
|
||||
p = p.replace(/\\/g, '/');
|
||||
}
|
||||
return p;
|
||||
return normalizePath(nativeRelative(a, b));
|
||||
}
|
||||
|
||||
76
packages/cli/src/util/plugins.ts
Normal file
76
packages/cli/src/util/plugins.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import code from '../util/output/code';
|
||||
import { getColorForPkgName } from '../util/output/color-name-cache';
|
||||
import cliPkgJson from '../util/pkg';
|
||||
import { scanParentDirs } from '@vercel/build-utils';
|
||||
import { Output } from './output';
|
||||
|
||||
const VERCEL_PLUGIN_PREFIX = 'vercel-plugin-';
|
||||
|
||||
export async function loadCliPlugins(cwd: string, output: Output) {
|
||||
const { packageJson } = await scanParentDirs(cwd, true);
|
||||
|
||||
let pluginCount = 0;
|
||||
const preBuildPlugins = [];
|
||||
const buildPlugins = [];
|
||||
const devServerPlugins = [];
|
||||
const devMiddlewarePlugins = [];
|
||||
const deps = new Set(
|
||||
[
|
||||
...Object.keys(packageJson?.dependencies || {}),
|
||||
...Object.keys(packageJson?.devDependencies || {}),
|
||||
...Object.keys(cliPkgJson.dependencies),
|
||||
].filter(dep => dep.startsWith(VERCEL_PLUGIN_PREFIX))
|
||||
);
|
||||
|
||||
for (let dep of deps) {
|
||||
pluginCount++;
|
||||
const resolved = require.resolve(dep, {
|
||||
paths: [cwd, process.cwd(), __dirname],
|
||||
});
|
||||
let plugin;
|
||||
try {
|
||||
plugin = require(resolved);
|
||||
|
||||
const color = getColorForPkgName(dep);
|
||||
if (typeof plugin.preBuild === 'function') {
|
||||
preBuildPlugins.push({
|
||||
plugin,
|
||||
name: dep,
|
||||
color,
|
||||
});
|
||||
}
|
||||
if (typeof plugin.build === 'function') {
|
||||
buildPlugins.push({
|
||||
plugin,
|
||||
name: dep,
|
||||
color,
|
||||
});
|
||||
}
|
||||
if (typeof plugin.startDevServer === 'function') {
|
||||
devServerPlugins.push({
|
||||
plugin,
|
||||
name: dep,
|
||||
color,
|
||||
});
|
||||
}
|
||||
if (typeof plugin.runDevMiddleware === 'function') {
|
||||
devMiddlewarePlugins.push({
|
||||
plugin,
|
||||
name: dep,
|
||||
color,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
output.error(`Failed to import ${code(dep)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pluginCount,
|
||||
preBuildPlugins,
|
||||
buildPlugins,
|
||||
devServerPlugins,
|
||||
devMiddlewarePlugins,
|
||||
};
|
||||
}
|
||||
5
packages/cli/src/util/projects/find-framework.ts
Normal file
5
packages/cli/src/util/projects/find-framework.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Framework, frameworks } from '@vercel/frameworks';
|
||||
|
||||
export function findFramework(slug?: string | null) {
|
||||
return (frameworks as any as Framework[]).find(f => f.slug === slug);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ const readFile = promisify(fs.readFile);
|
||||
const writeFile = promisify(fs.writeFile);
|
||||
|
||||
export const VERCEL_DIR = '.vercel';
|
||||
export const VERCEL_OUTPUT_DIR = '.output';
|
||||
export const VERCEL_DIR_FALLBACK = '.now';
|
||||
export const VERCEL_DIR_README = 'README.txt';
|
||||
export const VERCEL_DIR_PROJECT = 'project.json';
|
||||
@@ -67,12 +68,14 @@ async function getLink(path?: string): Promise<ProjectLink | null> {
|
||||
return getLinkFromDir(dir);
|
||||
}
|
||||
|
||||
async function getLinkFromDir(dir: string): Promise<ProjectLink | null> {
|
||||
export async function getLinkFromDir<T = ProjectLink>(
|
||||
dir: string
|
||||
): Promise<T | null> {
|
||||
try {
|
||||
const json = await readFile(join(dir, VERCEL_DIR_PROJECT), 'utf8');
|
||||
|
||||
const ajv = new AJV();
|
||||
const link: ProjectLink = JSON.parse(json);
|
||||
const link: T = JSON.parse(json);
|
||||
|
||||
if (!ajv.validate(linkSchema, link)) {
|
||||
throw new Error(
|
||||
@@ -241,16 +244,27 @@ export async function linkFolderToProject(
|
||||
try {
|
||||
const gitIgnorePath = join(path, '.gitignore');
|
||||
|
||||
const gitIgnore = await readFile(gitIgnorePath, 'utf8').catch(() => null);
|
||||
const EOL = gitIgnore && gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
|
||||
let gitIgnore =
|
||||
(await readFile(gitIgnorePath, 'utf8').catch(() => null)) ?? '';
|
||||
const EOL = gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
|
||||
let contentModified = false;
|
||||
|
||||
if (!gitIgnore || !gitIgnore.split(EOL).includes(VERCEL_DIR)) {
|
||||
await writeFile(
|
||||
gitIgnorePath,
|
||||
gitIgnore
|
||||
? `${gitIgnore}${EOL}${VERCEL_DIR}${EOL}`
|
||||
: `${VERCEL_DIR}${EOL}`
|
||||
);
|
||||
if (!gitIgnore.split(EOL).includes(VERCEL_DIR)) {
|
||||
gitIgnore += `${
|
||||
gitIgnore.endsWith(EOL) || gitIgnore.length === 0 ? '' : EOL
|
||||
}${VERCEL_DIR}${EOL}`;
|
||||
contentModified = true;
|
||||
}
|
||||
|
||||
if (!gitIgnore.split(EOL).includes(VERCEL_OUTPUT_DIR)) {
|
||||
gitIgnore += `${
|
||||
gitIgnore.endsWith(EOL) || gitIgnore.length === 0 ? '' : EOL
|
||||
}${VERCEL_OUTPUT_DIR}${EOL}`;
|
||||
contentModified = true;
|
||||
}
|
||||
|
||||
if (contentModified) {
|
||||
await writeFile(gitIgnorePath, gitIgnore);
|
||||
isGitIgnoreUpdated = true;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
42
packages/cli/src/util/projects/project-settings.ts
Normal file
42
packages/cli/src/util/projects/project-settings.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { writeFile } from 'fs-extra';
|
||||
import { Org, Project, ProjectLink } from '../../types';
|
||||
import { getLinkFromDir, VERCEL_DIR, VERCEL_DIR_PROJECT } from './link';
|
||||
import { join } from 'path';
|
||||
|
||||
export type ProjectLinkAndSettings = ProjectLink & {
|
||||
settings: {
|
||||
buildCommand: Project['buildCommand'];
|
||||
devCommand: Project['devCommand'];
|
||||
outputDirectory: Project['outputDirectory'];
|
||||
rootDirectory: Project['rootDirectory'];
|
||||
framework: Project['framework'];
|
||||
};
|
||||
};
|
||||
|
||||
// writeProjectSettings writes the project configuration to `vercel/project.json`
|
||||
// Write the project configuration to `.vercel/project.json`
|
||||
// that is needed for `vercel build` and `vercel dev` commands
|
||||
export async function writeProjectSettings(
|
||||
cwd: string,
|
||||
project: Project,
|
||||
org: Org
|
||||
) {
|
||||
return await writeFile(
|
||||
join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT),
|
||||
JSON.stringify({
|
||||
projectId: project.id,
|
||||
orgId: org.id,
|
||||
settings: {
|
||||
buildCommand: project.buildCommand,
|
||||
devCommand: project.devCommand,
|
||||
directoryListing: project.directoryListing,
|
||||
rootDirectory: project.rootDirectory,
|
||||
framework: project.framework,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export async function readProjectSettings(cwd: string) {
|
||||
return await getLinkFromDir<ProjectLinkAndSettings>(cwd);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { client } from '../mocks/client';
|
||||
import login from '../../src/commands/login';
|
||||
import { client } from '../mocks/client';
|
||||
import { useUser } from '../mocks/user';
|
||||
|
||||
describe('login', () => {
|
||||
it('should not allow the `--token` flag', async () => {
|
||||
@@ -10,4 +11,16 @@ describe('login', () => {
|
||||
'Error! `--token` may not be used with the "login" command\n'
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow login via email as argument', async () => {
|
||||
const user = useUser();
|
||||
client.setArgv('login', user.email);
|
||||
const exitCode = await login(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
expect(
|
||||
client.outputBuffer.includes(
|
||||
`Success! Email authentication complete for ${user.email}`
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
45
packages/cli/test/commands/pull.test.ts
Normal file
45
packages/cli/test/commands/pull.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import pull from '../../src/commands/pull';
|
||||
import { setupFixture } from '../helpers/setup-fixture';
|
||||
import { client } from '../mocks/client';
|
||||
import { defaultProject, useProject } from '../mocks/project';
|
||||
import { useTeams } from '../mocks/team';
|
||||
import { useUser } from '../mocks/user';
|
||||
|
||||
describe('pull', () => {
|
||||
it('should handle pulling', async () => {
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
useUser();
|
||||
useTeams();
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
name: 'vercel-pull-next',
|
||||
});
|
||||
client.setArgv('pull', '--yes', cwd);
|
||||
const exitCode = await pull(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
});
|
||||
|
||||
it('should handle custom --env flag', async () => {
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
useUser();
|
||||
useTeams();
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
name: 'vercel-pull-next',
|
||||
});
|
||||
const expectedEnvFilename = '.env.vercel';
|
||||
client.setArgv('pull', '--yes', `--env=${expectedEnvFilename}`, cwd);
|
||||
|
||||
const exitCode = await pull(client);
|
||||
const actualEnv = await fs.pathExists(path.join(cwd, expectedEnvFilename));
|
||||
const raw = await fs.readFile(path.join(cwd, expectedEnvFilename));
|
||||
|
||||
expect(exitCode).toEqual(0);
|
||||
expect(actualEnv).toBeTruthy();
|
||||
expect(raw.includes('# Created by Vercel CLI')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
3
packages/cli/test/fixtures/unit/edge-middleware-error/_middleware.js
vendored
Normal file
3
packages/cli/test/fixtures/unit/edge-middleware-error/_middleware.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default () => {
|
||||
throw new Error('asdf');
|
||||
};
|
||||
3
packages/cli/test/fixtures/unit/edge-middleware-invalid-response/_middleware.js
vendored
Normal file
3
packages/cli/test/fixtures/unit/edge-middleware-invalid-response/_middleware.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function () {
|
||||
return 'freecandy';
|
||||
}
|
||||
5
packages/cli/test/fixtures/unit/edge-middleware-ts/_middleware.ts
vendored
Normal file
5
packages/cli/test/fixtures/unit/edge-middleware-ts/_middleware.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { response } from './response';
|
||||
|
||||
export default () => {
|
||||
return new Response(response);
|
||||
};
|
||||
1
packages/cli/test/fixtures/unit/edge-middleware-ts/response.ts
vendored
Normal file
1
packages/cli/test/fixtures/unit/edge-middleware-ts/response.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export const response = 'response';
|
||||
10
packages/cli/test/fixtures/unit/edge-middleware/_middleware.js
vendored
Normal file
10
packages/cli/test/fixtures/unit/edge-middleware/_middleware.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import response from './response.json';
|
||||
|
||||
export default function () {
|
||||
return new Response(JSON.stringify(response), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/edge-middleware/index.html
vendored
Normal file
1
packages/cli/test/fixtures/unit/edge-middleware/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
not hello world
|
||||
3
packages/cli/test/fixtures/unit/edge-middleware/response.json
vendored
Normal file
3
packages/cli/test/fixtures/unit/edge-middleware/response.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"text": "hello world"
|
||||
}
|
||||
69
packages/cli/test/fixtures/unit/vercel-build-gatsby/.gitignore
vendored
Normal file
69
packages/cli/test/fixtures/unit/vercel-build-gatsby/.gitignore
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variable files
|
||||
.env*
|
||||
|
||||
# gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
4
packages/cli/test/fixtures/unit/vercel-build-gatsby/.prettierignore
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-build-gatsby/.prettierignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.cache
|
||||
package.json
|
||||
package-lock.json
|
||||
public
|
||||
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/.prettierrc
vendored
Normal file
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/.prettierrc
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
22
packages/cli/test/fixtures/unit/vercel-build-gatsby/LICENSE
vendored
Normal file
22
packages/cli/test/fixtures/unit/vercel-build-gatsby/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 gatsbyjs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
97
packages/cli/test/fixtures/unit/vercel-build-gatsby/README.md
vendored
Normal file
97
packages/cli/test/fixtures/unit/vercel-build-gatsby/README.md
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
|
||||
<p align="center">
|
||||
<a href="https://www.gatsbyjs.org">
|
||||
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
|
||||
</a>
|
||||
</p>
|
||||
<h1 align="center">
|
||||
Gatsby's default starter
|
||||
</h1>
|
||||
|
||||
Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
|
||||
|
||||
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._
|
||||
|
||||
## 🚀 Quick start
|
||||
|
||||
1. **Create a Gatsby site.**
|
||||
|
||||
Use the Gatsby CLI to create a new site, specifying the default starter.
|
||||
|
||||
```shell
|
||||
# create a new Gatsby site using the default starter
|
||||
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
|
||||
```
|
||||
|
||||
1. **Start developing.**
|
||||
|
||||
Navigate into your new site’s directory and start it up.
|
||||
|
||||
```shell
|
||||
cd my-default-starter/
|
||||
gatsby develop
|
||||
```
|
||||
|
||||
1. **Open the source code and start editing!**
|
||||
|
||||
Your site is now running at `http://localhost:8000`!
|
||||
|
||||
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._
|
||||
|
||||
Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!
|
||||
|
||||
## 🧐 What's inside?
|
||||
|
||||
A quick look at the top-level files and directories you'll see in a Gatsby project.
|
||||
|
||||
.
|
||||
├── node_modules
|
||||
├── src
|
||||
├── .gitignore
|
||||
├── .prettierrc
|
||||
├── gatsby-browser.js
|
||||
├── gatsby-config.js
|
||||
├── gatsby-node.js
|
||||
├── gatsby-ssr.js
|
||||
├── LICENSE
|
||||
├── package-lock.json
|
||||
├── package.json
|
||||
└── README.md
|
||||
|
||||
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
|
||||
|
||||
2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
|
||||
|
||||
3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
|
||||
|
||||
4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
|
||||
|
||||
5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
|
||||
|
||||
6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).
|
||||
|
||||
7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
|
||||
|
||||
8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
|
||||
|
||||
9. **`LICENSE`**: Gatsby is licensed under the MIT license.
|
||||
|
||||
10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).**
|
||||
|
||||
11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project.
|
||||
|
||||
12. **`README.md`**: A text file containing useful reference information about your project.
|
||||
|
||||
## 🎓 Learning Gatsby
|
||||
|
||||
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:
|
||||
|
||||
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
|
||||
|
||||
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
|
||||
|
||||
## 💫 Deploy
|
||||
|
||||
[](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
|
||||
|
||||
<!-- AUTO-GENERATED-CONTENT:END -->
|
||||
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-browser.js
vendored
Normal file
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-browser.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implement Gatsby's Browser APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/browser-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
34
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-config.js
vendored
Normal file
34
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-config.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `Gatsby Default Starter`,
|
||||
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
|
||||
author: `@gatsbyjs`,
|
||||
},
|
||||
plugins: [
|
||||
`gatsby-plugin-react-helmet`,
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `images`,
|
||||
path: `${__dirname}/src/images`,
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-plugin-sharp`,
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: `05-zero-config-gatsby`,
|
||||
short_name: `starter`,
|
||||
start_url: `/`,
|
||||
background_color: `#663399`,
|
||||
theme_color: `#663399`,
|
||||
display: `minimal-ui`,
|
||||
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
|
||||
},
|
||||
},
|
||||
// this (optional) plugin enables Progressive Web App + Offline functionality
|
||||
// To learn more, visit: https://gatsby.dev/offline
|
||||
// `gatsby-plugin-offline`,
|
||||
],
|
||||
}
|
||||
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-node.js
vendored
Normal file
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-node.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implement Gatsby's Node APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/node-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-ssr.js
vendored
Normal file
7
packages/cli/test/fixtures/unit/vercel-build-gatsby/gatsby-ssr.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/ssr-apis/
|
||||
*/
|
||||
|
||||
// You can delete this file if you're not using it
|
||||
43
packages/cli/test/fixtures/unit/vercel-build-gatsby/package.json
vendored
Normal file
43
packages/cli/test/fixtures/unit/vercel-build-gatsby/package.json
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "vercel-build-gatsby",
|
||||
"private": true,
|
||||
"description": "A simple starter to get up and developing quickly with Gatsby",
|
||||
"version": "0.1.0",
|
||||
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
|
||||
"dependencies": {
|
||||
"gatsby": "^2.17.6",
|
||||
"gatsby-image": "^2.2.30",
|
||||
"gatsby-plugin-manifest": "^2.2.25",
|
||||
"gatsby-plugin-offline": "^3.0.17",
|
||||
"gatsby-plugin-react-helmet": "^3.1.13",
|
||||
"gatsby-plugin-sharp": "^2.2.34",
|
||||
"gatsby-source-filesystem": "^2.1.35",
|
||||
"gatsby-transformer-sharp": "^2.3.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0",
|
||||
"react-helmet": "^5.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^1.18.2"
|
||||
},
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "gatsby build",
|
||||
"develop": "gatsby develop",
|
||||
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
|
||||
"start": "npm run develop",
|
||||
"serve": "gatsby serve",
|
||||
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/gatsbyjs/gatsby/issues"
|
||||
}
|
||||
}
|
||||
42
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/header.js
vendored
Normal file
42
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/header.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Link } from "gatsby"
|
||||
import PropTypes from "prop-types"
|
||||
import React from "react"
|
||||
|
||||
const Header = ({ siteTitle }) => (
|
||||
<header
|
||||
style={{
|
||||
background: `rebeccapurple`,
|
||||
marginBottom: `1.45rem`,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
margin: `0 auto`,
|
||||
maxWidth: 960,
|
||||
padding: `1.45rem 1.0875rem`,
|
||||
}}
|
||||
>
|
||||
<h1 style={{ margin: 0 }}>
|
||||
<Link
|
||||
to="/"
|
||||
style={{
|
||||
color: `white`,
|
||||
textDecoration: `none`,
|
||||
}}
|
||||
>
|
||||
{siteTitle}
|
||||
</Link>
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
Header.propTypes = {
|
||||
siteTitle: PropTypes.string,
|
||||
}
|
||||
|
||||
Header.defaultProps = {
|
||||
siteTitle: ``,
|
||||
}
|
||||
|
||||
export default Header
|
||||
32
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/image.js
vendored
Normal file
32
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/image.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from "react"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
import Img from "gatsby-image"
|
||||
|
||||
/*
|
||||
* This component is built using `gatsby-image` to automatically serve optimized
|
||||
* images with lazy loading and reduced file sizes. The image is loaded using a
|
||||
* `useStaticQuery`, which allows us to load the image from directly within this
|
||||
* component, rather than having to pass the image data down from pages.
|
||||
*
|
||||
* For more information, see the docs:
|
||||
* - `gatsby-image`: https://gatsby.dev/gatsby-image
|
||||
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
const Image = () => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 300) {
|
||||
...GatsbyImageSharpFluid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
|
||||
}
|
||||
|
||||
export default Image
|
||||
622
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/layout.css
vendored
Normal file
622
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/layout.css
vendored
Normal file
@@ -0,0 +1,622 @@
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
a {
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
a:active,
|
||||
a:hover {
|
||||
outline-width: 0;
|
||||
}
|
||||
abbr[title] {
|
||||
border-bottom: none;
|
||||
text-decoration: underline;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
font-weight: bolder;
|
||||
}
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
optgroup {
|
||||
font-weight: 700;
|
||||
}
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
[type="reset"],
|
||||
[type="submit"],
|
||||
button,
|
||||
html [type="button"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner,
|
||||
button::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring,
|
||||
button:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
fieldset {
|
||||
border: 1px solid silver;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
legend {
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
display: table;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
::-webkit-input-placeholder {
|
||||
color: inherit;
|
||||
opacity: 0.54;
|
||||
}
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
}
|
||||
html {
|
||||
font: 112.5%/1.45em georgia, serif;
|
||||
box-sizing: border-box;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
* {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
*:before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
color: hsla(0, 0%, 0%, 0.8);
|
||||
font-family: georgia, serif;
|
||||
font-weight: normal;
|
||||
word-wrap: break-word;
|
||||
font-kerning: normal;
|
||||
-moz-font-feature-settings: "kern", "liga", "clig", "calt";
|
||||
-ms-font-feature-settings: "kern", "liga", "clig", "calt";
|
||||
-webkit-font-feature-settings: "kern", "liga", "clig", "calt";
|
||||
font-feature-settings: "kern", "liga", "clig", "calt";
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
h1 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 2.25rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
h2 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 1.62671rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
h3 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 1.38316rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
h4 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 1rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
h5 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 0.85028rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
h6 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
color: inherit;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
font-weight: bold;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-size: 0.78405rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
hgroup {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
ul {
|
||||
margin-left: 1.45rem;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
list-style-position: outside;
|
||||
list-style-image: none;
|
||||
}
|
||||
ol {
|
||||
margin-left: 1.45rem;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
list-style-position: outside;
|
||||
list-style-image: none;
|
||||
}
|
||||
dl {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
dd {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
p {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
figure {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
pre {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.42;
|
||||
background: hsla(0, 0%, 0%, 0.04);
|
||||
border-radius: 3px;
|
||||
overflow: auto;
|
||||
word-wrap: normal;
|
||||
padding: 1.45rem;
|
||||
}
|
||||
table {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.45rem;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
fieldset {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 1.45rem;
|
||||
margin-right: 1.45rem;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
form {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
noscript {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
iframe {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
hr {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: calc(1.45rem - 1px);
|
||||
background: hsla(0, 0%, 0%, 0.2);
|
||||
border: none;
|
||||
height: 1px;
|
||||
}
|
||||
address {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 1.45rem;
|
||||
}
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
th {
|
||||
font-weight: bold;
|
||||
}
|
||||
li {
|
||||
margin-bottom: calc(1.45rem / 2);
|
||||
}
|
||||
ol li {
|
||||
padding-left: 0;
|
||||
}
|
||||
ul li {
|
||||
padding-left: 0;
|
||||
}
|
||||
li > ol {
|
||||
margin-left: 1.45rem;
|
||||
margin-bottom: calc(1.45rem / 2);
|
||||
margin-top: calc(1.45rem / 2);
|
||||
}
|
||||
li > ul {
|
||||
margin-left: 1.45rem;
|
||||
margin-bottom: calc(1.45rem / 2);
|
||||
margin-top: calc(1.45rem / 2);
|
||||
}
|
||||
blockquote *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
li *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
p *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
li > p {
|
||||
margin-bottom: calc(1.45rem / 2);
|
||||
}
|
||||
code {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.45rem;
|
||||
}
|
||||
kbd {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.45rem;
|
||||
}
|
||||
samp {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.45rem;
|
||||
}
|
||||
abbr {
|
||||
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
|
||||
cursor: help;
|
||||
}
|
||||
acronym {
|
||||
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
|
||||
cursor: help;
|
||||
}
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
|
||||
cursor: help;
|
||||
text-decoration: none;
|
||||
}
|
||||
thead {
|
||||
text-align: left;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
|
||||
font-feature-settings: "tnum";
|
||||
-moz-font-feature-settings: "tnum";
|
||||
-ms-font-feature-settings: "tnum";
|
||||
-webkit-font-feature-settings: "tnum";
|
||||
padding-left: 0.96667rem;
|
||||
padding-right: 0.96667rem;
|
||||
padding-top: 0.725rem;
|
||||
padding-bottom: calc(0.725rem - 1px);
|
||||
}
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
tt,
|
||||
code {
|
||||
background-color: hsla(0, 0%, 0%, 0.04);
|
||||
border-radius: 3px;
|
||||
font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
|
||||
"Liberation Mono", Menlo, Courier, monospace;
|
||||
padding: 0;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
pre code {
|
||||
background: none;
|
||||
line-height: 1.42;
|
||||
}
|
||||
code:before,
|
||||
code:after,
|
||||
tt:before,
|
||||
tt:after {
|
||||
letter-spacing: -0.2em;
|
||||
content: " ";
|
||||
}
|
||||
pre code:before,
|
||||
pre code:after,
|
||||
pre tt:before,
|
||||
pre tt:after {
|
||||
content: "";
|
||||
}
|
||||
@media only screen and (max-width: 480px) {
|
||||
html {
|
||||
font-size: 100%;
|
||||
}
|
||||
}
|
||||
52
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/layout.js
vendored
Normal file
52
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/layout.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Layout component that queries for data
|
||||
* with Gatsby's useStaticQuery component
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
import Header from "./header"
|
||||
import "./layout.css"
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query SiteTitleQuery {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header siteTitle={data.site.siteMetadata.title} />
|
||||
<div
|
||||
style={{
|
||||
margin: `0 auto`,
|
||||
maxWidth: 960,
|
||||
padding: `0px 1.0875rem 1.45rem`,
|
||||
paddingTop: 0,
|
||||
}}
|
||||
>
|
||||
<main>{children}</main>
|
||||
<footer>
|
||||
© {new Date().getFullYear()}, Built with
|
||||
{` `}
|
||||
<a href="https://www.gatsbyjs.org">Gatsby</a>
|
||||
</footer>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
}
|
||||
|
||||
export default Layout
|
||||
88
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/seo.js
vendored
Normal file
88
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/components/seo.js
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* SEO component that queries for data with
|
||||
* Gatsby's useStaticQuery React hook
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import Helmet from "react-helmet"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
function SEO({ description, lang, meta, title }) {
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
const metaDescription = description || site.siteMetadata.description
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
SEO.defaultProps = {
|
||||
lang: `en`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
}
|
||||
|
||||
SEO.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default SEO
|
||||
BIN
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/images/gatsby-astronaut.png
vendored
Normal file
BIN
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/images/gatsby-astronaut.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
BIN
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/images/gatsby-icon.png
vendored
Normal file
BIN
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/images/gatsby-icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
14
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/404.js
vendored
Normal file
14
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/404.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from "react"
|
||||
|
||||
import Layout from "../components/layout"
|
||||
import SEO from "../components/seo"
|
||||
|
||||
const NotFoundPage = () => (
|
||||
<Layout>
|
||||
<SEO title="404: Not found" />
|
||||
<h1>NOT FOUND</h1>
|
||||
<p>You just hit a route that doesn't exist... the sadness.</p>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default NotFoundPage
|
||||
21
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/index.js
vendored
Normal file
21
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/index.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from "react"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
import Layout from "../components/layout"
|
||||
import Image from "../components/image"
|
||||
import SEO from "../components/seo"
|
||||
|
||||
const IndexPage = () => (
|
||||
<Layout>
|
||||
<SEO title="Home" />
|
||||
<h1>Hi people</h1>
|
||||
<p>Welcome to your new Gatsby site.</p>
|
||||
<p>Now go build something great.</p>
|
||||
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
|
||||
<Image />
|
||||
</div>
|
||||
<Link to="/page-2/">Go to page 2</Link>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default IndexPage
|
||||
16
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/page-2.js
vendored
Normal file
16
packages/cli/test/fixtures/unit/vercel-build-gatsby/src/pages/page-2.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from "react"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
import Layout from "../components/layout"
|
||||
import SEO from "../components/seo"
|
||||
|
||||
const SecondPage = () => (
|
||||
<Layout>
|
||||
<SEO title="Page two" />
|
||||
<h1>Hi from the second page</h1>
|
||||
<p>Welcome to page 2</p>
|
||||
<Link to="/">Go back to the homepage</Link>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default SecondPage
|
||||
4
packages/cli/test/fixtures/unit/vercel-pull-next/.gitignore
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-pull-next/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.next
|
||||
yarn.lock
|
||||
.vercel
|
||||
.output
|
||||
12
packages/cli/test/fixtures/unit/vercel-pull-next/package.json
vendored
Normal file
12
packages/cli/test/fixtures/unit/vercel-pull-next/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next",
|
||||
"now-build": "next build"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^8.0.0",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0"
|
||||
}
|
||||
}
|
||||
11
packages/cli/test/fixtures/unit/vercel-pull-next/pages/index.js
vendored
Normal file
11
packages/cli/test/fixtures/unit/vercel-pull-next/pages/index.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { withRouter } from 'next/router';
|
||||
|
||||
function Index({ router }) {
|
||||
const data = {
|
||||
pathname: router.pathname,
|
||||
query: router.query,
|
||||
};
|
||||
return <div>{JSON.stringify(data)}</div>;
|
||||
}
|
||||
|
||||
export default withRouter(Index);
|
||||
1
packages/cli/test/fixtures/unit/vercel-pull-next/static/robots.txt
vendored
Normal file
1
packages/cli/test/fixtures/unit/vercel-pull-next/static/robots.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
User-Agent: *
|
||||
11
packages/cli/test/fixtures/unit/vercel-pull-next/vercel.json
vendored
Normal file
11
packages/cli/test/fixtures/unit/vercel-pull-next/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "vercel-pull-next",
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next@canary" }],
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "/index?route-param=b"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const getRevertAliasConfigFile = () => {
|
||||
],
|
||||
});
|
||||
};
|
||||
module.exports = async function prepare(session) {
|
||||
module.exports = async function prepare(session, binaryPath) {
|
||||
const spec = {
|
||||
'static-single-file': {
|
||||
'first.png': getImageFile(session, { size: 30 }),
|
||||
@@ -114,6 +114,23 @@ module.exports = async function prepare(session) {
|
||||
2
|
||||
),
|
||||
},
|
||||
'dev-fail-on-recursion-command': {
|
||||
'package.json': '{}',
|
||||
},
|
||||
'build-fail-on-recursion-command': {
|
||||
'package.json': '{}',
|
||||
},
|
||||
'build-fail-on-recursion-script': {
|
||||
'package.json': JSON.stringify(
|
||||
{
|
||||
scripts: {
|
||||
build: `${binaryPath} build`,
|
||||
},
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
},
|
||||
'static-deployment': {
|
||||
'index.txt': 'Hello World',
|
||||
},
|
||||
@@ -348,6 +365,10 @@ module.exports = async function prepare(session) {
|
||||
'project-link-dev': {
|
||||
'package.json': '{}',
|
||||
},
|
||||
'project-link-gitignore': {
|
||||
'package.json': '{}',
|
||||
'.gitignore': '.output',
|
||||
},
|
||||
'project-link-legacy': {
|
||||
'index.html': 'Hello',
|
||||
'vercel.json': '{"builds":[{"src":"*.html","use":"@vercel/static"}]}',
|
||||
|
||||
59
packages/cli/test/helpers/setup-fixture.ts
Normal file
59
packages/cli/test/helpers/setup-fixture.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import findUp from 'find-up';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import tmp from 'tmp-promise';
|
||||
|
||||
// tmp is supposed to be able to clean up automatically, but this doesn't always work within jest.
|
||||
// So we attempt to use its built-in cleanup mechanisms, but tests should ideally do their own cleanup too.
|
||||
tmp.setGracefulCleanup();
|
||||
|
||||
let fixturesRoot: string | undefined;
|
||||
let tempRoot: tmp.DirResult | undefined;
|
||||
let tempNumber = 0;
|
||||
|
||||
/**
|
||||
* Create a temp directory containing the given fixture name in a git repo.
|
||||
* Be sure to call `cleanupFixtures()` after all tests to clean up temp directories.
|
||||
*/
|
||||
export function setupFixture(fixtureName: string) {
|
||||
if (!fixturesRoot) {
|
||||
fixturesRoot = findUp.sync('fixtures', {
|
||||
cwd: __dirname,
|
||||
type: 'directory',
|
||||
});
|
||||
}
|
||||
|
||||
const fixturePath = path.join(fixturesRoot!, 'unit', fixtureName);
|
||||
if (!fs.existsSync(fixturePath)) {
|
||||
throw new Error(
|
||||
`Couldn't find fixture "${fixtureName}" under "${path.join(
|
||||
fixturesRoot!,
|
||||
'unit'
|
||||
)}"`
|
||||
);
|
||||
}
|
||||
|
||||
if (!tempRoot) {
|
||||
// Create a shared root temp directory for fixture files
|
||||
tempRoot = tmp.dirSync({ unsafeCleanup: true }); // clean up even if files are left
|
||||
}
|
||||
|
||||
const cwd = path.join(tempRoot.name, String(tempNumber++), fixtureName);
|
||||
|
||||
fs.mkdirpSync(cwd);
|
||||
fs.copySync(fixturePath, cwd);
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
export function cleanupFixtures() {
|
||||
if (tempRoot) {
|
||||
tempRoot.removeCallback();
|
||||
tempRoot = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// After all tests are run, we clean up our fixtures
|
||||
afterAll(() => {
|
||||
cleanupFixtures();
|
||||
});
|
||||
432
packages/cli/test/integration.js
vendored
432
packages/cli/test/integration.js
vendored
@@ -252,10 +252,69 @@ const createUser = async () => {
|
||||
|
||||
const getConfigAuthPath = () => path.join(globalDir, 'auth.json');
|
||||
|
||||
async function setupProject(process, projectName, overrides) {
|
||||
await waitForPrompt(process, chunk => /Set up [^?]+\?/.test(chunk));
|
||||
process.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(process, chunk => /Which scope [^?]+\?/.test(chunk));
|
||||
process.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes('Link to existing project?')
|
||||
);
|
||||
process.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
process.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
process.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes('Want to override the settings?')
|
||||
);
|
||||
|
||||
if (overrides) {
|
||||
process.stdin.write('yes\n');
|
||||
|
||||
const { buildCommand, outputDirectory, devCommand } = overrides;
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes(
|
||||
'Which settings would you like to overwrite (select multiple)?'
|
||||
)
|
||||
);
|
||||
process.stdin.write('a\n'); // 'a' means select all
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes(`What's your Build Command?`)
|
||||
);
|
||||
process.stdin.write(`${buildCommand ?? ''}\n`);
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes(`What's your Output Directory?`)
|
||||
);
|
||||
process.stdin.write(`${outputDirectory ?? ''}\n`);
|
||||
|
||||
await waitForPrompt(process, chunk =>
|
||||
chunk.includes(`What's your Development Command?`)
|
||||
);
|
||||
process.stdin.write(`${devCommand ?? ''}\n`);
|
||||
} else {
|
||||
process.stdin.write('no\n');
|
||||
}
|
||||
|
||||
await waitForPrompt(process, chunk => chunk.includes('Linked to'));
|
||||
}
|
||||
|
||||
test.before(async () => {
|
||||
try {
|
||||
await createUser();
|
||||
await prepareFixtures(contextName);
|
||||
await prepareFixtures(contextName, binaryPath);
|
||||
} catch (err) {
|
||||
console.log('Failed `test.before`');
|
||||
console.log(err);
|
||||
@@ -2227,13 +2286,93 @@ test('whoami', async t => {
|
||||
t.is(stdout, contextName, formatOutput({ stdout, stderr }));
|
||||
});
|
||||
|
||||
test('fail `now dev` dev script without now.json', async t => {
|
||||
test('[vercel dev] fails when dev script calls vercel dev recursively', async t => {
|
||||
const deploymentPath = fixture('now-dev-fail-dev-script');
|
||||
const { exitCode, stderr } = await execute(['dev', deploymentPath]);
|
||||
|
||||
t.is(exitCode, 1);
|
||||
t.true(
|
||||
stderr.includes('must not contain `now dev`'),
|
||||
stderr.includes('must not recursively invoke itself'),
|
||||
`Received instead: "${stderr}"`
|
||||
);
|
||||
});
|
||||
|
||||
test('[vercel dev] fails when development commad calls vercel dev recursively', async t => {
|
||||
const dir = fixture('dev-fail-on-recursion-command');
|
||||
const projectName = `dev-fail-on-recursion-command-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
const dev = execa(binaryPath, ['dev', ...defaultArgs], {
|
||||
cwd: dir,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
await setupProject(dev, projectName, {
|
||||
devCommand: `${binaryPath} dev`,
|
||||
});
|
||||
|
||||
const { exitCode, stderr } = await dev;
|
||||
|
||||
t.is(exitCode, 1);
|
||||
t.true(
|
||||
stderr.includes('must not recursively invoke itself'),
|
||||
`Received instead: "${stderr}"`
|
||||
);
|
||||
});
|
||||
|
||||
test('[vercel build] fails when build commad calls vercel build recursively', async t => {
|
||||
const dir = fixture('build-fail-on-recursion-command');
|
||||
const projectName = `build-fail-on-recursion-command-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
const build = execa(binaryPath, ['build', ...defaultArgs], {
|
||||
cwd: dir,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
await waitForPrompt(build, chunk =>
|
||||
chunk.includes('No Project Settings found locally')
|
||||
);
|
||||
build.stdin.write('yes\n');
|
||||
|
||||
await setupProject(build, projectName, {
|
||||
buildCommand: `${binaryPath} build`,
|
||||
});
|
||||
|
||||
const { exitCode, stderr } = await build;
|
||||
|
||||
t.is(exitCode, 1);
|
||||
t.true(
|
||||
stderr.includes('must not recursively invoke itself'),
|
||||
`Received instead: "${stderr}"`
|
||||
);
|
||||
});
|
||||
|
||||
test('[vercel build] fails when build script calls vercel build recursively', async t => {
|
||||
const dir = fixture('build-fail-on-recursion-script');
|
||||
const projectName = `build-fail-on-recursion-script-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
const build = execa(binaryPath, ['build', ...defaultArgs], {
|
||||
cwd: dir,
|
||||
reject: false,
|
||||
});
|
||||
|
||||
await waitForPrompt(build, chunk =>
|
||||
chunk.includes('No Project Settings found locally')
|
||||
);
|
||||
build.stdin.write('yes\n');
|
||||
|
||||
await setupProject(build, projectName);
|
||||
|
||||
const { exitCode, stderr } = await build;
|
||||
|
||||
t.is(exitCode, 1);
|
||||
t.true(
|
||||
stderr.includes('must not recursively invoke itself'),
|
||||
`Received instead: "${stderr}"`
|
||||
);
|
||||
});
|
||||
@@ -2544,7 +2683,7 @@ test('deploy a Lambda with 3 seconds of maxDuration', async t => {
|
||||
const url = new URL(output.stdout);
|
||||
|
||||
// Should time out
|
||||
url.pathname = '/api/wait-for/4';
|
||||
url.pathname = '/api/wait-for/5';
|
||||
const response1 = await fetch(url.href);
|
||||
t.is(
|
||||
response1.status,
|
||||
@@ -2553,7 +2692,7 @@ test('deploy a Lambda with 3 seconds of maxDuration', async t => {
|
||||
);
|
||||
|
||||
// Should not time out
|
||||
url.pathname = '/api/wait-for/2';
|
||||
url.pathname = '/api/wait-for/1';
|
||||
const response2 = await fetch(url.href);
|
||||
t.is(
|
||||
response2.status,
|
||||
@@ -2673,69 +2812,20 @@ test('ensure `github` and `scope` are not sent to the API', async t => {
|
||||
});
|
||||
|
||||
test('should show prompts to set up project during first deploy', async t => {
|
||||
const directory = fixture('project-link-deploy');
|
||||
const dir = fixture('project-link-deploy');
|
||||
const projectName = `project-link-deploy-${
|
||||
Math.random().toString(36).split('.')[1]
|
||||
}`;
|
||||
|
||||
// remove previously linked project if it exists
|
||||
await remove(path.join(directory, '.vercel'));
|
||||
await remove(path.join(dir, '.vercel'));
|
||||
|
||||
const now = execa(binaryPath, [directory, ...defaultArgs]);
|
||||
const now = execa(binaryPath, [dir, ...defaultArgs]);
|
||||
|
||||
await waitForPrompt(now, chunk => /Set up and deploy [^?]+\?/.test(chunk));
|
||||
now.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes('Which scope do you want to deploy to?')
|
||||
);
|
||||
now.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes('Link to existing project?')
|
||||
);
|
||||
now.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
now.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
now.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes('Want to override the settings?')
|
||||
);
|
||||
now.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes(
|
||||
'Which settings would you like to overwrite (select multiple)?'
|
||||
)
|
||||
);
|
||||
now.stdin.write('a\n'); // 'a' means select all
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes(`What's your Build Command?`)
|
||||
);
|
||||
now.stdin.write(
|
||||
`mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html\n`
|
||||
);
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes(`What's your Output Directory?`)
|
||||
);
|
||||
now.stdin.write(`o\n`);
|
||||
|
||||
await waitForPrompt(now, chunk =>
|
||||
chunk.includes(`What's your Development Command?`)
|
||||
);
|
||||
now.stdin.write(`\n`);
|
||||
|
||||
await waitForPrompt(now, chunk => chunk.includes('Linked to'));
|
||||
await setupProject(now, projectName, {
|
||||
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
||||
outputDirectory: 'o',
|
||||
});
|
||||
|
||||
const output = await now;
|
||||
|
||||
@@ -2743,19 +2833,17 @@ test('should show prompts to set up project during first deploy', async t => {
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is(
|
||||
(await readFile(path.join(directory, '.gitignore'))).toString(),
|
||||
'.vercel\n'
|
||||
);
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.vercel\n.output\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
await exists(path.join(directory, '.vercel', 'project.json')),
|
||||
await exists(path.join(dir, '.vercel', 'project.json')),
|
||||
true,
|
||||
'project.json should be created'
|
||||
);
|
||||
t.is(
|
||||
await exists(path.join(directory, '.vercel', 'README.txt')),
|
||||
await exists(path.join(dir, '.vercel', 'README.txt')),
|
||||
true,
|
||||
'README.txt should be created'
|
||||
);
|
||||
@@ -2769,13 +2857,7 @@ test('should show prompts to set up project during first deploy', async t => {
|
||||
// and output directory
|
||||
let stderr = '';
|
||||
const port = 58351;
|
||||
const dev = execa(binaryPath, [
|
||||
'dev',
|
||||
'--listen',
|
||||
port,
|
||||
directory,
|
||||
...defaultArgs,
|
||||
]);
|
||||
const dev = execa(binaryPath, ['dev', '--listen', port, dir, ...defaultArgs]);
|
||||
dev.stderr.setEncoding('utf8');
|
||||
|
||||
try {
|
||||
@@ -3309,55 +3391,10 @@ test('[vc link] should show prompts to set up project', async t => {
|
||||
|
||||
const vc = execa(binaryPath, ['link', ...defaultArgs], { cwd: dir });
|
||||
|
||||
await waitForPrompt(vc, chunk => /Set up [^?]+\?/.test(chunk));
|
||||
vc.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('Which scope should contain your project?')
|
||||
);
|
||||
vc.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(vc, chunk => chunk.includes('Link to existing project?'));
|
||||
vc.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
vc.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
vc.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes('Want to override the settings?')
|
||||
);
|
||||
vc.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes(
|
||||
'Which settings would you like to overwrite (select multiple)?'
|
||||
)
|
||||
);
|
||||
vc.stdin.write('a\n'); // 'a' means select all
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes(`What's your Build Command?`)
|
||||
);
|
||||
vc.stdin.write(`mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html\n`);
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes(`What's your Output Directory?`)
|
||||
);
|
||||
vc.stdin.write(`o\n`);
|
||||
|
||||
await waitForPrompt(vc, chunk =>
|
||||
chunk.includes(`What's your Development Command?`)
|
||||
);
|
||||
vc.stdin.write(`\n`);
|
||||
|
||||
await waitForPrompt(vc, chunk => chunk.includes('Linked to'));
|
||||
await setupProject(vc, projectName, {
|
||||
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
||||
outputDirectory: 'o',
|
||||
});
|
||||
|
||||
const output = await vc;
|
||||
|
||||
@@ -3365,7 +3402,8 @@ test('[vc link] should show prompts to set up project', async t => {
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.vercel\n.output\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3399,7 +3437,8 @@ test('[vc link --confirm] should not show prompts and autolink', async t => {
|
||||
t.regex(stderr, /Linked to /m);
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.vercel\n.output\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3414,6 +3453,29 @@ test('[vc link --confirm] should not show prompts and autolink', async t => {
|
||||
);
|
||||
});
|
||||
|
||||
test('[vc link] should not duplicate paths in .gitignore', async t => {
|
||||
const dir = fixture('project-link-gitignore');
|
||||
|
||||
// remove previously linked project if it exists
|
||||
await remove(path.join(dir, '.vercel'));
|
||||
|
||||
const { exitCode, stderr, stdout } = await execa(
|
||||
binaryPath,
|
||||
['link', '--confirm', ...defaultArgs],
|
||||
{ cwd: dir, reject: false }
|
||||
);
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||
|
||||
// Ensure the message is correct pattern
|
||||
t.regex(stderr, /Linked to /m);
|
||||
|
||||
// Ensure .gitignore is created
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.output\n.vercel\n');
|
||||
});
|
||||
|
||||
test('[vc dev] should show prompts to set up project', async t => {
|
||||
const dir = fixture('project-link-dev');
|
||||
const port = 58352;
|
||||
@@ -3428,62 +3490,14 @@ test('[vc dev] should show prompts to set up project', async t => {
|
||||
cwd: dir,
|
||||
});
|
||||
|
||||
await waitForPrompt(dev, chunk => /Set up and develop [^?]+\?/.test(chunk));
|
||||
dev.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Which scope should contain your project?')
|
||||
);
|
||||
dev.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Link to existing project?')
|
||||
);
|
||||
dev.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
dev.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
dev.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Want to override the settings?')
|
||||
);
|
||||
dev.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(
|
||||
'Which settings would you like to overwrite (select multiple)?'
|
||||
)
|
||||
);
|
||||
dev.stdin.write('a\n'); // 'a' means select all
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Build Command?`)
|
||||
);
|
||||
dev.stdin.write(
|
||||
`mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html\n`
|
||||
);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Output Directory?`)
|
||||
);
|
||||
dev.stdin.write(`o\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Development Command?`)
|
||||
);
|
||||
dev.stdin.write(`\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk => chunk.includes('Linked to'));
|
||||
await setupProject(dev, projectName, {
|
||||
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
||||
outputDirectory: 'o',
|
||||
});
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.vercel\n.output\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3549,7 +3563,8 @@ test('[vc link] should show project prompts but not framework when `builds` defi
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
|
||||
// Ensure .gitignore is created
|
||||
t.is((await readFile(path.join(dir, '.gitignore'))).toString(), '.vercel\n');
|
||||
const gitignore = await readFile(path.join(dir, '.gitignore'), 'utf8');
|
||||
t.is(gitignore, '.vercel\n.output\n');
|
||||
|
||||
// Ensure .vercel/project.json and .vercel/README.txt are created
|
||||
t.is(
|
||||
@@ -3578,59 +3593,12 @@ test('[vc dev] should send the platform proxy request headers to frontend dev se
|
||||
cwd: dir,
|
||||
});
|
||||
|
||||
await waitForPrompt(dev, chunk => /Set up and develop [^?]+\?/.test(chunk));
|
||||
dev.stdin.write('yes\n');
|
||||
await setupProject(dev, projectName, {
|
||||
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
||||
outputDirectory: 'o',
|
||||
devCommand: 'node server.js',
|
||||
});
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Which scope should contain your project?')
|
||||
);
|
||||
dev.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Link to existing project?')
|
||||
);
|
||||
dev.stdin.write('no\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('What’s your project’s name?')
|
||||
);
|
||||
dev.stdin.write(`${projectName}\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('In which directory is your code located?')
|
||||
);
|
||||
dev.stdin.write('\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes('Want to override the settings?')
|
||||
);
|
||||
dev.stdin.write('yes\n');
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(
|
||||
'Which settings would you like to overwrite (select multiple)?'
|
||||
)
|
||||
);
|
||||
dev.stdin.write('a\n'); // 'a' means select all
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Build Command?`)
|
||||
);
|
||||
dev.stdin.write(
|
||||
`mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html\n`
|
||||
);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Output Directory?`)
|
||||
);
|
||||
dev.stdin.write(`o\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk =>
|
||||
chunk.includes(`What's your Development Command?`)
|
||||
);
|
||||
dev.stdin.write(`node server.js\n`);
|
||||
|
||||
await waitForPrompt(dev, chunk => chunk.includes('Linked to'));
|
||||
await waitForPrompt(dev, chunk => chunk.includes('Ready! Available at'));
|
||||
|
||||
// Ensure that `vc dev` also works
|
||||
|
||||
@@ -56,7 +56,6 @@ export class MockClient extends Client {
|
||||
this.output = new Output();
|
||||
this.mockOutput = jest.fn();
|
||||
this.output.print = s => {
|
||||
//process.stdout.write(s);
|
||||
return this.mockOutput(s);
|
||||
};
|
||||
|
||||
|
||||
91
packages/cli/test/mocks/project.ts
Normal file
91
packages/cli/test/mocks/project.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { client } from './client';
|
||||
|
||||
const envs = [
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: '781dt89g8r2h789g',
|
||||
key: 'REDIS_CONNECTION_STRING',
|
||||
value: 'redis://abc123@redis.example.com:6379',
|
||||
target: ['production', 'preview'],
|
||||
gitBranch: null,
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361455,
|
||||
createdAt: 1557241361455,
|
||||
},
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: 'r124t6frtu25df16',
|
||||
key: 'SQL_CONNECTION_STRING',
|
||||
value: 'Server=sql.example.com;Database=app;Uid=root;Pwd=P455W0RD;',
|
||||
target: ['production'],
|
||||
gitBranch: null,
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361445,
|
||||
createdAt: 1557241361445,
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultProject = {
|
||||
id: 'foo',
|
||||
name: 'cli',
|
||||
accountId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
||||
createdAt: 1555413045188,
|
||||
updatedAt: 1555413045188,
|
||||
env: envs,
|
||||
targets: {
|
||||
production: {
|
||||
alias: ['foobar.com'],
|
||||
aliasAssigned: 1571239348998,
|
||||
createdAt: 1571239348998,
|
||||
createdIn: 'sfo1',
|
||||
deploymentHostname: 'a-project-name-rjtr4pz3f',
|
||||
forced: false,
|
||||
id: 'dpl_89qyp1cskzkLrVicDaZoDbjyHuDJ',
|
||||
meta: {},
|
||||
plan: 'pro',
|
||||
private: true,
|
||||
readyState: 'READY',
|
||||
requestedAt: 1571239348998,
|
||||
target: 'production',
|
||||
teamId: null,
|
||||
type: 'LAMBDAS',
|
||||
url: 'a-project-name-rjtr4pz3f.vercel.app',
|
||||
userId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
||||
},
|
||||
},
|
||||
latestDeployments: [
|
||||
{
|
||||
alias: ['foobar.com'],
|
||||
aliasAssigned: 1571239348998,
|
||||
createdAt: 1571239348998,
|
||||
createdIn: 'sfo1',
|
||||
deploymentHostname: 'a-project-name-rjtr4pz3f',
|
||||
forced: false,
|
||||
id: 'dpl_89qyp1cskzkLrVicDaZoDbjyHuDJ',
|
||||
meta: {},
|
||||
plan: 'pro',
|
||||
private: true,
|
||||
readyState: 'READY',
|
||||
requestedAt: 1571239348998,
|
||||
target: 'production',
|
||||
teamId: null,
|
||||
type: 'LAMBDAS',
|
||||
url: 'a-project-name-rjtr4pz3f.vercel.app',
|
||||
userId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function useProject(project = defaultProject) {
|
||||
client.scenario.get(`/projects/${project.name}`, (_req, res) => {
|
||||
res.json(project);
|
||||
});
|
||||
client.scenario.get(`/projects/${project.id}`, (_req, res) => {
|
||||
res.json(project);
|
||||
});
|
||||
client.scenario.get(`/v7/projects/${project.id}/env`, (_req, res) => {
|
||||
res.json({ envs });
|
||||
});
|
||||
|
||||
return { project, envs };
|
||||
}
|
||||
29
packages/cli/test/mocks/team.ts
Normal file
29
packages/cli/test/mocks/team.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import chance from 'chance';
|
||||
import { client } from './client';
|
||||
|
||||
export function useTeams() {
|
||||
const teams = [
|
||||
{
|
||||
id: chance().guid(),
|
||||
slug: chance().string({ length: 5, casing: 'lower' }),
|
||||
name: chance().company(),
|
||||
creatorId: chance().guid(),
|
||||
created: '2017-04-29T17:21:54.514Z',
|
||||
avatar: null,
|
||||
},
|
||||
];
|
||||
|
||||
for (let team of teams) {
|
||||
client.scenario.get(`/v1/team/${team.id}`, (_req, res) => {
|
||||
res.json(team);
|
||||
});
|
||||
}
|
||||
|
||||
client.scenario.get('/v1/teams', (_req, res) => {
|
||||
res.json({
|
||||
teams,
|
||||
});
|
||||
});
|
||||
|
||||
return teams;
|
||||
}
|
||||
@@ -2,20 +2,31 @@ import chance from 'chance';
|
||||
import { client } from './client';
|
||||
|
||||
export function useUser() {
|
||||
const userLimited = {
|
||||
const user = {
|
||||
id: chance().guid(),
|
||||
email: chance().email(),
|
||||
name: chance().name(),
|
||||
username: chance().first().toLowerCase(),
|
||||
};
|
||||
|
||||
client.scenario.get('/v2/user', (_req, res) => {
|
||||
res.json({
|
||||
user: userLimited,
|
||||
user,
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
...userLimited,
|
||||
};
|
||||
client.scenario.post('/registration', (_req, res) => {
|
||||
res.json({
|
||||
token: 'T1dmvPu36nmyYisXAs7IRzcR',
|
||||
securityCode: 'Practical Saola',
|
||||
});
|
||||
});
|
||||
|
||||
client.scenario.get('/registration/verify', (_req, res) => {
|
||||
res.json({
|
||||
token: 'hjkjn',
|
||||
email: user.email,
|
||||
});
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -335,4 +335,54 @@ describe('DevServer', () => {
|
||||
expect(body).toEqual('The page could not be found.\n\nNOT_FOUND\n');
|
||||
})
|
||||
);
|
||||
|
||||
it(
|
||||
'should support edge middleware',
|
||||
testFixture('edge-middleware', async server => {
|
||||
const response = await fetch(`${server.address}/index.html`);
|
||||
const body = await response.json();
|
||||
expect(body).toEqual(
|
||||
JSON.parse(
|
||||
fs.readFileSync(
|
||||
path.join(
|
||||
__dirname,
|
||||
'../../fixtures/unit/edge-middleware/response.json'
|
||||
),
|
||||
'utf8'
|
||||
)
|
||||
)
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
it(
|
||||
'should work with middleware written in typescript',
|
||||
testFixture('edge-middleware-ts', async server => {
|
||||
const response = await fetch(`${server.address}/index.html`);
|
||||
const body = await response.text();
|
||||
expect(body).toStrictEqual('response');
|
||||
})
|
||||
);
|
||||
|
||||
it(
|
||||
'should render an error page when the middleware throws',
|
||||
testFixture('edge-middleware-error', async server => {
|
||||
const response = await fetch(`${server.address}/index.html`);
|
||||
const body = await response.text();
|
||||
expect(body).toStrictEqual(
|
||||
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED\n'
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
it(
|
||||
'should render an error page when the middleware returns not a Response',
|
||||
testFixture('edge-middleware-invalid-response', async server => {
|
||||
const response = await fetch(`${server.address}/index.html`);
|
||||
const body = await response.text();
|
||||
expect(body).toStrictEqual(
|
||||
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED\n'
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ describe('getUpdateCommand', () => {
|
||||
it('should detect update command', async () => {
|
||||
const updateCommand = await getUpdateCommand();
|
||||
expect(updateCommand).toEqual(
|
||||
`yarn add vercel@${isCanary() ? 'canary' : 'latest'}`
|
||||
`npm i vercel@${isCanary() ? 'canary' : 'latest'}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "10.2.3-canary.12",
|
||||
"version": "10.2.3-canary.20",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -40,7 +40,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.12.3-canary.12",
|
||||
"@vercel/build-utils": "2.12.3-canary.19",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -88,6 +88,50 @@ export async function* checkDeploymentStatus(
|
||||
yield { type: 'ready', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (deploymentUpdate.checksState !== undefined) {
|
||||
if (
|
||||
deploymentUpdate.checksState === 'completed' &&
|
||||
!finishedEvents.has('checks-completed')
|
||||
) {
|
||||
finishedEvents.add('checks-completed');
|
||||
|
||||
if (deploymentUpdate.checksConclusion === 'succeeded') {
|
||||
yield {
|
||||
type: 'checks-conclusion-succeeded',
|
||||
payload: deploymentUpdate,
|
||||
};
|
||||
} else if (deploymentUpdate.checksConclusion === 'failed') {
|
||||
yield { type: 'checks-conclusion-failed', payload: deploymentUpdate };
|
||||
} else if (deploymentUpdate.checksConclusion === 'skipped') {
|
||||
yield {
|
||||
type: 'checks-conclusion-skipped',
|
||||
payload: deploymentUpdate,
|
||||
};
|
||||
} else if (deploymentUpdate.checksConclusion === 'canceled') {
|
||||
yield {
|
||||
type: 'checks-conclusion-canceled',
|
||||
payload: deploymentUpdate,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
deploymentUpdate.checksState === 'registered' &&
|
||||
!finishedEvents.has('checks-registered')
|
||||
) {
|
||||
finishedEvents.add('checks-registered');
|
||||
yield { type: 'checks-registered', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (
|
||||
deploymentUpdate.checksState === 'running' &&
|
||||
!finishedEvents.has('checks-running')
|
||||
) {
|
||||
finishedEvents.add('checks-running');
|
||||
yield { type: 'checks-running', payload: deploymentUpdate };
|
||||
}
|
||||
}
|
||||
|
||||
if (isAliasAssigned(deploymentUpdate)) {
|
||||
debug('Deployment alias assigned');
|
||||
return yield { type: 'alias-assigned', payload: deploymentUpdate };
|
||||
|
||||
@@ -77,7 +77,8 @@ export default function buildCreateDeployment() {
|
||||
let { fileList } = await buildFileTree(
|
||||
path,
|
||||
clientOptions.isDirectory,
|
||||
debug
|
||||
debug,
|
||||
clientOptions.prebuilt
|
||||
);
|
||||
|
||||
let configPath: string | undefined;
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface VercelClientOptions {
|
||||
teamId?: string;
|
||||
apiUrl?: string;
|
||||
force?: boolean;
|
||||
prebuilt?: boolean;
|
||||
withCache?: boolean;
|
||||
userAgent?: string;
|
||||
defaultName?: string;
|
||||
|
||||
@@ -31,6 +31,14 @@ const EVENTS_ARRAY = [
|
||||
'notice',
|
||||
'tip',
|
||||
'canceled',
|
||||
// Checks events
|
||||
'checks-registered',
|
||||
'checks-completed',
|
||||
'checks-running',
|
||||
'checks-conclusion-succeeded',
|
||||
'checks-conclusion-failed',
|
||||
'checks-conclusion-skipped',
|
||||
'checks-conclusion-canceled',
|
||||
] as const;
|
||||
|
||||
export type DeploymentEventType = typeof EVENTS_ARRAY[number];
|
||||
@@ -74,11 +82,12 @@ const maybeRead = async function <T>(path: string, default_: T) {
|
||||
export async function buildFileTree(
|
||||
path: string | string[],
|
||||
isDirectory: boolean,
|
||||
debug: Debug
|
||||
debug: Debug,
|
||||
prebuilt?: boolean
|
||||
): Promise<{ fileList: string[]; ignoreList: string[] }> {
|
||||
const ignoreList: string[] = [];
|
||||
let fileList: string[];
|
||||
let { ig, ignores } = await getVercelIgnore(path);
|
||||
let { ig, ignores } = await getVercelIgnore(path, prebuilt);
|
||||
|
||||
debug(`Found ${ignores.length} rules in .vercelignore`);
|
||||
debug('Building file tree...');
|
||||
@@ -109,36 +118,38 @@ export async function buildFileTree(
|
||||
}
|
||||
|
||||
export async function getVercelIgnore(
|
||||
cwd: string | string[]
|
||||
cwd: string | string[],
|
||||
prebuilt?: boolean
|
||||
): Promise<{ ig: Ignore; ignores: string[] }> {
|
||||
const ignores: string[] = [
|
||||
'.hg',
|
||||
'.git',
|
||||
'.gitmodules',
|
||||
'.svn',
|
||||
'.cache',
|
||||
'.next',
|
||||
'.now',
|
||||
'.vercel',
|
||||
'.npmignore',
|
||||
'.dockerignore',
|
||||
'.gitignore',
|
||||
'.*.swp',
|
||||
'.DS_Store',
|
||||
'.wafpicke-*',
|
||||
'.lock-wscript',
|
||||
'.env.local',
|
||||
'.env.*.local',
|
||||
'.venv',
|
||||
'npm-debug.log',
|
||||
'config.gypi',
|
||||
'node_modules',
|
||||
'__pycache__',
|
||||
'venv',
|
||||
'CVS',
|
||||
'.vercel_build_output',
|
||||
];
|
||||
|
||||
const ignores: string[] = prebuilt
|
||||
? ['*', '!.output', '!.output/**']
|
||||
: [
|
||||
'.hg',
|
||||
'.git',
|
||||
'.gitmodules',
|
||||
'.svn',
|
||||
'.cache',
|
||||
'.next',
|
||||
'.now',
|
||||
'.vercel',
|
||||
'.npmignore',
|
||||
'.dockerignore',
|
||||
'.gitignore',
|
||||
'.*.swp',
|
||||
'.DS_Store',
|
||||
'.wafpicke-*',
|
||||
'.lock-wscript',
|
||||
'.env.local',
|
||||
'.env.*.local',
|
||||
'.venv',
|
||||
'npm-debug.log',
|
||||
'config.gypi',
|
||||
'node_modules',
|
||||
'__pycache__',
|
||||
'venv',
|
||||
'CVS',
|
||||
'.output',
|
||||
];
|
||||
const cwds = Array.isArray(cwd) ? cwd : [cwd];
|
||||
|
||||
const files = await Promise.all(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "0.5.1-canary.8",
|
||||
"version": "0.5.1-canary.12",
|
||||
"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.4-canary.4",
|
||||
"@vercel/routing-utils": "1.11.4-canary.6",
|
||||
"ajv": "6.12.2",
|
||||
"typescript": "4.3.4"
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `blitz build`',
|
||||
value: 'blitz build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'blitz start',
|
||||
@@ -51,8 +52,7 @@ export const frameworks = [
|
||||
placeholder: 'Next.js default',
|
||||
},
|
||||
},
|
||||
devCommand: 'blitz start',
|
||||
buildCommand: 'blitz build',
|
||||
getFsOutputDir: async () => '.next',
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
{
|
||||
@@ -82,6 +82,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `next build`',
|
||||
value: 'next build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'next dev --port $PORT',
|
||||
@@ -97,8 +98,7 @@ export const frameworks = [
|
||||
dependencies: ['next-plugin-sentry', 'next-sentry-source-maps'],
|
||||
},
|
||||
],
|
||||
devCommand: 'next dev --port $PORT',
|
||||
buildCommand: 'next build',
|
||||
getFsOutputDir: async () => '.next',
|
||||
getOutputDirName: async () => 'public',
|
||||
cachePattern: '.next/cache/**',
|
||||
},
|
||||
@@ -129,6 +129,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `gatsby build`',
|
||||
value: 'gatsby build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'gatsby develop --port $PORT',
|
||||
@@ -139,9 +140,8 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'gatsby',
|
||||
devCommand: 'gatsby develop --port $PORT',
|
||||
buildCommand: 'gatsby build',
|
||||
getOutputDirName: async () => 'public',
|
||||
getFsOutputDir: async () => 'public',
|
||||
defaultRoutes: async (dirPrefix: string) => {
|
||||
// This file could be generated by gatsby-plugin-now or gatsby-plugin-zeit-now
|
||||
try {
|
||||
@@ -216,6 +216,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `hexo generate`',
|
||||
value: 'hexo generate',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'hexo server --port $PORT',
|
||||
@@ -226,8 +227,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'hexo',
|
||||
devCommand: 'hexo server --port $PORT',
|
||||
buildCommand: 'hexo generate',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
{
|
||||
@@ -255,6 +255,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `npx @11ty/eleventy`',
|
||||
value: 'npx @11ty/eleventy',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'npx @11ty/eleventy --serve --watch --port $PORT',
|
||||
@@ -265,8 +266,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@11ty/eleventy',
|
||||
devCommand: 'npx @11ty/eleventy --serve --watch --port $PORT',
|
||||
buildCommand: 'npx @11ty/eleventy',
|
||||
getFsOutputDir: async () => '_site',
|
||||
getOutputDirName: async () => '_site',
|
||||
cachePattern: '.cache/**',
|
||||
},
|
||||
@@ -295,6 +295,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `docusaurus build`',
|
||||
value: 'docusaurus build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'docusaurus start --port $PORT',
|
||||
@@ -305,8 +306,22 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@docusaurus/core',
|
||||
devCommand: 'docusaurus start --port $PORT',
|
||||
buildCommand: 'docusaurus build',
|
||||
getFsOutputDir: async (dirPrefix: string) => {
|
||||
const base = 'build';
|
||||
try {
|
||||
const location = join(dirPrefix, base);
|
||||
const content = await readdir(location, { withFileTypes: true });
|
||||
|
||||
// If there is only one file in it that is a dir we'll use it as dist dir
|
||||
if (content.length === 1 && content[0].isDirectory()) {
|
||||
return join(base, content[0].name);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error detecting output directory: `, error);
|
||||
}
|
||||
|
||||
return base;
|
||||
},
|
||||
getOutputDirName: async (dirPrefix: string) => {
|
||||
const base = 'build';
|
||||
try {
|
||||
@@ -323,6 +338,57 @@ export const frameworks = [
|
||||
|
||||
return base;
|
||||
},
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js)$',
|
||||
regex: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source:
|
||||
'^/assets/images/[^/]+-[0-9a-f]{32}\\.(ico|svg|jpg|jpeg|png|gif|webp)$',
|
||||
regex:
|
||||
'^/assets/images/[^/]+-[0-9a-f]{32}\\.(ico|svg|jpg|jpeg|png|gif|webp)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source:
|
||||
'^/assets/medias/[^/]+-[0-9a-f]{32}\\.(ogv|wav|mp3|m4a|aac|oga|flac)$',
|
||||
regex:
|
||||
'^/assets/medias/[^/]+-[0-9a-f]{32}\\.(ogv|wav|mp3|m4a|aac|oga|flac)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source:
|
||||
'^/assets/files/[^/]+-[0-9a-f]{32}\\.(pdf|doc|docx|xls|xlsx|zip|rar)$',
|
||||
regex:
|
||||
'^/assets/files/[^/]+-[0-9a-f]{32}\\.(pdf|doc|docx|xls|xlsx|zip|rar)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '^/ideal-img/[^/]+\\.[0-9a-f]{7}\\.\\d+\\.(png|jpe?g|gif)$',
|
||||
regex: '^/ideal-img/[^/]+\\.[0-9a-f]{7}\\.\\d+\\.(png|jpe?g|gif)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
],
|
||||
defaultRedirects: [
|
||||
{
|
||||
source: '.*',
|
||||
regex: '.*',
|
||||
statusCode: 404,
|
||||
destination: '404.html',
|
||||
},
|
||||
],
|
||||
defaultRoutes: [
|
||||
{
|
||||
src: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js)$',
|
||||
@@ -384,6 +450,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `docusaurus-build`',
|
||||
value: 'docusaurus-build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'docusaurus-start --port $PORT',
|
||||
@@ -394,8 +461,21 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'docusaurus',
|
||||
devCommand: 'docusaurus-start --port $PORT',
|
||||
buildCommand: 'docusaurus-build',
|
||||
getFsOutputDir: async (dirPrefix: string) => {
|
||||
const base = 'build';
|
||||
try {
|
||||
const location = join(dirPrefix, base);
|
||||
const content = await readdir(location, { withFileTypes: true });
|
||||
|
||||
// If there is only one file in it that is a dir we'll use it as dist dir
|
||||
if (content.length === 1 && content[0].isDirectory()) {
|
||||
return join(base, content[0].name);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error detecting output directory: `, error);
|
||||
}
|
||||
return base;
|
||||
},
|
||||
getOutputDirName: async (dirPrefix: string) => {
|
||||
const base = 'build';
|
||||
try {
|
||||
@@ -436,6 +516,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `preact build`',
|
||||
value: 'preact build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'preact watch --port $PORT',
|
||||
@@ -446,8 +527,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'preact-cli',
|
||||
devCommand: 'preact watch --port $PORT',
|
||||
buildCommand: 'preact build',
|
||||
getFsOutputDir: async () => 'build',
|
||||
getOutputDirName: async () => 'build',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -458,6 +538,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Dojo',
|
||||
@@ -486,6 +573,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `dojo build`',
|
||||
value: 'dojo build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'dojo build -m dev -w -s -p $PORT',
|
||||
@@ -496,8 +584,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@dojo/cli',
|
||||
devCommand: 'dojo build -m dev -w -s -p $PORT',
|
||||
buildCommand: 'dojo build',
|
||||
getFsOutputDir: async () => 'output/dist',
|
||||
getOutputDirName: async () => join('output', 'dist'),
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -513,6 +600,21 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaulHeaders: [
|
||||
{
|
||||
source: '/service-worker.js',
|
||||
regex: '/service-worker.js',
|
||||
headers: { 'cache-control': 's-maxage=0' },
|
||||
continue: true,
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Ember.js',
|
||||
@@ -538,6 +640,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `ember build`',
|
||||
value: 'ember build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'ember serve --port $PORT',
|
||||
@@ -548,8 +651,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'ember-cli',
|
||||
devCommand: 'ember serve --port $PORT',
|
||||
buildCommand: 'ember build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -560,6 +662,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Vue.js',
|
||||
@@ -586,6 +695,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `vue-cli-service build`',
|
||||
value: 'vue-cli-service build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'vue-cli-service serve --port $PORT',
|
||||
@@ -596,8 +706,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@vue/cli-service',
|
||||
devCommand: 'vue-cli-service serve --port $PORT',
|
||||
buildCommand: 'vue-cli-service build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -618,6 +727,27 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '^/[^/]*\\.(js|txt|ico|json)',
|
||||
regex: '^/[^/]*\\.(js|txt|ico|json)',
|
||||
headers: [{ key: 'cache-control', value: 'max-age=300' }],
|
||||
},
|
||||
{
|
||||
source: '^/(img|js|css|fonts|media)/[^/]+\\.[0-9a-f]{8}\\.*',
|
||||
regex: '^/(img|js|css|fonts|media)/[^/]+\\.[0-9a-f]{8}\\.*',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '^.*',
|
||||
regex: '^.*',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Scully',
|
||||
@@ -642,6 +772,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `ng build && scully`',
|
||||
value: 'ng build && scully',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'ng serve --port $PORT',
|
||||
@@ -652,8 +783,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@scullyio/init',
|
||||
devCommand: 'ng serve --port $PORT',
|
||||
buildCommand: 'ng build && scully',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist/static',
|
||||
},
|
||||
{
|
||||
@@ -680,6 +810,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `ng build`',
|
||||
value: 'ng build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'ng serve --port $PORT',
|
||||
@@ -689,8 +820,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@ionic/angular',
|
||||
devCommand: 'ng serve --port $PORT',
|
||||
buildCommand: 'ng build',
|
||||
getFsOutputDir: async () => 'www',
|
||||
getOutputDirName: async () => 'www',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -701,6 +831,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Angular',
|
||||
@@ -726,6 +863,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `ng build`',
|
||||
value: 'ng build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'ng serve --port $PORT',
|
||||
@@ -736,8 +874,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@angular/cli',
|
||||
devCommand: 'ng serve --port $PORT',
|
||||
buildCommand: 'ng build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async (dirPrefix: string) => {
|
||||
const base = 'dist';
|
||||
try {
|
||||
@@ -762,6 +899,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Polymer',
|
||||
@@ -787,6 +931,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `polymer build`',
|
||||
value: 'polymer build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'polymer serve --port $PORT',
|
||||
@@ -797,8 +942,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'polymer-cli',
|
||||
devCommand: 'polymer serve --port $PORT',
|
||||
buildCommand: 'polymer build',
|
||||
getFsOutputDir: async () => 'build',
|
||||
getOutputDirName: async (dirPrefix: string) => {
|
||||
const base = 'build';
|
||||
try {
|
||||
@@ -820,6 +964,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Svelte',
|
||||
@@ -850,6 +1001,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `rollup -c`',
|
||||
value: 'rollup -c',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'rollup -c -w',
|
||||
@@ -859,8 +1011,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'sirv-cli',
|
||||
devCommand: 'rollup -c -w',
|
||||
buildCommand: 'rollup -c',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -871,6 +1022,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
destination: '/index.html',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'SvelteKit',
|
||||
@@ -896,6 +1054,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `svelte-kit build`',
|
||||
value: 'svelte-kit build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'svelte-kit dev --port $PORT',
|
||||
@@ -905,8 +1064,7 @@ export const frameworks = [
|
||||
placeholder: 'public',
|
||||
},
|
||||
},
|
||||
devCommand: 'svelte-kit dev --port $PORT',
|
||||
buildCommand: 'svelte-kit build',
|
||||
getFsOutputDir: async () => '.output',
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
{
|
||||
@@ -933,6 +1091,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `react-scripts build`',
|
||||
value: 'react-scripts build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'react-scripts start',
|
||||
@@ -942,8 +1101,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@ionic/react',
|
||||
devCommand: 'react-scripts start',
|
||||
buildCommand: 'react-scripts build',
|
||||
getFsOutputDir: async () => 'build',
|
||||
getOutputDirName: async () => 'build',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -970,6 +1128,45 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '/static/(.*)',
|
||||
regex: '/static/(.*)',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 's-maxage=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/service-worker.js',
|
||||
regex: '/service-worker.js',
|
||||
headers: [{ key: 'cache-control', value: 's-maxage=0' }],
|
||||
},
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
headers: [{ key: 'cache-control', value: 's-maxage=0' }],
|
||||
},
|
||||
],
|
||||
defaultRedirects: [
|
||||
{
|
||||
source: '/static/(.*)',
|
||||
destination: '/404.html',
|
||||
statusCode: 404,
|
||||
regex: '/static/(.*)',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/sockjs-node/(.*)',
|
||||
destination: '/sockjs-node/$1',
|
||||
regex: '/sockjs-node/(.*)',
|
||||
},
|
||||
{
|
||||
source: '/(.*)',
|
||||
destination: '/index.html',
|
||||
regex: '/(.*)',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Create React App',
|
||||
@@ -1001,6 +1198,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `react-scripts build`',
|
||||
value: 'react-scripts build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'react-scripts start',
|
||||
@@ -1010,8 +1208,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'react-scripts',
|
||||
devCommand: 'react-scripts start',
|
||||
buildCommand: 'react-scripts build',
|
||||
getFsOutputDir: async () => 'build',
|
||||
getOutputDirName: async () => 'build',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -1038,6 +1235,45 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '/static/(.*)',
|
||||
regex: '/static/(.*)',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 's-maxage=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/service-worker.js',
|
||||
regex: '/service-worker.js',
|
||||
headers: [{ key: 'cache-control', value: 's-maxage=0' }],
|
||||
},
|
||||
{
|
||||
source: '/(.*)',
|
||||
regex: '/(.*)',
|
||||
headers: [{ key: 'cache-control', value: 's-maxage=0' }],
|
||||
},
|
||||
],
|
||||
defaultRedirects: [
|
||||
{
|
||||
source: '/static/(.*)',
|
||||
destination: '/404.html',
|
||||
statusCode: 404,
|
||||
regex: '/static/(.*)',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/sockjs-node/(.*)',
|
||||
destination: '/sockjs-node/$1',
|
||||
regex: '/sockjs-node/(.*)',
|
||||
},
|
||||
{
|
||||
source: '/(.*)',
|
||||
destination: '/index.html',
|
||||
regex: '/(.*)',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Gridsome',
|
||||
@@ -1063,6 +1299,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `gridsome build`',
|
||||
value: 'gridsome build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'gridsome develop -p $PORT',
|
||||
@@ -1073,8 +1310,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'gridsome',
|
||||
devCommand: 'gridsome develop -p $PORT',
|
||||
buildCommand: 'gridsome build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
},
|
||||
{
|
||||
@@ -1101,6 +1337,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `umi build`',
|
||||
value: 'umi build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'umi dev --port $PORT',
|
||||
@@ -1111,8 +1348,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'umi',
|
||||
devCommand: 'umi dev --port $PORT',
|
||||
buildCommand: 'umi build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -1123,6 +1359,13 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
destination: '/index.html',
|
||||
regex: '/(.*)',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Sapper',
|
||||
@@ -1148,6 +1391,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `sapper export`',
|
||||
value: 'sapper export',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'sapper dev --port $PORT',
|
||||
@@ -1158,8 +1402,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'sapper',
|
||||
devCommand: 'sapper dev --port $PORT',
|
||||
buildCommand: 'sapper export',
|
||||
getFsOutputDir: async () => '__sapper__/export',
|
||||
getOutputDirName: async () => '__sapper__/export',
|
||||
},
|
||||
{
|
||||
@@ -1186,6 +1429,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `saber build`',
|
||||
value: 'saber build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'saber --port $PORT',
|
||||
@@ -1196,8 +1440,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'saber',
|
||||
devCommand: 'saber --port $PORT',
|
||||
buildCommand: 'saber build',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -1213,6 +1456,23 @@ export const frameworks = [
|
||||
dest: '404.html',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '/_saber/.*',
|
||||
regex: '/_saber/.*',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
],
|
||||
defaultRedirects: [
|
||||
{
|
||||
source: '.*',
|
||||
statusCode: 404,
|
||||
destination: '404.html',
|
||||
regex: '.*',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Stencil',
|
||||
@@ -1238,6 +1498,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `stencil build`',
|
||||
value: 'stencil build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'stencil build --dev --watch --serve --port $PORT',
|
||||
@@ -1248,8 +1509,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: '@stencil/core',
|
||||
devCommand: 'stencil build --dev --watch --serve --port $PORT',
|
||||
buildCommand: 'stencil build',
|
||||
getFsOutputDir: async () => 'www',
|
||||
getOutputDirName: async () => 'www',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -1275,6 +1535,32 @@ export const frameworks = [
|
||||
dest: '/index.html',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '/assets/(.*)',
|
||||
regex: '/assets/(.*)',
|
||||
headers: [{ key: 'cache-control', value: 'max-age=2592000' }],
|
||||
},
|
||||
{
|
||||
source: '/build/p-.*',
|
||||
regex: '/build/p-.*',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 'max-age=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
{
|
||||
source: '/sw.js',
|
||||
regex: '/sw.js',
|
||||
headers: [{ key: 'cache-control', value: 'no-cache' }],
|
||||
},
|
||||
],
|
||||
defaultRewrites: [
|
||||
{
|
||||
source: '/(.*)',
|
||||
destination: '/index.html',
|
||||
regex: '/(.*)',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Nuxt.js',
|
||||
@@ -1301,6 +1587,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `nuxt generate`',
|
||||
value: 'nuxt generate',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'nuxt',
|
||||
@@ -1310,8 +1597,7 @@ export const frameworks = [
|
||||
},
|
||||
},
|
||||
dependency: 'nuxt',
|
||||
devCommand: 'nuxt',
|
||||
buildCommand: 'nuxt generate',
|
||||
getFsOutputDir: async () => '.output',
|
||||
getOutputDirName: async () => 'dist',
|
||||
cachePattern: '.nuxt/**',
|
||||
defaultRoutes: [
|
||||
@@ -1369,8 +1655,7 @@ export const frameworks = [
|
||||
placeholder: 'RedwoodJS default',
|
||||
},
|
||||
},
|
||||
devCommand: 'yarn rw dev --fwd="--port=$PORT --open=false',
|
||||
buildCommand: 'yarn rw deploy vercel',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
{
|
||||
@@ -1405,6 +1690,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `hugo -D --gc`',
|
||||
value: 'hugo -D --gc',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'hugo server -D -w -p $PORT',
|
||||
@@ -1414,8 +1700,16 @@ export const frameworks = [
|
||||
placeholder: '`public` or `publishDir` from the `config` file',
|
||||
},
|
||||
},
|
||||
devCommand: 'hugo server -D -w -p $PORT',
|
||||
buildCommand: 'hugo -D --gc',
|
||||
getFsOutputDir: async (dirPrefix: string): Promise<string> => {
|
||||
type HugoConfig = { publishDir?: string };
|
||||
const config = await readConfigFile<HugoConfig>(
|
||||
['config.json', 'config.yaml', 'config.toml'].map(fileName => {
|
||||
return join(dirPrefix, fileName);
|
||||
})
|
||||
);
|
||||
|
||||
return (config && config.publishDir) || 'public';
|
||||
},
|
||||
getOutputDirName: async (dirPrefix: string): Promise<string> => {
|
||||
type HugoConfig = { publishDir?: string };
|
||||
const config = await readConfigFile<HugoConfig>(
|
||||
@@ -1450,6 +1744,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `jekyll build`',
|
||||
value: 'jekyll build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'bundle exec jekyll serve --watch --port $PORT',
|
||||
@@ -1459,8 +1754,13 @@ export const frameworks = [
|
||||
placeholder: '`_site` or `destination` from `_config.yml`',
|
||||
},
|
||||
},
|
||||
devCommand: 'bundle exec jekyll serve --watch --port $PORT',
|
||||
buildCommand: 'jekyll build',
|
||||
getFsOutputDir: async (dirPrefix: string): Promise<string> => {
|
||||
type JekyllConfig = { destination?: string };
|
||||
const config = await readConfigFile<JekyllConfig>(
|
||||
join(dirPrefix, '_config.yml')
|
||||
);
|
||||
return (config && config.destination) || '_site';
|
||||
},
|
||||
getOutputDirName: async (dirPrefix: string): Promise<string> => {
|
||||
type JekyllConfig = { destination?: string };
|
||||
const config = await readConfigFile<JekyllConfig>(
|
||||
@@ -1492,6 +1792,7 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `brunch build --production`',
|
||||
value: 'brunch build --production',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'brunch watch --server --port $PORT',
|
||||
@@ -1501,8 +1802,7 @@ export const frameworks = [
|
||||
value: 'public',
|
||||
},
|
||||
},
|
||||
devCommand: 'brunch watch --server --port $PORT',
|
||||
buildCommand: 'brunch build --production',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
{
|
||||
@@ -1526,18 +1826,18 @@ export const frameworks = [
|
||||
value: 'bundle install',
|
||||
},
|
||||
buildCommand: {
|
||||
value: '`npm run build` or `bundle exec middleman build`',
|
||||
placeholder: '`npm run build` or `bundle exec middleman build`',
|
||||
value: 'bundle exec middleman build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'bundle exec middleman server -p $PORT',
|
||||
placeholder: 'bundle exec middleman server',
|
||||
value: 'bundle exec middleman server -p $PORT',
|
||||
},
|
||||
outputDirectory: {
|
||||
value: 'build',
|
||||
},
|
||||
},
|
||||
devCommand: 'bundle exec middleman server -p $PORT',
|
||||
buildCommand: 'bundle exec middleman build',
|
||||
getFsOutputDir: async () => 'build',
|
||||
getOutputDirName: async () => 'build',
|
||||
cachePattern: '{vendor/bin,vendor/cache,vendor/bundle}/**',
|
||||
},
|
||||
@@ -1565,15 +1865,14 @@ export const frameworks = [
|
||||
value: 'zola build',
|
||||
},
|
||||
devCommand: {
|
||||
value: 'zola serve --port $PORT',
|
||||
placeholder: 'zola serve',
|
||||
value: 'zola serve --port $PORT',
|
||||
},
|
||||
outputDirectory: {
|
||||
value: 'public',
|
||||
},
|
||||
},
|
||||
devCommand: 'zola serve --port $PORT',
|
||||
buildCommand: 'zola build',
|
||||
getFsOutputDir: async () => 'public',
|
||||
getOutputDirName: async () => 'public',
|
||||
defaultVersion: '0.13.0',
|
||||
},
|
||||
@@ -1602,17 +1901,18 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `vite build`',
|
||||
value: 'vite build',
|
||||
},
|
||||
devCommand: {
|
||||
placeholder: 'vite',
|
||||
value: 'vite',
|
||||
},
|
||||
outputDirectory: {
|
||||
value: 'dist',
|
||||
},
|
||||
},
|
||||
dependency: 'vite',
|
||||
devCommand: 'vite',
|
||||
buildCommand: 'vite build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
},
|
||||
{
|
||||
@@ -1639,17 +1939,18 @@ export const frameworks = [
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run build` or `parcel build`',
|
||||
value: 'parcel build',
|
||||
},
|
||||
devCommand: {
|
||||
placeholder: 'parcel',
|
||||
value: 'parcel',
|
||||
},
|
||||
outputDirectory: {
|
||||
placeholder: 'dist',
|
||||
value: 'dist',
|
||||
},
|
||||
},
|
||||
dependency: 'parcel',
|
||||
devCommand: 'parcel',
|
||||
buildCommand: 'parcel build',
|
||||
getFsOutputDir: async () => 'dist',
|
||||
getOutputDirName: async () => 'dist',
|
||||
defaultRoutes: [
|
||||
{
|
||||
@@ -1661,28 +1962,53 @@ export const frameworks = [
|
||||
handle: 'filesystem',
|
||||
},
|
||||
],
|
||||
defaultHeaders: [
|
||||
{
|
||||
source: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js|png|jpg|webp|avif|svg)$',
|
||||
regex: '^/[^./]+\\.[0-9a-f]{8}\\.(css|js|png|jpg|webp|avif|svg)$',
|
||||
headers: [
|
||||
{ key: 'cache-control', value: 's-maxage=31536000, immutable' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Other',
|
||||
slug: null,
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/other.svg',
|
||||
description: 'No framework or a unoptimized framework.',
|
||||
description: 'No framework or an unoptimized framework.',
|
||||
settings: {
|
||||
installCommand: {
|
||||
placeholder: '`yarn install` or `npm install`',
|
||||
},
|
||||
buildCommand: {
|
||||
placeholder: '`npm run vercel-build` or `npm run build`',
|
||||
value: null,
|
||||
},
|
||||
devCommand: {
|
||||
placeholder: 'None',
|
||||
value: null,
|
||||
},
|
||||
outputDirectory: {
|
||||
placeholder: '`public` if it exists, or `.`',
|
||||
},
|
||||
},
|
||||
devCommand: null,
|
||||
buildCommand: null,
|
||||
getFsOutputDir: async (dirPrefix: string): Promise<string> => {
|
||||
// Public if it exists or `.`
|
||||
let base = 'public';
|
||||
try {
|
||||
const location = join(dirPrefix, base);
|
||||
const content = await readdir(location, { withFileTypes: true });
|
||||
|
||||
// If there is only one file in it that is a dir we'll use it as dist dir
|
||||
if (content.length === 1 && content[0].isDirectory()) {
|
||||
return join(base, content[0].name);
|
||||
}
|
||||
} catch (_error) {
|
||||
base = '.';
|
||||
}
|
||||
return base;
|
||||
},
|
||||
getOutputDirName: async () => 'public',
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Route } from '@vercel/routing-utils';
|
||||
import { Header, Rewrite, Route } from '@vercel/routing-utils';
|
||||
|
||||
export interface FrameworkDetectionItem {
|
||||
/**
|
||||
@@ -26,12 +26,21 @@ export interface SettingValue {
|
||||
* A predefined setting for the detected framework
|
||||
* @example "next dev --port $PORT"
|
||||
*/
|
||||
value: string;
|
||||
value: string | null;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export type Setting = SettingValue | SettingPlaceholder;
|
||||
|
||||
export type Redirect = Rewrite & {
|
||||
statusCode?: number;
|
||||
permanent?: boolean;
|
||||
};
|
||||
|
||||
type RoutesManifestRegex = {
|
||||
regex: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Framework detection information.
|
||||
*/
|
||||
@@ -120,11 +129,11 @@ export interface Framework {
|
||||
/**
|
||||
* Default Build Command or a placeholder
|
||||
*/
|
||||
buildCommand: Setting;
|
||||
buildCommand: SettingValue;
|
||||
/**
|
||||
* Default Development Command or a placeholder
|
||||
*/
|
||||
devCommand: Setting;
|
||||
devCommand: SettingValue;
|
||||
/**
|
||||
* Default Output Directory
|
||||
*/
|
||||
@@ -148,12 +157,18 @@ export interface Framework {
|
||||
/**
|
||||
* Name of a dependency in `package.json` to detect this framework.
|
||||
* @example "hexo"
|
||||
* @deprecated use `detectors` instead (new frameworks should not use this prop)
|
||||
*/
|
||||
dependency?: string;
|
||||
/**
|
||||
* Function that returns the name of the directory that the framework outputs
|
||||
* its build results to. In some cases this is read from a configuration file.
|
||||
*/
|
||||
getFsOutputDir: (dirPrefix: string) => Promise<string>;
|
||||
/**
|
||||
* Function that returns the name of the directory that the framework outputs
|
||||
* its STATIC build results to. In some cases this is read from a configuration file.
|
||||
*/
|
||||
getOutputDirName: (dirPrefix: string) => Promise<string>;
|
||||
/**
|
||||
* An array (or a function that returns an array) of default `Route` rules that
|
||||
@@ -161,21 +176,32 @@ export interface Framework {
|
||||
* @example [{ handle: 'filesystem' }, { src: '.*', status: 404, dest: '404.html' }]
|
||||
*/
|
||||
defaultRoutes?: Route[] | ((dirPrefix: string) => Promise<Route[]>);
|
||||
/**
|
||||
* An array (or a function that returns an array) of default `Header` rules that
|
||||
* the framework uses.
|
||||
*/
|
||||
defaultHeaders?:
|
||||
| (Header & RoutesManifestRegex)[]
|
||||
| ((dirPrefix: string) => Promise<(Header & RoutesManifestRegex)[]>);
|
||||
/**
|
||||
* An array (or a function that returns an array) of default `Redirect` rules that
|
||||
* the framework uses.
|
||||
*/
|
||||
defaultRedirects?:
|
||||
| (Redirect & RoutesManifestRegex)[]
|
||||
| ((dirPrefix: string) => Promise<(Redirect & RoutesManifestRegex)[]>);
|
||||
/**
|
||||
* An array (or a function that returns an array) of default `Rewrite` rules that
|
||||
* the framework uses.
|
||||
*/
|
||||
defaultRewrites?:
|
||||
| (Rewrite & RoutesManifestRegex)[]
|
||||
| ((dirPrefix: string) => Promise<(Rewrite & RoutesManifestRegex)[]>);
|
||||
/**
|
||||
* A glob string of files to cache for future deployments.
|
||||
* @example ".cache/**"
|
||||
*/
|
||||
cachePattern?: string;
|
||||
/**
|
||||
* The default build command for the framework.
|
||||
* @example "next build"
|
||||
*/
|
||||
buildCommand: string | null;
|
||||
/**
|
||||
* The default development command for the framework.
|
||||
* @example "next dev"
|
||||
*/
|
||||
devCommand: string | null;
|
||||
/**
|
||||
* The default version of the framework command that is available within the
|
||||
* build image. Usually an environment variable can be set to override this.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user