mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-23 18:59:59 +00:00
Compare commits
114 Commits
@vercel/bu
...
@vercel/st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
1eeeaf23a1 | ||
|
|
f347164b6c | ||
|
|
ea4be8a001 | ||
|
|
19ac74d59e | ||
|
|
9a87d4ea8e | ||
|
|
35fd7b5f9c | ||
|
|
eb8db25845 | ||
|
|
5c3cd17074 | ||
|
|
72572ba6be | ||
|
|
b69a41a0aa | ||
|
|
7c35d7992b | ||
|
|
290fdc0506 | ||
|
|
fc2d9f99e6 | ||
|
|
1fd24fb4fc | ||
|
|
17c72f1d35 | ||
|
|
9c1154c108 | ||
|
|
613c384ce8 | ||
|
|
a9598d14e3 | ||
|
|
48935e92d8 | ||
|
|
1b1e72ab88 | ||
|
|
0f574f67f6 | ||
|
|
0d4be3f5f2 | ||
|
|
a971c2aa3a |
@@ -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
|
||||||
|
|||||||
4
.github/CONTRIBUTING.md
vendored
4
.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,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#### Why This Error Occurred
|
#### Why This Error Occurred
|
||||||
|
|
||||||
When supplying `regions` or `scale` settings, you
|
When supplying `regions` configuration, you
|
||||||
used an unknown or invalid dc identifier.
|
used an unknown or invalid DC identifier.
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
#### Possible Ways to Fix It
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ and DCs have to be in _lowercase_.
|
|||||||
- `gru`
|
- `gru`
|
||||||
- `iad`
|
- `iad`
|
||||||
|
|
||||||
In `now-cli`, they currently are transformed to
|
In Vercel CLI, they currently are transformed to
|
||||||
DC identifiers before being sent to our APIs.
|
DC identifiers before being sent to our APIs.
|
||||||
|
|
||||||
**Valid DC identifiers**:
|
**Valid DC identifiers**:
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# Missing `--dotenv` Target
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
You specified a path as the value for the `--dotenv` flag, but the target of the path doesn't exist.
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Make sure the target file you've specified exists and is readable by Vercel CLI. In addition, please ensure that the filename starts with a dot (example: `.env`) - then it should work.
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#### Why This Error Occurred
|
#### Why This Error Occurred
|
||||||
|
|
||||||
This error occurs when you have your application is not configured for Serverless Next.js build output.
|
This error occurs when your application is not configured for Serverless Next.js build output.
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
#### Possible Ways to Fix It
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
# Can't Set `regions` and `scale` Options Simultaneously
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
Your deployment's configuration contains a `regions` and `scale`
|
|
||||||
configuration simultaneously.
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
The `regions` setting is intended to be used to scale the
|
|
||||||
deployment to the supplied regions or datacenters identifiers
|
|
||||||
with default scale settings.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"regions": ["sfo", "bru", "gru", "iad"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `scale` object allows you to be more granular: you can decide a
|
|
||||||
`min` and `max` number of instances per region:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"scale": {
|
|
||||||
"sfo": { "min": 0, "max": 10 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
To solve this problem, use only one of the two ways of deciding
|
|
||||||
where to scale your deployment to.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Invalid Region or DC Identifier
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
When supplying a region or DC identifier in `vercel scale`,
|
|
||||||
we weren't able to recognize the value as valid.
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Check your `vercel scale` command make sure you are using a
|
|
||||||
valid string after the URL. Regions
|
|
||||||
and DCs have to be in _lowercase_.
|
|
||||||
|
|
||||||
**Valid region identifiers**:
|
|
||||||
|
|
||||||
- `all` (special, used to scale to all DCs, can only appear once)
|
|
||||||
- `sfo`
|
|
||||||
- `bru`
|
|
||||||
- `gru`
|
|
||||||
- `iad`
|
|
||||||
|
|
||||||
In Vercel CLI, they currently are transformed to
|
|
||||||
DC identifiers before being sent to our APIs.
|
|
||||||
|
|
||||||
**Valid DC identifiers**:
|
|
||||||
|
|
||||||
- `sfo1`
|
|
||||||
- `bru1`
|
|
||||||
- `gru1`
|
|
||||||
- `iad1`
|
|
||||||
|
|
||||||
To pass multiple ones, use a comma:
|
|
||||||
|
|
||||||
```
|
|
||||||
vercel scale my-url-123.now.sh sfo,bru,gru 1 5
|
|
||||||
```
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# `vercel scale ls` is deprecated
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
We have stopped supporting this command, in favor of
|
|
||||||
better alternatives.
|
|
||||||
|
|
||||||
`vercel scale ls` used to list all the scaling rules
|
|
||||||
for all your deployments. The output would be too long,
|
|
||||||
and it would often be hard to find the information
|
|
||||||
you needed in a long list of items.
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Instead of using `vercel scale ls` to list all your deployments
|
|
||||||
and their scaling rules, first use `vercel ls` to find
|
|
||||||
your deployment:
|
|
||||||
|
|
||||||
```console
|
|
||||||
vercel ls
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, select the URL of your deployment, which uniquely identifies it, and run:
|
|
||||||
|
|
||||||
```console
|
|
||||||
vercel inspect my-deployment-12345.now.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The `inspect` subcommand will give you your deployment's scale information, including what datacenters it's enabled on, the
|
|
||||||
current number of instances and minimums/maximums.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Scaling path alias
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
You tried to use `vercel scale` on a path alias (`vercel alias -r rules.json`).
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Path aliases are routes to instances. Instances can be scaled independent from each other.
|
|
||||||
You can view path aliases by running `vercel alias ls <id>`.
|
|
||||||
|
|
||||||
Documentation for Path Aliases can be found [here](https://vercel.com/docs/features/path-aliases).
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# No minimum scale settings on Cloud v2 deployments
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
An attempt was made at scaling a Cloud v2 deployment with a `min` scale
|
|
||||||
setting. This isn't supported yet.
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Ensure your scale settings (in `vercel.json`, the command you're running
|
|
||||||
or from a previous deployment who's alias you're trying to overwrite) has
|
|
||||||
the `min` scale setting set to `0`. You can do this by running
|
|
||||||
|
|
||||||
```
|
|
||||||
vercel scale <deployment> 0 10
|
|
||||||
```
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Verification Timeout
|
|
||||||
|
|
||||||
#### Why This Error Occurred
|
|
||||||
|
|
||||||
After the deployment build completed and the deployment state was set to `READY`,
|
|
||||||
instances failed to initialize properly.
|
|
||||||
|
|
||||||
The CLI attempted to verify that the scale settings of your instances matched,
|
|
||||||
but it couldn't do so within the allotted time (defaults to 2 minutes).
|
|
||||||
|
|
||||||
#### Possible Ways to Fix It
|
|
||||||
|
|
||||||
Instance verification is the process of ensuring that after
|
|
||||||
your deployment is ready, we can actually run (instantiate) your code.
|
|
||||||
|
|
||||||
If you configured [regions or scale](https://vercel.com/docs/features/scaling),
|
|
||||||
we ensure the minimums and maximums are met for the regions you enabled.
|
|
||||||
|
|
||||||
If you think your code is taking too long to instantiate, this can be due
|
|
||||||
to slow boot up times. You can supply `--no-verify` to skip verification
|
|
||||||
if you are confident your code runs properly.
|
|
||||||
|
|
||||||
If your application is not listening on a HTTP port, we might be failing to
|
|
||||||
instantiate your deployment as well. It might not be showing any errors,
|
|
||||||
but the deployment instance is effectively not routable and cannot be
|
|
||||||
verified.
|
|
||||||
|
|
||||||
If your instances are crashing before an HTTP port is exposed, verification
|
|
||||||
will fail as well. Double check your logs (e.g.: by running `vercel logs <url>`)
|
|
||||||
3
examples/ember/.gitignore
vendored
3
examples/ember/.gitignore
vendored
@@ -27,3 +27,6 @@
|
|||||||
# Environment Variables
|
# Environment Variables
|
||||||
.env
|
.env
|
||||||
.env.build
|
.env.build
|
||||||
|
|
||||||
|
# Vercel
|
||||||
|
.vercel
|
||||||
|
|||||||
3
examples/ember/public/robots.txt
Normal file
3
examples/ember/public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# http://www.robotstxt.org
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -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"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "9.5.1",
|
"next": "10.0.0",
|
||||||
"react": "16.13.1",
|
"react": "17.0.1",
|
||||||
"react-dom": "16.13.1"
|
"react-dom": "17.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
"husky": "3.0.4",
|
"husky": "3.0.4",
|
||||||
"json5": "2.1.1",
|
"json5": "2.1.1",
|
||||||
"lint-staged": "9.2.5",
|
"lint-staged": "9.2.5",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.1",
|
||||||
"npm-package-arg": "6.1.0",
|
"npm-package-arg": "6.1.0",
|
||||||
"prettier": "2.0.5"
|
"prettier": "2.0.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
"placeholder": "`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": {
|
||||||
|
"placeholder": "`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
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.1.2-canary.1",
|
||||||
"main": "frameworks.json",
|
"main": "frameworks.json",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
27
packages/frameworks/test/frameworks.unit.test.ts
vendored
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.2-canary.1",
|
"version": "2.5.5-canary.2",
|
||||||
"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.1.2-canary.1",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"aggregate-error": "3.0.1",
|
"aggregate-error": "3.0.1",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"js-yaml": "3.13.1",
|
"js-yaml": "3.13.1",
|
||||||
"minimatch": "3.0.4",
|
"minimatch": "3.0.4",
|
||||||
"multistream": "2.1.1",
|
"multistream": "2.1.1",
|
||||||
"node-fetch": "2.2.0",
|
"node-fetch": "2.6.1",
|
||||||
"semver": "6.1.1",
|
"semver": "6.1.1",
|
||||||
"ts-jest": "24.1.0",
|
"ts-jest": "24.1.0",
|
||||||
"typescript": "3.9.3",
|
"typescript": "3.9.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;
|
||||||
@@ -450,6 +451,10 @@ function detectFrontBuilder(
|
|||||||
config.devCommand = projectSettings.devCommand;
|
config.devCommand = projectSettings.devCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (projectSettings.installCommand) {
|
||||||
|
config.installCommand = projectSettings.installCommand;
|
||||||
|
}
|
||||||
|
|
||||||
if (projectSettings.buildCommand) {
|
if (projectSettings.buildCommand) {
|
||||||
config.buildCommand = projectSettings.buildCommand;
|
config.buildCommand = projectSettings.buildCommand;
|
||||||
}
|
}
|
||||||
@@ -458,7 +463,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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -1080,6 +1080,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: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "20.1.1-canary.2",
|
"version": "20.1.3-canary.6",
|
||||||
"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,9 +61,9 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.5.2-canary.1",
|
"@vercel/build-utils": "2.5.5-canary.2",
|
||||||
"@vercel/go": "1.1.6",
|
"@vercel/go": "1.1.6",
|
||||||
"@vercel/node": "1.8.2-canary.1",
|
"@vercel/node": "1.8.4",
|
||||||
"@vercel/python": "1.2.3",
|
"@vercel/python": "1.2.3",
|
||||||
"@vercel/ruby": "1.2.4",
|
"@vercel/ruby": "1.2.4",
|
||||||
"update-notifier": "4.1.0"
|
"update-notifier": "4.1.0"
|
||||||
@@ -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.1.2-canary.1",
|
||||||
"@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,8 +146,7 @@
|
|||||||
"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.0",
|
|
||||||
"npm-package-arg": "6.1.0",
|
"npm-package-arg": "6.1.0",
|
||||||
"nyc": "13.2.0",
|
"nyc": "13.2.0",
|
||||||
"ora": "3.4.0",
|
"ora": "3.4.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]) {
|
|
||||||
const alias = aliases.find(
|
|
||||||
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()}`);
|
output.log(`aliases found under ${chalk.bold(contextName)} ${lsStamp()}`);
|
||||||
console.log(printAliasTable(aliases));
|
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)}]`)
|
|
||||||
: // for legacy reasons, we might have situations
|
|
||||||
// where the deployment was deleted and the alias
|
// where the deployment was deleted and the alias
|
||||||
// not collected appropriately, and we need to handle it
|
// not collected appropriately, and we need to handle it
|
||||||
a.deployment && a.deployment.url
|
a.deployment && a.deployment.url ? a.deployment.url : chalk.gray('–'),
|
||||||
? 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export default async function set(
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For `now alias set <argument>`
|
// For `vercel alias set <argument>`
|
||||||
if (args.length === 1) {
|
if (args.length === 1) {
|
||||||
const deployment = handleCertError(
|
const deployment = handleCertError(
|
||||||
output,
|
output,
|
||||||
@@ -261,7 +261,7 @@ function handleSetupDomainError<T>(
|
|||||||
{ extraSpace: ' ' }
|
{ extraSpace: ' ' }
|
||||||
)}\n\n`
|
)}\n\n`
|
||||||
);
|
);
|
||||||
output.print(' Read more: https://err.sh/now/domain-verification\n');
|
output.print(' Read more: https://err.sh/vercel/domain-verification\n');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export default async function issue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (crtPath || keyPath || caPath) {
|
if (crtPath || keyPath || caPath) {
|
||||||
if (args.length !== 0 || (!crtPath || !keyPath || !caPath)) {
|
if (args.length !== 0 || !crtPath || !keyPath || !caPath) {
|
||||||
output.error(
|
output.error(
|
||||||
`Invalid number of arguments to create a custom certificate entry. Usage:`
|
`Invalid number of arguments to create a custom certificate entry. Usage:`
|
||||||
);
|
);
|
||||||
@@ -230,6 +230,8 @@ async function runStartOrder(
|
|||||||
output.print(
|
output.print(
|
||||||
` ${chalk.cyan(getCommandName(`certs issue ${cns.join(' ')}`))}\n`
|
` ${chalk.cyan(getCommandName(`certs issue ${cns.join(' ')}`))}\n`
|
||||||
);
|
);
|
||||||
output.print(' Read more: https://err.sh/now/solve-challenges-manually\n');
|
output.print(
|
||||||
|
' Read more: https://err.sh/vercel/solve-challenges-manually\n'
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import logo from '../../util/output/logo';
|
import logo from '../../util/output/logo';
|
||||||
import code from '../../util/output/code';
|
|
||||||
import note from '../../util/output/note';
|
|
||||||
import { getPkgName } from '../../util/pkg-name.ts';
|
import { getPkgName } from '../../util/pkg-name.ts';
|
||||||
|
|
||||||
export const help = () => `
|
export const help = () => `
|
||||||
@@ -70,12 +68,6 @@ export const help = () => `
|
|||||||
--prod Create a production deployment
|
--prod Create a production deployment
|
||||||
-c, --confirm Confirm default options and skip questions
|
-c, --confirm Confirm default options and skip questions
|
||||||
|
|
||||||
${note(
|
|
||||||
`To view the usage information for Now 1.0, run ${code(
|
|
||||||
`${getPkgName()} help deploy-v1`
|
|
||||||
)}`
|
|
||||||
)}
|
|
||||||
|
|
||||||
${chalk.dim('Examples:')}
|
${chalk.dim('Examples:')}
|
||||||
|
|
||||||
${chalk.gray('–')} Deploy the current directory
|
${chalk.gray('–')} Deploy the current directory
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const printDeploymentStatus = async (
|
|||||||
|
|
||||||
if (readyState !== 'READY') {
|
if (readyState !== 'READY') {
|
||||||
output.error(
|
output.error(
|
||||||
`Your deployment failed. Please retry later. More: https://err.sh/now/deployment-error`
|
`Your deployment failed. Please retry later. More: https://err.sh/vercel/deployment-error`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,6 @@ const printDeploymentStatus = async (
|
|||||||
chalk.dim(
|
chalk.dim(
|
||||||
`${indication.action || 'Learn More'}: ${indication.link}`
|
`${indication.action || 'Learn More'}: ${indication.link}`
|
||||||
) +
|
) +
|
||||||
newline +
|
|
||||||
newline;
|
newline;
|
||||||
output.print(message + link);
|
output.print(message + link);
|
||||||
}
|
}
|
||||||
@@ -248,11 +247,6 @@ export default async function main(
|
|||||||
const { isFile, path } = pathValidation;
|
const { isFile, path } = pathValidation;
|
||||||
const autoConfirm = argv['--confirm'] || isFile;
|
const autoConfirm = argv['--confirm'] || isFile;
|
||||||
|
|
||||||
// --no-scale
|
|
||||||
if (argv['--no-scale']) {
|
|
||||||
warn(`The option --no-scale is only supported on Now 1.0 deployments`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// deprecate --name
|
// deprecate --name
|
||||||
if (argv['--name']) {
|
if (argv['--name']) {
|
||||||
output.print(
|
output.print(
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export default async function main(ctx: NowContext) {
|
|||||||
'package.json'
|
'package.json'
|
||||||
)} must not contain ${cmd('now dev')}`
|
)} must not contain ${cmd('now dev')}`
|
||||||
);
|
);
|
||||||
output.error(`Learn More: http://err.sh/now/now-dev-as-dev-script`);
|
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (scripts && scripts.dev && /\bvercel\b\W+\bdev\b/.test(scripts.dev)) {
|
if (scripts && scripts.dev && /\bvercel\b\W+\bdev\b/.test(scripts.dev)) {
|
||||||
@@ -108,7 +108,7 @@ export default async function main(ctx: NowContext) {
|
|||||||
'package.json'
|
'package.json'
|
||||||
)} must not contain ${cmd('vercel dev')}`
|
)} must not contain ${cmd('vercel dev')}`
|
||||||
);
|
);
|
||||||
output.error(`Learn More: http://err.sh/now/now-dev-as-dev-script`);
|
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
125
packages/now-cli/src/commands/env/add.ts
vendored
125
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 { SYSTEM_ENV_VALUES } from '../../util/env/system-env';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
'--debug': boolean;
|
'--debug': boolean;
|
||||||
@@ -29,38 +31,71 @@ 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: 'Provided by System', value: ProjectEnvType.System },
|
||||||
|
],
|
||||||
|
})) as { inputEnvType: ProjectEnvType };
|
||||||
|
|
||||||
|
envType = answers.inputEnvType;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!envName) {
|
while (!envName) {
|
||||||
@@ -77,7 +112,7 @@ export default async function add(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const envs = await getEnvVariables(output, client, project.id, 4);
|
const { envs } = await getEnvVariables(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 +133,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: SYSTEM_ENV_VALUES.map(value => ({ name: value, value })),
|
||||||
|
});
|
||||||
|
|
||||||
|
envValue = systemEnvValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (envTargets.length === 0) {
|
while (envTargets.length === 0) {
|
||||||
@@ -127,7 +206,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 +235,3 @@ export default async function add(
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSystemEnvVariable(envName: string) {
|
|
||||||
return envName.startsWith('VERCEL_');
|
|
||||||
}
|
|
||||||
|
|||||||
37
packages/now-cli/src/commands/env/index.ts
vendored
37
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,14 +19,15 @@ 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]
|
||||||
|
|
||||||
@@ -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
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` : '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
8
packages/now-cli/src/commands/env/pull.ts
vendored
8
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 { ProjectEnvTarget, 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';
|
||||||
@@ -68,9 +68,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');
|
||||||
|
|||||||
37
packages/now-cli/src/commands/env/rm.ts
vendored
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');
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,13 +67,15 @@ export default function handleCertError<T>(
|
|||||||
output.print(
|
output.print(
|
||||||
` ${getCommandName(`certs issue --challenge-only <cns>`)}\n`
|
` ${getCommandName(`certs issue --challenge-only <cns>`)}\n`
|
||||||
);
|
);
|
||||||
output.print(' Read more: https://err.sh/now/dns-configuration-error\n');
|
output.print(
|
||||||
|
' Read more: https://err.sh/vercel/dns-configuration-error\n'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
output.print(
|
output.print(
|
||||||
` We configured them for you, but the propagation may take a few minutes. Please try again later.\n`
|
` We configured them for you, but the propagation may take a few minutes. Please try again later.\n`
|
||||||
);
|
);
|
||||||
output.print(
|
output.print(
|
||||||
' Read more: https://err.sh/now/dns-configuration-error\n\n'
|
' Read more: https://err.sh/vercel/dns-configuration-error\n\n'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -923,9 +923,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 +1372,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 +1490,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) {
|
||||||
|
|||||||
57
packages/now-cli/src/util/env/add-env-record.ts
vendored
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
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(' | ')}>`;
|
||||||
|
}
|
||||||
51
packages/now-cli/src/util/env/get-env-records.ts
vendored
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, Secret, ProjectEnvVariableV5 } from '../../types';
|
||||||
|
|
||||||
export default async function removeEnvRecord(
|
export default async function removeEnvRecord(
|
||||||
output: Output,
|
output: Output,
|
||||||
@@ -18,7 +18,7 @@ export default async function removeEnvRecord(
|
|||||||
envName
|
envName
|
||||||
)}${qs}`;
|
)}${qs}`;
|
||||||
|
|
||||||
const env = await client.fetch<ProjectEnvVariable>(urlProject, {
|
const env = await client.fetch<ProjectEnvVariableV5>(urlProject, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
32
packages/now-cli/src/util/env/system-env.ts
vendored
Normal file
32
packages/now-cli/src/util/env/system-env.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
export const SYSTEM_ENV_VALUES = [
|
||||||
|
'VERCEL_URL',
|
||||||
|
'VERCEL_GITHUB_COMMIT_ORG',
|
||||||
|
'VERCEL_GITHUB_COMMIT_REF',
|
||||||
|
'VERCEL_GITHUB_ORG',
|
||||||
|
'VERCEL_GITHUB_DEPLOYMENT',
|
||||||
|
'VERCEL_GITHUB_COMMIT_REPO',
|
||||||
|
'VERCEL_GITHUB_REPO',
|
||||||
|
'VERCEL_GITHUB_COMMIT_AUTHOR_LOGIN',
|
||||||
|
'VERCEL_GITHUB_COMMIT_AUTHOR_NAME',
|
||||||
|
'VERCEL_GITHUB_COMMIT_SHA',
|
||||||
|
'VERCEL_GITLAB_DEPLOYMENT',
|
||||||
|
'VERCEL_GITLAB_PROJECT_NAMESPACE',
|
||||||
|
'VERCEL_GITLAB_PROJECT_NAME',
|
||||||
|
'VERCEL_GITLAB_PROJECT_ID',
|
||||||
|
'VERCEL_GITLAB_PROJECT_PATH',
|
||||||
|
'VERCEL_GITLAB_COMMIT_REF',
|
||||||
|
'VERCEL_GITLAB_COMMIT_SHA',
|
||||||
|
'VERCEL_GITLAB_COMMIT_MESSAGE',
|
||||||
|
'VERCEL_GITLAB_COMMIT_AUTHOR_LOGIN',
|
||||||
|
'VERCEL_GITLAB_COMMIT_AUTHOR_NAME',
|
||||||
|
'VERCEL_BITBUCKET_DEPLOYMENT',
|
||||||
|
'VERCEL_BITBUCKET_REPO_OWNER',
|
||||||
|
'VERCEL_BITBUCKET_REPO_SLUG',
|
||||||
|
'VERCEL_BITBUCKET_REPO_NAME',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_REF',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_SHA',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_MESSAGE',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_AUTHOR_NAME',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_AUTHOR_URL',
|
||||||
|
'VERCEL_BITBUCKET_COMMIT_AUTHOR_AVATAR',
|
||||||
|
];
|
||||||
@@ -999,7 +999,7 @@ export class MissingDotenvVarsError extends NowError<
|
|||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
message += '\nRead more: https://err.sh/now/missing-env-file';
|
message += '\nRead more: https://err.sh/vercel/missing-env-file';
|
||||||
|
|
||||||
super({
|
super({
|
||||||
code: 'MISSING_DOTENV_VARS',
|
code: 'MISSING_DOTENV_VARS',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import getEnvVariables from './env/get-env-records';
|
|||||||
import getDecryptedSecret from './env/get-decrypted-secret';
|
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, Project, ProjectEnvType } from '../types';
|
||||||
|
|
||||||
import { Env } from '@vercel/build-utils';
|
import { Env } from '@vercel/build-utils';
|
||||||
|
|
||||||
@@ -12,9 +12,15 @@ export default async function getDecryptedEnvRecords(
|
|||||||
project: Project,
|
project: Project,
|
||||||
target: ProjectEnvTarget
|
target: ProjectEnvTarget
|
||||||
): Promise<Env> {
|
): Promise<Env> {
|
||||||
const envs = await getEnvVariables(output, client, project.id, 4, target);
|
const { envs } = await getEnvVariables(output, client, project.id, target);
|
||||||
const decryptedValues = await Promise.all(
|
const decryptedValues = await Promise.all(
|
||||||
envs.map(async env => {
|
envs.map(async env => {
|
||||||
|
if (env.type === ProjectEnvType.System) {
|
||||||
|
return { value: '', found: true };
|
||||||
|
} else if (env.type === ProjectEnvType.Plaintext) {
|
||||||
|
return { value: env.value, found: true };
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const value = await getDecryptedSecret(output, client, env.value);
|
const value = await getDecryptedSecret(output, client, env.value);
|
||||||
return { value, found: true };
|
return { value, found: true };
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export default class Now extends EventEmitter {
|
|||||||
const { key } = error;
|
const { key } = error;
|
||||||
err.message =
|
err.message =
|
||||||
`The env key ${key} has an invalid type: ${typeof env[key]}. ` +
|
`The env key ${key} has an invalid type: ${typeof env[key]}. ` +
|
||||||
'Please supply a String or a Number (https://err.sh/now-cli/env-value-invalid-type)';
|
'Please supply a String or a Number (https://err.sh/vercel-cli/env-value-invalid-type)';
|
||||||
} else if (code === 'unreferenced_build_specifications') {
|
} else if (code === 'unreferenced_build_specifications') {
|
||||||
const count = unreferencedBuildSpecs.length;
|
const count = unreferencedBuildSpecs.length;
|
||||||
const prefix = count === 1 ? 'build' : 'builds';
|
const prefix = count === 1 ? 'build' : 'builds';
|
||||||
|
|||||||
@@ -94,6 +94,17 @@ inquirer.prompt.prompts.checkbox.prototype.render = function(error) {
|
|||||||
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';
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
|
|||||||
boxen?: boxen.Options;
|
boxen?: boxen.Options;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const details = slug ? `https://err.sh/now/${slug}` : link;
|
const details = slug ? `https://err.sh/vercel/${slug}` : link;
|
||||||
|
|
||||||
print(
|
print(
|
||||||
boxen(
|
boxen(
|
||||||
@@ -66,7 +66,7 @@ export default function createOutput({ debug: debugEnabled = false } = {}) {
|
|||||||
action = 'Learn More'
|
action = 'Learn More'
|
||||||
) {
|
) {
|
||||||
print(`${chalk.red(`Error!`)} ${str}\n`);
|
print(`${chalk.red(`Error!`)} ${str}\n`);
|
||||||
const details = slug ? `https://err.sh/now/${slug}` : link;
|
const details = slug ? `https://err.sh/vercel/${slug}` : link;
|
||||||
if (details) {
|
if (details) {
|
||||||
print(`${chalk.bold(action)}: ${renderLink(details)}\n`);
|
print(`${chalk.bold(action)}: ${renderLink(details)}\n`);
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/now-cli/src/util/output/ellipsis.ts
Normal file
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;
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ export default function error(...input: string[] | [APIError]) {
|
|||||||
if (typeof input[0] === 'object') {
|
if (typeof input[0] === 'object') {
|
||||||
const { slug, message, link, action = 'Learn More' } = input[0];
|
const { slug, message, link, action = 'Learn More' } = input[0];
|
||||||
messages = [message];
|
messages = [message];
|
||||||
const details = slug ? `https://err.sh/now/${slug}` : link;
|
const details = slug ? `https://err.sh/vercel/${slug}` : link;
|
||||||
if (details) {
|
if (details) {
|
||||||
messages.push(`${chalk.bold(action)}: ${renderLink(details)}`);
|
messages.push(`${chalk.bold(action)}: ${renderLink(details)}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
3
packages/now-cli/test/dev/fixtures/10a-nextjs-routes/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
.vercel
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"next": "9.5.3",
|
||||||
|
"react": "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" }]
|
||||||
|
}
|
||||||
4862
packages/now-cli/test/dev/fixtures/10a-nextjs-routes/yarn.lock
Normal file
4862
packages/now-cli/test/dev/fixtures/10a-nextjs-routes/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,68 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "CommonJS"
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
|
|
||||||
|
/* Basic Options */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
"module": "CommonJS",
|
||||||
|
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||||
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||||
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||||
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||||
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||||
|
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||||
|
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||||
|
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
// "composite": true, /* Enable project compilation */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||||
|
// "removeComments": true, /* Do not emit comments to output. */
|
||||||
|
// "noEmit": true, /* Do not emit outputs. */
|
||||||
|
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||||
|
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||||
|
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||||
|
|
||||||
|
/* Strict Type-Checking Options */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||||
|
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||||
|
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||||
|
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||||
|
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||||
|
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||||
|
|
||||||
|
/* Additional Checks */
|
||||||
|
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||||
|
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||||
|
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||||
|
|
||||||
|
/* Module Resolution Options */
|
||||||
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
|
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||||
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||||
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
/* Source Map Options */
|
||||||
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
|
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||||
|
|
||||||
|
/* Experimental Options */
|
||||||
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
|
||||||
|
/* Advanced Options */
|
||||||
|
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
||||||
|
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import retry from 'async-retry';
|
|||||||
import { satisfies } from 'semver';
|
import { satisfies } from 'semver';
|
||||||
import { getDistTag } from '../../src/util/get-dist-tag';
|
import { getDistTag } from '../../src/util/get-dist-tag';
|
||||||
import { version as cliVersion } from '../../package.json';
|
import { version as cliVersion } from '../../package.json';
|
||||||
import { fetchTokenWithRetry } from '../../../../test/lib/deployment/now-deploy';
|
import { fetchCachedToken } from '../../../../test/lib/deployment/now-deploy';
|
||||||
|
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
const isCanary = () => getDistTag(cliVersion) === 'canary';
|
const isCanary = () => getDistTag(cliVersion) === 'canary';
|
||||||
@@ -245,7 +245,7 @@ function testFixtureStdio(
|
|||||||
const cwd = isExample
|
const cwd = isExample
|
||||||
? exampleAbsolute(directory)
|
? exampleAbsolute(directory)
|
||||||
: fixtureAbsolute(directory);
|
: fixtureAbsolute(directory);
|
||||||
const token = await fetchTokenWithRetry();
|
const token = await fetchCachedToken();
|
||||||
let deploymentUrl;
|
let deploymentUrl;
|
||||||
|
|
||||||
// Deploy fixture and link project
|
// Deploy fixture and link project
|
||||||
@@ -1180,6 +1180,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(
|
||||||
|
|||||||
@@ -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>',
|
||||||
|
|||||||
172
packages/now-cli/test/integration.js
vendored
172
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', '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,28 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvPull() {
|
async function nowEnvPull() {
|
||||||
@@ -549,7 +619,7 @@ 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('VERCEL_URL=""'));
|
||||||
}
|
}
|
||||||
@@ -603,7 +673,8 @@ 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['MY_SECRET_ENV_VAR'], 'my secret');
|
||||||
t.is(apiJson['VERCEL_URL'], host);
|
t.is(apiJson['VERCEL_URL'], host);
|
||||||
|
|
||||||
const homeUrl = `https://${host}`;
|
const homeUrl = `https://${host}`;
|
||||||
@@ -611,7 +682,8 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
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['MY_SECRET_ENV_VAR'], 'my secret');
|
||||||
t.is(homeJson['VERCEL_URL'], host);
|
t.is(homeJson['VERCEL_URL'], host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,14 +711,14 @@ 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['VERCEL_URL'], localhostNoProtocol);
|
||||||
|
|
||||||
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['VERCEL_URL'], localhostNoProtocol);
|
||||||
|
|
||||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||||
@@ -680,13 +752,15 @@ 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['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"}');
|
||||||
|
|
||||||
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['VERCEL_URL'], localhostNoProtocol);
|
||||||
|
t.is(homeJson['MY_STDIN_VAR'], '{"expect":"quotes"}');
|
||||||
|
|
||||||
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
vc.kill('SIGTERM', { forceKillAfterTimeout: 2000 });
|
||||||
|
|
||||||
@@ -702,12 +776,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 +808,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,6 +816,21 @@ 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 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function nowEnvRemoveWithNameOnly() {
|
async function nowEnvRemoveWithNameOnly() {
|
||||||
@@ -751,8 +855,10 @@ 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();
|
||||||
@@ -2365,7 +2471,6 @@ test('invalid `--token`', async t => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// We need to skip this test until `now-php` supports Runtime version 3
|
|
||||||
test('deploy a Lambda with a specific runtime', async t => {
|
test('deploy a Lambda with a specific runtime', async t => {
|
||||||
const directory = fixture('lambda-with-php-runtime');
|
const directory = fixture('lambda-with-php-runtime');
|
||||||
const output = await execute([directory, '--public', '--confirm']);
|
const output = await execute([directory, '--public', '--confirm']);
|
||||||
@@ -2374,7 +2479,8 @@ test('deploy a Lambda with a specific runtime', async t => {
|
|||||||
|
|
||||||
const { host: url } = new URL(output.stdout);
|
const { host: url } = new URL(output.stdout);
|
||||||
|
|
||||||
const [build] = await getDeploymentBuildsByUrl(url);
|
const builds = await getDeploymentBuildsByUrl(url);
|
||||||
|
const build = builds.find(b => b.use && b.use.includes('php')) || builds[0];
|
||||||
t.is(build.use, 'vercel-php@0.1.0', JSON.stringify(build, null, 2));
|
t.is(build.use, 'vercel-php@0.1.0', JSON.stringify(build, null, 2));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/client",
|
"name": "@vercel/client",
|
||||||
"version": "9.0.2-canary.1",
|
"version": "9.0.4-canary.3",
|
||||||
"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,14 +37,14 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.5.2-canary.1",
|
"@vercel/build-utils": "2.5.5-canary.2",
|
||||||
"@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",
|
||||||
"fs-extra": "8.0.1",
|
"fs-extra": "8.0.1",
|
||||||
"ignore": "4.0.6",
|
"ignore": "4.0.6",
|
||||||
"ms": "2.1.2",
|
"ms": "2.1.2",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.1",
|
||||||
"querystring": "^0.2.0",
|
"querystring": "^0.2.0",
|
||||||
"recursive-readdir": "2.2.2",
|
"recursive-readdir": "2.2.2",
|
||||||
"sleep-promise": "8.0.1"
|
"sleep-promise": "8.0.1"
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
const {
|
const {
|
||||||
fetchTokenWithRetry,
|
fetchCachedToken,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
} = require('../../../test/lib/deployment/now-deploy.js');
|
} = require('../../../test/lib/deployment/now-deploy.js');
|
||||||
|
|
||||||
export async function generateNewToken(): Promise<string> {
|
export async function generateNewToken(): Promise<string> {
|
||||||
const token = await fetchTokenWithRetry();
|
const token = await fetchCachedToken();
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/next",
|
"name": "@vercel/next",
|
||||||
"version": "2.6.25-canary.1",
|
"version": "2.6.39-canary.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index",
|
"main": "./dist/index",
|
||||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"@vercel/nft": "0.9.2",
|
"@vercel/nft": "0.9.2",
|
||||||
"async-sema": "3.0.1",
|
"async-sema": "3.0.1",
|
||||||
"buffer-crc32": "0.2.13",
|
"buffer-crc32": "0.2.13",
|
||||||
"escape-string-regexp": "3.0.0",
|
"escape-string-regexp": "2.0.0",
|
||||||
"execa": "2.0.4",
|
"execa": "2.0.4",
|
||||||
"find-up": "4.1.0",
|
"find-up": "4.1.0",
|
||||||
"fs-extra": "7.0.0",
|
"fs-extra": "7.0.0",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default async function createServerlessConfig(
|
|||||||
|
|
||||||
const primaryConfigPath = path.join(entryPath, 'next.config.js');
|
const primaryConfigPath = path.join(entryPath, 'next.config.js');
|
||||||
const secondaryConfigPath = path.join(workPath, 'next.config.js');
|
const secondaryConfigPath = path.join(workPath, 'next.config.js');
|
||||||
const backupConfigName = `next.config.original.${Date.now()}.js`;
|
const backupConfigName = `next.config.__vercel_builder_backup__.js`;
|
||||||
|
|
||||||
const hasPrimaryConfig = fs.existsSync(primaryConfigPath);
|
const hasPrimaryConfig = fs.existsSync(primaryConfigPath);
|
||||||
const hasSecondaryConfig = fs.existsSync(secondaryConfigPath);
|
const hasSecondaryConfig = fs.existsSync(secondaryConfigPath);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -326,6 +326,17 @@ export type RoutesManifest = {
|
|||||||
namedDataRouteRegex?: string;
|
namedDataRouteRegex?: string;
|
||||||
routeKeys?: { [named: string]: string };
|
routeKeys?: { [named: string]: string };
|
||||||
}>;
|
}>;
|
||||||
|
i18n?: {
|
||||||
|
localeDetection?: boolean;
|
||||||
|
defaultLocale: string;
|
||||||
|
locales: string[];
|
||||||
|
domains?: Array<{
|
||||||
|
http?: boolean;
|
||||||
|
domain: string;
|
||||||
|
locales?: string[];
|
||||||
|
defaultLocale: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getRoutesManifest(
|
export async function getRoutesManifest(
|
||||||
@@ -502,6 +513,41 @@ export async function getDynamicRoutes(
|
|||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LoaderKey = 'imgix' | 'cloudinary' | 'akamai' | 'default';
|
||||||
|
|
||||||
|
type ImagesManifest = {
|
||||||
|
version: number;
|
||||||
|
images: {
|
||||||
|
loader: LoaderKey;
|
||||||
|
sizes: number[];
|
||||||
|
domains: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getImagesManifest(
|
||||||
|
entryPath: string,
|
||||||
|
outputDirectory: string
|
||||||
|
): Promise<ImagesManifest | undefined> {
|
||||||
|
const pathImagesManifest = path.join(
|
||||||
|
entryPath,
|
||||||
|
outputDirectory,
|
||||||
|
'images-manifest.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasImagesManifest = await fs
|
||||||
|
.access(pathImagesManifest)
|
||||||
|
.then(() => true)
|
||||||
|
.catch(() => false);
|
||||||
|
|
||||||
|
if (!hasImagesManifest) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const imagesManifest: ImagesManifest = require(pathImagesManifest);
|
||||||
|
return imagesManifest;
|
||||||
|
}
|
||||||
|
|
||||||
function syncEnvVars(base: EnvConfig, removeEnv: EnvConfig, addEnv: EnvConfig) {
|
function syncEnvVars(base: EnvConfig, removeEnv: EnvConfig, addEnv: EnvConfig) {
|
||||||
// Remove any env vars from `removeEnv`
|
// Remove any env vars from `removeEnv`
|
||||||
// that are not present in the `addEnv`
|
// that are not present in the `addEnv`
|
||||||
@@ -711,6 +757,8 @@ export type NextPrerenderedRoutes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
omittedRoutes: string[];
|
omittedRoutes: string[];
|
||||||
|
|
||||||
|
notFoundRoutes: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getExportIntent(
|
export async function getExportIntent(
|
||||||
@@ -801,6 +849,7 @@ export async function getPrerenderManifest(
|
|||||||
fallbackRoutes: {},
|
fallbackRoutes: {},
|
||||||
bypassToken: null,
|
bypassToken: null,
|
||||||
omittedRoutes: [],
|
omittedRoutes: [],
|
||||||
|
notFoundRoutes: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,6 +895,7 @@ export async function getPrerenderManifest(
|
|||||||
preview: {
|
preview: {
|
||||||
previewModeId: string;
|
previewModeId: string;
|
||||||
};
|
};
|
||||||
|
notFoundRoutes?: string[];
|
||||||
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
|
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
|
||||||
|
|
||||||
switch (manifest.version) {
|
switch (manifest.version) {
|
||||||
@@ -860,6 +910,7 @@ export async function getPrerenderManifest(
|
|||||||
bypassToken:
|
bypassToken:
|
||||||
(manifest.preview && manifest.preview.previewModeId) || null,
|
(manifest.preview && manifest.preview.previewModeId) || null,
|
||||||
omittedRoutes: [],
|
omittedRoutes: [],
|
||||||
|
notFoundRoutes: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
@@ -914,8 +965,13 @@ export async function getPrerenderManifest(
|
|||||||
fallbackRoutes: {},
|
fallbackRoutes: {},
|
||||||
bypassToken: manifest.preview.previewModeId,
|
bypassToken: manifest.preview.previewModeId,
|
||||||
omittedRoutes: [],
|
omittedRoutes: [],
|
||||||
|
notFoundRoutes: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (manifest.notFoundRoutes) {
|
||||||
|
ret.notFoundRoutes.push(...manifest.notFoundRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
const {
|
const {
|
||||||
initialRevalidateSeconds,
|
initialRevalidateSeconds,
|
||||||
@@ -969,6 +1025,7 @@ export async function getPrerenderManifest(
|
|||||||
fallbackRoutes: {},
|
fallbackRoutes: {},
|
||||||
bypassToken: null,
|
bypassToken: null,
|
||||||
omittedRoutes: [],
|
omittedRoutes: [],
|
||||||
|
notFoundRoutes: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1000,11 +1057,78 @@ async function getSourceFilePathFromPage({
|
|||||||
workPath: string;
|
workPath: string;
|
||||||
page: string;
|
page: string;
|
||||||
}) {
|
}) {
|
||||||
|
let fsPath = path.join(workPath, 'pages', page);
|
||||||
if (await usesSrcDirectory(workPath)) {
|
if (await usesSrcDirectory(workPath)) {
|
||||||
return path.join('src', 'pages', page);
|
fsPath = path.join(workPath, 'src', 'pages', page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.join('pages', page);
|
if (fs.existsSync(fsPath)) {
|
||||||
|
return path.relative(workPath, fsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const extensionless = fsPath.slice(0, -3); // remove ".js"
|
||||||
|
fsPath = extensionless + '.ts';
|
||||||
|
if (fs.existsSync(fsPath)) {
|
||||||
|
return path.relative(workPath, fsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDirectory(extensionless)) {
|
||||||
|
fsPath = path.join(extensionless, 'index.js');
|
||||||
|
if (fs.existsSync(fsPath)) {
|
||||||
|
return path.relative(workPath, fsPath);
|
||||||
|
}
|
||||||
|
fsPath = path.join(extensionless, 'index.ts');
|
||||||
|
if (fs.existsSync(fsPath)) {
|
||||||
|
return path.relative(workPath, fsPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`WARNING: Unable to find source file for page ${page}`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDirectory(path: string) {
|
||||||
|
return fs.existsSync(path) && fs.lstatSync(path).isDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeLocalePath(
|
||||||
|
pathname: string,
|
||||||
|
locales?: string[]
|
||||||
|
): {
|
||||||
|
detectedLocale?: string;
|
||||||
|
pathname: string;
|
||||||
|
} {
|
||||||
|
let detectedLocale: string | undefined;
|
||||||
|
// first item will be empty string from splitting at first char
|
||||||
|
const pathnameParts = pathname.split('/');
|
||||||
|
|
||||||
|
(locales || []).some(locale => {
|
||||||
|
if (pathnameParts[1].toLowerCase() === locale.toLowerCase()) {
|
||||||
|
detectedLocale = locale;
|
||||||
|
pathnameParts.splice(1, 1);
|
||||||
|
pathname = pathnameParts.join('/') || '/';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
pathname,
|
||||||
|
detectedLocale,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addLocaleOrDefault(
|
||||||
|
pathname: string,
|
||||||
|
routesManifest?: RoutesManifest,
|
||||||
|
locale?: string
|
||||||
|
) {
|
||||||
|
if (!routesManifest?.i18n) return pathname;
|
||||||
|
if (!locale) locale = routesManifest.i18n.defaultLocale;
|
||||||
|
|
||||||
|
return locale
|
||||||
|
? `/${locale}${pathname === '/index' ? '' : pathname}`
|
||||||
|
: pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
22
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/next.config.js
vendored
Normal file
22
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/next.config.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
module.exports = {
|
||||||
|
generateBuildId() {
|
||||||
|
return 'testing-build-id';
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
localeDetection: false,
|
||||||
|
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||||
|
defaultLocale: 'en-US',
|
||||||
|
// TODO: testing locale domains support, will require custom
|
||||||
|
// testing set-up as test accounts are used currently
|
||||||
|
domains: [
|
||||||
|
{
|
||||||
|
domain: 'example.be',
|
||||||
|
defaultLocale: 'nl-BE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: 'example.fr',
|
||||||
|
defaultLocale: 'fr',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
517
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/now.json
vendored
Normal file
517
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/now.json
vendored
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [
|
||||||
|
{
|
||||||
|
"src": "package.json",
|
||||||
|
"use": "@vercel/next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "en;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl-NL;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "fr;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "en-US;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en-US",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl-NL<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/non-existent",
|
||||||
|
"status": 404
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en-US/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"nl\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"nl-NL\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/hello.txt",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "hello world!"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"nl\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"fr\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: update when directory listing is disabled
|
||||||
|
// and these are proper 404s
|
||||||
|
{
|
||||||
|
"path": "/en/not-found",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "Index of"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/not-found",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "Index of"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en-US/not-found",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL/not-found",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"nl-NL\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/not-found",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
|
||||||
|
// this will always be a 200 unless fallback: blocking is used
|
||||||
|
// since the static fallback page is served before the 404
|
||||||
|
// page is rendered
|
||||||
|
{
|
||||||
|
"path": "/en/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delay": 2000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustNotContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en/not-found/fallback/first.json",
|
||||||
|
"status": 404
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustNotContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/fr/not-found/fallback/first.json",
|
||||||
|
"status": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delay": 2000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/not-found/fallback/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en-US/index.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en/index.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/fr/index.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/nl/index.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"nl\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en-US/gsp.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en/gsp.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/fr/gsp.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/nl/gsp.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"locale\":\"nl\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "catchall"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/en-US/gsp/blocking/first.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"catchall\":\"yes\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "catchall"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"nl-NL\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/nl-NL/gsp/blocking/first.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"catchall\":\"yes\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "catchall"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp/blocking/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/_next/data/testing-build-id/fr/gsp/blocking/first.json",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"catchall\":\"yes\""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"next": "canary",
|
||||||
|
"react": "^16.8.6",
|
||||||
|
"react-dom": "^16.8.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
31
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/another.js
vendored
Normal file
31
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/another.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="another">another page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
21
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/auto-export/index.js
vendored
Normal file
21
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/auto-export/index.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="auto-export">auto-export page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/dynamic/[slug].js
vendored
Normal file
12
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/dynamic/[slug].js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Dynamic(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>dynamic page</p>
|
||||||
|
<p id="query">{JSON.stringify(router.query)}</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
const Slug = props => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<Link href="/gsp/blocking/hallo-wereld" locale={'nl-NL'}>
|
||||||
|
<a>/nl-NL/gsp/blocking/hallo-wereld</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/blocking/42" locale={'nl-NL'}>
|
||||||
|
<a>/nl-NL/gsp/blocking/42</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/blocking/hallo-welt" locale={'fr'}>
|
||||||
|
<a>/fr/gsp/blocking/hallo-welt</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/blocking/42" locale={'fr'}>
|
||||||
|
<a>/fr/gsp/blocking/42</a>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticProps = () => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
random: Math.random(),
|
||||||
|
catchall: 'yes',
|
||||||
|
},
|
||||||
|
revalidate: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = () => {
|
||||||
|
return {
|
||||||
|
paths: [],
|
||||||
|
fallback: 'blocking',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Slug;
|
||||||
51
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gsp/fallback/[slug].js
vendored
Normal file
51
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gsp/fallback/[slug].js
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (router.isFallback) return 'Loading...';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
random: Math.random(),
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
revalidate: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = ({ locales }) => {
|
||||||
|
const paths = [];
|
||||||
|
|
||||||
|
for (const locale of locales) {
|
||||||
|
paths.push({ params: { slug: 'first' }, locale });
|
||||||
|
paths.push({ params: { slug: 'second' }, locale });
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// the default locale will be used since one isn't defined here
|
||||||
|
paths,
|
||||||
|
fallback: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
32
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gsp/index.js
vendored
Normal file
32
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gsp/index.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should non-dynamic GSP pages pre-render for each locale?
|
||||||
|
export const getStaticProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (router.isFallback) return 'Loading...';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
random: Math.random(),
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
revalidate: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = () => {
|
||||||
|
return {
|
||||||
|
paths: [
|
||||||
|
{ params: { slug: 'first' } },
|
||||||
|
'/gsp/no-fallback/second',
|
||||||
|
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||||
|
'/nl-NL/gsp/no-fallback/second',
|
||||||
|
'/fr/gsp/no-fallback/first',
|
||||||
|
],
|
||||||
|
fallback: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
32
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gssp/[slug].js
vendored
Normal file
32
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gssp/[slug].js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gssp">gssp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
31
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gssp/index.js
vendored
Normal file
31
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/gssp/index.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gssp">gssp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
57
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/index.js
vendored
Normal file
57
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/index.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="index">index page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/another">
|
||||||
|
<a id="to-another">to /another</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp">
|
||||||
|
<a id="to-gsp">to /gsp</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/fallback/first">
|
||||||
|
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/fallback/hello">
|
||||||
|
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/no-fallback/first">
|
||||||
|
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gssp">
|
||||||
|
<a id="to-gssp">to /gssp</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gssp/first">
|
||||||
|
<a id="to-gssp-slug">to /gssp/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
random: Math.random(),
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
revalidate: 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
54
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/links.js
vendored
Normal file
54
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/links.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
const { nextLocale } = router.query;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="links">links page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/another" locale={nextLocale}>
|
||||||
|
<a id="to-another">to /another</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp" locale={nextLocale}>
|
||||||
|
<a id="to-gsp">to /gsp</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/fallback/first" locale={nextLocale}>
|
||||||
|
<a id="to-fallback-first">to /gsp/fallback/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/fallback/hello" locale={nextLocale}>
|
||||||
|
<a id="to-fallback-hello">to /gsp/fallback/hello</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gsp/no-fallback/first" locale={nextLocale}>
|
||||||
|
<a id="to-no-fallback-first">to /gsp/no-fallback/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gssp" locale={nextLocale}>
|
||||||
|
<a id="to-gssp">to /gssp</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
<Link href="/gssp/first" locale={nextLocale}>
|
||||||
|
<a id="to-gssp-slug">to /gssp/first</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make SSR page so we have query values immediately
|
||||||
|
export const getServerSideProps = () => {
|
||||||
|
return {
|
||||||
|
props: {},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (router.isFallback) return 'Loading...';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ params, locale, locales }) => {
|
||||||
|
if (locale === 'en' || locale === 'nl') {
|
||||||
|
return {
|
||||||
|
notFound: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = () => {
|
||||||
|
return {
|
||||||
|
// the default locale will be used since one isn't defined here
|
||||||
|
paths: ['first', 'second'].map(slug => ({
|
||||||
|
params: { slug },
|
||||||
|
})),
|
||||||
|
fallback: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
37
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/not-found/index.js
vendored
Normal file
37
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/pages/not-found/index.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ locale, locales }) => {
|
||||||
|
if (locale === 'en' || locale === 'nl') {
|
||||||
|
return {
|
||||||
|
notFound: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
1
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/public/hello.txt
vendored
Normal file
1
packages/now-next/test/fixtures/00-i18n-support-no-locale-detection/public/hello.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hello world!
|
||||||
21
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/next.config.js
vendored
Normal file
21
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/next.config.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
generateBuildId() {
|
||||||
|
return 'testing-build-id';
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
locales: ['nl-NL', 'nl-BE', 'nl', 'fr-BE', 'fr', 'en-US', 'en'],
|
||||||
|
defaultLocale: 'en-US',
|
||||||
|
// TODO: testing locale domains support, will require custom
|
||||||
|
// testing set-up as test accounts are used currently
|
||||||
|
domains: [
|
||||||
|
{
|
||||||
|
domain: 'example.be',
|
||||||
|
defaultLocale: 'nl-BE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
domain: 'example.fr',
|
||||||
|
defaultLocale: 'fr',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
359
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/now.json
vendored
Normal file
359
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/now.json
vendored
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [
|
||||||
|
{
|
||||||
|
"src": "package.json",
|
||||||
|
"use": "@vercel/next",
|
||||||
|
"config": {
|
||||||
|
"sharedLambdas": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "en;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 307,
|
||||||
|
"responseHeaders": {
|
||||||
|
"location": "//en/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 307,
|
||||||
|
"responseHeaders": {
|
||||||
|
"location": "//nl/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl-NL;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 307,
|
||||||
|
"responseHeaders": {
|
||||||
|
"location": "//nl-NL/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "fr;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 307,
|
||||||
|
"responseHeaders": {
|
||||||
|
"location": "//fr/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "en-US;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en-US",
|
||||||
|
"headers": {
|
||||||
|
"accept-language": "nl;q=0.9"
|
||||||
|
},
|
||||||
|
"fetchOptions": {
|
||||||
|
"redirect": "manual"
|
||||||
|
},
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "index page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl-NL<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/non-existent",
|
||||||
|
"status": 404
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"fr\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en-US/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"nl\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl-NL/non-existent",
|
||||||
|
"status": 404,
|
||||||
|
"mustContain": "lang=\"nl-NL\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/hello.txt",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "hello world!"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en-US\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"en\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"nl\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "dynamic page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/dynamic/hello",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "\"fr\""
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gsp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gsp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en-US<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">en<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/en/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">nl<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/nl/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "gssp page"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": ">fr<"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/fr/gssp/first",
|
||||||
|
"status": 200,
|
||||||
|
"mustContain": "slug\":\"first\""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"next": "canary",
|
||||||
|
"react": "^16.8.6",
|
||||||
|
"react-dom": "^16.8.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
31
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/another.js
vendored
Normal file
31
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/another.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="another">another page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
21
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/auto-export/index.js
vendored
Normal file
21
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/auto-export/index.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="auto-export">auto-export page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/dynamic/[slug].js
vendored
Normal file
12
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/dynamic/[slug].js
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Dynamic(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>dynamic page</p>
|
||||||
|
<p id="query">{JSON.stringify(router.query)}</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
44
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gsp/fallback/[slug].js
vendored
Normal file
44
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gsp/fallback/[slug].js
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (router.isFallback) return 'Loading...';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = () => {
|
||||||
|
return {
|
||||||
|
// the default locale will be used since one isn't defined here
|
||||||
|
paths: ['first', 'second'].map(slug => ({
|
||||||
|
params: { slug },
|
||||||
|
})),
|
||||||
|
fallback: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
32
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gsp/index.js
vendored
Normal file
32
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gsp/index.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should non-dynamic GSP pages pre-render for each locale?
|
||||||
|
export const getStaticProps = ({ locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (router.isFallback) return 'Loading...';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gsp">gsp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStaticPaths = () => {
|
||||||
|
return {
|
||||||
|
paths: [
|
||||||
|
{ params: { slug: 'first' } },
|
||||||
|
'/gsp/no-fallback/second',
|
||||||
|
{ params: { slug: 'first' }, locale: 'en-US' },
|
||||||
|
'/nl-NL/gsp/no-fallback/second',
|
||||||
|
],
|
||||||
|
fallback: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
32
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gssp/[slug].js
vendored
Normal file
32
packages/now-next/test/fixtures/00-i18n-support-no-shared-lambdas/pages/gssp/[slug].js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
export default function Page(props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p id="gssp">gssp page</p>
|
||||||
|
<p id="props">{JSON.stringify(props)}</p>
|
||||||
|
<p id="router-locale">{router.locale}</p>
|
||||||
|
<p id="router-locales">{JSON.stringify(router.locales)}</p>
|
||||||
|
<p id="router-query">{JSON.stringify(router.query)}</p>
|
||||||
|
<p id="router-pathname">{router.pathname}</p>
|
||||||
|
<p id="router-as-path">{router.asPath}</p>
|
||||||
|
<Link href="/">
|
||||||
|
<a id="to-index">to /</a>
|
||||||
|
</Link>
|
||||||
|
<br />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps = ({ params, locale, locales }) => {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
params,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user