Compare commits
205 Commits
vercel@20.
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b60467d2f | ||
|
|
4384a6104f | ||
|
|
f40f95ff37 | ||
|
|
90c05250b0 | ||
|
|
030880fe74 | ||
|
|
02bc88f33b | ||
|
|
38ff557cad | ||
|
|
47c34842d5 | ||
|
|
d21b215ad0 | ||
|
|
5827737fd5 | ||
|
|
a9e078d410 | ||
|
|
b4d9b17fb8 | ||
|
|
02c55bf634 | ||
|
|
08af15055f | ||
|
|
0597aaa5e4 | ||
|
|
176856a1ea | ||
|
|
375a55ebed | ||
|
|
7d33a05581 | ||
|
|
0377c8b737 | ||
|
|
662d546388 | ||
|
|
8c514b5608 | ||
|
|
a6ec53d9d3 | ||
|
|
3ad5903f70 | ||
|
|
3cf155e999 | ||
|
|
d9a298d97c | ||
|
|
487d3c8554 | ||
|
|
9d0bfd3656 | ||
|
|
ec75333569 | ||
|
|
51aab912a2 | ||
|
|
670b2653c0 | ||
|
|
f71686fdad | ||
|
|
ec9c8ce150 | ||
|
|
a2048fc6d3 | ||
|
|
09ff9cda9f | ||
|
|
3a4d6f7848 | ||
|
|
9a0d676c0d | ||
|
|
25cd7b9e6e | ||
|
|
f926d5516c | ||
|
|
4603383850 | ||
|
|
c0c57889c8 | ||
|
|
85908a0524 | ||
|
|
503b9a2429 | ||
|
|
eac8f32ae7 | ||
|
|
3f76fefde6 | ||
|
|
79ddc5746b | ||
|
|
9a14615b43 | ||
|
|
6d6ccbdc25 | ||
|
|
704424ec58 | ||
|
|
c471127c69 | ||
|
|
c02dc9ac49 | ||
|
|
dd10e8cc77 | ||
|
|
cf69c2398c | ||
|
|
e48707571f | ||
|
|
6051fe6f0c | ||
|
|
2b3ba8a14f | ||
|
|
25bea3f83e | ||
|
|
b3e1828ebe | ||
|
|
e0e2a8e87e | ||
|
|
37ec89796d | ||
|
|
d3e2a4c4db | ||
|
|
ece3645914 | ||
|
|
fee386493b | ||
|
|
d95ed184ab | ||
|
|
aef8e6388e | ||
|
|
ba43e88603 | ||
|
|
e61f9740c4 | ||
|
|
c4b010fe8b | ||
|
|
db18eb091f | ||
|
|
360e62d172 | ||
|
|
8c3cd0332d | ||
|
|
f5f276021e | ||
|
|
9fbec823f3 | ||
|
|
18c3dd3a63 | ||
|
|
5a4a20b33f | ||
|
|
4489ed0c85 | ||
|
|
359f23daf1 | ||
|
|
4ef92e85db | ||
|
|
659c4d6ccd | ||
|
|
e93d477df8 | ||
|
|
f64625655b | ||
|
|
25a8189997 | ||
|
|
25c3e627cf | ||
|
|
1d6d8b530f | ||
|
|
e821cc0ae7 | ||
|
|
8ecbdc5d03 | ||
|
|
895224985b | ||
|
|
0f42a63c03 | ||
|
|
81e4c9e6fe | ||
|
|
a0a29dc836 | ||
|
|
c1f9d51d7a | ||
|
|
422f0558c1 | ||
|
|
f064ae2908 | ||
|
|
58c3e636f0 | ||
|
|
d5081367f3 | ||
|
|
0ee88366ff | ||
|
|
9ae42c9e92 | ||
|
|
62b8df4a8d | ||
|
|
73ec7f3018 | ||
|
|
2d24a75ca6 | ||
|
|
3f92c42ad6 | ||
|
|
d824f79d5a | ||
|
|
eefbf3a52d | ||
|
|
dda793018b | ||
|
|
9e588068ea | ||
|
|
76a7a51bdc | ||
|
|
5f5b5b0340 | ||
|
|
a0ce373dc9 | ||
|
|
049ffb268b | ||
|
|
94483c8b36 | ||
|
|
078f9de44e | ||
|
|
0ae41f97a4 | ||
|
|
9fb6a1ec4c | ||
|
|
21be46c8bb | ||
|
|
91942fc4d2 | ||
|
|
8e02f2289f | ||
|
|
4205d643a1 | ||
|
|
b2dda4dbb9 | ||
|
|
f36eac3d0a | ||
|
|
a2c56425f4 | ||
|
|
c759bfda9c | ||
|
|
57995001ac | ||
|
|
e5553d8ec2 | ||
|
|
dcee5b16c7 | ||
|
|
b190f2e118 | ||
|
|
2389d3e936 | ||
|
|
0f4ed1965a | ||
|
|
e1e38ee536 | ||
|
|
dc1ff00610 | ||
|
|
5f31736603 | ||
|
|
9a57cc72dd | ||
|
|
9d9c5f3753 | ||
|
|
deeefc0c93 | ||
|
|
5c23b08bc1 | ||
|
|
7c4e25ccce | ||
|
|
1bfa310945 | ||
|
|
c96062266b | ||
|
|
5bea99c1d9 | ||
|
|
358be773a2 | ||
|
|
9ebf4e531d | ||
|
|
71e79258b7 | ||
|
|
1dfafe7040 | ||
|
|
78ed452a99 | ||
|
|
d408e2ef1a | ||
|
|
8ebb1fd9ce | ||
|
|
4eb5ad625c | ||
|
|
7164f6e58e | ||
|
|
a36d084b3e | ||
|
|
8a16447fed | ||
|
|
efda4ab6b9 | ||
|
|
16060a71a9 | ||
|
|
b18e0a7415 | ||
|
|
1251f11a97 | ||
|
|
07235e22f6 | ||
|
|
81011df816 | ||
|
|
c8d31bdcf7 | ||
|
|
5e7f1158ad | ||
|
|
df5aa1f10d | ||
|
|
eb1ba97309 | ||
|
|
8047d6de49 | ||
|
|
7470ff3724 | ||
|
|
8340d9327c | ||
|
|
d278425810 | ||
|
|
8b26bbe643 | ||
|
|
fa8e1e73c8 | ||
|
|
f8abcbcd9f | ||
|
|
e18ff683b2 | ||
|
|
f28293a5a8 | ||
|
|
a4963a89c7 | ||
|
|
21df39fe8c | ||
|
|
5ad9d61451 | ||
|
|
8b5a2aa44f | ||
|
|
d0da1ce195 | ||
|
|
fd5d3b2921 | ||
|
|
d22bdeb8d0 | ||
|
|
c120fd82f9 | ||
|
|
2474a80ff1 | ||
|
|
cc1cdbe610 | ||
|
|
0b92f8ceee | ||
|
|
be82a88d1a | ||
|
|
64da08f0f2 | ||
|
|
2e957fce55 | ||
|
|
c7ead151f5 | ||
|
|
e2baf9b00f | ||
|
|
ba8ef7bc98 | ||
|
|
c5d04e0d4f | ||
|
|
b4f849418d | ||
|
|
b37c4f211e | ||
|
|
f06efe167c | ||
|
|
296d8da676 | ||
|
|
981e4183c6 | ||
|
|
1706a00cb9 | ||
|
|
d7bd03cf1d | ||
|
|
e27ff8d2e0 | ||
|
|
bc6da39cc2 | ||
|
|
727109c64a | ||
|
|
817410a8e2 | ||
|
|
e022e7b79c | ||
|
|
dda6c24a3d | ||
|
|
7c922a4092 | ||
|
|
376dec8f33 | ||
|
|
16e101d262 | ||
|
|
41ce1a4291 | ||
|
|
449f35cf33 | ||
|
|
d683402bba | ||
|
|
2051a1cd9b |
@@ -34,6 +34,7 @@ packages/now-node-bridge/bridge.*
|
|||||||
|
|
||||||
# now-static-build
|
# now-static-build
|
||||||
packages/now-static-build/test/fixtures
|
packages/now-static-build/test/fixtures
|
||||||
|
packages/now-static-build/test/build-fixtures
|
||||||
|
|
||||||
# redwood
|
# redwood
|
||||||
packages/redwood/test/fixtures
|
packages/redwood/test/fixtures
|
||||||
|
|||||||
13
.github/CONTRIBUTING.md
vendored
@@ -73,8 +73,8 @@ The logs of this deployment will contain the actual error which may help you to
|
|||||||
Some of the Builders use `@vercel/nft` to tree-shake files before deployment. If you suspect an error with this tree-shaking mechanism, you can create the following script in your project:
|
Some of the Builders use `@vercel/nft` to tree-shake files before deployment. If you suspect an error with this tree-shaking mechanism, you can create the following script in your project:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const trace = require('@vercel/nft');
|
const { nodeFileTrace } = require('@vercel/nft');
|
||||||
trace(['path/to/entrypoint.js'], {
|
nodeFileTrace(['path/to/entrypoint.js'], {
|
||||||
ts: true,
|
ts: true,
|
||||||
mixedModules: true,
|
mixedModules: true,
|
||||||
})
|
})
|
||||||
@@ -94,12 +94,3 @@ Sometimes you want to test changes to a Builder against an existing project, may
|
|||||||
4. Run `vercel *.tgz` to upload the tarball file and get a URL
|
4. Run `vercel *.tgz` to upload the tarball file and get a URL
|
||||||
5. Edit any existing `vercel.json` project and replace `use` with the URL
|
5. Edit any existing `vercel.json` project and replace `use` with the URL
|
||||||
6. Run `vercel` or `vercel dev` to deploy with the experimental Builder
|
6. Run `vercel` or `vercel dev` to deploy with the experimental Builder
|
||||||
|
|
||||||
## Add a New Framework
|
|
||||||
|
|
||||||
You can add support for a new Framework by creating a Pull Request for this repository and following the steps below:
|
|
||||||
|
|
||||||
1. Add the Framework to the `@vercel/frameworks` package: The file is located in `./packages/frameworks/frameworks.json`. You can copy the structure of an existing one and adjust the required fields. Note that the `settings` property either contains a `value` or a `placeholder`. The `value` property is used when something is not configurable, the `placeholder` is used when something is configurable and can be changed with configuration. An example would be the Output Directory for Hugo, it's `public` by default but can be changed through its config file, so we use `placeholder` with an explanation of what can be used.
|
|
||||||
2. Add an example to the `./examples` directory: The name of the directory should equal the slug of the framework used in `@vercel/frameworks`. The `.github/EXAMPLE_README_TEMPLATE.md` file can be used to create a `README.md` file for the example.
|
|
||||||
3. Update the `@vercel/static-build` package: The file `./packages/now-static-build/src/frameworks.ts` has to be extended. You can add default routes that will always be applied to projects that use this Framework or specify some paths that will be cached to speed up the build process.
|
|
||||||
4. After your Pull Request has been merged and released, other users can select the example on the Vercel dashboard and deploy it.
|
|
||||||
|
|||||||
20
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
### Related Issues
|
||||||
|
|
||||||
|
> Fixes #1
|
||||||
|
> Related to #2
|
||||||
|
|
||||||
|
### 📋 Checklist
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please keep your PR as a Draft until the checklist is complete
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Tests
|
||||||
|
|
||||||
|
- [ ] The code changed/added as part of this PR has been covered with tests
|
||||||
|
- [ ] All tests pass locally with `yarn test-unit`
|
||||||
|
|
||||||
|
#### Code Review
|
||||||
|
|
||||||
|
- [ ] This PR has a concise title and thorough description useful to a reviewer
|
||||||
|
- [ ] Issue from task tracker has a link to this PR
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
version = 1
|
version = 1
|
||||||
|
|
||||||
[merge]
|
[merge]
|
||||||
automerge_label = "automerge"
|
automerge_label = ["semver-major","semver-minor","semver-patch"]
|
||||||
blacklist_title_regex = "^WIP.*"
|
blacklist_title_regex = "^WIP.*"
|
||||||
blacklist_labels = ["work in progress"]
|
blacklist_labels = ["work in progress"]
|
||||||
method = "squash"
|
method = "squash"
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ You're running Vercel CLI in a non-terminal context and there are no credentials
|
|||||||
|
|
||||||
#### Possible Ways to Fix It
|
#### Possible Ways to Fix It
|
||||||
|
|
||||||
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can either get the token from the `./vercel/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
|
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can create a new token on your [Settings page](https://vercel.com/account/tokens).
|
||||||
- Ensure that both `~/vercel/auth.json` and `~/vercel/config.json` exist
|
- Run `vercel login` to sign in and generate a new token
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { NowRequest, NowResponse } from '@now/node';
|
import { NowRequest, NowResponse } from '@vercel/node';
|
||||||
|
|
||||||
export default (_req: NowRequest, res: NowResponse) => {
|
export default (_req: NowRequest, res: NowResponse) => {
|
||||||
const date = new Date().toString();
|
const date = new Date().toString();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"react-helmet": "^5.2.0"
|
"react-helmet": "^5.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@now/node": "^1.3.0"
|
"@vercel/node": "1.8.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "gatsby develop",
|
"dev": "gatsby develop",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function Index() {
|
|||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/vercel/vercel/blob/master/gatsby"
|
href="https://github.com/vercel/vercel/tree/master/examples/gatsby"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1107,15 +1107,6 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.3"
|
"@nodelib/fs.scandir" "2.1.3"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
"@now/node@^1.3.0":
|
|
||||||
version "1.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@now/node/-/node-1.7.1.tgz#764a0c6bcb24967f8014c4f73ad238c292996fe3"
|
|
||||||
integrity sha512-+srVKopsVTPDR3u9eOjJryZroLTrPp8XEOuIDGBdfFcJuS7qpAomctSbfyA7WNyjC0ExtUxELqBg5sAedG5+2g==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
ts-node "8.9.1"
|
|
||||||
typescript "3.9.3"
|
|
||||||
|
|
||||||
"@pieh/friendly-errors-webpack-plugin@1.7.0-chalk-2":
|
"@pieh/friendly-errors-webpack-plugin@1.7.0-chalk-2":
|
||||||
version "1.7.0-chalk-2"
|
version "1.7.0-chalk-2"
|
||||||
resolved "https://registry.yarnpkg.com/@pieh/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0-chalk-2.tgz#2e9da9d3ade9d18d013333eb408c457d04eabac0"
|
resolved "https://registry.yarnpkg.com/@pieh/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0-chalk-2.tgz#2e9da9d3ade9d18d013333eb408c457d04eabac0"
|
||||||
@@ -1409,6 +1400,15 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
wonka "^4.0.14"
|
wonka "^4.0.14"
|
||||||
|
|
||||||
|
"@vercel/node@1.8.5":
|
||||||
|
version "1.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vercel/node/-/node-1.8.5.tgz#2c8b9532f1bb25734a9964c52973386ed78022d4"
|
||||||
|
integrity sha512-1iw7FSR8Oau6vZB1MWfBnA5q2a/IqRHiSZSbt8lz0dyTF599q8pc5GcSv/TvmrYaEGzh3+N0S4cbmuMCqVlwJg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
ts-node "8.9.1"
|
||||||
|
typescript "3.9.3"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.9.0":
|
"@webassemblyjs/ast@1.9.0":
|
||||||
version "1.9.0"
|
version "1.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
|
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
|
|||||||
|
|
||||||
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
|
||||||
|
|
||||||
|
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||||
|
|
||||||
## Learn More
|
## Learn More
|
||||||
|
|
||||||
To learn more about Next.js, take a look at the following resources:
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "9.5.1",
|
"next": "10.0.5",
|
||||||
"react": "16.13.1",
|
"react": "17.0.1",
|
||||||
"react-dom": "16.13.1"
|
"react-dom": "17.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
}
|
}
|
||||||
|
|||||||
7
examples/svelte/.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
|
/node_modules/
|
||||||
|
/public/build/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
|
||||||
public/bundle.*
|
|
||||||
.env
|
.env
|
||||||
|
.env.local
|
||||||
.env.build
|
.env.build
|
||||||
|
|
||||||
|
.vercel
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
yarn.lock
|
|
||||||
README.md
|
|
||||||
@@ -1,24 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "svelte-app",
|
"name": "svelte-app",
|
||||||
"version": "1.0.0",
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c",
|
||||||
|
"dev": "rollup -c -w",
|
||||||
|
"start": "sirv public"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^13.0.0",
|
"@rollup/plugin-commonjs": "^14.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^8.1.0",
|
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"rollup": "^2.3.4",
|
||||||
"rollup": "^2.18.0",
|
"rollup-plugin-livereload": "^2.0.0",
|
||||||
"rollup-plugin-livereload": "^1.0.0",
|
"rollup-plugin-svelte": "^6.0.0",
|
||||||
"rollup-plugin-svelte": "^5.0.3",
|
"rollup-plugin-terser": "^7.0.0",
|
||||||
"rollup-plugin-terser": "^6.1.0",
|
|
||||||
"svelte": "^3.0.0"
|
"svelte": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sirv-cli": "^1.0.1"
|
"sirv-cli": "^1.0.0"
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "rollup -c",
|
|
||||||
"autobuild": "rollup -c -w",
|
|
||||||
"dev": "run-p start:dev autobuild",
|
|
||||||
"start": "sirv public --single",
|
|
||||||
"start:dev": "sirv public --single --dev"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf8" />
|
<meta charset='utf-8'>
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
|
|
||||||
<title>Svelte + Node.js API</title>
|
<title>Svelte + Node.js API</title>
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||||
<link rel="stylesheet" href="/global.css" />
|
<link rel='stylesheet' href='/global.css'>
|
||||||
<link rel="stylesheet" href="/bundle.css" />
|
<link rel='stylesheet' href='/build/bundle.css'>
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<script defer src='/build/bundle.js'></script>
|
||||||
<script src="/bundle.js"></script>
|
</head>
|
||||||
</body>
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -6,42 +6,70 @@ import { terser } from 'rollup-plugin-terser';
|
|||||||
|
|
||||||
const production = !process.env.ROLLUP_WATCH;
|
const production = !process.env.ROLLUP_WATCH;
|
||||||
|
|
||||||
|
function serve() {
|
||||||
|
let server;
|
||||||
|
|
||||||
|
function toExit() {
|
||||||
|
if (server) server.kill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
writeBundle() {
|
||||||
|
if (server) return;
|
||||||
|
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||||
|
stdio: ['ignore', 'inherit', 'inherit'],
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGTERM', toExit);
|
||||||
|
process.on('exit', toExit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
input: 'src/main.js',
|
input: 'src/main.js',
|
||||||
output: {
|
output: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
name: 'app',
|
name: 'app',
|
||||||
file: 'public/bundle.js',
|
file: 'public/build/bundle.js'
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
svelte({
|
svelte({
|
||||||
// enable run-time checks when not in production
|
// enable run-time checks when not in production
|
||||||
dev: !production,
|
dev: !production,
|
||||||
// we'll extract any component CSS out into
|
// we'll extract any component CSS out into
|
||||||
// a separate file — better for performance
|
// a separate file - better for performance
|
||||||
css: css => {
|
css: css => {
|
||||||
css.write('public/bundle.css');
|
css.write('bundle.css');
|
||||||
},
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// If you have external dependencies installed from
|
// If you have external dependencies installed from
|
||||||
// npm, you'll most likely need these plugins. In
|
// npm, you'll most likely need these plugins. In
|
||||||
// some cases you'll need additional configuration —
|
// some cases you'll need additional configuration -
|
||||||
// consult the documentation for details:
|
// consult the documentation for details:
|
||||||
// https://github.com/rollup/rollup-plugin-commonjs
|
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||||
resolve({ browser: true }),
|
resolve({
|
||||||
commonjs(),
|
browser: true,
|
||||||
|
dedupe: ['svelte']
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
|
||||||
// Watch the `public` directory and refresh the
|
// In dev mode, call `npm run start` once
|
||||||
// browser on changes when not in production
|
// the bundle has been generated
|
||||||
!production && livereload('public'),
|
!production && serve(),
|
||||||
|
|
||||||
// If we're building for production (npm run build
|
// Watch the `public` directory and refresh the
|
||||||
// instead of npm run dev), minify
|
// browser on changes when not in production
|
||||||
production && terser(),
|
!production && livereload('public'),
|
||||||
],
|
|
||||||
watch: {
|
// If we're building for production (npm run build
|
||||||
clearScreen: false,
|
// instead of npm run dev), minify
|
||||||
},
|
production && terser()
|
||||||
|
],
|
||||||
|
watch: {
|
||||||
|
clearScreen: false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
128
examples/svelte/scripts/setupTypeScript.js
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/** This script modifies the project to support TS code in .svelte files like:
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export let name: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
As well as validating the code for CI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** To work on this script:
|
||||||
|
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require("fs")
|
||||||
|
const path = require("path")
|
||||||
|
const { argv } = require("process")
|
||||||
|
|
||||||
|
const projectRoot = argv[2] || path.join(__dirname, "..")
|
||||||
|
|
||||||
|
// Add deps to pkg.json
|
||||||
|
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
|
||||||
|
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
|
||||||
|
"svelte-check": "^1.0.0",
|
||||||
|
"svelte-preprocess": "^4.0.0",
|
||||||
|
"@rollup/plugin-typescript": "^6.0.0",
|
||||||
|
"typescript": "^3.9.3",
|
||||||
|
"tslib": "^2.0.0",
|
||||||
|
"@tsconfig/svelte": "^1.0.0"
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add script for checking
|
||||||
|
packageJSON.scripts = Object.assign(packageJSON.scripts, {
|
||||||
|
"validate": "svelte-check"
|
||||||
|
})
|
||||||
|
|
||||||
|
// Write the package JSON
|
||||||
|
fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " "))
|
||||||
|
|
||||||
|
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
|
||||||
|
const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
|
||||||
|
const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
|
||||||
|
fs.renameSync(beforeMainJSPath, afterMainTSPath)
|
||||||
|
|
||||||
|
// Switch the app.svelte file to use TS
|
||||||
|
const appSveltePath = path.join(projectRoot, "src", "App.svelte")
|
||||||
|
let appFile = fs.readFileSync(appSveltePath, "utf8")
|
||||||
|
appFile = appFile.replace("<script>", '<script lang="ts">')
|
||||||
|
appFile = appFile.replace("export let name;", 'export let name: string;')
|
||||||
|
fs.writeFileSync(appSveltePath, appFile)
|
||||||
|
|
||||||
|
// Edit rollup config
|
||||||
|
const rollupConfigPath = path.join(projectRoot, "rollup.config.js")
|
||||||
|
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8")
|
||||||
|
|
||||||
|
// Edit imports
|
||||||
|
rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
|
||||||
|
import sveltePreprocess from 'svelte-preprocess';
|
||||||
|
import typescript from '@rollup/plugin-typescript';`)
|
||||||
|
|
||||||
|
// Replace name of entry point
|
||||||
|
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
|
||||||
|
|
||||||
|
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
|
||||||
|
// Instead we look for `css:` then the next `}` and add the preprocessor to that
|
||||||
|
let foundCSS = false
|
||||||
|
let match
|
||||||
|
|
||||||
|
// https://regex101.com/r/OtNjwo/1
|
||||||
|
const configEditor = new RegExp(/css:.|\n*}/gmi)
|
||||||
|
while (( match = configEditor.exec(rollupConfig)) != null) {
|
||||||
|
if (foundCSS) {
|
||||||
|
const endOfCSSIndex = match.index + 1
|
||||||
|
rollupConfig = rollupConfig.slice(0, endOfCSSIndex) + ",\n preprocess: sveltePreprocess()," + rollupConfig.slice(endOfCSSIndex);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (match[0].includes("css:")) foundCSS = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add TypeScript
|
||||||
|
rollupConfig = rollupConfig.replace(
|
||||||
|
'commonjs(),',
|
||||||
|
'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),'
|
||||||
|
);
|
||||||
|
fs.writeFileSync(rollupConfigPath, rollupConfig)
|
||||||
|
|
||||||
|
// Add TSConfig
|
||||||
|
const tsconfig = `{
|
||||||
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
|
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
|
||||||
|
}`
|
||||||
|
const tsconfigPath = path.join(projectRoot, "tsconfig.json")
|
||||||
|
fs.writeFileSync(tsconfigPath, tsconfig)
|
||||||
|
|
||||||
|
// Delete this script, but not during testing
|
||||||
|
if (!argv[2]) {
|
||||||
|
// Remove the script
|
||||||
|
fs.unlinkSync(path.join(__filename))
|
||||||
|
|
||||||
|
// Check for Mac's DS_store file, and if it's the only one left remove it
|
||||||
|
const remainingFiles = fs.readdirSync(path.join(__dirname))
|
||||||
|
if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
|
||||||
|
fs.unlinkSync(path.join(__dirname, '.DS_store'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the scripts folder is empty
|
||||||
|
if (fs.readdirSync(path.join(__dirname)).length === 0) {
|
||||||
|
// Remove the scripts folder
|
||||||
|
fs.rmdirSync(path.join(__dirname))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the extension recommendation
|
||||||
|
fs.mkdirSync(path.join(projectRoot, ".vscode"))
|
||||||
|
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
|
||||||
|
"recommendations": ["svelte.svelte-vscode"]
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
console.log("Converted to TypeScript.")
|
||||||
|
|
||||||
|
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
|
||||||
|
console.log("\nYou will need to re-run your dependency manager to get started.")
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import App from './App.svelte';
|
import App from './App.svelte';
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.body,
|
target: document.body,
|
||||||
props: {
|
props: {
|
||||||
name: 'world',
|
name: 'world'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
635
examples/svelte/yarn.lock
Normal file
@@ -0,0 +1,635 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.10.4":
|
||||||
|
version "7.10.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
|
||||||
|
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.10.4"
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.10.4":
|
||||||
|
version "7.10.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
|
||||||
|
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
|
||||||
|
|
||||||
|
"@babel/highlight@^7.10.4":
|
||||||
|
version "7.10.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
|
||||||
|
integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.10.4"
|
||||||
|
chalk "^2.0.0"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@polka/url@^1.0.0-next.9":
|
||||||
|
version "1.0.0-next.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71"
|
||||||
|
integrity sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==
|
||||||
|
|
||||||
|
"@rollup/plugin-commonjs@^14.0.0":
|
||||||
|
version "14.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0"
|
||||||
|
integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw==
|
||||||
|
dependencies:
|
||||||
|
"@rollup/pluginutils" "^3.0.8"
|
||||||
|
commondir "^1.0.1"
|
||||||
|
estree-walker "^1.0.1"
|
||||||
|
glob "^7.1.2"
|
||||||
|
is-reference "^1.1.2"
|
||||||
|
magic-string "^0.25.2"
|
||||||
|
resolve "^1.11.0"
|
||||||
|
|
||||||
|
"@rollup/plugin-node-resolve@^8.0.0":
|
||||||
|
version "8.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz#261d79a680e9dc3d86761c14462f24126ba83575"
|
||||||
|
integrity sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==
|
||||||
|
dependencies:
|
||||||
|
"@rollup/pluginutils" "^3.1.0"
|
||||||
|
"@types/resolve" "1.17.1"
|
||||||
|
builtin-modules "^3.1.0"
|
||||||
|
deep-freeze "^0.0.1"
|
||||||
|
deepmerge "^4.2.2"
|
||||||
|
is-module "^1.0.0"
|
||||||
|
resolve "^1.17.0"
|
||||||
|
|
||||||
|
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
|
||||||
|
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "0.0.39"
|
||||||
|
estree-walker "^1.0.1"
|
||||||
|
picomatch "^2.2.2"
|
||||||
|
|
||||||
|
"@types/estree@*":
|
||||||
|
version "0.0.45"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
|
||||||
|
integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
|
||||||
|
|
||||||
|
"@types/estree@0.0.39":
|
||||||
|
version "0.0.39"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
||||||
|
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
||||||
|
|
||||||
|
"@types/node@*":
|
||||||
|
version "14.14.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
||||||
|
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
||||||
|
|
||||||
|
"@types/resolve@1.17.1":
|
||||||
|
version "1.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
|
||||||
|
integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
|
ansi-styles@^3.2.1:
|
||||||
|
version "3.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||||
|
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
|
||||||
|
dependencies:
|
||||||
|
color-convert "^1.9.0"
|
||||||
|
|
||||||
|
anymatch@~3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
|
||||||
|
integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
|
||||||
|
dependencies:
|
||||||
|
normalize-path "^3.0.0"
|
||||||
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
|
async-limiter@~1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
|
||||||
|
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
|
||||||
|
|
||||||
|
balanced-match@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
|
binary-extensions@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
|
||||||
|
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
|
||||||
|
|
||||||
|
brace-expansion@^1.1.7:
|
||||||
|
version "1.1.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
|
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||||
|
dependencies:
|
||||||
|
balanced-match "^1.0.0"
|
||||||
|
concat-map "0.0.1"
|
||||||
|
|
||||||
|
braces@~3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||||
|
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||||
|
dependencies:
|
||||||
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
buffer-from@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
|
builtin-modules@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
|
||||||
|
integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
|
||||||
|
|
||||||
|
chalk@^2.0.0:
|
||||||
|
version "2.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^3.2.1"
|
||||||
|
escape-string-regexp "^1.0.5"
|
||||||
|
supports-color "^5.3.0"
|
||||||
|
|
||||||
|
chokidar@^3.3.0:
|
||||||
|
version "3.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b"
|
||||||
|
integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==
|
||||||
|
dependencies:
|
||||||
|
anymatch "~3.1.1"
|
||||||
|
braces "~3.0.2"
|
||||||
|
glob-parent "~5.1.0"
|
||||||
|
is-binary-path "~2.1.0"
|
||||||
|
is-glob "~4.0.1"
|
||||||
|
normalize-path "~3.0.0"
|
||||||
|
readdirp "~3.5.0"
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.1.2"
|
||||||
|
|
||||||
|
color-convert@^1.9.0:
|
||||||
|
version "1.9.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
|
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
|
||||||
|
dependencies:
|
||||||
|
color-name "1.1.3"
|
||||||
|
|
||||||
|
color-name@1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||||
|
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||||
|
|
||||||
|
commander@^2.20.0:
|
||||||
|
version "2.20.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
|
||||||
|
commondir@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||||
|
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
|
||||||
|
|
||||||
|
concat-map@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
|
console-clear@^1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7"
|
||||||
|
integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==
|
||||||
|
|
||||||
|
deep-freeze@^0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84"
|
||||||
|
integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=
|
||||||
|
|
||||||
|
deepmerge@^4.2.2:
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||||
|
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||||
|
|
||||||
|
escape-string-regexp@^1.0.5:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
|
estree-walker@^0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||||
|
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||||
|
|
||||||
|
estree-walker@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
|
||||||
|
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
|
||||||
|
|
||||||
|
fill-range@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||||
|
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||||
|
dependencies:
|
||||||
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
|
fs.realpath@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
|
fsevents@~2.1.2:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
|
||||||
|
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
|
||||||
|
|
||||||
|
function-bind@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
|
get-port@^3.2.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
|
||||||
|
integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
|
||||||
|
|
||||||
|
glob-parent@~5.1.0:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||||
|
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
|
||||||
|
dependencies:
|
||||||
|
is-glob "^4.0.1"
|
||||||
|
|
||||||
|
glob@^7.1.2:
|
||||||
|
version "7.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||||
|
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
has-flag@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
|
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||||
|
|
||||||
|
has-flag@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||||
|
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||||
|
|
||||||
|
has@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||||
|
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
|
inflight@^1.0.4:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
|
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
||||||
|
dependencies:
|
||||||
|
once "^1.3.0"
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
inherits@2:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
|
is-binary-path@~2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||||
|
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||||
|
dependencies:
|
||||||
|
binary-extensions "^2.0.0"
|
||||||
|
|
||||||
|
is-core-module@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946"
|
||||||
|
integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==
|
||||||
|
dependencies:
|
||||||
|
has "^1.0.3"
|
||||||
|
|
||||||
|
is-extglob@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||||
|
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||||
|
|
||||||
|
is-glob@^4.0.1, is-glob@~4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
|
||||||
|
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
|
||||||
|
dependencies:
|
||||||
|
is-extglob "^2.1.1"
|
||||||
|
|
||||||
|
is-module@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
|
||||||
|
integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=
|
||||||
|
|
||||||
|
is-number@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||||
|
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||||
|
|
||||||
|
is-reference@^1.1.2:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
|
||||||
|
integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "*"
|
||||||
|
|
||||||
|
jest-worker@^26.2.1:
|
||||||
|
version "26.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
|
||||||
|
integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
merge-stream "^2.0.0"
|
||||||
|
supports-color "^7.0.0"
|
||||||
|
|
||||||
|
js-tokens@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
|
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||||
|
|
||||||
|
kleur@^3.0.0:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||||
|
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||||
|
|
||||||
|
livereload-js@^3.1.0:
|
||||||
|
version "3.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.1.tgz#61f887468086762e61fb2987412cf9d1dda99202"
|
||||||
|
integrity sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==
|
||||||
|
|
||||||
|
livereload@^0.9.1:
|
||||||
|
version "0.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.1.tgz#65125dabdf2db4fd3f1169e953fe56e3bcc6f477"
|
||||||
|
integrity sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==
|
||||||
|
dependencies:
|
||||||
|
chokidar "^3.3.0"
|
||||||
|
livereload-js "^3.1.0"
|
||||||
|
opts ">= 1.2.0"
|
||||||
|
ws "^6.2.1"
|
||||||
|
|
||||||
|
local-access@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.0.1.tgz#5121258146d64e869046c642ea4f1dd39ff942bb"
|
||||||
|
integrity sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA==
|
||||||
|
|
||||||
|
magic-string@^0.25.2:
|
||||||
|
version "0.25.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
||||||
|
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
|
||||||
|
dependencies:
|
||||||
|
sourcemap-codec "^1.4.4"
|
||||||
|
|
||||||
|
merge-stream@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||||
|
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
|
||||||
|
|
||||||
|
mime@^2.3.1:
|
||||||
|
version "2.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
|
||||||
|
integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
|
||||||
|
|
||||||
|
minimatch@^3.0.4:
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
|
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
|
mri@^1.1.0:
|
||||||
|
version "1.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
|
||||||
|
integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
|
||||||
|
|
||||||
|
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||||
|
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||||
|
|
||||||
|
once@^1.3.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
|
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||||
|
dependencies:
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
"opts@>= 1.2.0":
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
|
||||||
|
integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
|
||||||
|
|
||||||
|
path-is-absolute@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
|
|
||||||
|
path-parse@^1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||||
|
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||||
|
|
||||||
|
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2:
|
||||||
|
version "2.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||||
|
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||||
|
|
||||||
|
randombytes@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
|
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "^5.1.0"
|
||||||
|
|
||||||
|
readdirp@~3.5.0:
|
||||||
|
version "3.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
|
||||||
|
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
|
||||||
|
dependencies:
|
||||||
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
|
require-relative@^0.8.7:
|
||||||
|
version "0.8.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
|
||||||
|
integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
|
||||||
|
|
||||||
|
resolve@^1.11.0, resolve@^1.17.0:
|
||||||
|
version "1.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
|
||||||
|
integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
|
||||||
|
dependencies:
|
||||||
|
is-core-module "^2.1.0"
|
||||||
|
path-parse "^1.0.6"
|
||||||
|
|
||||||
|
rollup-plugin-livereload@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.0.tgz#d3928d74e8cf2ae4286c5dd46b770fd3f3b82313"
|
||||||
|
integrity sha512-oC/8NqumGYuphkqrfszOHUUIwzKsaHBICw6QRwT5uD07gvePTS+HW+GFwu6f9K8W02CUuTvtIM9AWJrbj4wE1A==
|
||||||
|
dependencies:
|
||||||
|
livereload "^0.9.1"
|
||||||
|
|
||||||
|
rollup-plugin-svelte@^6.0.0:
|
||||||
|
version "6.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-6.1.1.tgz#66362cf0500fb7a848283ebcf19d289a60ef0871"
|
||||||
|
integrity sha512-ijnm0pH1ScrY4uxwaNXBpNVejVzpL2769hIEbAlnqNUWZrffLspu5/k9/l/Wsj3NrEHLQ6wCKGagVJonyfN7ow==
|
||||||
|
dependencies:
|
||||||
|
require-relative "^0.8.7"
|
||||||
|
rollup-pluginutils "^2.8.2"
|
||||||
|
sourcemap-codec "^1.4.8"
|
||||||
|
|
||||||
|
rollup-plugin-terser@^7.0.0:
|
||||||
|
version "7.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"
|
||||||
|
integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.10.4"
|
||||||
|
jest-worker "^26.2.1"
|
||||||
|
serialize-javascript "^4.0.0"
|
||||||
|
terser "^5.0.0"
|
||||||
|
|
||||||
|
rollup-pluginutils@^2.8.2:
|
||||||
|
version "2.8.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
|
||||||
|
integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
|
||||||
|
dependencies:
|
||||||
|
estree-walker "^0.6.1"
|
||||||
|
|
||||||
|
rollup@^2.3.4:
|
||||||
|
version "2.33.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.1.tgz#802795164164ee63cd47769d8879c33ec8ae0c40"
|
||||||
|
integrity sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.1.2"
|
||||||
|
|
||||||
|
sade@^1.6.0:
|
||||||
|
version "1.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
|
||||||
|
integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==
|
||||||
|
dependencies:
|
||||||
|
mri "^1.1.0"
|
||||||
|
|
||||||
|
safe-buffer@^5.1.0:
|
||||||
|
version "5.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
|
semiver@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/semiver/-/semiver-1.1.0.tgz#9c97fb02c21c7ce4fcf1b73e2c7a24324bdddd5f"
|
||||||
|
integrity sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==
|
||||||
|
|
||||||
|
serialize-javascript@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
|
||||||
|
integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
|
||||||
|
dependencies:
|
||||||
|
randombytes "^2.1.0"
|
||||||
|
|
||||||
|
sirv-cli@^1.0.0:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-1.0.8.tgz#150c3f62694203a86cf5d71ec60e6ff4c34064a9"
|
||||||
|
integrity sha512-bJI+kkzQvMKfAOfgLzv09kWsdymLm39LgKmGjacB19GHIAQLCvXXg8e8HzcofTjDZlA8zVv4dQjU9SWkNzkJhw==
|
||||||
|
dependencies:
|
||||||
|
console-clear "^1.1.0"
|
||||||
|
get-port "^3.2.0"
|
||||||
|
kleur "^3.0.0"
|
||||||
|
local-access "^1.0.1"
|
||||||
|
sade "^1.6.0"
|
||||||
|
semiver "^1.0.0"
|
||||||
|
sirv "^1.0.7"
|
||||||
|
tinydate "^1.0.0"
|
||||||
|
|
||||||
|
sirv@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.7.tgz#ad8ca1f84430777a59162592626c2b8e9b9f1384"
|
||||||
|
integrity sha512-QMT2OTD3CTr8de9VByPmvSEeyt6k8/Cxg0J2kQJ5HNhIWfhFg9ypcIWWzez9rPWnGj+WtJ7AZD/MdT/vdilV/A==
|
||||||
|
dependencies:
|
||||||
|
"@polka/url" "^1.0.0-next.9"
|
||||||
|
mime "^2.3.1"
|
||||||
|
totalist "^1.0.0"
|
||||||
|
|
||||||
|
source-map-support@~0.5.19:
|
||||||
|
version "0.5.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||||
|
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
source-map "^0.6.0"
|
||||||
|
|
||||||
|
source-map@^0.6.0:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
|
source-map@~0.7.2:
|
||||||
|
version "0.7.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||||
|
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||||
|
|
||||||
|
sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
|
||||||
|
version "1.4.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||||
|
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
|
||||||
|
|
||||||
|
supports-color@^5.3.0:
|
||||||
|
version "5.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
|
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
|
supports-color@^7.0.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||||
|
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
svelte@^3.0.0:
|
||||||
|
version "3.29.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.29.7.tgz#e254eb2d0d609ce0fd60f052d444ac4a66d90f7d"
|
||||||
|
integrity sha512-rx0g311kBODvEWUU01DFBUl3MJuJven04bvTVFUG/w0On/wuj0PajQY/QlXcJndFxG+W1s8iXKaB418tdHWc3A==
|
||||||
|
|
||||||
|
terser@^5.0.0:
|
||||||
|
version "5.3.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.8.tgz#991ae8ba21a3d990579b54aa9af11586197a75dd"
|
||||||
|
integrity sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==
|
||||||
|
dependencies:
|
||||||
|
commander "^2.20.0"
|
||||||
|
source-map "~0.7.2"
|
||||||
|
source-map-support "~0.5.19"
|
||||||
|
|
||||||
|
tinydate@^1.0.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tinydate/-/tinydate-1.3.0.tgz#e6ca8e5a22b51bb4ea1c3a2a4fd1352dbd4c57fb"
|
||||||
|
integrity sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==
|
||||||
|
|
||||||
|
to-regex-range@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||||
|
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||||
|
dependencies:
|
||||||
|
is-number "^7.0.0"
|
||||||
|
|
||||||
|
totalist@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
||||||
|
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
|
||||||
|
|
||||||
|
wrappy@1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||||
|
|
||||||
|
ws@^6.2.1:
|
||||||
|
version "6.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
|
||||||
|
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
|
||||||
|
dependencies:
|
||||||
|
async-limiter "~1.0.0"
|
||||||
@@ -17,6 +17,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `blitz build`"
|
"placeholder": "`npm run build` or `blitz build`"
|
||||||
},
|
},
|
||||||
@@ -47,6 +50,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `next build`"
|
"placeholder": "`npm run build` or `next build`"
|
||||||
},
|
},
|
||||||
@@ -56,7 +62,13 @@
|
|||||||
"outputDirectory": {
|
"outputDirectory": {
|
||||||
"placeholder": "Next.js default"
|
"placeholder": "Next.js default"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"recommendedIntegrations": [
|
||||||
|
{
|
||||||
|
"id": "oac_5lUsiANun1DEzgLg0NZx5Es3",
|
||||||
|
"dependencies": ["next-plugin-sentry", "next-sentry-source-maps"]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Gatsby.js",
|
"name": "Gatsby.js",
|
||||||
@@ -76,6 +88,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `gatsby build`"
|
"placeholder": "`npm run build` or `gatsby build`"
|
||||||
},
|
},
|
||||||
@@ -105,6 +120,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `hexo generate`"
|
"placeholder": "`npm run build` or `hexo generate`"
|
||||||
},
|
},
|
||||||
@@ -134,6 +152,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `npx @11ty/eleventy`"
|
"placeholder": "`npm run build` or `npx @11ty/eleventy`"
|
||||||
},
|
},
|
||||||
@@ -162,6 +183,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `docusaurus build`"
|
"placeholder": "`npm run build` or `docusaurus build`"
|
||||||
},
|
},
|
||||||
@@ -190,6 +214,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `docusaurus-build`"
|
"placeholder": "`npm run build` or `docusaurus-build`"
|
||||||
},
|
},
|
||||||
@@ -218,6 +245,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `preact build`"
|
"placeholder": "`npm run build` or `preact build`"
|
||||||
},
|
},
|
||||||
@@ -249,6 +279,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `dojo build`"
|
"placeholder": "`npm run build` or `dojo build`"
|
||||||
},
|
},
|
||||||
@@ -277,6 +310,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `ember build`"
|
"placeholder": "`npm run build` or `ember build`"
|
||||||
},
|
},
|
||||||
@@ -305,6 +341,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `vue-cli-service build`"
|
"placeholder": "`npm run build` or `vue-cli-service build`"
|
||||||
},
|
},
|
||||||
@@ -333,6 +372,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `ng build && scully`"
|
"placeholder": "`npm run build` or `ng build && scully`"
|
||||||
},
|
},
|
||||||
@@ -361,6 +403,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `ng build`"
|
"placeholder": "`npm run build` or `ng build`"
|
||||||
},
|
},
|
||||||
@@ -389,6 +434,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `ng build`"
|
"placeholder": "`npm run build` or `ng build`"
|
||||||
},
|
},
|
||||||
@@ -417,6 +465,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `polymer build`"
|
"placeholder": "`npm run build` or `polymer build`"
|
||||||
},
|
},
|
||||||
@@ -445,6 +496,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `rollup -c`"
|
"placeholder": "`npm run build` or `rollup -c`"
|
||||||
},
|
},
|
||||||
@@ -473,6 +527,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `react-scripts build`"
|
"placeholder": "`npm run build` or `react-scripts build`"
|
||||||
},
|
},
|
||||||
@@ -505,6 +562,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `react-scripts build`"
|
"placeholder": "`npm run build` or `react-scripts build`"
|
||||||
},
|
},
|
||||||
@@ -533,6 +593,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `gridsome build`"
|
"placeholder": "`npm run build` or `gridsome build`"
|
||||||
},
|
},
|
||||||
@@ -561,6 +624,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `umi build`"
|
"placeholder": "`npm run build` or `umi build`"
|
||||||
},
|
},
|
||||||
@@ -589,6 +655,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `sapper export`"
|
"placeholder": "`npm run build` or `sapper export`"
|
||||||
},
|
},
|
||||||
@@ -617,6 +686,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `saber build`"
|
"placeholder": "`npm run build` or `saber build`"
|
||||||
},
|
},
|
||||||
@@ -645,6 +717,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `stencil build`"
|
"placeholder": "`npm run build` or `stencil build`"
|
||||||
},
|
},
|
||||||
@@ -673,6 +748,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `nuxt generate`"
|
"placeholder": "`npm run build` or `nuxt generate`"
|
||||||
},
|
},
|
||||||
@@ -703,6 +781,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"value": "yarn rw build && yarn rw db up --no-db-client --auto-approve && yarn rw dataMigrate up"
|
"value": "yarn rw build && yarn rw db up --no-db-client --auto-approve && yarn rw dataMigrate up"
|
||||||
},
|
},
|
||||||
@@ -737,6 +818,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "None"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `hugo -D --gc`"
|
"placeholder": "`npm run build` or `hugo -D --gc`"
|
||||||
},
|
},
|
||||||
@@ -764,6 +848,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"value": "bundle install"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `jekyll build`"
|
"placeholder": "`npm run build` or `jekyll build`"
|
||||||
},
|
},
|
||||||
@@ -791,6 +878,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run build` or `brunch build --production`"
|
"placeholder": "`npm run build` or `brunch build --production`"
|
||||||
},
|
},
|
||||||
@@ -818,6 +908,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"value": "bundle install"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"value": "`npm run build` or `bundle exec middleman build`"
|
"value": "`npm run build` or `bundle exec middleman build`"
|
||||||
},
|
},
|
||||||
@@ -835,6 +928,9 @@
|
|||||||
"logo": "https://raw.githubusercontent.com/vercel/vercel/master/packages/frameworks/logos/other.svg",
|
"logo": "https://raw.githubusercontent.com/vercel/vercel/master/packages/frameworks/logos/other.svg",
|
||||||
"description": "No framework or a unoptimized framework.",
|
"description": "No framework or a unoptimized framework.",
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"installCommand": {
|
||||||
|
"placeholder": "`yarn install` or `npm install`"
|
||||||
|
},
|
||||||
"buildCommand": {
|
"buildCommand": {
|
||||||
"placeholder": "`npm run vercel-build` or `npm run build`"
|
"placeholder": "`npm run vercel-build` or `npm run build`"
|
||||||
},
|
},
|
||||||
|
|||||||
4
packages/frameworks/index.d.ts
vendored
@@ -31,4 +31,8 @@ export interface Framework {
|
|||||||
devCommand: Setting;
|
devCommand: Setting;
|
||||||
outputDirectory: Setting;
|
outputDirectory: Setting;
|
||||||
};
|
};
|
||||||
|
recommendedIntegrations?: {
|
||||||
|
id: string;
|
||||||
|
dependencies: string[];
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/frameworks",
|
"name": "@vercel/frameworks",
|
||||||
"version": "0.1.1",
|
"version": "0.2.0",
|
||||||
"main": "frameworks.json",
|
"main": "frameworks.json",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
27
packages/frameworks/test/frameworks.unit.test.ts
vendored
@@ -89,14 +89,39 @@ const Schema = {
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
required: ['buildCommand', 'devCommand', 'outputDirectory'],
|
required: [
|
||||||
|
'installCommand',
|
||||||
|
'buildCommand',
|
||||||
|
'devCommand',
|
||||||
|
'outputDirectory',
|
||||||
|
],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
|
installCommand: SchemaSettings,
|
||||||
buildCommand: SchemaSettings,
|
buildCommand: SchemaSettings,
|
||||||
devCommand: SchemaSettings,
|
devCommand: SchemaSettings,
|
||||||
outputDirectory: SchemaSettings,
|
outputDirectory: SchemaSettings,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
recommendedIntegrations: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['id', 'dependencies'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/build-utils",
|
"name": "@vercel/build-utils",
|
||||||
"version": "2.5.3",
|
"version": "2.7.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.js",
|
"types": "./dist/index.d.js",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"@types/node-fetch": "^2.1.6",
|
"@types/node-fetch": "^2.1.6",
|
||||||
"@types/semver": "6.0.0",
|
"@types/semver": "6.0.0",
|
||||||
"@types/yazl": "^2.4.1",
|
"@types/yazl": "^2.4.1",
|
||||||
"@vercel/frameworks": "0.1.1",
|
"@vercel/frameworks": "0.2.0",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"aggregate-error": "3.0.1",
|
"aggregate-error": "3.0.1",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ interface Options {
|
|||||||
projectSettings?: {
|
projectSettings?: {
|
||||||
framework?: string | null;
|
framework?: string | null;
|
||||||
devCommand?: string | null;
|
devCommand?: string | null;
|
||||||
|
installCommand?: string | null;
|
||||||
buildCommand?: string | null;
|
buildCommand?: string | null;
|
||||||
outputDirectory?: string | null;
|
outputDirectory?: string | null;
|
||||||
createdAt?: number;
|
createdAt?: number;
|
||||||
@@ -42,9 +43,8 @@ export function sortFiles(fileA: string, fileB: string) {
|
|||||||
export function detectApiExtensions(builders: Builder[]): Set<string> {
|
export function detectApiExtensions(builders: Builder[]): Set<string> {
|
||||||
return new Set<string>(
|
return new Set<string>(
|
||||||
builders
|
builders
|
||||||
.filter(
|
.filter((b): b is Builder & { src: string } =>
|
||||||
b =>
|
Boolean(b.config && b.config.zeroConfig && b.src?.startsWith('api/'))
|
||||||
b.config && b.config.zeroConfig && b.src && b.src.startsWith('api/')
|
|
||||||
)
|
)
|
||||||
.map(b => extname(b.src))
|
.map(b => extname(b.src))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
@@ -55,22 +55,28 @@ export function detectApiDirectory(builders: Builder[]): string | null {
|
|||||||
// TODO: We eventually want to save the api directory to
|
// TODO: We eventually want to save the api directory to
|
||||||
// builder.config.apiDirectory so it is only detected once
|
// builder.config.apiDirectory so it is only detected once
|
||||||
const found = builders.some(
|
const found = builders.some(
|
||||||
b => b.config && b.config.zeroConfig && b.src.startsWith('api/')
|
b => b.config && b.config.zeroConfig && b.src?.startsWith('api/')
|
||||||
);
|
);
|
||||||
return found ? 'api' : null;
|
return found ? 'api' : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace this function with `config.outputDirectory`
|
// TODO: Replace this function with `config.outputDirectory`
|
||||||
function getPublicBuilder(builders: Builder[]): Builder | null {
|
function getPublicBuilder(
|
||||||
const builder = builders.find(
|
builders: Builder[]
|
||||||
builder =>
|
): (Builder & { src: string }) | null {
|
||||||
|
for (const builder of builders) {
|
||||||
|
if (
|
||||||
|
typeof builder.src === 'string' &&
|
||||||
isOfficialRuntime('static', builder.use) &&
|
isOfficialRuntime('static', builder.use) &&
|
||||||
/^.*\/\*\*\/\*$/.test(builder.src) &&
|
/^.*\/\*\*\/\*$/.test(builder.src) &&
|
||||||
builder.config &&
|
builder.config &&
|
||||||
builder.config.zeroConfig === true
|
builder.config.zeroConfig === true
|
||||||
);
|
) {
|
||||||
|
return builder as Builder & { src: string };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return builder || null;
|
return null;
|
||||||
}
|
}
|
||||||
export function detectOutputDirectory(builders: Builder[]): string | null {
|
export function detectOutputDirectory(builders: Builder[]): string | null {
|
||||||
// TODO: We eventually want to save the output directory to
|
// TODO: We eventually want to save the output directory to
|
||||||
@@ -360,7 +366,7 @@ function maybeGetApiBuilder(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = apiMatches.find(({ src }) => {
|
const match = apiMatches.find(({ src = '**' }) => {
|
||||||
return src === fileName || minimatch(fileName, src);
|
return src === fileName || minimatch(fileName, src);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -450,6 +456,10 @@ function detectFrontBuilder(
|
|||||||
config.devCommand = projectSettings.devCommand;
|
config.devCommand = projectSettings.devCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof projectSettings.installCommand === 'string') {
|
||||||
|
config.installCommand = projectSettings.installCommand;
|
||||||
|
}
|
||||||
|
|
||||||
if (projectSettings.buildCommand) {
|
if (projectSettings.buildCommand) {
|
||||||
config.buildCommand = projectSettings.buildCommand;
|
config.buildCommand = projectSettings.buildCommand;
|
||||||
}
|
}
|
||||||
@@ -458,7 +468,10 @@ function detectFrontBuilder(
|
|||||||
config.outputDirectory = projectSettings.outputDirectory;
|
config.outputDirectory = projectSettings.outputDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg && (framework !== null || createdAt < Date.parse('2020-03-01'))) {
|
if (
|
||||||
|
pkg &&
|
||||||
|
(framework === undefined || createdAt < Date.parse('2020-03-01'))
|
||||||
|
) {
|
||||||
const deps: PackageJson['dependencies'] = {
|
const deps: PackageJson['dependencies'] = {
|
||||||
...pkg.dependencies,
|
...pkg.dependencies,
|
||||||
...pkg.devDependencies,
|
...pkg.devDependencies,
|
||||||
@@ -981,7 +994,6 @@ function getRouteResult(
|
|||||||
rewriteRoutes.push({
|
rewriteRoutes.push({
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
status: 404,
|
status: 404,
|
||||||
continue: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -292,6 +292,11 @@ export async function runNpmInstall(
|
|||||||
opts.prettyCommand = 'yarn install';
|
opts.prettyCommand = 'yarn install';
|
||||||
command = 'yarn';
|
command = 'yarn';
|
||||||
commandArgs = ['install', ...args];
|
commandArgs = ['install', ...args];
|
||||||
|
|
||||||
|
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||||
|
if (!env.YARN_NODE_LINKER) {
|
||||||
|
env.YARN_NODE_LINKER = 'node-modules';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NPM_ONLY_PRODUCTION) {
|
if (process.env.NPM_ONLY_PRODUCTION) {
|
||||||
@@ -388,10 +393,17 @@ export async function runPackageJsonScript(
|
|||||||
prettyCommand,
|
prettyCommand,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||||
|
const env: typeof process.env = { ...spawnOpts?.env };
|
||||||
|
if (!env.YARN_NODE_LINKER) {
|
||||||
|
env.YARN_NODE_LINKER = 'node-modules';
|
||||||
|
}
|
||||||
|
|
||||||
const prettyCommand = `yarn run ${scriptName}`;
|
const prettyCommand = `yarn run ${scriptName}`;
|
||||||
console.log(`Running "${prettyCommand}"`);
|
console.log(`Running "${prettyCommand}"`);
|
||||||
await spawnAsync('yarn', ['run', scriptName], {
|
await spawnAsync('yarn', ['run', scriptName], {
|
||||||
...spawnOpts,
|
...spawnOpts,
|
||||||
|
env,
|
||||||
cwd: destPath,
|
cwd: destPath,
|
||||||
prettyCommand,
|
prettyCommand,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export interface Config {
|
|||||||
import?: { [key: string]: string };
|
import?: { [key: string]: string };
|
||||||
functions?: BuilderFunctions;
|
functions?: BuilderFunctions;
|
||||||
outputDirectory?: string;
|
outputDirectory?: string;
|
||||||
|
installCommand?: string;
|
||||||
buildCommand?: string;
|
buildCommand?: string;
|
||||||
devCommand?: string;
|
devCommand?: string;
|
||||||
framework?: string;
|
framework?: string;
|
||||||
@@ -335,7 +336,7 @@ export interface NodeVersion {
|
|||||||
|
|
||||||
export interface Builder {
|
export interface Builder {
|
||||||
use: string;
|
use: string;
|
||||||
src: string;
|
src?: string;
|
||||||
config?: Config;
|
config?: Config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
packages/now-build-utils/test/fixtures/19-yarn-v2/api/index.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const { camelCase } = require('camel-case');
|
||||||
|
|
||||||
|
module.exports = (req, res) => {
|
||||||
|
res.end(camelCase('camel-case module is working'));
|
||||||
|
};
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
|
||||||
"probes": [{ "path": "/", "mustContain": "Svelte app" }]
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"svelte": "^3.0.0"
|
"svelte": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"camel-case": "^4.1.2",
|
||||||
"sirv-cli": "^0.4.4"
|
"sirv-cli": "^0.4.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
packages/now-build-utils/test/fixtures/19-yarn-v2/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [
|
||||||
|
{ "src": "package.json", "use": "@vercel/static-build" },
|
||||||
|
{ "src": "api/index.js", "use": "@vercel/node" }
|
||||||
|
],
|
||||||
|
"probes": [
|
||||||
|
{ "path": "/", "mustContain": "Svelte app" },
|
||||||
|
{ "path": "/api", "mustContain": "camelCaseModuleIsWorking" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -270,6 +270,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"camel-case@npm:^4.1.2":
|
||||||
|
version: 4.1.2
|
||||||
|
resolution: "camel-case@npm:4.1.2"
|
||||||
|
dependencies:
|
||||||
|
pascal-case: ^3.1.2
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 3/0b8dcfb424c9497e45984b88ef005c66bdf8e877e36365aedfc3cf73182684fde5a14cf2c526579c0351a5f27dc39a00f1edecc25d43606075fea948c504e37f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"caseless@npm:~0.12.0":
|
"caseless@npm:~0.12.0":
|
||||||
version: 0.12.0
|
version: 0.12.0
|
||||||
resolution: "caseless@npm:0.12.0"
|
resolution: "caseless@npm:0.12.0"
|
||||||
@@ -850,6 +860,15 @@ fsevents@~2.1.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"lower-case@npm:^2.0.2":
|
||||||
|
version: 2.0.2
|
||||||
|
resolution: "lower-case@npm:2.0.2"
|
||||||
|
dependencies:
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 3/aabaca9cef65f7564a1005b625664527e4d169e363101e65773f8f6ff2fdcf09884a3bc02990cd7a62cf05f3538114af25ee7bef553f1ca3208c8a77ac75cbfa
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"magic-string@npm:^0.25.2":
|
"magic-string@npm:^0.25.2":
|
||||||
version: 0.25.7
|
version: 0.25.7
|
||||||
resolution: "magic-string@npm:0.25.7"
|
resolution: "magic-string@npm:0.25.7"
|
||||||
@@ -944,6 +963,16 @@ fsevents@~2.1.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"no-case@npm:^3.0.4":
|
||||||
|
version: 3.0.4
|
||||||
|
resolution: "no-case@npm:3.0.4"
|
||||||
|
dependencies:
|
||||||
|
lower-case: ^2.0.2
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 3/84db4909caec37504c6655f995a004067f8733be8cd8d849f1578661b60a1685e086325fa4e1a5e8ce94e7416c1d0f037e2a00f635a14457183de80ab4fc7612
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"node-gyp@npm:latest":
|
"node-gyp@npm:latest":
|
||||||
version: 6.1.0
|
version: 6.1.0
|
||||||
resolution: "node-gyp@npm:6.1.0"
|
resolution: "node-gyp@npm:6.1.0"
|
||||||
@@ -1057,6 +1086,16 @@ fsevents@~2.1.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pascal-case@npm:^3.1.2":
|
||||||
|
version: 3.1.2
|
||||||
|
resolution: "pascal-case@npm:3.1.2"
|
||||||
|
dependencies:
|
||||||
|
no-case: ^3.0.4
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 3/31708cecab221482edc81e2bd9b9d8282d72d4f1443b31f39725aa23768c5e42d93c4c014f1bc90f7f074e2a70d5091e4892ea370e550affc9ccf1d33c900bcd
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-is-absolute@npm:^1.0.0":
|
"path-is-absolute@npm:^1.0.0":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "path-is-absolute@npm:1.0.1"
|
resolution: "path-is-absolute@npm:1.0.1"
|
||||||
@@ -1447,6 +1486,7 @@ fsevents@~2.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@rollup/plugin-commonjs": ^12.0.0
|
"@rollup/plugin-commonjs": ^12.0.0
|
||||||
"@rollup/plugin-node-resolve": ^8.0.0
|
"@rollup/plugin-node-resolve": ^8.0.0
|
||||||
|
camel-case: ^4.1.2
|
||||||
rollup: ^2.3.4
|
rollup: ^2.3.4
|
||||||
rollup-plugin-livereload: ^1.0.0
|
rollup-plugin-livereload: ^1.0.0
|
||||||
rollup-plugin-svelte: ^5.0.3
|
rollup-plugin-svelte: ^5.0.3
|
||||||
@@ -1517,6 +1557,13 @@ fsevents@~2.1.2:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"tslib@npm:^2.0.3":
|
||||||
|
version: 2.0.3
|
||||||
|
resolution: "tslib@npm:2.0.3"
|
||||||
|
checksum: 3/447bfca5deaa157806c3f77eaba74d05dd0b38b014e47ce79d98b5c77ce7d91b00a687ba13ca1b5a74d35ca1098ac7a072c0a97fad06f0266612f2a03a6c8e8f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tunnel-agent@npm:^0.6.0":
|
"tunnel-agent@npm:^0.6.0":
|
||||||
version: 0.6.0
|
version: 0.6.0
|
||||||
resolution: "tunnel-agent@npm:0.6.0"
|
resolution: "tunnel-agent@npm:0.6.0"
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ describe('Test `detectBuilders`', () => {
|
|||||||
|
|
||||||
const { builders } = await detectBuilders(files);
|
const { builders } = await detectBuilders(files);
|
||||||
expect(builders!.length).toBe(7);
|
expect(builders!.length).toBe(7);
|
||||||
expect(builders!.some(b => b.src.endsWith('_test.go'))).toBe(false);
|
expect(builders!.some(b => b.src!.endsWith('_test.go'))).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('just public', async () => {
|
it('just public', async () => {
|
||||||
@@ -833,6 +833,50 @@ describe('Test `detectBuilders`', () => {
|
|||||||
describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
||||||
const featHandleMiss = true;
|
const featHandleMiss = true;
|
||||||
|
|
||||||
|
it('should select "installCommand"', async () => {
|
||||||
|
const pkg = {
|
||||||
|
scripts: { build: 'next build' },
|
||||||
|
dependencies: { next: '9.0.0' },
|
||||||
|
};
|
||||||
|
const files = ['package.json', 'pages/index.js', 'public/index.html'];
|
||||||
|
const { builders, errors } = await detectBuilders(files, pkg, {
|
||||||
|
featHandleMiss,
|
||||||
|
projectSettings: {
|
||||||
|
installCommand: 'npx pnpm install',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(errors).toBe(null);
|
||||||
|
expect(builders).toBeDefined();
|
||||||
|
expect(builders!.length).toStrictEqual(1);
|
||||||
|
expect(builders![0].src).toStrictEqual('package.json');
|
||||||
|
expect(builders![0].use).toStrictEqual('@vercel/next');
|
||||||
|
expect(builders![0].config!.zeroConfig).toStrictEqual(true);
|
||||||
|
expect(builders![0].config!.installCommand).toStrictEqual(
|
||||||
|
'npx pnpm install'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should select empty "installCommand"', async () => {
|
||||||
|
const pkg = {
|
||||||
|
scripts: { build: 'next build' },
|
||||||
|
dependencies: { next: '9.0.0' },
|
||||||
|
};
|
||||||
|
const files = ['package.json', 'pages/index.js', 'public/index.html'];
|
||||||
|
const { builders, errors } = await detectBuilders(files, pkg, {
|
||||||
|
featHandleMiss,
|
||||||
|
projectSettings: {
|
||||||
|
installCommand: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(errors).toBe(null);
|
||||||
|
expect(builders).toBeDefined();
|
||||||
|
expect(builders!.length).toStrictEqual(1);
|
||||||
|
expect(builders![0].src).toStrictEqual('package.json');
|
||||||
|
expect(builders![0].use).toStrictEqual('@vercel/next');
|
||||||
|
expect(builders![0].config!.zeroConfig).toStrictEqual(true);
|
||||||
|
expect(builders![0].config!.installCommand).toStrictEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
it('should never select now.json src', async () => {
|
it('should never select now.json src', async () => {
|
||||||
const files = ['docs/index.md', 'mkdocs.yml', 'now.json'];
|
const files = ['docs/index.md', 'mkdocs.yml', 'now.json'];
|
||||||
const { builders, errors } = await detectBuilders(files, null, {
|
const { builders, errors } = await detectBuilders(files, null, {
|
||||||
@@ -1080,6 +1124,46 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
|||||||
expect(errorRoutes).toStrictEqual([]);
|
expect(errorRoutes).toStrictEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Using "Create React App" framework with `next` in dependencies should NOT autodetect Next.js for new projects', async () => {
|
||||||
|
const pkg = {
|
||||||
|
scripts: {
|
||||||
|
dev: 'react-scripts start',
|
||||||
|
build: 'react-scripts build',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
next: '9.3.5',
|
||||||
|
react: '16.13.1',
|
||||||
|
'react-dom': '16.13.1',
|
||||||
|
'react-scripts': '2.1.1',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const files = ['package.json', 'src/index.js', 'public/favicon.ico'];
|
||||||
|
const projectSettings = {
|
||||||
|
framework: 'create-react-app',
|
||||||
|
buildCommand: 'react-scripts build',
|
||||||
|
createdAt: Date.parse('2020-07-01'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { builders, errorRoutes } = await detectBuilders(files, pkg, {
|
||||||
|
projectSettings,
|
||||||
|
featHandleMiss,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(builders).toEqual([
|
||||||
|
{
|
||||||
|
use: '@vercel/static-build',
|
||||||
|
src: 'package.json',
|
||||||
|
config: {
|
||||||
|
zeroConfig: true,
|
||||||
|
framework: projectSettings.framework,
|
||||||
|
buildCommand: projectSettings.buildCommand,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(errorRoutes!.length).toBe(1);
|
||||||
|
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||||
|
});
|
||||||
|
|
||||||
it('Using "Other" framework with Storybook should NOT autodetect Next.js for new projects', async () => {
|
it('Using "Other" framework with Storybook should NOT autodetect Next.js for new projects', async () => {
|
||||||
const pkg = {
|
const pkg = {
|
||||||
scripts: {
|
scripts: {
|
||||||
@@ -1257,7 +1341,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
|
|||||||
featHandleMiss,
|
featHandleMiss,
|
||||||
});
|
});
|
||||||
expect(builders!.length).toBe(7);
|
expect(builders!.length).toBe(7);
|
||||||
expect(builders!.some(b => b.src.endsWith('_test.go'))).toBe(false);
|
expect(builders!.some(b => b.src!.endsWith('_test.go'))).toBe(false);
|
||||||
expect(errorRoutes!.length).toBe(1);
|
expect(errorRoutes!.length).toBe(1);
|
||||||
expect((errorRoutes![0] as Source).status).toBe(404);
|
expect((errorRoutes![0] as Source).status).toBe(404);
|
||||||
});
|
});
|
||||||
@@ -2309,7 +2393,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(errorRoutes).toStrictEqual([
|
expect(errorRoutes).toStrictEqual([
|
||||||
@@ -2411,7 +2494,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2449,7 +2531,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2487,7 +2568,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2520,7 +2600,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2548,7 +2627,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2579,7 +2657,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2606,7 +2683,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2641,7 +2717,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
expect(errorRoutes).toStrictEqual([
|
expect(errorRoutes).toStrictEqual([
|
||||||
@@ -2736,7 +2811,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2769,7 +2843,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2803,7 +2876,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2829,7 +2901,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2853,7 +2924,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2878,7 +2948,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2899,7 +2968,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -2934,7 +3002,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -2992,7 +3059,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3025,7 +3091,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3059,7 +3124,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3078,7 +3142,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3102,7 +3165,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3127,7 +3189,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3209,6 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
|
|||||||
{
|
{
|
||||||
status: 404,
|
status: 404,
|
||||||
src: '^/api(/.*)?$',
|
src: '^/api(/.*)?$',
|
||||||
continue: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "20.1.1",
|
"version": "21.1.0",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"description": "The command-line interface for Vercel",
|
"description": "The command-line interface for Vercel",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "node ./scripts/preinstall.js",
|
"preinstall": "node ./scripts/preinstall.js",
|
||||||
"test-unit": "nyc ava test/unit.js test/dev-builder.unit.js test/dev-router.unit.js test/dev-server.unit.js test/dev-validate.unit.js --serial --fail-fast --verbose",
|
"test-unit": "nyc ava test/unit.js test/dev-builder.unit.js test/dev-router.unit.js test/dev-server.unit.js test/dev-validate.unit.js --serial --fail-fast --verbose",
|
||||||
"test-integration-cli": "ava test/integration.js --serial --fail-fast --verbose",
|
"test-integration-cli": "rimraf test/fixtures/integration && ava test/integration.js --serial --fail-fast --verbose",
|
||||||
"test-integration-dev": "ava test/dev/integration.js --serial --fail-fast --verbose",
|
"test-integration-dev": "ava test/dev/integration.js --serial --fail-fast --verbose",
|
||||||
"prepublishOnly": "yarn build",
|
"prepublishOnly": "yarn build",
|
||||||
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
|
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
|
||||||
@@ -61,11 +61,11 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.5.3",
|
"@vercel/build-utils": "2.7.0",
|
||||||
"@vercel/go": "1.1.6",
|
"@vercel/go": "1.1.7",
|
||||||
"@vercel/node": "1.8.3",
|
"@vercel/node": "1.9.0",
|
||||||
"@vercel/python": "1.2.3",
|
"@vercel/python": "1.2.4",
|
||||||
"@vercel/ruby": "1.2.4",
|
"@vercel/ruby": "1.2.5",
|
||||||
"update-notifier": "4.1.0"
|
"update-notifier": "4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
"@types/universal-analytics": "0.4.2",
|
"@types/universal-analytics": "0.4.2",
|
||||||
"@types/which": "1.3.2",
|
"@types/which": "1.3.2",
|
||||||
"@types/write-json-file": "2.2.1",
|
"@types/write-json-file": "2.2.1",
|
||||||
"@vercel/frameworks": "0.1.1",
|
"@vercel/frameworks": "0.2.0",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"@zeit/fun": "0.11.2",
|
"@zeit/fun": "0.11.2",
|
||||||
"@zeit/source-map-support": "0.6.2",
|
"@zeit/source-map-support": "0.6.2",
|
||||||
@@ -146,7 +146,6 @@
|
|||||||
"minimatch": "3.0.4",
|
"minimatch": "3.0.4",
|
||||||
"mri": "1.1.5",
|
"mri": "1.1.5",
|
||||||
"ms": "2.1.2",
|
"ms": "2.1.2",
|
||||||
"nanoid": "3.0.2",
|
|
||||||
"node-fetch": "2.6.1",
|
"node-fetch": "2.6.1",
|
||||||
"npm-package-arg": "6.1.0",
|
"npm-package-arg": "6.1.0",
|
||||||
"nyc": "13.2.0",
|
"nyc": "13.2.0",
|
||||||
@@ -158,6 +157,7 @@
|
|||||||
"psl": "1.1.31",
|
"psl": "1.1.31",
|
||||||
"qr-image": "3.2.0",
|
"qr-image": "3.2.0",
|
||||||
"raw-body": "2.4.1",
|
"raw-body": "2.4.1",
|
||||||
|
"rimraf": "3.0.2",
|
||||||
"semver": "5.5.0",
|
"semver": "5.5.0",
|
||||||
"serve-handler": "6.1.1",
|
"serve-handler": "6.1.1",
|
||||||
"sinon": "4.4.2",
|
"sinon": "4.4.2",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const help = () => {
|
|||||||
|
|
||||||
${chalk.dim('Commands:')}
|
${chalk.dim('Commands:')}
|
||||||
|
|
||||||
ls [app] Show all aliases (or per app name)
|
ls Show all aliases
|
||||||
set <deployment> <alias> Create a new alias
|
set <deployment> <alias> Create a new alias
|
||||||
rm <alias> Remove an alias using its hostname
|
rm <alias> Remove an alias using its hostname
|
||||||
|
|
||||||
@@ -39,19 +39,19 @@ const help = () => {
|
|||||||
-N, --next Show next page of results
|
-N, --next Show next page of results
|
||||||
${chalk.dim('Examples:')}
|
${chalk.dim('Examples:')}
|
||||||
|
|
||||||
${chalk.gray('–')} Add a new alias to ${chalk.underline('my-api.now.sh')}
|
${chalk.gray('–')} Add a new alias to ${chalk.underline('my-api.vercel.app')}
|
||||||
|
|
||||||
${chalk.cyan(
|
${chalk.cyan(
|
||||||
`$ ${getPkgName()} alias set ${chalk.underline(
|
`$ ${getPkgName()} alias set ${chalk.underline(
|
||||||
'api-ownv3nc9f8.now.sh'
|
'api-ownv3nc9f8.vercel.app'
|
||||||
)} ${chalk.underline('my-api.now.sh')}`
|
)} ${chalk.underline('my-api.vercel.app')}`
|
||||||
)}
|
)}
|
||||||
|
|
||||||
Custom domains work as alias targets
|
Custom domains work as alias targets
|
||||||
|
|
||||||
${chalk.cyan(
|
${chalk.cyan(
|
||||||
`$ ${getPkgName()} alias set ${chalk.underline(
|
`$ ${getPkgName()} alias set ${chalk.underline(
|
||||||
'api-ownv3nc9f8.now.sh'
|
'api-ownv3nc9f8.vercel.app'
|
||||||
)} ${chalk.underline('my-api.com')}`
|
)} ${chalk.underline('my-api.com')}`
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
import plural from 'pluralize';
|
|
||||||
import table from 'text-table';
|
import table from 'text-table';
|
||||||
import Now from '../../util';
|
import Now from '../../util';
|
||||||
import Client from '../../util/client.ts';
|
import Client from '../../util/client.ts';
|
||||||
@@ -52,21 +51,17 @@ export default async function ls(ctx, opts, args, output) {
|
|||||||
const lsStamp = stamp();
|
const lsStamp = stamp();
|
||||||
let cancelWait;
|
let cancelWait;
|
||||||
|
|
||||||
if (args.length > 1) {
|
if (args.length > 0) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${chalk.cyan(
|
`Invalid number of arguments. Usage: ${chalk.cyan(
|
||||||
`${getCommandName('alias ls [alias]')}`
|
`${getCommandName('alias ls')}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelWait = output.spinner(
|
cancelWait = output.spinner(
|
||||||
args[0]
|
`Fetching aliases under ${chalk.bold(contextName)}`
|
||||||
? `Fetching alias details for "${args[0]}" under ${chalk.bold(
|
|
||||||
contextName
|
|
||||||
)}`
|
|
||||||
: `Fetching aliases under ${chalk.bold(contextName)}`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const { aliases, pagination } = await getAliases(
|
const { aliases, pagination } = await getAliases(
|
||||||
@@ -76,32 +71,8 @@ export default async function ls(ctx, opts, args, output) {
|
|||||||
);
|
);
|
||||||
if (cancelWait) cancelWait();
|
if (cancelWait) cancelWait();
|
||||||
|
|
||||||
if (args[0]) {
|
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
|
||||||
const alias = aliases.find(
|
console.log(printAliasTable(aliases));
|
||||||
item => item.uid === args[0] || item.alias === args[0]
|
|
||||||
);
|
|
||||||
if (!alias) {
|
|
||||||
output.error(`Could not match path alias for: ${args[0]}`);
|
|
||||||
now.close();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts['--json']) {
|
|
||||||
console.log(JSON.stringify({ rules: alias.rules }, null, 2));
|
|
||||||
} else {
|
|
||||||
const rules = alias.rules || [];
|
|
||||||
output.log(
|
|
||||||
`${rules.length} path alias ${plural(
|
|
||||||
'rule',
|
|
||||||
rules.length
|
|
||||||
)} found under ${chalk.bold(contextName)} ${lsStamp()}`
|
|
||||||
);
|
|
||||||
output.print(`${printPathAliasTable(rules)}\n`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
|
|
||||||
console.log(printAliasTable(aliases));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pagination && pagination.count === 20) {
|
if (pagination && pagination.count === 20) {
|
||||||
const flags = getCommandFlags(opts, ['_', '--next']);
|
const flags = getCommandFlags(opts, ['_', '--next']);
|
||||||
@@ -121,14 +92,10 @@ function printAliasTable(aliases) {
|
|||||||
[
|
[
|
||||||
['source', 'url', 'age'].map(h => chalk.gray(h)),
|
['source', 'url', 'age'].map(h => chalk.gray(h)),
|
||||||
...aliases.map(a => [
|
...aliases.map(a => [
|
||||||
a.rules && a.rules.length
|
// for legacy reasons, we might have situations
|
||||||
? chalk.cyan(`[${plural('rule', a.rules.length, true)}]`)
|
// where the deployment was deleted and the alias
|
||||||
: // for legacy reasons, we might have situations
|
// not collected appropriately, and we need to handle it
|
||||||
// where the deployment was deleted and the alias
|
a.deployment && a.deployment.url ? a.deployment.url : chalk.gray('–'),
|
||||||
// not collected appropriately, and we need to handle it
|
|
||||||
a.deployment && a.deployment.url
|
|
||||||
? a.deployment.url
|
|
||||||
: chalk.gray('–'),
|
|
||||||
a.alias,
|
a.alias,
|
||||||
ms(Date.now() - new Date(a.createdAt)),
|
ms(Date.now() - new Date(a.createdAt)),
|
||||||
]),
|
]),
|
||||||
@@ -140,21 +107,3 @@ function printAliasTable(aliases) {
|
|||||||
}
|
}
|
||||||
).replace(/^/gm, ' ')}\n\n`;
|
).replace(/^/gm, ' ')}\n\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function printPathAliasTable(rules) {
|
|
||||||
const header = [['pathname', 'method', 'dest'].map(s => chalk.gray(s))];
|
|
||||||
return `${table(
|
|
||||||
header.concat(
|
|
||||||
rules.map(rule => [
|
|
||||||
rule.pathname ? rule.pathname : chalk.cyan('[fallthrough]'),
|
|
||||||
rule.method ? rule.method : '*',
|
|
||||||
rule.dest,
|
|
||||||
])
|
|
||||||
),
|
|
||||||
{
|
|
||||||
align: ['l', 'l', 'l', 'l'],
|
|
||||||
hsep: ' '.repeat(6),
|
|
||||||
stringLength: strlen,
|
|
||||||
}
|
|
||||||
).replace(/^(.*)/gm, ' $1')}\n`;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import getScope from '../../util/get-scope.ts';
|
|||||||
import removeAliasById from '../../util/alias/remove-alias-by-id';
|
import removeAliasById from '../../util/alias/remove-alias-by-id';
|
||||||
import stamp from '../../util/output/stamp.ts';
|
import stamp from '../../util/output/stamp.ts';
|
||||||
import strlen from '../../util/strlen.ts';
|
import strlen from '../../util/strlen.ts';
|
||||||
import promptBool from '../../util/prompt-bool';
|
import confirm from '../../util/input/confirm';
|
||||||
import { isValidName } from '../../util/is-valid-name';
|
import { isValidName } from '../../util/is-valid-name';
|
||||||
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
|
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
|
||||||
import { getCommandName } from '../../util/pkg-name.ts';
|
import { getCommandName } from '../../util/pkg-name.ts';
|
||||||
@@ -108,5 +108,5 @@ async function confirmAliasRemove(output, alias) {
|
|||||||
|
|
||||||
output.log(`The following alias will be removed permanently`);
|
output.log(`The following alias will be removed permanently`);
|
||||||
output.print(` ${tbl}\n`);
|
output.print(` ${tbl}\n`);
|
||||||
return promptBool(output, chalk.red('Are you sure?'));
|
return confirm(chalk.red('Are you sure?'), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ function handleCreateAliasError<T>(
|
|||||||
}
|
}
|
||||||
if (error instanceof ERRORS.InvalidAlias) {
|
if (error instanceof ERRORS.InvalidAlias) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid alias. Please confirm that the alias you provided is a valid hostname. Note: For \`now.sh\`, only sub and sub-sub domains are supported.`
|
`Invalid alias. Please confirm that the alias you provided is a valid hostname. Note: For \`vercel.app\`, only sub and sub-sub domains are supported.`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ import { resolve, join } from 'path';
|
|||||||
import DevServer from '../../util/dev/server';
|
import DevServer from '../../util/dev/server';
|
||||||
import parseListen from '../../util/dev/parse-listen';
|
import parseListen from '../../util/dev/parse-listen';
|
||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import { NowContext } from '../../types';
|
import { NowContext, ProjectEnvVariable } from '../../types';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import { getLinkedProject } from '../../util/projects/link';
|
import { getLinkedProject } from '../../util/projects/link';
|
||||||
import { getFrameworks } from '../../util/get-frameworks';
|
import { getFrameworks } from '../../util/get-frameworks';
|
||||||
import { isSettingValue } from '../../util/is-setting-value';
|
import { isSettingValue } from '../../util/is-setting-value';
|
||||||
import { ProjectSettings, ProjectEnvTarget } from '../../types';
|
import { ProjectSettings } from '../../types';
|
||||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||||
import { Env } from '@vercel/build-utils';
|
|
||||||
import setupAndLink from '../../util/link/setup-and-link';
|
import setupAndLink from '../../util/link/setup-and-link';
|
||||||
|
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
'--debug'?: boolean;
|
'--debug'?: boolean;
|
||||||
@@ -70,7 +70,8 @@ export default async function dev(
|
|||||||
let devCommand: string | undefined;
|
let devCommand: string | undefined;
|
||||||
let frameworkSlug: string | undefined;
|
let frameworkSlug: string | undefined;
|
||||||
let projectSettings: ProjectSettings | undefined;
|
let projectSettings: ProjectSettings | undefined;
|
||||||
let environmentVars: Env | undefined;
|
let projectEnvs: ProjectEnvVariable[] = [];
|
||||||
|
let systemEnvValues: string[] = [];
|
||||||
if (link.status === 'linked') {
|
if (link.status === 'linked') {
|
||||||
const { project, org } = link;
|
const { project, org } = link;
|
||||||
client.currentTeam = org.type === 'team' ? org.id : undefined;
|
client.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||||
@@ -98,12 +99,12 @@ export default async function dev(
|
|||||||
cwd = join(cwd, project.rootDirectory);
|
cwd = join(cwd, project.rootDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
environmentVars = await getDecryptedEnvRecords(
|
[{ envs: projectEnvs }, { systemEnvValues }] = await Promise.all([
|
||||||
output,
|
getDecryptedEnvRecords(output, client, project.id),
|
||||||
client,
|
project.autoExposeSystemEnvs
|
||||||
project,
|
? getSystemEnvValues(output, client, project.id)
|
||||||
ProjectEnvTarget.Development
|
: { systemEnvValues: [] },
|
||||||
);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const devServer = new DevServer(cwd, {
|
const devServer = new DevServer(cwd, {
|
||||||
@@ -112,7 +113,8 @@ export default async function dev(
|
|||||||
devCommand,
|
devCommand,
|
||||||
frameworkSlug,
|
frameworkSlug,
|
||||||
projectSettings,
|
projectSettings,
|
||||||
environmentVars,
|
projectEnvs,
|
||||||
|
systemEnvValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
process.once('SIGINT', () => devServer.stop());
|
process.once('SIGINT', () => devServer.stop());
|
||||||
|
|||||||
131
packages/now-cli/src/commands/env/add.ts
vendored
@@ -1,6 +1,6 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import { ProjectEnvTarget, Project } from '../../types';
|
import { ProjectEnvTarget, Project, Secret, ProjectEnvType } from '../../types';
|
||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import stamp from '../../util/output/stamp';
|
import stamp from '../../util/output/stamp';
|
||||||
@@ -11,12 +11,14 @@ import {
|
|||||||
getEnvTargetPlaceholder,
|
getEnvTargetPlaceholder,
|
||||||
getEnvTargetChoices,
|
getEnvTargetChoices,
|
||||||
} from '../../util/env/env-target';
|
} from '../../util/env/env-target';
|
||||||
|
import { isValidEnvType, getEnvTypePlaceholder } from '../../util/env/env-type';
|
||||||
import readStandardInput from '../../util/input/read-standard-input';
|
import readStandardInput from '../../util/input/read-standard-input';
|
||||||
import param from '../../util/output/param';
|
import param from '../../util/output/param';
|
||||||
import withSpinner from '../../util/with-spinner';
|
import withSpinner from '../../util/with-spinner';
|
||||||
import { emoji, prependEmoji } from '../../util/emoji';
|
import { emoji, prependEmoji } from '../../util/emoji';
|
||||||
import { isKnownError } from '../../util/env/known-error';
|
import { isKnownError } from '../../util/env/known-error';
|
||||||
import { getCommandName } from '../../util/pkg-name';
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
|
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
'--debug': boolean;
|
'--debug': boolean;
|
||||||
@@ -29,38 +31,74 @@ export default async function add(
|
|||||||
args: string[],
|
args: string[],
|
||||||
output: Output
|
output: Output
|
||||||
) {
|
) {
|
||||||
const stdInput = await readStandardInput();
|
// improve the way we show inquirer prompts
|
||||||
let [envName, envTarget] = args;
|
require('../../util/input/patch-inquirer');
|
||||||
|
|
||||||
if (args.length > 2) {
|
const stdInput = await readStandardInput();
|
||||||
|
let [envTypeArg, envName, envTargetArg] = args;
|
||||||
|
|
||||||
|
if (args.length > 3) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${getCommandName(
|
`Invalid number of arguments. Usage: ${getCommandName(
|
||||||
`env add <name> ${getEnvTargetPlaceholder()}`
|
`env add ${getEnvTypePlaceholder()} <name> ${getEnvTargetPlaceholder()}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdInput && (!envName || !envTarget)) {
|
if (stdInput && (!envTypeArg || !envName || !envTargetArg)) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${getCommandName(
|
`Invalid number of arguments. Usage: ${getCommandName(
|
||||||
`env add <name> <target> < <file>`
|
`env add ${getEnvTypePlaceholder()} <name> <target> < <file>`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let envTargets: ProjectEnvTarget[] = [];
|
let envTargets: ProjectEnvTarget[] = [];
|
||||||
if (envTarget) {
|
if (envTargetArg) {
|
||||||
if (!isValidEnvTarget(envTarget)) {
|
if (!isValidEnvTarget(envTargetArg)) {
|
||||||
output.error(
|
output.error(
|
||||||
`The Environment ${param(
|
`The Environment ${param(
|
||||||
envTarget
|
envTargetArg
|
||||||
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
|
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
envTargets.push(envTarget);
|
envTargets.push(envTargetArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let envType: ProjectEnvType;
|
||||||
|
if (envTypeArg) {
|
||||||
|
if (!isValidEnvType(envTypeArg)) {
|
||||||
|
output.error(
|
||||||
|
`The Environment Variable type ${param(
|
||||||
|
envTypeArg
|
||||||
|
)} is invalid. It must be one of: ${getEnvTypePlaceholder()}.`
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
envType = envTypeArg;
|
||||||
|
} else {
|
||||||
|
const answers = (await inquirer.prompt({
|
||||||
|
name: 'inputEnvType',
|
||||||
|
type: 'list',
|
||||||
|
message: `Which type of Environment Variable do you want to add?`,
|
||||||
|
choices: [
|
||||||
|
{ name: 'Plaintext', value: ProjectEnvType.Plaintext },
|
||||||
|
{
|
||||||
|
name: `Secret (can be created using ${getCommandName('secret add')})`,
|
||||||
|
value: ProjectEnvType.Secret,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Reference to System Environment Variable',
|
||||||
|
value: ProjectEnvType.System,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})) as { inputEnvType: ProjectEnvType };
|
||||||
|
|
||||||
|
envType = answers.inputEnvType;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!envName) {
|
while (!envName) {
|
||||||
@@ -77,7 +115,10 @@ export default async function add(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const envs = await getEnvVariables(output, client, project.id, 4);
|
const [{ envs }, { systemEnvValues }] = await Promise.all([
|
||||||
|
getEnvVariables(output, client, project.id),
|
||||||
|
getSystemEnvValues(output, client, project.id),
|
||||||
|
]);
|
||||||
const existing = new Set(
|
const existing = new Set(
|
||||||
envs.filter(r => r.key === envName).map(r => r.target)
|
envs.filter(r => r.key === envName).map(r => r.target)
|
||||||
);
|
);
|
||||||
@@ -98,15 +139,59 @@ export default async function add(
|
|||||||
|
|
||||||
if (stdInput) {
|
if (stdInput) {
|
||||||
envValue = stdInput;
|
envValue = stdInput;
|
||||||
} else if (isSystemEnvVariable(envName)) {
|
} else if (envType === ProjectEnvType.Plaintext) {
|
||||||
envValue = '';
|
|
||||||
} else {
|
|
||||||
const { inputValue } = await inquirer.prompt({
|
const { inputValue } = await inquirer.prompt({
|
||||||
type: 'password',
|
type: 'input',
|
||||||
name: 'inputValue',
|
name: 'inputValue',
|
||||||
message: `What’s the value of ${envName}?`,
|
message: `What’s the value of ${envName}?`,
|
||||||
});
|
});
|
||||||
|
|
||||||
envValue = inputValue || '';
|
envValue = inputValue || '';
|
||||||
|
} else if (envType === ProjectEnvType.Secret) {
|
||||||
|
let secretId: string | null = null;
|
||||||
|
|
||||||
|
while (!secretId) {
|
||||||
|
let { secretName } = await inquirer.prompt({
|
||||||
|
type: 'input',
|
||||||
|
name: 'secretName',
|
||||||
|
message: `What’s the value of ${envName}?`,
|
||||||
|
});
|
||||||
|
|
||||||
|
secretName = secretName || '';
|
||||||
|
|
||||||
|
if (secretName[0] === '@') {
|
||||||
|
secretName = secretName.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const secret = await client.fetch<Secret>(
|
||||||
|
`/v2/now/secrets/${encodeURIComponent(secretName)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
secretId = secret.uid;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.status === 404) {
|
||||||
|
output.error(
|
||||||
|
`Please enter the name of an existing Secret (can be created with ${getCommandName(
|
||||||
|
'secret add'
|
||||||
|
)}).`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
envValue = secretId;
|
||||||
|
} else {
|
||||||
|
const { systemEnvValue } = await inquirer.prompt({
|
||||||
|
name: 'systemEnvValue',
|
||||||
|
type: 'list',
|
||||||
|
message: `What’s the value of ${envName}?`,
|
||||||
|
choices: systemEnvValues.map(value => ({ name: value, value })),
|
||||||
|
});
|
||||||
|
|
||||||
|
envValue = systemEnvValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (envTargets.length === 0) {
|
while (envTargets.length === 0) {
|
||||||
@@ -127,7 +212,15 @@ export default async function add(
|
|||||||
const addStamp = stamp();
|
const addStamp = stamp();
|
||||||
try {
|
try {
|
||||||
await withSpinner('Saving', () =>
|
await withSpinner('Saving', () =>
|
||||||
addEnvRecord(output, client, project.id, envName, envValue, envTargets)
|
addEnvRecord(
|
||||||
|
output,
|
||||||
|
client,
|
||||||
|
project.id,
|
||||||
|
envType,
|
||||||
|
envName,
|
||||||
|
envValue,
|
||||||
|
envTargets
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (isKnownError(error) && error.serverMessage) {
|
if (isKnownError(error) && error.serverMessage) {
|
||||||
@@ -148,7 +241,3 @@ export default async function add(
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSystemEnvVariable(envName: string) {
|
|
||||||
return envName.startsWith('VERCEL_');
|
|
||||||
}
|
|
||||||
|
|||||||
43
packages/now-cli/src/commands/env/index.ts
vendored
@@ -6,6 +6,7 @@ import getArgs from '../../util/get-args';
|
|||||||
import getSubcommand from '../../util/get-subcommand';
|
import getSubcommand from '../../util/get-subcommand';
|
||||||
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
||||||
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
|
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
|
||||||
|
import { getEnvTypePlaceholder } from '../../util/env/env-type';
|
||||||
import { getLinkedProject } from '../../util/projects/link';
|
import { getLinkedProject } from '../../util/projects/link';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import handleError from '../../util/handle-error';
|
import handleError from '../../util/handle-error';
|
||||||
@@ -18,16 +19,17 @@ import ls from './ls';
|
|||||||
import rm from './rm';
|
import rm from './rm';
|
||||||
|
|
||||||
const help = () => {
|
const help = () => {
|
||||||
const placeholder = getEnvTargetPlaceholder();
|
const typePlaceholder = getEnvTypePlaceholder();
|
||||||
|
const targetPlaceholder = getEnvTargetPlaceholder();
|
||||||
console.log(`
|
console.log(`
|
||||||
${chalk.bold(`${logo} ${getPkgName()} env`)} [options] <command>
|
${chalk.bold(`${logo} ${getPkgName()} env`)} [options] <command>
|
||||||
|
|
||||||
${chalk.dim('Commands:')}
|
${chalk.dim('Commands:')}
|
||||||
|
|
||||||
ls [environment] List all variables for the specified Environment
|
ls [environment] List all variables for the specified Environment
|
||||||
add [name] [environment] Add an Environment Variable (see examples below)
|
add [type] [name] [environment] Add an Environment Variable (see examples below)
|
||||||
rm [name] [environment] Remove an Environment Variable (see examples below)
|
rm [name] [environment] Remove an Environment Variable (see examples below)
|
||||||
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env]
|
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env]
|
||||||
|
|
||||||
${chalk.dim('Options:')}
|
${chalk.dim('Options:')}
|
||||||
|
|
||||||
@@ -42,27 +44,32 @@ const help = () => {
|
|||||||
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
|
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
|
||||||
'TOKEN'
|
'TOKEN'
|
||||||
)} Login token
|
)} Login token
|
||||||
-N, --next Show next page of results
|
|
||||||
|
|
||||||
${chalk.dim('Examples:')}
|
${chalk.dim('Examples:')}
|
||||||
|
|
||||||
${chalk.gray('–')} Add a new variable to multiple Environments
|
${chalk.gray('–')} Add a new variable to multiple Environments
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} env add <name>`)}
|
${chalk.cyan(`$ ${getPkgName()} env add ${typePlaceholder} <name>`)}
|
||||||
${chalk.cyan(`$ ${getPkgName()} env add API_TOKEN`)}
|
${chalk.cyan(`$ ${getPkgName()} env add secret API_TOKEN`)}
|
||||||
|
|
||||||
${chalk.gray('–')} Add a new variable for a specific Environment
|
${chalk.gray('–')} Add a new variable for a specific Environment
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} env add <name> ${placeholder}`)}
|
${chalk.cyan(
|
||||||
${chalk.cyan(`$ ${getPkgName()} env add DB_CONNECTION production`)}
|
`$ ${getPkgName()} env add ${typePlaceholder} <name> ${targetPlaceholder}`
|
||||||
|
)}
|
||||||
|
${chalk.cyan(`$ ${getPkgName()} env add secret DB_PASS production`)}
|
||||||
|
|
||||||
${chalk.gray('–')} Add a new Environment Variable from stdin
|
${chalk.gray('–')} Add a new Environment Variable from stdin
|
||||||
|
|
||||||
${chalk.cyan(
|
${chalk.cyan(
|
||||||
`$ cat <file> | ${getPkgName()} env add <name> ${placeholder}`
|
`$ cat <file> | ${getPkgName()} env add ${typePlaceholder} <name> ${targetPlaceholder}`
|
||||||
|
)}
|
||||||
|
${chalk.cyan(
|
||||||
|
`$ cat ~/.npmrc | ${getPkgName()} env add plain NPM_RC preview`
|
||||||
|
)}
|
||||||
|
${chalk.cyan(
|
||||||
|
`$ ${getPkgName()} env add plain API_URL production < url.txt`
|
||||||
)}
|
)}
|
||||||
${chalk.cyan(`$ cat ~/.npmrc | ${getPkgName()} env add NPM_RC preview`)}
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} env add DB_PASS production < secret.txt`)}
|
|
||||||
|
|
||||||
${chalk.gray('–')} Remove an variable from multiple Environments
|
${chalk.gray('–')} Remove an variable from multiple Environments
|
||||||
|
|
||||||
@@ -71,14 +78,8 @@ const help = () => {
|
|||||||
|
|
||||||
${chalk.gray('–')} Remove a variable from a specific Environment
|
${chalk.gray('–')} Remove a variable from a specific Environment
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} env rm <name> ${placeholder}`)}
|
${chalk.cyan(`$ ${getPkgName()} env rm <name> ${targetPlaceholder}`)}
|
||||||
${chalk.cyan(`$ ${getPkgName()} env rm NPM_RC preview`)}
|
${chalk.cyan(`$ ${getPkgName()} env rm NPM_RC preview`)}
|
||||||
|
|
||||||
${chalk.gray('–')} Paginate results, where ${chalk.dim(
|
|
||||||
'`1584722256178`'
|
|
||||||
)} is the time in milliseconds since the UNIX epoch.
|
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} env ls --next 1584722256178`)}
|
|
||||||
`);
|
`);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -96,8 +97,6 @@ export default async function main(ctx: NowContext) {
|
|||||||
argv = getArgs(ctx.argv.slice(2), {
|
argv = getArgs(ctx.argv.slice(2), {
|
||||||
'--yes': Boolean,
|
'--yes': Boolean,
|
||||||
'-y': '--yes',
|
'-y': '--yes',
|
||||||
'--next': Number,
|
|
||||||
'-N': '--next',
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error);
|
handleError(error);
|
||||||
|
|||||||
73
packages/now-cli/src/commands/env/ls.ts
vendored
@@ -1,7 +1,12 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import { ProjectEnvVariable, ProjectEnvTarget, Project } from '../../types';
|
import {
|
||||||
|
ProjectEnvTarget,
|
||||||
|
Project,
|
||||||
|
ProjectEnvVariable,
|
||||||
|
ProjectEnvType,
|
||||||
|
} from '../../types';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import formatTable from '../../util/format-table';
|
import formatTable from '../../util/format-table';
|
||||||
import getEnvVariables from '../../util/env/get-env-records';
|
import getEnvVariables from '../../util/env/get-env-records';
|
||||||
@@ -11,12 +16,13 @@ import {
|
|||||||
} from '../../util/env/env-target';
|
} from '../../util/env/env-target';
|
||||||
import stamp from '../../util/output/stamp';
|
import stamp from '../../util/output/stamp';
|
||||||
import param from '../../util/output/param';
|
import param from '../../util/output/param';
|
||||||
import getCommandFlags from '../../util/get-command-flags';
|
|
||||||
import { getCommandName } from '../../util/pkg-name';
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
|
import ellipsis from '../../util/output/ellipsis';
|
||||||
|
// @ts-ignore
|
||||||
|
import title from 'title';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
'--debug': boolean;
|
'--debug': boolean;
|
||||||
'--next'?: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function ls(
|
export default async function ls(
|
||||||
@@ -26,8 +32,6 @@ export default async function ls(
|
|||||||
args: string[],
|
args: string[],
|
||||||
output: Output
|
output: Output
|
||||||
) {
|
) {
|
||||||
const { '--next': nextTimestamp } = opts;
|
|
||||||
|
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${getCommandName(
|
`Invalid number of arguments. Usage: ${getCommandName(
|
||||||
@@ -50,42 +54,21 @@ export default async function ls(
|
|||||||
|
|
||||||
const lsStamp = stamp();
|
const lsStamp = stamp();
|
||||||
|
|
||||||
if (typeof nextTimestamp !== 'undefined' && Number.isNaN(nextTimestamp)) {
|
const { envs } = await getEnvVariables(output, client, project.id, envTarget);
|
||||||
output.error('Please provide a number for flag --next');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await getEnvVariables(
|
|
||||||
output,
|
|
||||||
client,
|
|
||||||
project.id,
|
|
||||||
5,
|
|
||||||
envTarget,
|
|
||||||
nextTimestamp
|
|
||||||
);
|
|
||||||
const { envs: records, pagination } = data;
|
|
||||||
output.log(
|
output.log(
|
||||||
`${
|
`${
|
||||||
records.length > 0 ? 'Environment Variables' : 'No Environment Variables'
|
envs.length > 0 ? 'Environment Variables' : 'No Environment Variables'
|
||||||
} found in Project ${chalk.bold(project.name)} ${chalk.gray(lsStamp())}`
|
} found in Project ${chalk.bold(project.name)} ${chalk.gray(lsStamp())}`
|
||||||
);
|
);
|
||||||
console.log(getTable(records));
|
console.log(getTable(envs));
|
||||||
|
|
||||||
if (pagination && pagination.count === 20) {
|
|
||||||
const flags = getCommandFlags(opts, ['_', '--next']);
|
|
||||||
output.log(
|
|
||||||
`To display the next page run ${getCommandName(
|
|
||||||
`env ls${flags} --next ${pagination.next}`
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTable(records: ProjectEnvVariable[]) {
|
function getTable(records: ProjectEnvVariable[]) {
|
||||||
return formatTable(
|
return formatTable(
|
||||||
['name', 'value', 'environment', 'created'],
|
['name', 'value', 'environments', 'created'],
|
||||||
['l', 'l', 'l', 'l', 'l'],
|
['l', 'l', 'l', 'l', 'l'],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -96,17 +79,27 @@ function getTable(records: ProjectEnvVariable[]) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRow({
|
function getRow(env: ProjectEnvVariable) {
|
||||||
key,
|
let value: string;
|
||||||
system = false,
|
if (env.type === ProjectEnvType.Plaintext) {
|
||||||
target,
|
// replace space characters (line-break, etc.) with simple spaces
|
||||||
createdAt = 0,
|
// to make sure the displayed value is a single line
|
||||||
}: ProjectEnvVariable) {
|
const singleLineValue = env.value.replace(/\s/g, ' ');
|
||||||
|
|
||||||
|
value = chalk.gray(ellipsis(singleLineValue, 19));
|
||||||
|
} else if (env.type === ProjectEnvType.System) {
|
||||||
|
value = chalk.gray.italic(env.value);
|
||||||
|
} else {
|
||||||
|
value = chalk.gray.italic('Encrypted');
|
||||||
|
}
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
return [
|
return [
|
||||||
chalk.bold(key),
|
chalk.bold(env.key),
|
||||||
chalk.gray(chalk.italic(system ? 'Populated by System' : 'Encrypted')),
|
value,
|
||||||
target || '',
|
(Array.isArray(env.target) ? env.target : [env.target || ''])
|
||||||
`${ms(now - createdAt)} ago`,
|
.map(title)
|
||||||
|
.join(', '),
|
||||||
|
env.createdAt ? `${ms(now - env.createdAt)} ago` : '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
38
packages/now-cli/src/commands/env/pull.ts
vendored
@@ -1,7 +1,7 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { ProjectEnvTarget, Project } from '../../types';
|
import { Project } from '../../types';
|
||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import promptBool from '../../util/prompt-bool';
|
import confirm from '../../util/input/confirm';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import stamp from '../../util/output/stamp';
|
import stamp from '../../util/output/stamp';
|
||||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||||
@@ -12,7 +12,8 @@ import { promises, openSync, closeSync, readSync } from 'fs';
|
|||||||
import { emoji, prependEmoji } from '../../util/emoji';
|
import { emoji, prependEmoji } from '../../util/emoji';
|
||||||
import { getCommandName } from '../../util/pkg-name';
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
const { writeFile } = promises;
|
const { writeFile } = promises;
|
||||||
import { Env } from '@vercel/build-utils';
|
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';
|
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
||||||
|
|
||||||
@@ -68,9 +69,9 @@ export default async function pull(
|
|||||||
} else if (
|
} else if (
|
||||||
exists &&
|
exists &&
|
||||||
!skipConfirmation &&
|
!skipConfirmation &&
|
||||||
!(await promptBool(
|
!(await confirm(
|
||||||
output,
|
`Found existing file ${param(filename)}. Do you want to overwrite?`,
|
||||||
`Found existing file ${param(filename)}. Do you want to overwrite?`
|
false
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
output.log('Aborted');
|
output.log('Aborted');
|
||||||
@@ -84,15 +85,22 @@ export default async function pull(
|
|||||||
);
|
);
|
||||||
const pullStamp = stamp();
|
const pullStamp = stamp();
|
||||||
|
|
||||||
const records: Env = await withSpinner(
|
const [
|
||||||
'Downloading',
|
{ envs: projectEnvs },
|
||||||
async () =>
|
{ systemEnvValues },
|
||||||
await getDecryptedEnvRecords(
|
] = await withSpinner('Downloading', () =>
|
||||||
output,
|
Promise.all([
|
||||||
client,
|
getDecryptedEnvRecords(output, client, project.id),
|
||||||
project,
|
project.autoExposeSystemEnvs
|
||||||
ProjectEnvTarget.Development
|
? getSystemEnvValues(output, client, project.id)
|
||||||
)
|
: { systemEnvValues: [] },
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
const records = exposeSystemEnvs(
|
||||||
|
projectEnvs,
|
||||||
|
systemEnvValues,
|
||||||
|
project.autoExposeSystemEnvs
|
||||||
);
|
);
|
||||||
|
|
||||||
const contents =
|
const contents =
|
||||||
|
|||||||
37
packages/now-cli/src/commands/env/rm.ts
vendored
@@ -1,8 +1,8 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import inquirer from 'inquirer';
|
import inquirer from 'inquirer';
|
||||||
import { ProjectEnvTarget, Project } from '../../types';
|
import { ProjectEnvTarget, Project, ProjectEnvVariableV5 } from '../../types';
|
||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import promptBool from '../../util/prompt-bool';
|
import confirm from '../../util/input/confirm';
|
||||||
import removeEnvRecord from '../../util/env/remove-env-record';
|
import removeEnvRecord from '../../util/env/remove-env-record';
|
||||||
import getEnvVariables from '../../util/env/get-env-records';
|
import getEnvVariables from '../../util/env/get-env-records';
|
||||||
import {
|
import {
|
||||||
@@ -30,6 +30,9 @@ export default async function rm(
|
|||||||
args: string[],
|
args: string[],
|
||||||
output: Output
|
output: Output
|
||||||
) {
|
) {
|
||||||
|
// improve the way we show inquirer prompts
|
||||||
|
require('../../util/input/patch-inquirer');
|
||||||
|
|
||||||
if (args.length > 2) {
|
if (args.length > 2) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments. Usage: ${getCommandName(
|
`Invalid number of arguments. Usage: ${getCommandName(
|
||||||
@@ -69,7 +72,20 @@ export default async function rm(
|
|||||||
envName = inputName;
|
envName = inputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const envs = await getEnvVariables(output, client, project.id, 4);
|
const data = await getEnvVariables(output, client, project.id);
|
||||||
|
|
||||||
|
// we expand env vars with multiple targets
|
||||||
|
const envs: ProjectEnvVariableV5[] = [];
|
||||||
|
for (let env of data.envs) {
|
||||||
|
if (Array.isArray(env.target)) {
|
||||||
|
for (let target of env.target) {
|
||||||
|
envs.push({ ...env, target });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
envs.push({ ...env, target: env.target });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const existing = new Set(
|
const existing = new Set(
|
||||||
envs.filter(r => r.key === envName).map(r => r.target)
|
envs.filter(r => r.key === envName).map(r => r.target)
|
||||||
);
|
);
|
||||||
@@ -79,7 +95,7 @@ export default async function rm(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (envTargets.length === 0) {
|
while (envTargets.length === 0) {
|
||||||
const choices = getEnvTargetChoices().filter(c => existing.has(c.value));
|
const choices = getEnvTargetChoices().filter(c => existing.has(c.value));
|
||||||
if (choices.length === 0) {
|
if (choices.length === 0) {
|
||||||
output.error(
|
output.error(
|
||||||
@@ -97,6 +113,13 @@ export default async function rm(
|
|||||||
message: `Remove ${envName} from which Environments (select multiple)?`,
|
message: `Remove ${envName} from which Environments (select multiple)?`,
|
||||||
choices,
|
choices,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (inputTargets.length === 0) {
|
||||||
|
output.error(
|
||||||
|
'Please select an Environment to remove the Environment Variable from.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
envTargets = inputTargets;
|
envTargets = inputTargets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,11 +127,11 @@ export default async function rm(
|
|||||||
const skipConfirmation = opts['--yes'];
|
const skipConfirmation = opts['--yes'];
|
||||||
if (
|
if (
|
||||||
!skipConfirmation &&
|
!skipConfirmation &&
|
||||||
!(await promptBool(
|
!(await confirm(
|
||||||
output,
|
|
||||||
`Removing Environment Variable ${param(
|
`Removing Environment Variable ${param(
|
||||||
envName
|
envName
|
||||||
)} from Project ${chalk.bold(project.name)}. Are you sure?`
|
)} from Project ${chalk.bold(project.name)}. Are you sure?`,
|
||||||
|
false
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
output.log('Aborted');
|
output.log('Aborted');
|
||||||
|
|||||||
@@ -51,12 +51,6 @@ const help = () => {
|
|||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} ls my-app`)}
|
${chalk.cyan(`$ ${getPkgName()} ls my-app`)}
|
||||||
|
|
||||||
${chalk.gray(
|
|
||||||
'–'
|
|
||||||
)} List all deployments and all instances for the app ${chalk.dim('`my-app`')}
|
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} ls my-app --all`)}
|
|
||||||
|
|
||||||
${chalk.gray('–')} Filter deployments by metadata
|
${chalk.gray('–')} Filter deployments by metadata
|
||||||
|
|
||||||
${chalk.cyan(`$ ${getPkgName()} ls -m key1=value1 -m key2=value2`)}
|
${chalk.cyan(`$ ${getPkgName()} ls -m key1=value1 -m key2=value2`)}
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ function printLogRaw(log) {
|
|||||||
|
|
||||||
if (log.object) {
|
if (log.object) {
|
||||||
console.log(log.object);
|
console.log(log.object);
|
||||||
} else {
|
} else if (typeof log.text === 'string') {
|
||||||
console.log(
|
console.log(
|
||||||
log.text
|
log.text
|
||||||
.replace(/\n$/, '')
|
.replace(/\n$/, '')
|
||||||
|
|||||||
@@ -117,12 +117,6 @@ export type Deployment = {
|
|||||||
creator: { uid: string };
|
creator: { uid: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
type PathAliasRule = {
|
|
||||||
pathname: string;
|
|
||||||
method: Array<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'>;
|
|
||||||
dest: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Alias = {
|
export type Alias = {
|
||||||
uid: string;
|
uid: string;
|
||||||
alias: string;
|
alias: string;
|
||||||
@@ -137,13 +131,6 @@ export type Alias = {
|
|||||||
email: string;
|
email: string;
|
||||||
};
|
};
|
||||||
deploymentId?: string;
|
deploymentId?: string;
|
||||||
rules?: PathAliasRule[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PathRule = {
|
|
||||||
dest: string;
|
|
||||||
pathname?: string;
|
|
||||||
method?: Array<string>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DNSRecord = {
|
export type DNSRecord = {
|
||||||
@@ -216,12 +203,23 @@ export enum ProjectEnvTarget {
|
|||||||
Development = 'development',
|
Development = 'development',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectEnvType {
|
||||||
|
Plaintext = 'plain',
|
||||||
|
Secret = 'secret',
|
||||||
|
System = 'system',
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProjectEnvVariable {
|
export interface ProjectEnvVariable {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
type: ProjectEnvType;
|
||||||
configurationId?: string | null;
|
configurationId?: string | null;
|
||||||
createdAt?: number;
|
createdAt?: number;
|
||||||
updatedAt?: number;
|
updatedAt?: number;
|
||||||
|
target?: ProjectEnvTarget | ProjectEnvTarget[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProjectEnvVariableV5 extends ProjectEnvVariable {
|
||||||
target?: ProjectEnvTarget;
|
target?: ProjectEnvTarget;
|
||||||
system?: boolean;
|
system?: boolean;
|
||||||
}
|
}
|
||||||
@@ -232,6 +230,8 @@ export interface ProjectSettings {
|
|||||||
buildCommand?: string | null;
|
buildCommand?: string | null;
|
||||||
outputDirectory?: string | null;
|
outputDirectory?: string | null;
|
||||||
rootDirectory?: string | null;
|
rootDirectory?: string | null;
|
||||||
|
autoExposeSystemEnvs?: boolean;
|
||||||
|
directoryListing?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Project extends ProjectSettings {
|
export interface Project extends ProjectSettings {
|
||||||
@@ -245,6 +245,7 @@ export interface Project extends ProjectSettings {
|
|||||||
framework?: string | null;
|
framework?: string | null;
|
||||||
rootDirectory?: string | null;
|
rootDirectory?: string | null;
|
||||||
latestDeployments?: Partial<Deployment>[];
|
latestDeployments?: Partial<Deployment>[];
|
||||||
|
autoExposeSystemEnvs?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Org {
|
export interface Org {
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ export default async function processDeployment({
|
|||||||
if (event.type === 'created') {
|
if (event.type === 'created') {
|
||||||
deployingSpinner();
|
deployingSpinner();
|
||||||
|
|
||||||
|
if (bar && !bar.complete) {
|
||||||
|
bar.tick(bar.total + 1);
|
||||||
|
}
|
||||||
|
|
||||||
now._host = event.payload.url;
|
now._host = event.payload.url;
|
||||||
|
|
||||||
await linkFolderToProject(
|
await linkFolderToProject(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import chalk from 'chalk';
|
||||||
import execa from 'execa';
|
import execa from 'execa';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import npa from 'npm-package-arg';
|
import npa from 'npm-package-arg';
|
||||||
@@ -8,9 +9,10 @@ import { mkdirp, readJSON, writeJSON } from 'fs-extra';
|
|||||||
import { NowBuildError, PackageJson } from '@vercel/build-utils';
|
import { NowBuildError, PackageJson } from '@vercel/build-utils';
|
||||||
import cliPkg from '../pkg';
|
import cliPkg from '../pkg';
|
||||||
|
|
||||||
import { NoBuilderCacheError } from '../errors-ts';
|
import cmd from '../output/cmd';
|
||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import { getDistTag } from '../get-dist-tag';
|
import { getDistTag } from '../get-dist-tag';
|
||||||
|
import { NoBuilderCacheError } from '../errors-ts';
|
||||||
|
|
||||||
import * as staticBuilder from './static-builder';
|
import * as staticBuilder from './static-builder';
|
||||||
import { BuilderWithPackage } from './types';
|
import { BuilderWithPackage } from './types';
|
||||||
@@ -261,7 +263,9 @@ async function npmInstall(
|
|||||||
throw new NowBuildError({
|
throw new NowBuildError({
|
||||||
message:
|
message:
|
||||||
(result as any).code === 'ENOENT'
|
(result as any).code === 'ENOENT'
|
||||||
? '`npm` is not installed'
|
? `Command not found: ${chalk.cyan(
|
||||||
|
'npm'
|
||||||
|
)}\nPlease ensure that ${cmd('npm')} is properly installed`
|
||||||
: 'Failed to install `vercel dev` dependencies',
|
: 'Failed to install `vercel dev` dependencies',
|
||||||
code: 'NPM_INSTALL_ERROR',
|
code: 'NPM_INSTALL_ERROR',
|
||||||
link: 'https://vercel.link/npm-install-failed-dev',
|
link: 'https://vercel.link/npm-install-failed-dev',
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ export async function executeBuild(
|
|||||||
filesRemoved,
|
filesRemoved,
|
||||||
// This env distiniction is only necessary to maintain
|
// This env distiniction is only necessary to maintain
|
||||||
// backwards compatibility with the `@vercel/next` builder.
|
// backwards compatibility with the `@vercel/next` builder.
|
||||||
env: envConfigs.runEnv,
|
env: { ...envConfigs.runEnv },
|
||||||
buildEnv: envConfigs.buildEnv,
|
buildEnv: { ...envConfigs.buildEnv },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ export async function getBuildMatches(
|
|||||||
const builds = nowConfig.builds || [{ src: '**', use: '@vercel/static' }];
|
const builds = nowConfig.builds || [{ src: '**', use: '@vercel/static' }];
|
||||||
|
|
||||||
for (const buildConfig of builds) {
|
for (const buildConfig of builds) {
|
||||||
let { src, use } = buildConfig;
|
let { src = '**', use } = buildConfig;
|
||||||
|
|
||||||
if (!use) {
|
if (!use) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
41
packages/now-cli/src/util/dev/expose-system-envs.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { ProjectEnvType, ProjectEnvVariable } from '../../types';
|
||||||
|
import { Env } from '@vercel/build-utils';
|
||||||
|
|
||||||
|
function getSystemEnvValue(
|
||||||
|
systemEnvRef: string,
|
||||||
|
{ vercelUrl }: { vercelUrl?: string }
|
||||||
|
) {
|
||||||
|
if (systemEnvRef === 'VERCEL_URL') {
|
||||||
|
return vercelUrl || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function exposeSystemEnvs(
|
||||||
|
projectEnvs: ProjectEnvVariable[],
|
||||||
|
systemEnvValues: string[],
|
||||||
|
autoExposeSystemEnvs: boolean | undefined,
|
||||||
|
vercelUrl?: string
|
||||||
|
) {
|
||||||
|
const envs: Env = {};
|
||||||
|
|
||||||
|
if (autoExposeSystemEnvs) {
|
||||||
|
envs['VERCEL'] = '1';
|
||||||
|
envs['VERCEL_ENV'] = 'development';
|
||||||
|
|
||||||
|
for (const key of systemEnvValues) {
|
||||||
|
envs[key] = getSystemEnvValue(key, { vercelUrl });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let env of projectEnvs) {
|
||||||
|
if (env.type === ProjectEnvType.System) {
|
||||||
|
envs[env.key] = getSystemEnvValue(env.value, { vercelUrl });
|
||||||
|
} else {
|
||||||
|
envs[env.key] = env.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return envs;
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ import {
|
|||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import _frameworks, { Framework } from '@vercel/frameworks';
|
import _frameworks, { Framework } from '@vercel/frameworks';
|
||||||
|
|
||||||
|
import cmd from '../output/cmd';
|
||||||
import link from '../output/link';
|
import link from '../output/link';
|
||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import { relative } from '../path-helpers';
|
import { relative } from '../path-helpers';
|
||||||
@@ -85,7 +86,8 @@ import {
|
|||||||
HttpHeadersConfig,
|
HttpHeadersConfig,
|
||||||
EnvConfigs,
|
EnvConfigs,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { ProjectSettings } from '../../types';
|
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
||||||
|
import exposeSystemEnvs from './expose-system-envs';
|
||||||
|
|
||||||
const frameworkList = _frameworks as Framework[];
|
const frameworkList = _frameworks as Framework[];
|
||||||
const frontendRuntimeSet = new Set(
|
const frontendRuntimeSet = new Set(
|
||||||
@@ -149,14 +151,16 @@ export default class DevServer {
|
|||||||
private updateBuildersTimeout: NodeJS.Timeout | undefined;
|
private updateBuildersTimeout: NodeJS.Timeout | undefined;
|
||||||
private startPromise: Promise<void> | null;
|
private startPromise: Promise<void> | null;
|
||||||
|
|
||||||
private environmentVars: Env | undefined;
|
private systemEnvValues: string[];
|
||||||
|
private projectEnvs: ProjectEnvVariable[];
|
||||||
|
|
||||||
constructor(cwd: string, options: DevServerOptions) {
|
constructor(cwd: string, options: DevServerOptions) {
|
||||||
this.cwd = cwd;
|
this.cwd = cwd;
|
||||||
this.debug = options.debug;
|
this.debug = options.debug;
|
||||||
this.output = options.output;
|
this.output = options.output;
|
||||||
this.envConfigs = { buildEnv: {}, runEnv: {}, allEnv: {} };
|
this.envConfigs = { buildEnv: {}, runEnv: {}, allEnv: {} };
|
||||||
this.environmentVars = options.environmentVars;
|
this.systemEnvValues = options.systemEnvValues || [];
|
||||||
|
this.projectEnvs = options.projectEnvs || [];
|
||||||
this.files = {};
|
this.files = {};
|
||||||
this.address = '';
|
this.address = '';
|
||||||
this.devCommand = options.devCommand;
|
this.devCommand = options.devCommand;
|
||||||
@@ -491,7 +495,7 @@ export default class DevServer {
|
|||||||
const dotenv = await fs.readFile(filePath, 'utf8');
|
const dotenv = await fs.readFile(filePath, 'utf8');
|
||||||
this.output.debug(`Using local env: ${filePath}`);
|
this.output.debug(`Using local env: ${filePath}`);
|
||||||
env = parseDotenv(dotenv);
|
env = parseDotenv(dotenv);
|
||||||
env = this.populateVercelEnvVars(env);
|
env = this.injectSystemValuesInDotenv(env);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code !== 'ENOENT') {
|
if (err.code !== 'ENOENT') {
|
||||||
throw err;
|
throw err;
|
||||||
@@ -642,10 +646,30 @@ export default class DevServer {
|
|||||||
|
|
||||||
let allEnv = { ...buildEnv, ...runEnv };
|
let allEnv = { ...buildEnv, ...runEnv };
|
||||||
|
|
||||||
// If no .env/.build.env is present, fetch and use cloud environment variables
|
// If no .env/.build.env is present, use cloud environment variables
|
||||||
if (Object.keys(allEnv).length === 0) {
|
if (Object.keys(allEnv).length === 0) {
|
||||||
const cloudEnv = this.populateVercelEnvVars(this.environmentVars);
|
const cloudEnv = exposeSystemEnvs(
|
||||||
allEnv = runEnv = buildEnv = cloudEnv;
|
this.projectEnvs || [],
|
||||||
|
this.systemEnvValues || [],
|
||||||
|
this.projectSettings?.autoExposeSystemEnvs,
|
||||||
|
new URL(this.address).host
|
||||||
|
);
|
||||||
|
|
||||||
|
allEnv = { ...cloudEnv };
|
||||||
|
runEnv = { ...cloudEnv };
|
||||||
|
buildEnv = { ...cloudEnv };
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy NOW_REGION env variable
|
||||||
|
runEnv['NOW_REGION'] = 'dev1';
|
||||||
|
buildEnv['NOW_REGION'] = 'dev1';
|
||||||
|
allEnv['NOW_REGION'] = 'dev1';
|
||||||
|
|
||||||
|
// mirror how VERCEL_REGION is injected in prod/preview
|
||||||
|
// only inject in `runEnvs`, because `allEnvs` is exposed to dev command
|
||||||
|
// and should not contain VERCEL_REGION
|
||||||
|
if (this.projectSettings?.autoExposeSystemEnvs) {
|
||||||
|
runEnv['VERCEL_REGION'] = 'dev1';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.envConfigs = { buildEnv, runEnv, allEnv };
|
this.envConfigs = { buildEnv, runEnv, allEnv };
|
||||||
@@ -753,23 +777,15 @@ export default class DevServer {
|
|||||||
return merged;
|
return merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
populateVercelEnvVars(env: Env | undefined): Env {
|
injectSystemValuesInDotenv(env: Env): Env {
|
||||||
if (!env) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const name of Object.keys(env)) {
|
for (const name of Object.keys(env)) {
|
||||||
if (name === 'VERCEL_URL') {
|
if (name === 'VERCEL_URL') {
|
||||||
const host = new URL(this.address).host;
|
env['VERCEL_URL'] = new URL(this.address).host;
|
||||||
env['VERCEL_URL'] = host;
|
|
||||||
} else if (name === 'VERCEL_REGION') {
|
} else if (name === 'VERCEL_REGION') {
|
||||||
env['VERCEL_REGION'] = 'dev1';
|
env['VERCEL_REGION'] = 'dev1';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always set NOW_REGION to match production
|
|
||||||
env['NOW_REGION'] = 'dev1';
|
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +887,7 @@ export default class DevServer {
|
|||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
this.updateBuildersPromise = null;
|
this.updateBuildersPromise = null;
|
||||||
this.output.error(`Failed to update builders: ${err.message}`);
|
this.output.prettyError(err);
|
||||||
this.output.debug(err.stack);
|
this.output.debug(err.stack);
|
||||||
});
|
});
|
||||||
}, ms('30s'));
|
}, ms('30s'));
|
||||||
@@ -923,9 +939,17 @@ export default class DevServer {
|
|||||||
await once(this.watcher, 'ready');
|
await once(this.watcher, 'ready');
|
||||||
|
|
||||||
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
||||||
this.server.on('upgrade', (req, socket, head) => {
|
this.server.on('upgrade', async (req, socket, head) => {
|
||||||
|
await this.startPromise;
|
||||||
|
if (!this.devProcessPort) {
|
||||||
|
this.output.debug(
|
||||||
|
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
||||||
|
);
|
||||||
|
socket.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const target = `http://localhost:${this.devProcessPort}`;
|
const target = `http://localhost:${this.devProcessPort}`;
|
||||||
this.output.debug(`Detected upgrade event, proxying to ${target}`);
|
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
||||||
this.proxy.ws(req, socket, head, { target });
|
this.proxy.ws(req, socket, head, { target });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1364,6 +1388,7 @@ export default class DevServer {
|
|||||||
const missRoutes = handleMap.get('miss') || [];
|
const missRoutes = handleMap.get('miss') || [];
|
||||||
const hitRoutes = handleMap.get('hit') || [];
|
const hitRoutes = handleMap.get('hit') || [];
|
||||||
const errorRoutes = handleMap.get('error') || [];
|
const errorRoutes = handleMap.get('error') || [];
|
||||||
|
const filesystemRoutes = handleMap.get('filesystem') || [];
|
||||||
const phases: (HandleValue | null)[] = [null, 'filesystem'];
|
const phases: (HandleValue | null)[] = [null, 'filesystem'];
|
||||||
|
|
||||||
let routeResult: RouteResult | null = null;
|
let routeResult: RouteResult | null = null;
|
||||||
@@ -1481,6 +1506,11 @@ export default class DevServer {
|
|||||||
// end the phase
|
// end the phase
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phase === null && filesystemRoutes.length === 0) {
|
||||||
|
// hack to skip the reset from null to filesystem
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match && routeResult && errorRoutes.length > 0) {
|
if (!match && routeResult && errorRoutes.length > 0) {
|
||||||
@@ -1644,15 +1674,24 @@ export default class DevServer {
|
|||||||
isDev: true,
|
isDev: true,
|
||||||
requestPath,
|
requestPath,
|
||||||
devCacheDir,
|
devCacheDir,
|
||||||
env: envConfigs.runEnv,
|
env: { ...envConfigs.runEnv },
|
||||||
buildEnv: envConfigs.buildEnv,
|
buildEnv: { ...envConfigs.buildEnv },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// `startDevServer()` threw an error. Most likely this means the dev
|
// `startDevServer()` threw an error. Most likely this means the dev
|
||||||
// server process exited before sending the port information message
|
// server process exited before sending the port information message
|
||||||
// (missing dependency at runtime, for example).
|
// (missing dependency at runtime, for example).
|
||||||
debug(`Error starting "${builderPkg.name}" dev server: ${err}`);
|
if (err.code === 'ENOENT') {
|
||||||
|
err.message = `Command not found: ${chalk.cyan(
|
||||||
|
err.path,
|
||||||
|
...err.spawnargs
|
||||||
|
)}\nPlease ensure that ${cmd(err.path)} is properly installed`;
|
||||||
|
err.link = 'https://vercel.link/command-not-found';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.output.prettyError(err);
|
||||||
|
|
||||||
await this.sendError(
|
await this.sendError(
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
@@ -1865,6 +1904,12 @@ export default class DevServer {
|
|||||||
requestPath: string,
|
requestPath: string,
|
||||||
nowRequestId: string
|
nowRequestId: string
|
||||||
): boolean {
|
): boolean {
|
||||||
|
// If the "directory listing" feature is disabled in the
|
||||||
|
// Project's settings, then don't render the directory listing
|
||||||
|
if (this.projectSettings?.directoryListing === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let prefix = requestPath;
|
let prefix = requestPath;
|
||||||
if (prefix.length > 0 && !prefix.endsWith('/')) {
|
if (prefix.length > 0 && !prefix.endsWith('/')) {
|
||||||
prefix += '/';
|
prefix += '/';
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
import { NowConfig } from '@vercel/client';
|
import { NowConfig } from '@vercel/client';
|
||||||
import { HandleValue, Route } from '@vercel/routing-utils';
|
import { HandleValue, Route } from '@vercel/routing-utils';
|
||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import { ProjectSettings } from '../../types';
|
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
||||||
|
|
||||||
export { NowConfig };
|
export { NowConfig };
|
||||||
|
|
||||||
@@ -27,7 +27,8 @@ export interface DevServerOptions {
|
|||||||
devCommand?: string;
|
devCommand?: string;
|
||||||
frameworkSlug?: string;
|
frameworkSlug?: string;
|
||||||
projectSettings?: ProjectSettings;
|
projectSettings?: ProjectSettings;
|
||||||
environmentVars?: Env;
|
systemEnvValues?: string[];
|
||||||
|
projectEnvs?: ProjectEnvVariable[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnvConfigs {
|
export interface EnvConfigs {
|
||||||
@@ -49,6 +50,7 @@ export interface EnvConfigs {
|
|||||||
|
|
||||||
export interface BuildMatch extends BuildConfig {
|
export interface BuildMatch extends BuildConfig {
|
||||||
entrypoint: string;
|
entrypoint: string;
|
||||||
|
src: string;
|
||||||
builderWithPkg: BuilderWithPackage;
|
builderWithPkg: BuilderWithPackage;
|
||||||
buildOutput: BuilderOutputs;
|
buildOutput: BuilderOutputs;
|
||||||
buildResults: Map<string | null, BuildResult>;
|
buildResults: Map<string | null, BuildResult>;
|
||||||
|
|||||||
57
packages/now-cli/src/util/env/add-env-record.ts
vendored
@@ -1,60 +1,39 @@
|
|||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import Client from '../client';
|
import Client from '../client';
|
||||||
import { Secret, ProjectEnvTarget, ProjectEnvVariable } from '../../types';
|
import {
|
||||||
import { customAlphabet } from 'nanoid';
|
Secret,
|
||||||
import slugify from '@sindresorhus/slugify';
|
ProjectEnvTarget,
|
||||||
|
ProjectEnvVariableV5,
|
||||||
|
ProjectEnvType,
|
||||||
|
} from '../../types';
|
||||||
|
|
||||||
export default async function addEnvRecord(
|
export default async function addEnvRecord(
|
||||||
output: Output,
|
output: Output,
|
||||||
client: Client,
|
client: Client,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
envName: string,
|
type: ProjectEnvType,
|
||||||
envValue: string | undefined,
|
key: string,
|
||||||
|
envValue: string,
|
||||||
targets: ProjectEnvTarget[]
|
targets: ProjectEnvTarget[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
output.debug(
|
output.debug(
|
||||||
`Adding Environment Variable ${envName} to ${targets.length} targets`
|
`Adding ${type} Environment Variable ${key} to ${targets.length} targets`
|
||||||
);
|
);
|
||||||
|
|
||||||
let values: string[] | undefined;
|
let value = envValue;
|
||||||
|
|
||||||
if (envValue) {
|
if (type === ProjectEnvType.Secret) {
|
||||||
const secrets = await Promise.all(
|
const secret = await client.fetch<Secret>(
|
||||||
targets.map(target =>
|
`/v2/now/secrets/${encodeURIComponent(envValue)}`
|
||||||
client.fetch<Secret>('/v2/now/secrets', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: generateSecretName(envName, target),
|
|
||||||
value: envValue,
|
|
||||||
projectId: projectId,
|
|
||||||
decryptable: target === ProjectEnvTarget.Development,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
values = secrets.map(secret => secret.uid);
|
value = secret.uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = targets.map((target, i) => ({
|
const body = { type, key, value, target: targets };
|
||||||
key: envName,
|
|
||||||
value: values ? values[i] : '',
|
|
||||||
target,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const urlProject = `/v4/projects/${projectId}/env`;
|
const urlProject = `/v6/projects/${projectId}/env`;
|
||||||
await client.fetch<ProjectEnvVariable>(urlProject, {
|
await client.fetch<ProjectEnvVariableV5>(urlProject, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const randomSecretSuffix = customAlphabet(
|
|
||||||
'123456789abcdefghijklmnopqrstuvwxyz',
|
|
||||||
4
|
|
||||||
);
|
|
||||||
|
|
||||||
function generateSecretName(envName: string, target: ProjectEnvTarget) {
|
|
||||||
return `${
|
|
||||||
slugify(envName).substring(0, 80) // we truncate because the max secret length is 100
|
|
||||||
}-${target}-${randomSecretSuffix()}`;
|
|
||||||
}
|
|
||||||
|
|||||||
15
packages/now-cli/src/util/env/env-type.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ProjectEnvType } from '../../types';
|
||||||
|
|
||||||
|
function envTypes(): string[] {
|
||||||
|
return Object.values(ProjectEnvType);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isValidEnvType(
|
||||||
|
type?: string
|
||||||
|
): type is ProjectEnvType | undefined {
|
||||||
|
return typeof type === 'undefined' || envTypes().includes(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEnvTypePlaceholder() {
|
||||||
|
return `<${envTypes().join(' | ')}>`;
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { Output } from '../output';
|
|
||||||
import Client from '../client';
|
|
||||||
import { Secret } from '../../types';
|
|
||||||
|
|
||||||
export default async function getDecryptedSecret(
|
|
||||||
output: Output,
|
|
||||||
client: Client,
|
|
||||||
secretId: string
|
|
||||||
): Promise<string> {
|
|
||||||
if (!secretId) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
output.debug(`Fetching decrypted secret ${secretId}`);
|
|
||||||
const url = `/v2/now/secrets/${secretId}?decrypt=true`;
|
|
||||||
const secret = await client.fetch<Secret>(url);
|
|
||||||
return secret.value;
|
|
||||||
}
|
|
||||||
51
packages/now-cli/src/util/env/get-env-records.ts
vendored
@@ -1,69 +1,24 @@
|
|||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import Client from '../client';
|
import Client from '../client';
|
||||||
import {
|
import { ProjectEnvVariable, ProjectEnvTarget } from '../../types';
|
||||||
ProjectEnvVariable,
|
|
||||||
ProjectEnvTarget,
|
|
||||||
PaginationOptions,
|
|
||||||
} from '../../types';
|
|
||||||
import { URLSearchParams } from 'url';
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
type ApiVersion = 4 | 5;
|
|
||||||
|
|
||||||
type APIV4Response = ProjectEnvVariable[];
|
|
||||||
|
|
||||||
interface APIV5Response {
|
|
||||||
pagination: PaginationOptions;
|
|
||||||
envs: ProjectEnvVariable[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function getEnvVariables(
|
export default async function getEnvVariables(
|
||||||
output: Output,
|
output: Output,
|
||||||
client: Client,
|
client: Client,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
apiVersion: 4,
|
|
||||||
target?: ProjectEnvTarget
|
target?: ProjectEnvTarget
|
||||||
): Promise<APIV4Response>;
|
|
||||||
|
|
||||||
export default async function getEnvVariables(
|
|
||||||
output: Output,
|
|
||||||
client: Client,
|
|
||||||
projectId: string,
|
|
||||||
apiVersion: 5,
|
|
||||||
target?: ProjectEnvTarget,
|
|
||||||
next?: number
|
|
||||||
): Promise<APIV5Response>;
|
|
||||||
|
|
||||||
export default async function getEnvVariables<V extends ApiVersion>(
|
|
||||||
output: Output,
|
|
||||||
client: Client,
|
|
||||||
projectId: string,
|
|
||||||
apiVersion: V,
|
|
||||||
target?: ProjectEnvTarget,
|
|
||||||
next?: number
|
|
||||||
) {
|
) {
|
||||||
output.debug(
|
output.debug(
|
||||||
`Fetching Environment Variables of project ${projectId} and target ${target}`
|
`Fetching Environment Variables of project ${projectId} and target ${target}`
|
||||||
);
|
);
|
||||||
const query = new URLSearchParams();
|
const query = new URLSearchParams();
|
||||||
if (apiVersion >= 5) {
|
|
||||||
query.set('limit', String(20));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
query.set('target', target);
|
query.set('target', target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next) {
|
const url = `/v6/projects/${projectId}/env?${query}`;
|
||||||
query.set('until', String(next));
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `/v${apiVersion}/projects/${projectId}/env?${query}`;
|
return client.fetch<{ envs: ProjectEnvVariable[] }>(url);
|
||||||
|
|
||||||
if (apiVersion === 5) {
|
|
||||||
return client.fetch<APIV5Response>(url);
|
|
||||||
} else if (apiVersion === 4) {
|
|
||||||
return client.fetch<APIV4Response>(url);
|
|
||||||
} else {
|
|
||||||
throw new Error('Unknown version: ' + apiVersion);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
12
packages/now-cli/src/util/env/get-system-env-values.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Output } from '../output';
|
||||||
|
import Client from '../client';
|
||||||
|
|
||||||
|
export default async function getSystemEnvValues(
|
||||||
|
output: Output,
|
||||||
|
client: Client,
|
||||||
|
projectId: string
|
||||||
|
) {
|
||||||
|
output.debug(`Fetching System Environment Values of project ${projectId}`);
|
||||||
|
const url = `/v6/projects/${projectId}/system-env-values`;
|
||||||
|
return client.fetch<{ systemEnvValues: string[] }>(url);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import Client from '../client';
|
import Client from '../client';
|
||||||
import { ProjectEnvTarget, Secret, ProjectEnvVariable } from '../../types';
|
import { ProjectEnvTarget, ProjectEnvVariableV5 } from '../../types';
|
||||||
|
|
||||||
export default async function removeEnvRecord(
|
export default async function removeEnvRecord(
|
||||||
output: Output,
|
output: Output,
|
||||||
@@ -18,32 +18,7 @@ export default async function removeEnvRecord(
|
|||||||
envName
|
envName
|
||||||
)}${qs}`;
|
)}${qs}`;
|
||||||
|
|
||||||
const env = await client.fetch<ProjectEnvVariable>(urlProject, {
|
await client.fetch<ProjectEnvVariableV5>(urlProject, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (env && env.value) {
|
|
||||||
const idOrName = env.value.startsWith('@') ? env.value.slice(1) : env.value;
|
|
||||||
const urlSecret = `/v2/now/secrets/${idOrName}`;
|
|
||||||
let secret: Secret | undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
secret = await client.fetch<Secret>(urlSecret);
|
|
||||||
} catch (error) {
|
|
||||||
if (error && error.status === 404) {
|
|
||||||
// User likely deleted the secret before the env var, so we can still report success
|
|
||||||
output.debug(
|
|
||||||
`Skipped ${env.key} because secret ${idOrName} was already deleted`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since integrations add global secrets, we must only delete if the secret was
|
|
||||||
// specifically added to this project
|
|
||||||
if (secret && secret.projectId === projectId) {
|
|
||||||
await client.fetch<Secret>(urlSecret, { method: 'DELETE' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,65 @@
|
|||||||
import getEnvVariables from './env/get-env-records';
|
|
||||||
import getDecryptedSecret from './env/get-decrypted-secret';
|
|
||||||
import Client from './client';
|
import Client from './client';
|
||||||
import { Output } from './output/create-output';
|
import { Output } from './output/create-output';
|
||||||
import { ProjectEnvTarget, Project } from '../types';
|
import {
|
||||||
|
ProjectEnvTarget,
|
||||||
import { Env } from '@vercel/build-utils';
|
ProjectEnvType,
|
||||||
|
ProjectEnvVariable,
|
||||||
|
Secret,
|
||||||
|
} from '../types';
|
||||||
|
import getEnvRecords from './env/get-env-records';
|
||||||
|
|
||||||
export default async function getDecryptedEnvRecords(
|
export default async function getDecryptedEnvRecords(
|
||||||
output: Output,
|
output: Output,
|
||||||
client: Client,
|
client: Client,
|
||||||
project: Project,
|
projectId: string
|
||||||
target: ProjectEnvTarget
|
): Promise<{ envs: ProjectEnvVariable[] }> {
|
||||||
): Promise<Env> {
|
const { envs } = await getEnvRecords(
|
||||||
const envs = await getEnvVariables(output, client, project.id, 4, target);
|
output,
|
||||||
const decryptedValues = await Promise.all(
|
client,
|
||||||
envs.map(async env => {
|
projectId,
|
||||||
try {
|
ProjectEnvTarget.Development
|
||||||
const value = await getDecryptedSecret(output, client, env.value);
|
);
|
||||||
return { value, found: true };
|
|
||||||
} catch (error) {
|
const envsWithDecryptedSecrets = await Promise.all(
|
||||||
if (error && error.status === 404) {
|
envs.map(async ({ type, key, value }) => {
|
||||||
return { value: '', found: false };
|
// it's not possible to create secret env variables for development
|
||||||
|
// anymore but we keep this because legacy env variables with "decryptable"
|
||||||
|
// secret values still exit in our system
|
||||||
|
if (type === ProjectEnvType.Secret) {
|
||||||
|
try {
|
||||||
|
const secretIdOrName = value;
|
||||||
|
|
||||||
|
if (!secretIdOrName) {
|
||||||
|
return { type, key, value: '', found: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
output.debug(`Fetching decrypted secret ${secretIdOrName}`);
|
||||||
|
const secret = await client.fetch<Secret>(
|
||||||
|
`/v2/now/secrets/${secretIdOrName}?decrypt=true`
|
||||||
|
);
|
||||||
|
|
||||||
|
return { type, key, value: secret.value, found: true };
|
||||||
|
} catch (error) {
|
||||||
|
if (error && error.status === 404) {
|
||||||
|
return { type, key, value: '', found: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { type, key, value, found: true };
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const results: Env = {};
|
for (let env of envsWithDecryptedSecrets) {
|
||||||
for (let i = 0; i < decryptedValues.length; i++) {
|
if (!env.found) {
|
||||||
const { key } = envs[i];
|
|
||||||
const { value, found } = decryptedValues[i];
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
output.print('');
|
output.print('');
|
||||||
output.warn(
|
output.warn(
|
||||||
`Unable to download variable ${key} because associated secret was deleted`
|
`Unable to download variable ${env.key} because associated secret was deleted`
|
||||||
);
|
);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
results[key] = value ? value : '';
|
|
||||||
}
|
}
|
||||||
return results;
|
|
||||||
|
return { envs: envsWithDecryptedSecrets };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import chalk from 'chalk';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/base.js#L126
|
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/base.js#L126
|
||||||
const getQuestion = function() {
|
const getQuestion = function () {
|
||||||
let message = `${chalk.gray('?')} ${this.opt.message} `;
|
let message = `${chalk.gray('?')} ${this.opt.message} `;
|
||||||
|
|
||||||
if (this.opt.type === 'confirm') {
|
if (this.opt.type === 'confirm') {
|
||||||
@@ -35,7 +35,7 @@ inquirer.prompt.prompts.input.prototype.getQuestion = getQuestion;
|
|||||||
inquirer.prompt.prompts.confirm.prototype.getQuestion = getQuestion;
|
inquirer.prompt.prompts.confirm.prototype.getQuestion = getQuestion;
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/list.js#L80
|
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/list.js#L80
|
||||||
inquirer.prompt.prompts.list.prototype.render = function() {
|
inquirer.prompt.prompts.list.prototype.render = function () {
|
||||||
// Render question
|
// Render question
|
||||||
let message = this.getQuestion();
|
let message = this.getQuestion();
|
||||||
|
|
||||||
@@ -89,11 +89,22 @@ function listRender(choices, pointer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/checkbox.js#L84
|
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/checkbox.js#L84
|
||||||
inquirer.prompt.prompts.checkbox.prototype.render = function(error) {
|
inquirer.prompt.prompts.checkbox.prototype.render = function (error) {
|
||||||
// Render question
|
// Render question
|
||||||
let message = this.getQuestion();
|
let message = this.getQuestion();
|
||||||
let bottomContent = '';
|
let bottomContent = '';
|
||||||
|
|
||||||
|
if (!this.spaceKeyPressed) {
|
||||||
|
message +=
|
||||||
|
'(Press ' +
|
||||||
|
chalk.cyan.bold('<space>') +
|
||||||
|
' to select, ' +
|
||||||
|
chalk.cyan.bold('<a>') +
|
||||||
|
' to toggle all, ' +
|
||||||
|
chalk.cyan.bold('<i>') +
|
||||||
|
' to invert selection)';
|
||||||
|
}
|
||||||
|
|
||||||
// Render choices or answer depending on the state
|
// Render choices or answer depending on the state
|
||||||
if (this.status === 'answered') {
|
if (this.status === 'answered') {
|
||||||
message += this.selection.length > 0 ? this.selection.join(', ') : 'None';
|
message += this.selection.length > 0 ? this.selection.join(', ') : 'None';
|
||||||
@@ -118,7 +129,7 @@ function renderChoices(choices, pointer) {
|
|||||||
let output = '';
|
let output = '';
|
||||||
let separatorOffset = 0;
|
let separatorOffset = 0;
|
||||||
|
|
||||||
choices.forEach(function(choice, i) {
|
choices.forEach(function (choice, i) {
|
||||||
if (choice.type === 'separator') {
|
if (choice.type === 'separator') {
|
||||||
separatorOffset++;
|
separatorOffset++;
|
||||||
output += '' + choice + '\n';
|
output += '' + choice + '\n';
|
||||||
@@ -151,7 +162,7 @@ function renderChoices(choices, pointer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/input.js#L44
|
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/input.js#L44
|
||||||
inquirer.prompt.prompts.input.prototype.render = function(error) {
|
inquirer.prompt.prompts.input.prototype.render = function (error) {
|
||||||
let bottomContent = '';
|
let bottomContent = '';
|
||||||
let appendContent = '';
|
let appendContent = '';
|
||||||
let message = this.getQuestion();
|
let message = this.getQuestion();
|
||||||
@@ -178,7 +189,7 @@ inquirer.prompt.prompts.input.prototype.render = function(error) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/confirm.js#L64
|
// adjusted from https://github.com/SBoudrias/Inquirer.js/blob/942908f17319343d1acc7b876f990797c5695918/packages/inquirer/lib/prompts/confirm.js#L64
|
||||||
inquirer.prompt.prompts.confirm.prototype.render = function(answer) {
|
inquirer.prompt.prompts.confirm.prototype.render = function (answer) {
|
||||||
let message = this.getQuestion();
|
let message = this.getQuestion();
|
||||||
|
|
||||||
if (this.status === 'answered') {
|
if (this.status === 'answered') {
|
||||||
|
|||||||
3
packages/now-cli/src/util/output/ellipsis.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default function ellipsis(str: string, length: number) {
|
||||||
|
return str.length > length ? `${str.slice(0, length - 1)}…` : str;
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import chalk from 'chalk';
|
|
||||||
import { Output } from './output';
|
|
||||||
|
|
||||||
async function promptBool(output: Output, message: string): Promise<boolean> {
|
|
||||||
return new Promise<boolean>(resolve => {
|
|
||||||
output.print(`${chalk.gray('>')} ${message} ${chalk.gray('[y/N] ')}`);
|
|
||||||
process.stdin
|
|
||||||
.on('data', d => {
|
|
||||||
process.stdin.pause();
|
|
||||||
resolve(
|
|
||||||
d
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.toLowerCase() === 'y'
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.resume();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default promptBool;
|
|
||||||
3
packages/now-cli/test/dev/fixtures/10a-nextjs-routes/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
.vercel
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"workspaces": [
|
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "9.5.1",
|
"next": "9.5.3",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1"
|
"react-dom": "16.13.1"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = (_req, res) => {
|
||||||
|
res.end('Hello Routes');
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
function Index() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<h1>Next.js with routes</h1>
|
||||||
|
<a href="/hello">/hello</a>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Index;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"routes": [{ "src": "/hello", "dest": "/api/hello" }]
|
||||||
|
}
|
||||||
4
packages/now-cli/test/dev/fixtures/30-next-image-optimization/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.next
|
||||||
|
!public
|
||||||
|
yarn.lock
|
||||||
|
.vercel
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
"build": "next build"
|
"build": "next build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "canary",
|
"next": "canary",
|
||||||
"react": "^16.8.6",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^16.8.6"
|
"react-dom": "^17.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Home Page</h1>
|
||||||
|
<hr />
|
||||||
|
<h2>Optimized</h2>
|
||||||
|
<Image src="/test.png" width="400" height="400" />
|
||||||
|
<hr />
|
||||||
|
<h2>Original</h2>
|
||||||
|
<img src="/test.png" width="400" height="400" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="400.000000pt" height="400.000000pt" viewBox="0 0 400.000000 400.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M0 2000 l0 -2000 2000 0 2000 0 0 2000 0 2000 -2000 0 -2000 0 0
|
||||||
|
-2000z m2401 118 l396 -693 -398 -3 c-220 -1 -578 -1 -798 0 l-398 3 396 693
|
||||||
|
c217 380 398 692 401 692 3 0 184 -312 401 -692z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 635 B |
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"build": {
|
||||||
|
"env": {
|
||||||
|
"FORCE_BUILDER_TAG": "canary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
packages/now-cli/test/dev/fixtures/missing-src-property/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package.json
|
||||||
|
yarn.lock
|
||||||
|
.now
|
||||||
|
.vercel
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
hello:index.txt
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"builds": [
|
||||||
|
{
|
||||||
|
"use": "@vercel/static"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -128,14 +128,13 @@ async function testPath(
|
|||||||
status,
|
status,
|
||||||
path,
|
path,
|
||||||
expectedText,
|
expectedText,
|
||||||
headers = {},
|
expectedHeaders = {},
|
||||||
method = 'GET',
|
fetchOpts = {}
|
||||||
body = undefined
|
|
||||||
) {
|
) {
|
||||||
const opts = { redirect: 'manual-dont-change', method, body };
|
const opts = { ...fetchOpts, redirect: 'manual-dont-change' };
|
||||||
const url = `${origin}${path}`;
|
const url = `${origin}${path}`;
|
||||||
const res = await fetch(url, opts);
|
const res = await fetch(url, opts);
|
||||||
const msg = `Testing response from ${method} ${url}`;
|
const msg = `Testing response from ${fetchOpts.method || 'GET'} ${url}`;
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
t.is(res.status, status, msg);
|
t.is(res.status, status, msg);
|
||||||
validateResponseHeaders(t, res);
|
validateResponseHeaders(t, res);
|
||||||
@@ -150,8 +149,8 @@ async function testPath(
|
|||||||
expectedText.lastIndex = 0; // reset since we test twice
|
expectedText.lastIndex = 0; // reset since we test twice
|
||||||
t.regex(actualText, expectedText);
|
t.regex(actualText, expectedText);
|
||||||
}
|
}
|
||||||
if (headers) {
|
if (expectedHeaders) {
|
||||||
Object.entries(headers).forEach(([key, expectedValue]) => {
|
Object.entries(expectedHeaders).forEach(([key, expectedValue]) => {
|
||||||
let actualValue = res.headers.get(key);
|
let actualValue = res.headers.get(key);
|
||||||
if (key.toLowerCase() === 'location' && actualValue === '//') {
|
if (key.toLowerCase() === 'location' && actualValue === '//') {
|
||||||
// HACK: `node-fetch` has strange behavior for location header so fix it
|
// HACK: `node-fetch` has strange behavior for location header so fix it
|
||||||
@@ -233,7 +232,7 @@ async function testFixture(directory, opts = {}, args = []) {
|
|||||||
function testFixtureStdio(
|
function testFixtureStdio(
|
||||||
directory,
|
directory,
|
||||||
fn,
|
fn,
|
||||||
{ expectedCode = 0, skipDeploy, isExample } = {}
|
{ expectedCode = 0, skipDeploy, isExample, projectSettings } = {}
|
||||||
) {
|
) {
|
||||||
return async t => {
|
return async t => {
|
||||||
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
||||||
@@ -250,24 +249,51 @@ function testFixtureStdio(
|
|||||||
|
|
||||||
// Deploy fixture and link project
|
// Deploy fixture and link project
|
||||||
if (!skipDeploy) {
|
if (!skipDeploy) {
|
||||||
const project = join(cwd, '.vercel', 'project.json');
|
const projectJsonPath = join(cwd, '.vercel', 'project.json');
|
||||||
if (await fs.exists(project)) {
|
await fs.remove(projectJsonPath);
|
||||||
await fs.unlink(project);
|
|
||||||
}
|
|
||||||
const gitignore = join(cwd, '.gitignore');
|
const gitignore = join(cwd, '.gitignore');
|
||||||
const gitignoreOrig = await fs.exists(gitignore);
|
const hasGitignore = await fs.exists(gitignore);
|
||||||
let { stdout, stderr, exitCode } = await execa(
|
|
||||||
binaryPath,
|
try {
|
||||||
['-t', token, '--confirm', '--public', '--no-clipboard', '--debug'],
|
// Run `vc link`
|
||||||
{ cwd, reject: false }
|
const { exitCode: linkExitCode } = await execa(
|
||||||
);
|
binaryPath,
|
||||||
console.log({ stdout, stderr, exitCode });
|
['-t', token, 'link', '--confirm'],
|
||||||
if (!gitignoreOrig && (await fs.exists(gitignore))) {
|
{ cwd, stdio: 'inherit', reject: false }
|
||||||
await fs.unlink(gitignore);
|
);
|
||||||
}
|
t.is(linkExitCode, 0);
|
||||||
t.is(exitCode, expectedCode);
|
|
||||||
if (expectedCode === 0) {
|
// Patch the project with any non-default properties
|
||||||
deploymentUrl = new URL(stdout).host;
|
if (projectSettings) {
|
||||||
|
const { projectId } = await fs.readJson(projectJsonPath);
|
||||||
|
const res = await fetch(
|
||||||
|
`https://api.vercel.com/v2/projects/${projectId}`,
|
||||||
|
{
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(projectSettings),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
t.is(res.status, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run `vc deploy`
|
||||||
|
let { exitCode, stdout } = await execa(
|
||||||
|
binaryPath,
|
||||||
|
['-t', token, 'deploy', '--public', '--no-clipboard', '--debug'],
|
||||||
|
{ cwd, stdio: ['ignore', 'pipe', 'inherit'], reject: false }
|
||||||
|
);
|
||||||
|
console.log({ exitCode, stdout });
|
||||||
|
t.is(exitCode, expectedCode);
|
||||||
|
if (expectedCode === 0) {
|
||||||
|
deploymentUrl = new URL(stdout).host;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (!hasGitignore) {
|
||||||
|
await fs.remove(gitignore);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,9 +413,12 @@ test(
|
|||||||
async testPath => {
|
async testPath => {
|
||||||
await testPath(200, '/', /<div id="redwood-app">/m);
|
await testPath(200, '/', /<div id="redwood-app">/m);
|
||||||
await testPath(200, '/about', /<div id="redwood-app">/m);
|
await testPath(200, '/about', /<div id="redwood-app">/m);
|
||||||
const reqBody = '{"query":"{redwood{version}}"}';
|
const fetchOpts = {
|
||||||
|
method: 'POST',
|
||||||
|
body: '{"query":"{redwood{version}}"}',
|
||||||
|
};
|
||||||
const resBody = '{"data":{"redwood":{"version":"0.15.0"}}}';
|
const resBody = '{"data":{"redwood":{"version":"0.15.0"}}}';
|
||||||
await testPath(200, '/api/graphql', resBody, {}, 'POST', reqBody);
|
await testPath(200, '/api/graphql', resBody, {}, fetchOpts);
|
||||||
},
|
},
|
||||||
{ isExample: true }
|
{ isExample: true }
|
||||||
)
|
)
|
||||||
@@ -620,14 +649,6 @@ test(
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
/*
|
|
||||||
test(
|
|
||||||
'[vercel dev] displays directory listing after miss',
|
|
||||||
testFixtureStdio('handle-miss-display-dir-list', async (testPath) => {
|
|
||||||
await testPath(404, '/post', /one.html/m);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'[vercel dev] does not display directory listing after 404',
|
'[vercel dev] does not display directory listing after 404',
|
||||||
@@ -945,12 +966,16 @@ test(
|
|||||||
'Access-Control-Allow-Methods':
|
'Access-Control-Allow-Methods':
|
||||||
'GET, POST, OPTIONS, HEAD, PATCH, PUT, DELETE',
|
'GET, POST, OPTIONS, HEAD, PATCH, PUT, DELETE',
|
||||||
};
|
};
|
||||||
await testPath(200, '/', 'status api', headers, 'GET');
|
await testPath(200, '/', 'status api', headers, { method: 'GET' });
|
||||||
await testPath(200, '/', 'status api', headers, 'POST');
|
await testPath(200, '/', 'status api', headers, { method: 'POST' });
|
||||||
await testPath(200, '/api/status.js', 'status api', headers, 'GET');
|
await testPath(200, '/api/status.js', 'status api', headers, {
|
||||||
await testPath(200, '/api/status.js', 'status api', headers, 'POST');
|
method: 'GET',
|
||||||
await testPath(204, '/', '', headers, 'OPTIONS');
|
});
|
||||||
await testPath(204, '/api/status.js', '', headers, 'OPTIONS');
|
await testPath(200, '/api/status.js', 'status api', headers, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
await testPath(204, '/', '', headers, { method: 'OPTIONS' });
|
||||||
|
await testPath(204, '/api/status.js', '', headers, { method: 'OPTIONS' });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1050,12 +1075,16 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'[vercel dev] 00-list-directory',
|
'[vercel dev] 00-list-directory',
|
||||||
testFixtureStdio('00-list-directory', async testPath => {
|
testFixtureStdio(
|
||||||
await testPath(200, '/', /Files within/m);
|
'00-list-directory',
|
||||||
await testPath(200, '/', /test[0-3]\.txt/m);
|
async testPath => {
|
||||||
await testPath(200, '/', /\.well-known/m);
|
await testPath(200, '/', /Files within/m);
|
||||||
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
|
await testPath(200, '/', /test[0-3]\.txt/m);
|
||||||
})
|
await testPath(200, '/', /\.well-known/m);
|
||||||
|
await testPath(200, '/.well-known/keybase.txt', 'proof goes here');
|
||||||
|
},
|
||||||
|
{ projectSettings: { directoryListing: true } }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
@@ -1180,6 +1209,14 @@ test(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'[vercel dev] 10a-nextjs-routes',
|
||||||
|
testFixtureStdio('10a-nextjs-routes', async testPath => {
|
||||||
|
await testPath(200, '/', /Next.js with routes/m);
|
||||||
|
await testPath(200, '/hello', /Hello Routes/m);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'[vercel dev] 12-polymer-node',
|
'[vercel dev] 12-polymer-node',
|
||||||
testFixtureStdio(
|
testFixtureStdio(
|
||||||
@@ -1587,6 +1624,61 @@ test(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'[vercel dev] 30-next-image-optimization',
|
||||||
|
testFixtureStdio('30-next-image-optimization', async testPath => {
|
||||||
|
const toUrl = (url, w, q) => {
|
||||||
|
const query = new URLSearchParams();
|
||||||
|
query.append('url', url);
|
||||||
|
query.append('w', w);
|
||||||
|
query.append('q', q);
|
||||||
|
return `/_next/image?${query}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectHeader = accept => ({
|
||||||
|
'content-type': accept,
|
||||||
|
'cache-control': 'public, max-age=0, must-revalidate',
|
||||||
|
});
|
||||||
|
const fetchOpts = accept => ({ method: 'GET', headers: { accept } });
|
||||||
|
await testPath(200, '/', /Home Page/m);
|
||||||
|
await testPath(
|
||||||
|
200,
|
||||||
|
toUrl('/test.jpg', 64, 100),
|
||||||
|
null,
|
||||||
|
expectHeader('image/webp'),
|
||||||
|
fetchOpts('image/webp')
|
||||||
|
);
|
||||||
|
await testPath(
|
||||||
|
200,
|
||||||
|
toUrl('/test.png', 64, 90),
|
||||||
|
null,
|
||||||
|
expectHeader('image/webp'),
|
||||||
|
fetchOpts('image/webp')
|
||||||
|
);
|
||||||
|
await testPath(
|
||||||
|
200,
|
||||||
|
toUrl('/test.gif', 64, 80),
|
||||||
|
null,
|
||||||
|
expectHeader('image/webp'),
|
||||||
|
fetchOpts('image/webp')
|
||||||
|
);
|
||||||
|
await testPath(
|
||||||
|
200,
|
||||||
|
toUrl('/test.svg', 64, 70),
|
||||||
|
null,
|
||||||
|
expectHeader('image/svg+xml'),
|
||||||
|
fetchOpts('image/webp')
|
||||||
|
);
|
||||||
|
await testPath(
|
||||||
|
200,
|
||||||
|
toUrl('/animated.gif', 64, 60),
|
||||||
|
null,
|
||||||
|
expectHeader('image/gif'),
|
||||||
|
fetchOpts('image/gif')
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'[vercel dev] Use `@vercel/python` with Flask requirements.txt',
|
'[vercel dev] Use `@vercel/python` with Flask requirements.txt',
|
||||||
testFixtureStdio('python-flask', async testPath => {
|
testFixtureStdio('python-flask', async testPath => {
|
||||||
@@ -1687,3 +1779,11 @@ test(
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'[vercel dev] Do not fail if `src` is missing',
|
||||||
|
testFixtureStdio('missing-src-property', async testPath => {
|
||||||
|
await testPath(200, '/', /hello:index.txt/m);
|
||||||
|
await testPath(404, '/i-do-not-exist');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ module.exports = async function prepare(session) {
|
|||||||
'first.png': getImageFile(session, { size: 30 }),
|
'first.png': getImageFile(session, { size: 30 }),
|
||||||
'second.png': getImageFile(session, { size: 20 }),
|
'second.png': getImageFile(session, { size: 20 }),
|
||||||
},
|
},
|
||||||
'single-dotfile': {
|
|
||||||
'.testing': 'i am a dotfile',
|
|
||||||
},
|
|
||||||
'empty-directory': {},
|
'empty-directory': {},
|
||||||
'config-scope-property-email': {
|
'config-scope-property-email': {
|
||||||
'now.json': `{ "scope": "${session}@zeit.pub", "builds": [ { "src": "*.html", "use": "@now/static" } ] }`,
|
'now.json': `{ "scope": "${session}@zeit.pub", "builds": [ { "src": "*.html", "use": "@now/static" } ] }`,
|
||||||
@@ -207,23 +204,6 @@ module.exports = async function prepare(session) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
'alias-rules': {
|
|
||||||
'rules.json': JSON.stringify({
|
|
||||||
rules: [
|
|
||||||
// for example:
|
|
||||||
// { pathname: '/', dest: '' },
|
|
||||||
// { pathname: '/', dest: '', method: 'GET' }
|
|
||||||
// Will be generated by the actual test
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
'invalid-rules.json': JSON.stringify({
|
|
||||||
what: { what: 0 },
|
|
||||||
}),
|
|
||||||
'invalid-type-rules.json': JSON.stringify({
|
|
||||||
rules: { what: 0 },
|
|
||||||
}),
|
|
||||||
'invalid-json-rules.json': '==ok',
|
|
||||||
},
|
|
||||||
'zero-config-next-js': {
|
'zero-config-next-js': {
|
||||||
'pages/index.js':
|
'pages/index.js':
|
||||||
'export default () => <div><h1>Now CLI test</h1><p>Zero-config + Next.js</p></div>',
|
'export default () => <div><h1>Now CLI test</h1><p>Zero-config + Next.js</p></div>',
|
||||||
|
|||||||
374
packages/now-cli/test/integration.js
vendored
@@ -422,6 +422,19 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createSecret() {
|
||||||
|
const name = `my-secret${Math.floor(Math.random() * 10000)}`;
|
||||||
|
|
||||||
|
const res = await apiFetch('/v2/now/secrets', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ name, value: 'my secret' }),
|
||||||
|
});
|
||||||
|
|
||||||
|
t.is(res.status, 200);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
async function nowEnvLsIsEmpty() {
|
async function nowEnvLsIsEmpty() {
|
||||||
const { exitCode, stderr, stdout } = await execa(
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
@@ -436,26 +449,34 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.regex(stderr, /No Environment Variables found in Project/gm);
|
t.regex(stderr, /No Environment Variables found in Project/gm);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvAdd() {
|
async function nowEnvAddPlaintext() {
|
||||||
const now = execa(binaryPath, ['env', 'add', ...defaultArgs], {
|
const now = execa(binaryPath, ['env', 'add', ...defaultArgs], {
|
||||||
reject: false,
|
reject: false,
|
||||||
cwd: target,
|
cwd: target,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await waitForPrompt(now, chunk =>
|
||||||
|
chunk.includes('Which type of Environment Variable do you want to add?')
|
||||||
|
);
|
||||||
|
now.stdin.write('\n'); // select plaintext
|
||||||
|
|
||||||
await waitForPrompt(now, chunk =>
|
await waitForPrompt(now, chunk =>
|
||||||
chunk.includes('What’s the name of the variable?')
|
chunk.includes('What’s the name of the variable?')
|
||||||
);
|
);
|
||||||
now.stdin.write('MY_ENV_VAR\n');
|
now.stdin.write('MY_PLAINTEXT_ENV_VAR\n');
|
||||||
await waitForPrompt(
|
await waitForPrompt(
|
||||||
now,
|
now,
|
||||||
chunk =>
|
chunk =>
|
||||||
chunk.includes('What’s the value of') && chunk.includes('MY_ENV_VAR')
|
chunk.includes('What’s the value of') &&
|
||||||
|
chunk.includes('MY_PLAINTEXT_ENV_VAR')
|
||||||
);
|
);
|
||||||
now.stdin.write('MY_VALUE\n');
|
now.stdin.write('my plaintext value\n');
|
||||||
|
|
||||||
await waitForPrompt(
|
await waitForPrompt(
|
||||||
now,
|
now,
|
||||||
chunk =>
|
chunk =>
|
||||||
chunk.includes('which Environments') && chunk.includes('MY_ENV_VAR')
|
chunk.includes('which Environments') &&
|
||||||
|
chunk.includes('MY_PLAINTEXT_ENV_VAR')
|
||||||
);
|
);
|
||||||
now.stdin.write('a\n'); // select all
|
now.stdin.write('a\n'); // select all
|
||||||
|
|
||||||
@@ -464,10 +485,47 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function nowEnvAddSecret(secretName) {
|
||||||
|
const now = execa(binaryPath, ['env', 'add', ...defaultArgs], {
|
||||||
|
reject: false,
|
||||||
|
cwd: target,
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitForPrompt(now, chunk =>
|
||||||
|
chunk.includes('Which type of Environment Variable do you want to add?')
|
||||||
|
);
|
||||||
|
now.stdin.write('j\n'); // select secret
|
||||||
|
|
||||||
|
await waitForPrompt(now, chunk =>
|
||||||
|
chunk.includes('What’s the name of the variable?')
|
||||||
|
);
|
||||||
|
now.stdin.write('MY_SECRET_ENV_VAR\n');
|
||||||
|
|
||||||
|
await waitForPrompt(
|
||||||
|
now,
|
||||||
|
chunk =>
|
||||||
|
chunk.includes('What’s the value of') &&
|
||||||
|
chunk.includes('MY_SECRET_ENV_VAR')
|
||||||
|
);
|
||||||
|
now.stdin.write(`@${secretName}\n`);
|
||||||
|
|
||||||
|
await waitForPrompt(
|
||||||
|
now,
|
||||||
|
chunk =>
|
||||||
|
chunk.includes('which Environments') &&
|
||||||
|
chunk.includes('MY_SECRET_ENV_VAR')
|
||||||
|
);
|
||||||
|
now.stdin.write('j \n'); // select preview
|
||||||
|
|
||||||
|
const { exitCode, stderr, stdout } = await now;
|
||||||
|
|
||||||
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
}
|
||||||
|
|
||||||
async function nowEnvAddFromStdin() {
|
async function nowEnvAddFromStdin() {
|
||||||
const now = execa(
|
const now = execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['env', 'add', 'MY_STDIN_VAR', 'development', ...defaultArgs],
|
['env', 'add', 'plain', 'MY_STDIN_VAR', 'development', ...defaultArgs],
|
||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
cwd: target,
|
cwd: target,
|
||||||
@@ -481,13 +539,20 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
async function nowEnvAddSystemEnv() {
|
async function nowEnvAddSystemEnv() {
|
||||||
const now = execa(
|
const now = execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['env', 'add', 'VERCEL_URL', ...defaultArgs],
|
['env', 'add', 'system', 'NEXT_PUBLIC_VERCEL_URL', ...defaultArgs],
|
||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
cwd: target,
|
cwd: target,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await waitForPrompt(
|
||||||
|
now,
|
||||||
|
chunk =>
|
||||||
|
chunk.includes('What’s the value of') && chunk.includes('VERCEL_URL')
|
||||||
|
);
|
||||||
|
now.stdin.write(`\n`); // select VERCEL_URL
|
||||||
|
|
||||||
await waitForPrompt(
|
await waitForPrompt(
|
||||||
now,
|
now,
|
||||||
chunk =>
|
chunk =>
|
||||||
@@ -513,23 +578,63 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
t.regex(stderr, /Environment Variables found in Project/gm);
|
t.regex(stderr, /Environment Variables found in Project/gm);
|
||||||
|
|
||||||
|
console.log(stdout);
|
||||||
|
|
||||||
const lines = stdout.split('\n');
|
const lines = stdout.split('\n');
|
||||||
|
|
||||||
const myEnvVars = lines.filter(line => line.includes('MY_ENV_VAR'));
|
const plaintextEnvs = lines.filter(line =>
|
||||||
t.is(myEnvVars.length, 3);
|
line.includes('MY_PLAINTEXT_ENV_VAR')
|
||||||
t.regex(myEnvVars.join('\n'), /development/gm);
|
);
|
||||||
t.regex(myEnvVars.join('\n'), /preview/gm);
|
t.is(plaintextEnvs.length, 1);
|
||||||
t.regex(myEnvVars.join('\n'), /production/gm);
|
t.regex(plaintextEnvs[0], /Production, Preview, Development/gm);
|
||||||
|
|
||||||
const myStdinVars = lines.filter(line => line.includes('MY_STDIN_VAR'));
|
const secretEnvs = lines.filter(line => line.includes('MY_SECRET_ENV_VAR'));
|
||||||
t.is(myStdinVars.length, 1);
|
t.is(secretEnvs.length, 1);
|
||||||
t.regex(myStdinVars.join('\n'), /development/gm);
|
t.regex(secretEnvs[0], /Preview/gm);
|
||||||
|
|
||||||
const vercelVars = lines.filter(line => line.includes('VERCEL_URL'));
|
const stdinEnvs = lines.filter(line => line.includes('MY_STDIN_VAR'));
|
||||||
t.is(vercelVars.length, 3);
|
t.is(stdinEnvs.length, 1);
|
||||||
t.regex(vercelVars.join('\n'), /development/gm);
|
t.regex(stdinEnvs[0], /Development/gm);
|
||||||
t.regex(vercelVars.join('\n'), /preview/gm);
|
|
||||||
t.regex(vercelVars.join('\n'), /production/gm);
|
const systemEnvs = lines.filter(line => line.includes('VERCEL_URL'));
|
||||||
|
t.is(systemEnvs.length, 1);
|
||||||
|
t.regex(systemEnvs[0], /VERCEL_URL/gm);
|
||||||
|
t.regex(systemEnvs[0], /Production, Preview, Development/gm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we create a "legacy" env variable that contains a decryptable secret
|
||||||
|
// to check that vc env pull and vc dev work correctly with decryptable secrets
|
||||||
|
async function createEnvWithDecryptableSecret() {
|
||||||
|
console.log('creating an env variable with a decryptable secret');
|
||||||
|
|
||||||
|
const name = `my-secret${Math.floor(Math.random() * 10000)}`;
|
||||||
|
|
||||||
|
const res = await apiFetch('/v2/now/secrets', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
name,
|
||||||
|
value: 'decryptable value',
|
||||||
|
decryptable: true,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
t.is(res.status, 200);
|
||||||
|
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
const link = require(path.join(target, '.vercel/project.json'));
|
||||||
|
|
||||||
|
const resEnv = await apiFetch(`/v4/projects/${link.projectId}/env`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
key: 'MY_DECRYPTABLE_SECRET_ENV',
|
||||||
|
value: json.uid,
|
||||||
|
target: ['development'],
|
||||||
|
type: 'secret',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
t.is(resEnv.status, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvPull() {
|
async function nowEnvPull() {
|
||||||
@@ -549,9 +654,10 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.true(contents.startsWith('# Created by Vercel CLI\n'));
|
t.true(contents.startsWith('# Created by Vercel CLI\n'));
|
||||||
|
|
||||||
const lines = new Set(contents.split('\n'));
|
const lines = new Set(contents.split('\n'));
|
||||||
t.true(lines.has('MY_ENV_VAR="MY_VALUE"'));
|
t.true(lines.has('MY_PLAINTEXT_ENV_VAR="my plaintext value"'));
|
||||||
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'));
|
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'));
|
||||||
t.true(lines.has('VERCEL_URL=""'));
|
t.true(lines.has('NEXT_PUBLIC_VERCEL_URL=""'));
|
||||||
|
t.true(lines.has('MY_DECRYPTABLE_SECRET_ENV="decryptable value"'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvPullOverwrite() {
|
async function nowEnvPullOverwrite() {
|
||||||
@@ -603,16 +709,18 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
const apiRes = await fetch(apiUrl);
|
const apiRes = await fetch(apiUrl);
|
||||||
t.is(apiRes.status, 200, formatOutput({ stderr, stdout }));
|
t.is(apiRes.status, 200, formatOutput({ stderr, stdout }));
|
||||||
const apiJson = await apiRes.json();
|
const apiJson = await apiRes.json();
|
||||||
t.is(apiJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(apiJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
t.is(apiJson['VERCEL_URL'], host);
|
t.is(apiJson['MY_SECRET_ENV_VAR'], 'my secret');
|
||||||
|
t.is(apiJson['NEXT_PUBLIC_VERCEL_URL'], host);
|
||||||
|
|
||||||
const homeUrl = `https://${host}`;
|
const homeUrl = `https://${host}`;
|
||||||
console.log({ homeUrl });
|
console.log({ homeUrl });
|
||||||
const homeRes = await fetch(homeUrl);
|
const homeRes = await fetch(homeUrl);
|
||||||
t.is(homeRes.status, 200, formatOutput({ stderr, stdout }));
|
t.is(homeRes.status, 200, formatOutput({ stderr, stdout }));
|
||||||
const homeJson = await homeRes.json();
|
const homeJson = await homeRes.json();
|
||||||
t.is(homeJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(homeJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
t.is(homeJson['VERCEL_URL'], host);
|
t.is(homeJson['MY_SECRET_ENV_VAR'], 'my secret');
|
||||||
|
t.is(homeJson['NEXT_PUBLIC_VERCEL_URL'], host);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowDevWithEnv() {
|
async function nowDevWithEnv() {
|
||||||
@@ -630,8 +738,6 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
const localhostNoProtocol = localhost[0].slice('http://'.length);
|
|
||||||
|
|
||||||
const apiUrl = `${localhost[0]}/api/get-env`;
|
const apiUrl = `${localhost[0]}/api/get-env`;
|
||||||
const apiRes = await fetch(apiUrl);
|
const apiRes = await fetch(apiUrl);
|
||||||
|
|
||||||
@@ -639,15 +745,17 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
|
|
||||||
const apiJson = await apiRes.json();
|
const apiJson = await apiRes.json();
|
||||||
|
|
||||||
t.is(apiJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(apiJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
t.is(apiJson['VERCEL_URL'], localhostNoProtocol);
|
t.is(apiJson['NEXT_PUBLIC_VERCEL_URL'], '');
|
||||||
|
t.is(apiJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||||
|
|
||||||
const homeUrl = localhost[0];
|
const homeUrl = localhost[0];
|
||||||
|
|
||||||
const homeRes = await fetch(homeUrl);
|
const homeRes = await fetch(homeUrl);
|
||||||
const homeJson = await homeRes.json();
|
const homeJson = await homeRes.json();
|
||||||
t.is(homeJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(homeJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
t.is(homeJson['VERCEL_URL'], localhostNoProtocol);
|
t.is(homeJson['NEXT_PUBLIC_VERCEL_URL'], '');
|
||||||
|
t.is(homeJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||||
|
|
||||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||||
|
|
||||||
@@ -679,14 +787,105 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
|
|
||||||
const apiJson = await apiRes.json();
|
const apiJson = await apiRes.json();
|
||||||
|
|
||||||
t.is(apiJson['VERCEL_URL'], localhostNoProtocol);
|
t.is(apiJson['NEXT_PUBLIC_VERCEL_URL'], localhostNoProtocol);
|
||||||
t.is(apiJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(apiJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
|
t.is(apiJson['MY_STDIN_VAR'], '{"expect":"quotes"}');
|
||||||
|
t.is(apiJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||||
|
|
||||||
const homeUrl = localhost[0];
|
const homeUrl = localhost[0];
|
||||||
const homeRes = await fetch(homeUrl);
|
const homeRes = await fetch(homeUrl);
|
||||||
const homeJson = await homeRes.json();
|
const homeJson = await homeRes.json();
|
||||||
t.is(homeJson['MY_ENV_VAR'], 'MY_VALUE');
|
t.is(homeJson['MY_PLAINTEXT_ENV_VAR'], 'my plaintext value');
|
||||||
|
t.is(homeJson['NEXT_PUBLIC_VERCEL_URL'], localhostNoProtocol);
|
||||||
|
t.is(homeJson['MY_STDIN_VAR'], '{"expect":"quotes"}');
|
||||||
|
t.is(homeJson['MY_DECRYPTABLE_SECRET_ENV'], 'decryptable value');
|
||||||
|
|
||||||
|
// system env vars are automatically exposed
|
||||||
|
t.is(apiJson['VERCEL'], '1');
|
||||||
|
t.is(homeJson['VERCEL'], '1');
|
||||||
|
|
||||||
|
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||||
|
|
||||||
|
const { exitCode, stderr, stdout } = await vc;
|
||||||
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function enableAutoExposeSystemEnvs() {
|
||||||
|
const link = require(path.join(target, '.vercel/project.json'));
|
||||||
|
|
||||||
|
const res = await apiFetch(`/v2/projects/${link.projectId}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify({ autoExposeSystemEnvs: true }),
|
||||||
|
});
|
||||||
|
|
||||||
|
t.is(res.status, 200);
|
||||||
|
if (res.status === 200) {
|
||||||
|
console.log(
|
||||||
|
`Set autoExposeSystemEnvs=true for project ${link.projectId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function nowEnvPullFetchSystemVars() {
|
||||||
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
|
binaryPath,
|
||||||
|
['env', 'pull', '-y', ...defaultArgs],
|
||||||
|
{
|
||||||
|
reject: false,
|
||||||
|
cwd: target,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
|
||||||
|
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||||
|
|
||||||
|
const lines = new Set(contents.split('\n'));
|
||||||
|
t.true(lines.has('VERCEL="1"'));
|
||||||
|
t.true(lines.has('VERCEL_URL=""'));
|
||||||
|
t.true(lines.has('NEXT_PUBLIC_VERCEL_URL=""'));
|
||||||
|
t.true(lines.has('VERCEL_ENV="development"'));
|
||||||
|
t.true(lines.has('VERCEL_GIT_PROVIDER=""'));
|
||||||
|
t.true(lines.has('VERCEL_GIT_REPO_SLUG=""'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function nowDevAndFetchSystemVars() {
|
||||||
|
const vc = execa(binaryPath, ['dev', ...defaultArgs], {
|
||||||
|
reject: false,
|
||||||
|
cwd: target,
|
||||||
|
});
|
||||||
|
|
||||||
|
let localhost = undefined;
|
||||||
|
await waitForPrompt(vc, chunk => {
|
||||||
|
if (chunk.includes('Ready! Available at')) {
|
||||||
|
localhost = /(https?:[^\s]+)/g.exec(chunk);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const apiUrl = `${localhost[0]}/api/get-env`;
|
||||||
|
const apiRes = await fetch(apiUrl);
|
||||||
|
|
||||||
|
const localhostNoProtocol = localhost[0].slice('http://'.length);
|
||||||
|
|
||||||
|
const apiJson = await apiRes.json();
|
||||||
|
t.is(apiJson['VERCEL'], '1');
|
||||||
|
t.is(apiJson['VERCEL_URL'], localhostNoProtocol);
|
||||||
|
t.is(apiJson['VERCEL_ENV'], 'development');
|
||||||
|
t.is(apiJson['VERCEL_REGION'], 'dev1');
|
||||||
|
t.is(apiJson['VERCEL_GIT_PROVIDER'], '');
|
||||||
|
t.is(apiJson['VERCEL_GIT_REPO_SLUG'], '');
|
||||||
|
|
||||||
|
const homeUrl = localhost[0];
|
||||||
|
const homeRes = await fetch(homeUrl);
|
||||||
|
const homeJson = await homeRes.json();
|
||||||
|
t.is(homeJson['VERCEL'], '1');
|
||||||
t.is(homeJson['VERCEL_URL'], localhostNoProtocol);
|
t.is(homeJson['VERCEL_URL'], localhostNoProtocol);
|
||||||
|
t.is(homeJson['VERCEL_ENV'], 'development');
|
||||||
|
t.is(homeJson['VERCEL_REGION'], undefined);
|
||||||
|
t.is(homeJson['VERCEL_GIT_PROVIDER'], '');
|
||||||
|
t.is(homeJson['VERCEL_GIT_REPO_SLUG'], '');
|
||||||
|
|
||||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||||
|
|
||||||
@@ -702,12 +901,27 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
await waitForPrompt(now, chunk =>
|
await waitForPrompt(now, chunk =>
|
||||||
chunk.includes('What’s the name of the variable?')
|
chunk.includes('What’s the name of the variable?')
|
||||||
);
|
);
|
||||||
now.stdin.write('MY_ENV_VAR\n');
|
now.stdin.write('MY_PLAINTEXT_ENV_VAR\n');
|
||||||
|
|
||||||
|
// expect error if no environment is selected
|
||||||
|
await waitForPrompt(
|
||||||
|
now,
|
||||||
|
chunk =>
|
||||||
|
chunk.includes('which Environments') &&
|
||||||
|
chunk.includes('MY_PLAINTEXT_ENV_VAR')
|
||||||
|
);
|
||||||
|
now.stdin.write('\n'); // select none
|
||||||
|
await waitForPrompt(now, chunk =>
|
||||||
|
chunk.includes(
|
||||||
|
'Please select an Environment to remove the Environment Variable from.'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
await waitForPrompt(
|
await waitForPrompt(
|
||||||
now,
|
now,
|
||||||
chunk =>
|
chunk =>
|
||||||
chunk.includes('which Environments') && chunk.includes('MY_ENV_VAR')
|
chunk.includes('which Environments') &&
|
||||||
|
chunk.includes('MY_PLAINTEXT_ENV_VAR')
|
||||||
);
|
);
|
||||||
now.stdin.write('a\n'); // select all
|
now.stdin.write('a\n'); // select all
|
||||||
|
|
||||||
@@ -719,7 +933,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
async function nowEnvRemoveWithArgs() {
|
async function nowEnvRemoveWithArgs() {
|
||||||
const { exitCode, stderr, stdout } = await execa(
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['env', 'rm', 'MY_STDIN_VAR', 'development', '-y', ...defaultArgs],
|
['env', 'rm', 'MY_SECRET_ENV_VAR', 'preview', '-y', ...defaultArgs],
|
||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
cwd: target,
|
cwd: target,
|
||||||
@@ -727,12 +941,49 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
|
||||||
|
const {
|
||||||
|
exitCode: exitCode2,
|
||||||
|
stderr: stderr2,
|
||||||
|
stdout: stdout2,
|
||||||
|
} = await execa(
|
||||||
|
binaryPath,
|
||||||
|
['env', 'rm', 'MY_STDIN_VAR', 'development', '-y', ...defaultArgs],
|
||||||
|
{
|
||||||
|
reject: false,
|
||||||
|
cwd: target,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(exitCode2, 0, formatOutput({ stderr2, stdout2 }));
|
||||||
|
|
||||||
|
const {
|
||||||
|
exitCode: exitCode3,
|
||||||
|
stderr: stderr3,
|
||||||
|
stdout: stdout3,
|
||||||
|
} = await execa(
|
||||||
|
binaryPath,
|
||||||
|
[
|
||||||
|
'env',
|
||||||
|
'rm',
|
||||||
|
'MY_DECRYPTABLE_SECRET_ENV',
|
||||||
|
'development',
|
||||||
|
'-y',
|
||||||
|
...defaultArgs,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
reject: false,
|
||||||
|
cwd: target,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(exitCode3, 0, formatOutput({ stderr3, stdout3 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvRemoveWithNameOnly() {
|
async function nowEnvRemoveWithNameOnly() {
|
||||||
const vc = execa(
|
const vc = execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['env', 'rm', 'VERCEL_URL', '-y', ...defaultArgs],
|
['env', 'rm', 'NEXT_PUBLIC_VERCEL_URL', '-y', ...defaultArgs],
|
||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
cwd: target,
|
cwd: target,
|
||||||
@@ -742,7 +993,8 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
await waitForPrompt(
|
await waitForPrompt(
|
||||||
vc,
|
vc,
|
||||||
chunk =>
|
chunk =>
|
||||||
chunk.includes('which Environments') && chunk.includes('VERCEL_URL')
|
chunk.includes('which Environments') &&
|
||||||
|
chunk.includes('NEXT_PUBLIC_VERCEL_URL')
|
||||||
);
|
);
|
||||||
vc.stdin.write('a\n'); // select all
|
vc.stdin.write('a\n'); // select all
|
||||||
|
|
||||||
@@ -751,11 +1003,14 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await nowDeploy();
|
await nowDeploy();
|
||||||
|
const secretName = await createSecret();
|
||||||
await nowEnvLsIsEmpty();
|
await nowEnvLsIsEmpty();
|
||||||
await nowEnvAdd();
|
await nowEnvAddPlaintext();
|
||||||
|
await nowEnvAddSecret(secretName);
|
||||||
await nowEnvAddFromStdin();
|
await nowEnvAddFromStdin();
|
||||||
await nowEnvAddSystemEnv();
|
await nowEnvAddSystemEnv();
|
||||||
await nowEnvLsIncludesVar();
|
await nowEnvLsIncludesVar();
|
||||||
|
await createEnvWithDecryptableSecret();
|
||||||
await nowEnvPull();
|
await nowEnvPull();
|
||||||
await nowEnvPullOverwrite();
|
await nowEnvPullOverwrite();
|
||||||
await nowEnvPullConfirm();
|
await nowEnvPullConfirm();
|
||||||
@@ -763,6 +1018,10 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
await nowDevWithEnv();
|
await nowDevWithEnv();
|
||||||
fs.unlinkSync(path.join(target, '.env'));
|
fs.unlinkSync(path.join(target, '.env'));
|
||||||
await nowDevAndFetchCloudVars();
|
await nowDevAndFetchCloudVars();
|
||||||
|
await enableAutoExposeSystemEnvs();
|
||||||
|
await nowEnvPullFetchSystemVars();
|
||||||
|
fs.unlinkSync(path.join(target, '.env'));
|
||||||
|
await nowDevAndFetchSystemVars();
|
||||||
await nowEnvRemove();
|
await nowEnvRemove();
|
||||||
await nowEnvRemoveWithArgs();
|
await nowEnvRemoveWithArgs();
|
||||||
await nowEnvRemoveWithNameOnly();
|
await nowEnvRemoveWithNameOnly();
|
||||||
@@ -1307,7 +1566,7 @@ test('ensure we render a warning for deployments with no files', async t => {
|
|||||||
t.is(res.status, 404);
|
t.is(res.status, 404);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('output logs of a 2.0 deployment', async t => {
|
test('output logs with "short" output', async t => {
|
||||||
const { stderr, stdout, exitCode } = await execa(
|
const { stderr, stdout, exitCode } = await execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['logs', context.deployment, ...defaultArgs],
|
['logs', context.deployment, ...defaultArgs],
|
||||||
@@ -1324,13 +1583,21 @@ test('output logs of a 2.0 deployment', async t => {
|
|||||||
stderr.includes(`Fetched deployment "${context.deployment}"`),
|
stderr.includes(`Fetched deployment "${context.deployment}"`),
|
||||||
formatOutput({ stderr, stdout })
|
formatOutput({ stderr, stdout })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// "short" format includes timestamps
|
||||||
|
t.truthy(
|
||||||
|
stdout.match(
|
||||||
|
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
t.is(exitCode, 0);
|
t.is(exitCode, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('output logs of a 2.0 deployment without annotate', async t => {
|
test('output logs with "raw" output', async t => {
|
||||||
const { stderr, stdout, exitCode } = await execa(
|
const { stderr, stdout, exitCode } = await execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['logs', context.deployment, ...defaultArgs],
|
['logs', context.deployment, ...defaultArgs, '--output', 'raw'],
|
||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
}
|
}
|
||||||
@@ -1340,12 +1607,19 @@ test('output logs of a 2.0 deployment without annotate', async t => {
|
|||||||
console.log(stdout);
|
console.log(stdout);
|
||||||
console.log(exitCode);
|
console.log(exitCode);
|
||||||
|
|
||||||
t.true(!stderr.includes('[now-builder-debug]'));
|
t.true(
|
||||||
t.true(!stderr.includes('START RequestId'));
|
stderr.includes(`Fetched deployment "${context.deployment}"`),
|
||||||
t.true(!stderr.includes('END RequestId'));
|
formatOutput({ stderr, stdout })
|
||||||
t.true(!stderr.includes('REPORT RequestId'));
|
);
|
||||||
t.true(!stderr.includes('Init Duration'));
|
|
||||||
t.true(!stderr.includes('XRAY TraceId'));
|
// "raw" format does not include timestamps
|
||||||
|
t.is(
|
||||||
|
null,
|
||||||
|
stdout.match(
|
||||||
|
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
t.is(exitCode, 0);
|
t.is(exitCode, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/client",
|
"name": "@vercel/client",
|
||||||
"version": "9.0.2",
|
"version": "9.0.5",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
"homepage": "https://vercel.com",
|
"homepage": "https://vercel.com",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.5.3",
|
"@vercel/build-utils": "2.7.0",
|
||||||
"@zeit/fetch": "5.2.0",
|
"@zeit/fetch": "5.2.0",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
"async-sema": "3.0.0",
|
"async-sema": "3.0.0",
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export async function getVercelIgnore(
|
|||||||
'__pycache__',
|
'__pycache__',
|
||||||
'venv',
|
'venv',
|
||||||
'CVS',
|
'CVS',
|
||||||
|
'.vercel_build_output',
|
||||||
];
|
];
|
||||||
|
|
||||||
const cwds = Array.isArray(cwd) ? cwd : [cwd];
|
const cwds = Array.isArray(cwd) ? cwd : [cwd];
|
||||||
|
|||||||
@@ -285,8 +285,8 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mainModGoContents = modMainGoContents
|
const mainModGoContents = modMainGoContents
|
||||||
.replace('__NOW_HANDLER_PACKAGE_NAME', goPackageName)
|
.replace('__VC_HANDLER_PACKAGE_NAME', goPackageName)
|
||||||
.replace('__NOW_HANDLER_FUNC_NAME', goFuncName);
|
.replace('__VC_HANDLER_FUNC_NAME', goFuncName);
|
||||||
|
|
||||||
if (isGoModExist && isGoModInRootDir) {
|
if (isGoModExist && isGoModInRootDir) {
|
||||||
debug('[mod-root] Write main file to ' + downloadPath);
|
debug('[mod-root] Write main file to ' + downloadPath);
|
||||||
@@ -405,13 +405,13 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go
|
|||||||
'utf8'
|
'utf8'
|
||||||
);
|
);
|
||||||
const mainGoContents = origianlMainGoContents.replace(
|
const mainGoContents = origianlMainGoContents.replace(
|
||||||
'__NOW_HANDLER_FUNC_NAME',
|
'__VC_HANDLER_FUNC_NAME',
|
||||||
handlerFunctionName
|
handlerFunctionName
|
||||||
);
|
);
|
||||||
|
|
||||||
// in order to allow the user to have `main.go`,
|
// in order to allow the user to have `main.go`,
|
||||||
// we need our `main.go` to be called something else
|
// we need our `main.go` to be called something else
|
||||||
const mainGoFileName = 'main__now__go__.go';
|
const mainGoFileName = 'main__vc__go__.go';
|
||||||
|
|
||||||
// Go doesn't like to build files in different directories,
|
// Go doesn't like to build files in different directories,
|
||||||
// so now we place `main.go` together with the user code
|
// so now we place `main.go` together with the user code
|
||||||
@@ -580,9 +580,9 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go`
|
|||||||
};
|
};
|
||||||
} else if (Array.isArray(result)) {
|
} else if (Array.isArray(result)) {
|
||||||
// Got "exit" event from child process
|
// Got "exit" event from child process
|
||||||
throw new Error(
|
const [exitCode, signal] = result;
|
||||||
`Failed to start dev server for "${entrypointWithExt}" (code=${result[0]}, signal=${result[1]})`
|
const reason = signal ? `"${signal}" signal` : `exit code ${exitCode}`;
|
||||||
);
|
throw new Error(`\`go run ${entrypointWithExt}\` failed with ${reason}`);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unexpected result type: ${typeof result}`);
|
throw new Error(`Unexpected result type: ${typeof result}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
|
vc.Start(http.HandlerFunc(__VC_HANDLER_FUNC_NAME))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"__NOW_HANDLER_PACKAGE_NAME"
|
"__VC_HANDLER_PACKAGE_NAME"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
vc "github.com/vercel/go-bridge/go/bridge"
|
vc "github.com/vercel/go-bridge/go/bridge"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
vc.Start(http.HandlerFunc(__NOW_HANDLER_FUNC_NAME))
|
vc.Start(http.HandlerFunc(__VC_HANDLER_FUNC_NAME))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/go",
|
"name": "@vercel/go",
|
||||||
"version": "1.1.6",
|
"version": "1.1.7",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index",
|
"main": "./dist/index",
|
||||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||||
|
|||||||
2
packages/now-next/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
/dist
|
|
||||||
/src/now__bridge.ts
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
bridge_defs="$(dirname $(pwd))/now-node-bridge/src/bridge.ts"
|
|
||||||
|
|
||||||
cp -v "$bridge_defs" src/now__bridge.ts
|
|
||||||
|
|
||||||
tsc
|
|
||||||
|
|
||||||
ncc build src/dev-server.ts -e @vercel/build-utils -e @now/build-utils -o dist/dev
|
|
||||||
mv dist/dev/index.js dist/dev-server.js
|
|
||||||
rm -rf dist/dev
|
|
||||||
|
|
||||||
ncc build src/index.ts -e @vercel/build-utils -e @now/build-utils -o dist/main
|
|
||||||
mv dist/main/index.js dist/index.js
|
|
||||||
rm -rf dist/main
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@vercel/next",
|
|
||||||
"version": "2.6.26",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "./dist/index",
|
|
||||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "./build.sh",
|
|
||||||
"test-integration-once": "jest --env node --verbose --runInBand --bail",
|
|
||||||
"prepublishOnly": "./build.sh"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/vercel/vercel.git",
|
|
||||||
"directory": "packages/now-next"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/aws-lambda": "8.10.19",
|
|
||||||
"@types/buffer-crc32": "0.2.0",
|
|
||||||
"@types/find-up": "4.0.0",
|
|
||||||
"@types/fs-extra": "8.0.0",
|
|
||||||
"@types/next-server": "8.0.0",
|
|
||||||
"@types/resolve-from": "5.0.1",
|
|
||||||
"@types/semver": "6.0.0",
|
|
||||||
"@types/yazl": "2.4.1",
|
|
||||||
"@vercel/nft": "0.9.2",
|
|
||||||
"async-sema": "3.0.1",
|
|
||||||
"buffer-crc32": "0.2.13",
|
|
||||||
"escape-string-regexp": "3.0.0",
|
|
||||||
"execa": "2.0.4",
|
|
||||||
"find-up": "4.1.0",
|
|
||||||
"fs-extra": "7.0.0",
|
|
||||||
"get-port": "5.0.0",
|
|
||||||
"resolve-from": "5.0.0",
|
|
||||||
"semver": "6.1.1",
|
|
||||||
"set-cookie-parser": "2.4.6",
|
|
||||||
"typescript": "3.9.3",
|
|
||||||
"yazl": "https://github.com/ijjk/yazl#70949c55b482647669ce37023017b1514c42b33c"
|
|
||||||
}
|
|
||||||
}
|
|
||||||