Compare commits

..

100 Commits

Author SHA1 Message Date
Steven
8189fb2373 Publish Stable
- @vercel/build-utils@2.3.1
 - vercel@19.0.1
 - @vercel/client@8.0.1
 - @vercel/go@1.1.1
 - @vercel/next@2.6.1
 - @vercel/node@1.6.1
 - @vercel/python@1.2.1
 - @vercel/ruby@1.2.1
 - @vercel/static-build@0.17.1
2020-05-11 09:10:40 -04:00
Nathan Rajlich
76f544cbea Publish Canary
- @vercel/build-utils@2.3.1-canary.0
 - vercel@19.0.1-canary.0
 - @vercel/client@8.0.1-canary.0
 - @vercel/go@1.1.1-canary.0
 - @vercel/next@2.6.1-canary.0
 - @vercel/node@1.6.1-canary.0
 - @vercel/python@1.2.1-canary.0
 - @vercel/ruby@1.2.1-canary.0
 - @vercel/static-build@0.17.1-canary.0
2020-05-09 13:54:05 -07:00
Nathan Rajlich
e246d2ed71 [client] Throw an error if both .vercelignore and .nowignore exist (#4311)
* [client] Throw an error if both `.vercelignore` and `.nowignore` exist

* Remove `.`

* Add tests

* Update test

* [cli] Properly clear spinner if `createDeployment()` async generator throws an error

* Update packages/now-client/src/utils/index.ts

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

* Update packages/now-client/tests/vercelignore.test.ts

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

Co-authored-by: Steven <steven@ceriously.com>
2020-05-09 03:02:16 -07:00
Steven
ed4c759c49 [all] Fix runtimes to work with old versions of CLI (#4317)
This PR fixes an issue where old versions of the CLI would update to the latest builder, but not have a copy of `@vercel/build-utils` because they only shipped with `@now/build-utils`. So in this case, we can fallback to the other package. We must be careful to only import types from `@vercel/build-utils` and anything needed at runtime must be imported from `./build-utils` wrapper.
2020-05-09 04:00:01 +00:00
Steven
2656647891 [cli] Fix error message to display correct config name (#4309)
This PR fixes an issue when the error message assumed the config was `vercel.json` even when the user had `now.json`.

### Before

```
Error! The property `foo` is not allowed in vercel.json – please remove it.
```

### After

```
 Error! The property `foo` is not allowed in now.json – please remove it.
```

Co-authored-by: Nathan Rajlich <n@n8.io>
2020-05-08 19:45:53 -04:00
Steven
3b3c468f3a [cli] Fix deploying v1 with secrets (#4315)
This PR fixes a regression from PR #4084 where secrets were paginated so some v1 deployments that had more than 20 secrets were unable to deploy since CLI version 19.
2020-05-08 23:08:05 +00:00
Nathan Rajlich
4214de2ce0 [built-utils] Make getPlatformEnv() throw if both NOW_ and VERCEL_ are defined (#4313)
Also adds unit tests.
2020-05-08 15:17:29 -07:00
Nathan Rajlich
40b7af4349 [cli] Fix now dev infinite loop for yarn workspaces (#4310)
A couple quick fixes to `now dev` to land on stable, before #4254 gets merged for canary.
2020-05-08 20:37:20 +00:00
Steven
f4d86cb9df [now-cli] Update now env add to skip value if system var (#4306)
This PR updates the CLI to work the same as the dashboard and skip the env var value if the name indicates that it is a [System Environment Variables](https://vercel.com/docs/v2/build-step#system-environment-variables).

Co-authored-by: Luc <luc.leray@gmail.com>
2020-05-08 11:41:41 -04:00
Nathan Rajlich
0492fcb0fc [now-cli] Fix update Changelog URL (#4302)
Incorrect URL: https://github.com/zeit/now/releases/tag/now@19.0.0

Correct URL: https://github.com/zeit/now/releases/tag/vercel@19.0.0
2020-05-08 01:47:36 +00:00
Nathan Rajlich
3a217dc750 [now-build-utils] Use @vercel runtimes for zero-config (#4300)
This reverts commit 8a9b67a3f3 (#4284),
now that `@vercel` runtimes work in production.
2020-05-08 00:02:30 +00:00
Steven
b626f3fe57 Publish Stable
- @vercel/frameworks@0.0.14
 - @vercel/build-utils@2.3.0
 - @vercel/cgi@1.0.5
 - vercel@19.0.0
 - @vercel/client@8.0.0
 - @vercel/go@1.1.0
 - @vercel/next@2.6.0
 - @vercel/node-bridge@1.3.0
 - @vercel/node@1.6.0
 - @vercel/python@1.2.0
 - @vercel/routing-utils@1.8.2
 - @vercel/ruby@1.2.0
 - @vercel/static-build@0.17.0
2020-05-07 18:52:35 -04:00
Steven
96bc0c9bee Publish Canary
- vercel@18.0.1-canary.24
2020-05-07 17:56:40 -04:00
Steven
f4ff8c0268 [now-cli] Change precedence of auth directory (#4299) 2020-05-07 23:55:35 +02:00
Steven
1a5681f287 [now-cli] Add getTitleName() and update getCommandName() (#4296)
This PR adds two functions:

* `getTitleName()` - used to get the uppercase Vercel or Now package name, for example `vercel --version`
* `getCommandName()` - used to get the `vercel` command followed by subcommands, for example in error suggestions
2020-05-07 21:24:15 +00:00
Ana Trajkovska
88b66ae646 Publish Canary
- vercel@18.0.1-canary.23
2020-05-07 22:37:48 +02:00
Ana Trajkovska
db0124782a Implement pagination for vercel teams ls (#4294)
* Implement pagination for `now teams ls`

* Set default empty object

* Use output logger

* Trigger build
2020-05-07 22:36:54 +02:00
Nathan Rajlich
a7a5d4d169 [now-cli] Special case @vercel/static when updating builders (#4295) 2020-05-07 19:40:52 +00:00
Nathan Rajlich
4b39e96c28 Ensure the npm registry is used during "Publish" workflow (#4286)
Unset the `npm_config_registry` env var which yarn overwrites to the
yarn registry, which we don't want since the `.npmrc` file that gets
created is configured to the npm registry.
2020-05-07 19:00:16 +00:00
Steven
f459db9f83 [now-cli] Add e2e test for vercel.json and .vercelignore (#4292)
This PR adds a test for a deployment as well as `now dev` to ensure both `vercel.json` and `.vercelignore` are applied.

I also fixed the remaining test helpers to work with `vercel.json`.
2020-05-07 18:04:37 +00:00
Ana Trajkovska
ad19021969 Publish Canary
- vercel@18.0.1-canary.22
2020-05-07 18:54:37 +02:00
Ana Trajkovska
95e41874e4 Replace now with vercel in pagination message (#4290) 2020-05-07 18:49:15 +02:00
Ana Trajkovska
4d20a1d77b Publish Canary
- vercel@18.0.1-canary.21
2020-05-07 14:56:28 +02:00
Ana Trajkovska
325ee261cb Implement pagination for now dns ls (#4257) 2020-05-07 14:53:08 +02:00
Nathan Rajlich
2e0cee490d Publish Canary
- @vercel/build-utils@2.2.2-canary.8
 - vercel@18.0.1-canary.20
 - @vercel/client@7.1.1-canary.5
 - @vercel/go@1.0.8-canary.2
 - @vercel/next@2.5.5-canary.7
 - @vercel/node@1.5.2-canary.9
 - @vercel/python@1.1.7-canary.3
 - @vercel/ruby@1.1.1-canary.2
 - @vercel/static-build@0.16.1-canary.6
2020-05-06 22:16:10 -07:00
Nathan Rajlich
8a9b67a3f3 [now-build-utils] Use @now runtimes for zero-config (#4284)
* [now-build-utils] Use `@now` runtimes for zero-config

This is a temporary change until the `@vercel` runtimes work in
production.

* Temporary fix to E2E
2020-05-06 22:09:06 -07:00
Nathan Rajlich
f1d9a5da96 [now-build-utils][now-cli] Fix isOfficialRuntime() edge case bug (#4282)
Fixes a bug where `isOfficialRuntime('static', '@now/static-build')` was returning `true` when it should have been `false`.

And use the function from `@vercel/build-utils` in Vercel CLI.
2020-05-07 03:33:35 +00:00
Nathan Rajlich
8d9c463e1f [now-cli] Update references to Now CLI as Vercel CLI (#4279)
Update references to Now CLI as Vercel CLI 

Co-authored-by: Steven <steven@ceriously.com>
2020-05-06 21:15:20 -04:00
Steven
e07e8f841a [now-cli] Add special case for .vercel.app (#4281)
There are a few places the CLI needs to know about the special suffix `.now.sh` so we also need to include the upcoming `.vercel.app` suffix.
2020-05-07 01:09:21 +00:00
Steven
0b8a2c0dab [now-cli] Update README.md image (#4278)
This PR updates the name, logo, and tagline.

This will look correct in both light mode and dark mode and the text is no longer part of the image.
2020-05-06 19:44:24 -04:00
Shu Ding
9c2b7132fa add cors headers (#4280) 2020-05-07 07:40:29 +08:00
Steven
d4639a5108 [now-cli] Rename bin to support vercel and vc (#4277)
We want to make sure the bin matches the [installed package name](https://docs.npmjs.com/files/package.json#bin).

This means `npm i -g now` will remain `now` and `npm i -g vercel` will use `vercel` as the binary name.

This allows support for different versions on one machine such as `npm i -g now@17 vercel@19` for example.

In addition, we will also install a shorthand `vc` so you can do `vc env pull` for example.
2020-05-06 23:12:06 +00:00
Steven
ba25004ea8 [all] Check for VERCEL_ environment variables with getPlatformEnv() (#4274)
Added the following env vars, most are undocumented but its good to be consistent:

- `VERCEL_REGION`
- `VERCEL_DEBUG`
- `VERCEL_BUILDER_DEBUG`
- `VERCEL_TOKEN`
- `__VERCEL_SKIP_DEV_CMD`

I also updated the error code prefixes to remove `NOW_`.
There `code` isn't used anywhere, this is just to make it unique and a little shorter.
2020-05-06 22:13:12 +00:00
Steven
639a9b03d2 [now-cli][now-go][now-python] Use `<project>/.vercel/cache' dir during dev (#4273)
We renamed `.now` to `.vercel` in #4234 but still fallback to `.now` if it exists. This is because we don't want users to have to re-link all their existing projects. So we need to make sure that the Runtimes know which directory to use for caching. This PR introduces the `devCacheDir` for this purpose.
2020-05-06 19:23:39 +00:00
Nathan Rajlich
28ffdfbeef Add logging to debug failed npm publish for legacy package names in CI (#4266)
As you can see in https://github.com/zeit/now/runs/647945621,
the final step for publishing the legacy `@now` packages failed
with a 401 error from npm.

This additional logging an to attempt to debug why that is happening.
2020-05-06 18:22:09 +00:00
Steven
5e222d3c03 [tests] Fix cancel workflow pattern (#4264)
Sometimes, the "Cancel" workflow wouldn't run because it didn't match the branch name.
This PR will fix the glob to match any branch name.

- `*`: Matches zero or more characters, but does not match the `/` character.
- `**`: Matches zero or more of any character.

https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
2020-05-06 02:14:55 +00:00
Steven
94c8464728 [now-node][now-static-build] Add test for timezone utc (#4265)
This PR adds a couple tests to ensure that the timezone offset is `0` meaning [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time).
2020-05-06 01:14:35 +00:00
Nathan Rajlich
898478d1e1 Publish Canary
- @vercel/frameworks@0.0.14-canary.0
 - @vercel/build-utils@2.2.2-canary.7
 - @vercel/cgi@1.0.5-canary.1
 - vercel@18.0.1-canary.19
 - @vercel/client@7.1.1-canary.4
 - @vercel/go@1.0.8-canary.1
 - @vercel/next@2.5.5-canary.6
 - @vercel/node-bridge@1.2.7-canary.3
 - @vercel/node@1.5.2-canary.8
 - @vercel/python@1.1.7-canary.2
 - @vercel/routing-utils@1.8.2-canary.5
 - @vercel/ruby@1.1.1-canary.1
 - @vercel/static-build@0.16.1-canary.5
2020-05-05 17:11:39 -07:00
Nathan Rajlich
8a68211cad [all] Rename packages to vercel and add logic to publish legacy package names to npm (#4233)
https://vercel.com/blog/zeit-is-now-vercel

* Updates all org packages from `@now` to `@vercel`
* Updates Now CLI package name from `now` to `vercel`
  * Packages contains `"bin"` entries for _both_ `vercel` and `now` in the package.json
* Updates `now-client` package name to `@vercel/client` (org scoped, for authenticity)

There is also a new `publish-legacy.sh` script which ensures that all the legacy package names (i.e. `now`, `now-client`, `@now/node`, etc.) will still be published as well.

We will remove this legacy publishing logic on Jan 1, 2021.
2020-05-05 23:43:57 +00:00
Steven
2765207c93 Publish Canary
- @now/build-utils@2.2.2-canary.6
 - now@18.0.1-canary.18
 - now-client@7.1.1-canary.3
 - @now/routing-utils@1.8.2-canary.4
 - @now/static-build@0.16.1-canary.4
2020-05-05 15:06:47 -04:00
Steven
6b52cfdbc7 [now-cli][now-client] Add support for vercel config files (#4234)
This PR renames the CLI and config files to `vercel`.

https://vercel.com/blog/zeit-is-now-vercel

### Complete
- [x] Help menus and error messages should print cli name from `package.json`
- [x] `now.json` => `vercel.json`
- [x] `.nowignore` => `.vercelignore`
- [x] `~/.now` => `~/.vercel`
- [x] `<project>/.now/project.json` => `<project>/.vercel/project.json`

### TODO
I'm going to do the remaining work in a follow-up PR:
- [ ] `<project>/.now/cache` => `<project>/.vercel/cache` (Runtimes sometimes use this)
- [ ] `NOW_*` special cased environment variables
- [ ] `*.now.sh` special cased url suffix
2020-05-05 14:58:05 -04:00
Ana Trajkovska
f474fa1b8c Publish Canary
- now@18.0.1-canary.17
2020-05-05 01:48:14 +02:00
Ana Trajkovska
2cdee19804 [now-cli] Implement pagination for now env ls (#4200)
This PR implements pagination for listing environment variables for a project.
2020-05-04 23:47:05 +00:00
Steven
e9066a3ead Publish Canary
- @now/build-utils@2.2.2-canary.5
 - now@18.0.1-canary.16
 - @now/node@1.5.2-canary.7
2020-05-04 14:37:51 -04:00
Luc
1461fbe331 [tests] add "no only" and "no skip" eslint rules (#4229)
* add "no only" and "no skip" eslint rules

* ignore irrelevant eslint error

Co-authored-by: Steven <steven@ceriously.com>
2020-05-02 11:35:49 +02:00
Nathan Rajlich
099bc6dbf6 Temporarily revert @TooTallNate's now dev updates (#4231)
Needs more time for testing, and we are preparing a new stable release.

This will be un-reverted after the stable release is tagged.
2020-05-02 00:52:21 +00:00
Steven
fe0d762aca Revert "[now-routing-utils] Fix redirect // when cleanUrls and trailingSlash enabled" (#4232)
Reverts zeit/now#4227

This somehow got merged even though the tests didn't pass. Reverting until it can be merged cleanly.
2020-05-01 22:59:53 +00:00
Steven
07c9c0bb6e [now-routing-utils] Fix redirect // when cleanUrls and trailingSlash enabled (#4227)
This PR fixed a corner case when the user defined both `cleanUrls: true` and `trailingSlash: true` and then visited `/index.html` which would attempt to redirect to the invalid `//` path.
2020-05-01 20:44:39 +00:00
Steven
243018b736 [now-cli] Fix CORS headers in now dev (#4225)
This PR fixes a bug where the headers were not applied when exiting with a status code such as 204.

This is a common pattern for CORS where you want `OPTIONS` method respond with 204 status due to a preflight request.

I also updated the test suite to support the `method` property and ensured a body with empty string is asserted.
2020-05-01 14:29:36 -04:00
JJ Kasper
99436b986a Publish Canary
- @now/build-utils@2.2.2-canary.4
 - now@18.0.1-canary.15
 - now-client@7.1.1-canary.2
 - @now/next@2.5.5-canary.5
 - @now/node@1.5.2-canary.6
 - @now/static-build@0.16.1-canary.3
2020-05-01 13:23:17 -05:00
JJ Kasper
dfdef0f6fd [now-next] Update to pass dynamic page values in the query (#4196)
As discussed this updates to leverage the new named regexes and route keys output in the `routes-manifest.json` to pass the dyname page values in the query to ensure we're handling edge cases with the new custom routes support

Note: the `yarnPreferOffline` change is unrelated and was added to make debugging easier as the build can fail when using this option and the cache is invalid for some packages. 

x-ref: https://github.com/zeit/next.js/pull/12250
2020-05-01 18:08:09 +00:00
Steven
921327d878 [api] Update build script (#4224)
In PR #3514, we added a `/api` directory for functions and a `/public` directory which was created at build time.

This moves the build script to be `now-build` so we don't don't need to build everything in the repo and also no longer need to special case the git env vars.
2020-05-01 09:42:40 -04:00
Arunoda Susiripala
c48fd3e891 Update README.md 2020-05-01 12:18:51 +05:30
Nathan Rajlich
5142e32bed [now-cli] Update now dev HTML templates to use "Vercel" (#4216) 2020-05-01 00:25:01 +00:00
Steven
d360169b06 [now dev] Fix handle: miss override headers (#4217)
Fixes a bug with `now dev` where headers from the `miss` phase were overriding when they shouldn't be.

```json
{
  "version": 2,
  "routes": [
    {
      "handle": "filesystem"
    },
    {
      "src": "/([^/]+)",
      "headers": { "override": "one" },
      "dest": "/blog/$1",
      "check": true
    },
    {
      "handle": "miss"
    },
    {
      "src": "/(.*)",
      "dest": "/src/$1",
      "check": true
    },
    {
      "src": "/src/blog/([^/]+)",
      "headers": { "test": "1", "override": "two" },
      "dest": "/src/blog/$1.html",
      "check": true
    }
  ]
}
```
2020-04-30 23:51:02 +00:00
Nathan Rajlich
7b1893b9f7 [now-node] Use project env vars in startDevServer() and respect NODEJS_HELPERS env var (#4211)
Depends on #4210.
2020-04-30 15:12:46 -07:00
Steven
fb07360b71 [tests] Run now dev tests agains real deployments (#4183)
This PR makes sure that all the `now dev` tests have a corresponding deployment and each assert is also compared to the deployment.

If you want to opt-out of this behavior, for example a test that is meant for specific dev functionality, then there is an option `skipDeploy: true`.

This also fixes a bug where headers were not assigned during proxying to a dev server.
2020-04-30 17:36:32 -04:00
Nathan Rajlich
3a00aed989 [now-cli] Pass in env vars to startDevServer() in now dev (#4210)
The Runtime is expected to set up these env vars in the dev server
child processes that it spawns.
2020-04-30 14:32:29 -07:00
JJ Kasper
64944f8926 [now-cli] (Major) Upload .env files but ignore .local files (#4205)
As discussed this updates to no longer ignore all `.env` files by default and only ignores local env files which matches what we default the `.gitignore` to in our default `create-next-app` [template](20b62de8d7/packages/create-next-app/templates/default/gitignore (L26-L30))

A separate docs PR has been made here https://github.com/zeit/docs/pull/1808 which can be landed after this PR
2020-04-30 21:13:53 +00:00
Nathan Rajlich
5e4eee4db1 [now-cli] Only update build matches once per HTTP request (#4212)
Minor optimization since the "serve" function sometimes gets invoked
recursively.
2020-04-30 20:34:30 +00:00
Nathan Rajlich
a1a5e0ef0d [now-node] Make "without helpers" config option work as expected in startDevServer() (#4208) 2020-04-30 10:49:29 -07:00
Steven
91b9b7f880 Publish Canary
- now@18.0.1-canary.14
 - @now/node@1.5.2-canary.5
2020-04-30 09:20:16 -04:00
Nathan Rajlich
8e29924165 [now-node] Add TypeScript support to startDevServer() (#4185)
Using `ts-node`, with asynchronous type checking via `tsc --no-emit`.

This also removes `ncc` of `typescript` during the build in favor of
having typescript be a regular npm "dependency".
2020-04-30 09:19:30 -04:00
Luis Alvarez D
9083b558f0 Switch to Vercel in the command help for now domains (#4193)
Noticed that we still say `Zeit` while using the now cli.

The inspect command still points to zeit.co when I tested it some hours ago but that seems to be fixed already 😄
2020-04-29 18:19:16 +00:00
Ana Trajkovska
0bf8c3751b Publish Canary
- @now/cgi@1.0.5-canary.0
 - now@18.0.1-canary.13
 - now-client@7.1.1-canary.1
 - @now/next@2.5.5-canary.4
 - @now/node-bridge@1.2.7-canary.2
 - @now/node@1.5.2-canary.4
 - @now/python@1.1.7-canary.1
2020-04-29 12:52:06 +02:00
Ana Trajkovska
3ef832fdbe [now-cli] Implement pagination for now projects ls (#4186)
* Implement pagination for `now projects ls`

* Fix spacing
2020-04-29 12:50:05 +02:00
Nathan Rajlich
4bc6ebe286 [now-cli] Assert 200 status code in dev server unit tests (#4184) 2020-04-28 15:42:25 -07:00
Steven
5660474739 [tests] Remove test.only() so all tests will execute (#4180)
Fix a regression from #4160, specifically bab5794641acbf2ae3f419faf0b1d3565fbf1de3 that was preventing the CLI tests from running.
2020-04-28 19:52:38 +00:00
Nathan Rajlich
e85a62703c [now-cli] Use yarn for now dev integration tests (#4175)
This was switched to `npm` for debugging purposes in #4124, but at this
point we can switch it back to `yarn` so the tests don't take as long.

Co-authored-by: Leo Lamprecht <leo@zeit.co>
2020-04-28 21:09:49 +02:00
Steven
3a3cfd4d7b [tests] Fix remaining lint errors (#4179)
As a follow up to #4178, this fixes the final lint errors so we can run in CI.

Since lint is very quick, about 8 seconds, we can run it on the entire repo instead of only changed files.

I also disabled a couple rules that were leading to 500 warnings we would likely never change.
2020-04-28 11:37:10 -04:00
Nimish Gupta
9570d64b67 fix: removed linting errors on yarn lint (#4178) 2020-04-28 09:11:46 -04:00
Nathan Rajlich
e77ea00e9d Publish Canary
- now@18.0.1-canary.12
2020-04-27 18:22:41 -07:00
Nathan Rajlich
aebe77d222 [now-cli] Make nowCliPkg parameter non-optional (#4173)
To prevent bugs like https://github.com/zeit/now/pull/4163.
2020-04-27 18:21:05 -07:00
Nathan Rajlich
53cb2cc4c5 [now-cli] Don't print "Error starting dev server" message by default (#4172)
It's not useful information and distracts from whatever the actual error
message was from the dev server, which is what the user is actually
interested in.
2020-04-28 01:20:33 +00:00
Arunoda Susiripala
4d75ed5117 [now-cli] Allow to accept equal sign(=) as a value for meta (#4160)
Currently if the value is `=` it will throw an error from the API.
2020-04-28 00:18:51 +00:00
Nathan Rajlich
e6c84dd70b [now-cli] Add 1 minute timeout to now login integration tests (#4166) 2020-04-27 23:21:50 +00:00
Nathan Rajlich
d51f0d0f06 [now-cli] Remove "Stopping now dev server" message (#4165) 2020-04-27 15:01:23 -07:00
JJ Kasper
4cd35c48a2 Publish Canary
- now@18.0.1-canary.11
 - @now/next@2.5.5-canary.3
2020-04-27 16:48:43 -05:00
JJ Kasper
69ac4f3eb8 [now-next] Update error throwing to use NowBuildError (#4167)
Per https://github.com/zeit/now/pull/4161#discussion_r416042826 this updates to use `NowBuildError` for our errors instead of the standard `Error` instance
2020-04-27 20:40:32 +00:00
Nathan Rajlich
2c9cbe20f3 [now-cli] Fix logic to not install bundled runtimes into cache dir for now dev (#4163) 2020-04-27 12:21:29 -07:00
Ana Trajkovska
4ddd2f016c Publish Canary
- @now/build-utils@2.2.2-canary.3
 - now@18.0.1-canary.10
 - @now/next@2.5.5-canary.2
 - @now/routing-utils@1.8.2-canary.3
2020-04-27 20:56:36 +02:00
JJ Kasper
76f61cbbf0 [now-next] Provide a better error when failing to load routes-manifest (#4161)
This updates the error message shown when we fail to load the `routes-manifest` which appears to be happening most often when an incorrect output directory is configured for a Next.js application
2020-04-27 18:05:03 +00:00
YuLe
23fe8affec [now-cli] Use imported pkg instead of require("../package.json") (#4159) 2020-04-27 10:32:33 -07:00
Steven
5334caad54 [api] Use 405 method not allowed (#4148)
I was doing a diff and noticed this returns the wrong status code.

This PR changes the unknown method response to [405 Method Not Allowed](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405) status code.
2020-04-27 11:38:22 -04:00
Steven
103e4117c3 [now-routing-utils] Add support for permanent in redirects (#4150)
This adds `permanent` for `redirects` defined in Next.js RFC https://github.com/zeit/next.js/issues/9081

```json
{
  "redirects": [
    { "source": "/foo", "destination": "/api/foo", "permanent": true }
  ]
}
```
2020-04-27 11:37:15 -04:00
Ana Trajkovska
3e774d0531 Implement pagination for now dns ls <domain> (#4134)
Co-authored-by: Nathan Rajlich <n@n8.io>
2020-04-27 15:26:53 +02:00
Nathan Rajlich
5e2139f408 Publish Canary
- now@18.0.1-canary.9
2020-04-24 17:33:32 -07:00
Nathan Rajlich
55e4bffcd2 [now-cli] Add the core Runtimes as npm dependencies for now dev (#4117)
Rather than creating a `builders.tar.gz` file with the core Runtimes and
bundling that tarball with Now CLI, simply have them be regular npm
dependencies so that they are installed into Now CLI's `node_modules`
directory.

When one of the core runtimes is specified for a build, the runtime will be
required as a regular module dependency of Now CLI, and the builders cache
will never touched.

Bundled runtimes are also no longer updated, making the runtime versions
pinned to the version of Now CLI.

Logic for the builders cache directory still remains, but will now only be
used when using a Community Runtime (or development tarball URL).
2020-04-25 00:19:58 +00:00
Nathan Rajlich
de3a066934 [now-cli] Use npx to invoke ncc in build script (#4146)
The previous file path for ncc isn't always reliable during development,
depending on which directory `yarn` is invoked in inside the monorepo.

Using `npx` ensures the version specified in the now-cli `package.json`
is used even if it's installed at the root of the monorepo.
2020-04-24 20:05:25 +00:00
Steven
257b0ca5b6 Publish Canary
- now@18.0.1-canary.8
2020-04-24 14:09:01 -04:00
Nathan Rajlich
e826d48814 [now-cli] Remove yarn as a dev dependency (#4141)
Remove yarn dependency since it is no longer used.

Co-authored-by: Steven <steven@ceriously.com>
2020-04-24 12:06:00 -04:00
Nathan Rajlich
d4ecfb04bb [now-cli] Update chokidar to v3.3.1 (#4142)
For Node 14 support:

> npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+.
> Upgrade to chokidar 3 with 15x less dependencies.
2020-04-24 09:25:21 -04:00
Steven
cad10e1918 [now-cli] (Major) Change project settings inheritance (#4135)
When Now CLI 17 introduce the `.now` directory with project settings, it started assuming that the current project scope should be used for all commands. This made `now switch` do nothing unless you changed the current directory.

This PR is a _major_ semver change so that the only commands that inherit the project settings are:

- `now deploy`
- `now dev`
- `now env`

For example, `now ls` will not observe project settings and instead observe `now switch`.
2020-04-24 13:06:01 +00:00
Nathan Rajlich
1e221c48f9 [now-cli] Ensure the builders.tar.gz file is finished extracting (#4124)
`now dev` integration tests have been failing as of recently with failures to require Runtime builders from the builder cache. Upon investigation, it turns out that the `builders.tar.gz` file was not being completely extracted since the integration tests complete quickly and then kill the Now CLI process, which has not yet completed the extraction.

Fix is to ensure the tarball extraction promise is fully resolved before cleanly shutting down.

Also now applying the clean shutdown logic upon `SIGTERM` signal, which is what the integration tests send to shut down the Now CLI process.
2020-04-23 21:49:20 +00:00
Nathan Rajlich
15221bf19c [now-cli] Add the x-vercel-id and x-vercel-cache response headers to now dev (#4137)
Matches current production.
2020-04-23 12:58:25 -07:00
Paco
2513fecaf4 [examples] Update vercel.svg in Next.js example (#4128)
* Update vercel.svg in Next.js example

* Update to thinner variant
2020-04-23 12:42:08 -07:00
Nathan Rajlich
d723d985e3 [now-cli] Prevent infinite loop for Runtime "module not found" in now dev (#4126) 2020-04-23 12:41:47 -07:00
Steven
2d0a71946b Publish Canary
- now@18.0.1-canary.7
 - @now/static-build@0.16.1-canary.2
2020-04-22 17:55:24 -04:00
Steven
4b7af4d7d3 [now-cli] Fix flicker from file upload progress bar (#4125)
This PR fixes a bug where deploying a new project would flicker between two states: the upload progress bar and "Setting up Project" spinner.
2020-04-22 17:48:47 -04:00
Steven
8e3f4a1ca2 [now-static-build] Add tests for gem install of native deps (#4123)
These tests ensure we can install native dependencies with `gem install` such as:
- `rmagic`
- `ruby-vips`

Co-authored-by: Nathan Rajlich <n@n8.io>
2020-04-22 16:25:44 -04:00
470 changed files with 8847 additions and 8986 deletions

View File

@@ -92,7 +92,7 @@ Sometimes you want to test changes to a Builder against an existing project, may
2. Run `yarn build` to compile typescript and other build steps
3. Run `npm pack` to create a tarball file
4. Run `now *.tgz` to upload the tarball file and get a URL
5. Edit any existing `now.json` project and replace `use` with the URL
5. Edit any existing `vercel.json` project and replace `use` with the URL
6. Run `now` or `now dev` to deploy with the experimental Builder
## Add a New Framework

View File

@@ -2,7 +2,7 @@ name: Cancel
on:
push:
branches:
- '*'
- '**'
- '!master'
jobs:

View File

@@ -22,9 +22,6 @@ jobs:
- uses: actions/checkout@v2
- run: git fetch origin master --depth=10
- run: git fetch origin ${{ github.ref }} --depth=10
- name: Install Hugo
if: matrix.os == 'macos-latest'
run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/now-cli/test/dev/fixtures/08-hugo/
- run: yarn install
- run: yarn run build
- uses: actions/setup-node@v1

View File

@@ -11,7 +11,7 @@ on:
jobs:
test:
name: Dev
timeout-minutes: 30
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
@@ -31,3 +31,6 @@ jobs:
with:
node-version: ${{ matrix.node }}
- run: yarn test-integration-dev --clean false
env:
ZEIT_TEAM_TOKEN: ${{ secrets.ZEIT_TEAM_TOKEN }}
ZEIT_REGISTRATION_URL: ${{ secrets.ZEIT_REGISTRATION_URL }}

View File

@@ -25,9 +25,10 @@ jobs:
- uses: actions/setup-node@v1
- run: yarn install
- run: yarn run build
- run: yarn run test-lint
- run: yarn run lint
if: matrix.os == 'ubuntu-latest' && matrix.node == 12 # only run lint once
- run: yarn run test-unit --clean false
- run: yarn workspace now run coverage
if: matrix.os == 'ubuntu-latest' && matrix.node == 12 # only run once
- run: yarn workspace vercel run coverage
if: matrix.os == 'ubuntu-latest' && matrix.node == 12 # only run coverage once
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

3
.gitignore vendored
View File

@@ -6,6 +6,7 @@ npm-debug.log
yarn-error.log
.nyc_output
coverage
coverage.lcov
*.swp
*.bak
*.tgz
@@ -19,6 +20,8 @@ packages/now-cli/test/**/node_modules
packages/now-cli/test/dev/fixtures/08-hugo/hugo
packages/now-cli/test/dev/fixtures/**/dist
packages/now-cli/test/dev/fixtures/**/public
packages/now-cli/test/dev/fixtures/**/.now
packages/now-cli/test/dev/fixtures/**/.vercel
packages/now-cli/test/fixtures/integration
test/lib/deployment/failed-page.txt
.DS_Store

View File

@@ -3,7 +3,7 @@
The following page is a reference for how to create a Runtime using the available Runtime API.
A Runtime is an npm module that exposes a `build` function and optionally an `analyze` function and `prepareCache` function.
Official Runtimes are published to [npmjs.com](https://npmjs.com) as a package and referenced in the `use` property of the `now.json` configuration file.
Official Runtimes are published to [npmjs.com](https://npmjs.com) as a package and referenced in the `use` property of the `vercel.json` configuration file.
However, the `use` property will work with any [npm install argument](https://docs.npmjs.com/cli/install) such as a git repo url which is useful for testing your Runtime.
See the [Runtimes Documentation](https://vercel.com/docs/runtimes) to view example usage.
@@ -143,7 +143,7 @@ The exported functions [`analyze`](#analyze), [`build`](#build), and [`prepareCa
- `entrypoint`: Name of entrypoint file for this particular build job. Value `files[entrypoint]` is guaranteed to exist and be a valid [File](#files) reference. `entrypoint` is always a discrete file and never a glob, since globs are expanded into separate builds at deployment time.
- `workPath`: A writable temporary directory where you are encouraged to perform your build process. This directory will be populated with the restored cache from the previous run (if any) for [`analyze`](#analyze) and [`build`](#build).
- `cachePath`: A writable temporary directory where you can build a cache for the next run. This is only passed to `prepareCache`.
- `config`: An arbitrary object passed from by the user in the [Build definition](#defining-the-build-step) in `now.json`.
- `config`: An arbitrary object passed from by the user in the [Build definition](#defining-the-build-step) in `vercel.json`.
## Examples

View File

@@ -1,11 +1,15 @@
![now](https://assets.zeit.co/image/upload/v1581518533/repositories/now-cli/v4.png)
<p align="center">
<img src="https://assets.vercel.com/image/upload/v1588805858/repositories/vercel/logo.png" height="96">
<h3 align="center">Vercel</h3>
<p align="center">Develop. Preview. Ship.</p>
</p>
[![CI Status](https://badgen.net/github/checks/zeit/now?label=CI)](https://github.com/zeit/now/actions?workflow=CI)
[![Join the community on GitHub Discussions](https://badgen.net/badge/join%20the%20discussion/on%20github/black?icon=github)](https://github.com/zeit/now/discussions)
## Usage
Get started by [Importing a Git Project](https://vercel.com/import) and use `git push` to deploy. Alternatively, you can [install Now CLI](https://vercel.com/download).
Get started by [Importing a Git Project](https://vercel.com/import) and use `git push` to deploy. Alternatively, you can [install Vercel CLI](https://vercel.com/download).
## Documentation
@@ -17,7 +21,7 @@ For details on how to use Vercel, check out our [documentation](https://vercel.c
2. Install dependencies with `yarn install`
3. Compile the code: `yarn build`
4. Link the package to the global module directory: `cd ./packages/now-cli && yarn link`
5. You can now start using `now` anywhere inside the command line
5. You can start using `vercel` anywhere inside the command line
As always, you should use `yarn test-unit` to run the tests and see if your changes have broken anything.

View File

@@ -17,9 +17,9 @@ export function withApiHandler(handler: Handler): Handler {
}
if (req.method !== 'GET') {
return res.status(404).json({
return res.status(405).json({
error: {
code: 'not_found',
code: 'method_not_allowed',
message: 'Only GET requests are supported for this endpoint.',
},
});

View File

@@ -19,5 +19,8 @@ export default withApiHandler(async function(
req: NowRequest,
res: NowResponse
) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.setHeader('Access-Control-Allow-Headers', 'Authorization, Accept, Content-Type');
return res.status(200).json(frameworks);
});

View File

@@ -7,9 +7,9 @@ used an unknown or invalid dc identifier.
#### Possible Ways to Fix It
Check your `now.json` or `--regions` flag and
Check your `vercel.json` or `--regions` flag and
make sure you are using a valid string. Regions
and DCs have to be in *lowercase*.
and DCs have to be in _lowercase_.
**Valid region identifiers**:
@@ -19,7 +19,7 @@ and DCs have to be in *lowercase*.
- `gru`
- `iad`
In `now-cli`, they currently are transformed to
In `now-cli`, they currently are transformed to
DC identifiers before being sent to our APIs.
**Valid DC identifiers**:

View File

@@ -8,4 +8,4 @@ The `--token` flag was specified, but its contents are invalid.
The `--token` flag must only contain numbers (0-9) and letters from the alphabet (a-z and A-Z). This needs to be the token of the user account as which you'd like to act.
You can either get the token from the `./now/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
You can either get the token from the `./vercel/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).

View File

@@ -2,7 +2,7 @@
#### Why This Error Occurred
You ran `now dev` inside a project that contains a `now.json` file with `env` or `build.env` properties that use [Now Secrets](https://vercel.com/docs/v2/build-step#environment-variables).
You ran `now dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Now Secrets](https://vercel.com/docs/v2/build-step#environment-variables).
In order to use environment variables in your project locally that have values defined using the Now Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env` or `.env.build` file.

View File

@@ -8,4 +8,4 @@ The `--token` flag was specified, but there's no value for it available.
In order to make it work, you need to specify a value for the `--token` flag. This needs to be the token of the user account as which you'd like to act.
You can either get the token from the `./now/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
You can either get the token from the `./vercel/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).

View File

@@ -6,5 +6,5 @@ You're running Now CLI in a non-terminal context and there are no credentials av
#### Possible Ways to Fix It
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can either get the token from the `./now/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
- Ensure that both `~/now/auth.json` and `~/now/config.json` exist
- Specify a value for the `--token` flag (this needs to be the token of the user account as which you'd like to act). You can either get the token from the `./vercel/auth.json` file located in your user directory or [from the dashboard](https://vercel.com/account/tokens).
- Ensure that both `~/vercel/auth.json` and `~/vercel/config.json` exist

View File

@@ -0,0 +1,11 @@
# Routes Manifest Could Not Be Found
#### Why This Error Occurred
This could be caused by a failure during the build or an incorrect output directory being configured for your Next.js project.
#### Possible Ways to Fix It
Check for any build errors in the logs and ensure that the output directory setting is either not changed or is pointing to the location of the `.next` output folder (`distDir`).
If you are running `next export` you should **not** need to customize the output directory to `out` since the builder automatically detects `next export` being run and uses the output from it.

View File

@@ -7,11 +7,10 @@ setting. This isn't supported yet.
#### Possible Ways to Fix It
Ensure your scale settings (in `now.json`, the command you're running
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
the `min` scale setting set to `0`. You can do this by running
```
now scale <deployment> 0 10
```

View File

@@ -1,10 +1,3 @@
<svg width="82" height="16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="url(#prefix__paint0_linear)" d="M9.018 0l9.019 16H0L9.018 0z"/>
<path fill="#333" fill-rule="evenodd" d="M51.634 12.028h-6.492V2.052h6.492v1.256H46.61v3.007h4.37V7.57h-4.37v3.202h5.024v1.255zm-14.063 0h-7.235v-1.096l5.342-7.624h-5.253V2.052h7.058v1.097l-5.342 7.623h5.43v1.256zm21.88 0h6.333v-1.256h-2.423V3.308h2.423V2.052h-6.332v1.256h2.441v7.465h-2.441v1.255zm18.22 0h-1.468v-8.72h-3.36V2.052h8.225v1.256H77.67v8.72z" clip-rule="evenodd"/>
<defs>
<linearGradient id="prefix__paint0_linear" x1="28.022" x2="16.189" y1="22.991" y2="8.569" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff"/>
<stop offset="1"/>
</linearGradient>
</defs>
<svg width="70" height="16" viewBox="0 0 70 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.255.05l9.108 15.753H.148L9.255.05zM39.434 8.418c0-2.535-1.87-4.307-4.554-4.307-2.683 0-4.554 1.772-4.554 4.307 0 2.487 2.019 4.308 4.8 4.308 1.526 0 2.905-.566 3.79-1.6l-1.673-.96c-.517.517-1.28.837-2.117.837-1.23 0-2.29-.665-2.658-1.674l-.074-.172h6.966a3.76 3.76 0 00.074-.739zm-7.065-.738l.05-.148c.32-1.058 1.255-1.698 2.436-1.698 1.207 0 2.117.64 2.437 1.698l.05.148h-4.973zM65.945 8.418c0-2.535-1.871-4.307-4.554-4.307-2.683 0-4.554 1.772-4.554 4.307 0 2.487 2.018 4.308 4.8 4.308 1.526 0 2.904-.566 3.79-1.6l-1.673-.96c-.517.517-1.28.837-2.117.837-1.23 0-2.29-.665-2.659-1.674l-.073-.172h6.966a3.76 3.76 0 00.074-.739zM58.88 7.68l.05-.148c.32-1.058 1.255-1.698 2.436-1.698 1.206 0 2.117.64 2.437 1.698l.05.148H58.88zM54.13 7.015l1.673-.96c-.788-1.23-2.19-1.92-3.89-1.92-2.682 0-4.553 1.773-4.553 4.308 0 2.536 1.87 4.308 4.554 4.308 1.698 0 3.101-.69 3.89-1.92l-1.675-.96c-.443.738-1.23 1.157-2.215 1.157-1.55 0-2.585-1.034-2.585-2.585 0-1.55 1.034-2.585 2.585-2.585.96 0 1.772.419 2.215 1.157zM69.637 1.428h-1.97v11.077h1.97V1.428zM31.779 1.428h-2.265L25.182 8.91l-4.333-7.483H18.56l6.622 11.421 6.597-11.421zM45.71 6.4c.222 0 .444.025.665.074V4.382c-1.673.049-3.249.984-3.249 2.141V4.382h-1.97v8.123h1.97v-3.52c0-1.527 1.059-2.585 2.585-2.585z" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 794 B

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,14 +1,13 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"packages": ["packages/*"],
"command": {
"publish": {
"npmClient": "npm",
"allowBranch": ["master", "canary"],
"registry": "https://registry.npmjs.org/"
}
},
"version": "independent"
}
"npmClient": "yarn",
"useWorkspaces": true,
"packages": ["packages/*"],
"command": {
"publish": {
"npmClient": "npm",
"allowBranch": ["master"],
"registry": "https://registry.npmjs.org/"
}
},
"version": "independent"
}

View File

@@ -1,5 +1,5 @@
{
"name": "now-builders",
"name": "vercel-monorepo",
"version": "0.0.0",
"private": true,
"license": "MIT",
@@ -22,10 +22,12 @@
"buffer-replace": "1.0.0",
"eslint": "6.2.2",
"eslint-config-prettier": "6.1.0",
"eslint-plugin-jest": "23.8.2",
"husky": "3.0.4",
"json5": "2.1.1",
"lint-staged": "9.2.5",
"node-fetch": "2.6.0",
"npm-package-arg": "6.1.0",
"prettier": "1.18.2"
},
"scripts": {
@@ -36,7 +38,7 @@
"publish-from-github": "./utils/publish.sh",
"changelog": "node utils/changelog.js",
"build": "node utils/run.js build all",
"test-lint": "node utils/run.js test-lint",
"now-build": "mkdir -p public && echo '<a href=\"https://vercel.com/import\">Import</a>' > public/output.html",
"test-unit": "node utils/run.js test-unit",
"test-integration-cli": "node utils/run.js test-integration-cli",
"test-integration-once": "node utils/run.js test-integration-once",
@@ -71,6 +73,9 @@
"sourceType": "module",
"modules": true
},
"plugins": [
"jest"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
@@ -89,8 +94,12 @@
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-unused-vars": 2,
"@typescript-eslint/no-use-before-define": 0
"@typescript-eslint/no-use-before-define": 0,
"jest/no-disabled-tests": 2,
"jest/no-focused-tests": 2
},
"overrides": [
{

View File

@@ -1,6 +1,6 @@
{
"name": "@now/frameworks",
"version": "0.0.13",
"name": "@vercel/frameworks",
"version": "0.0.14",
"main": "frameworks.json",
"license": "UNLICENSED"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "2.2.2-canary.2",
"name": "@vercel/build-utils",
"version": "2.3.1",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -12,8 +12,8 @@
},
"scripts": {
"build": "./build.sh",
"test-unit": "jest --env node --verbose --runInBand test/unit.*test.*",
"test-integration-once": "jest --env node --verbose --runInBand test/integration.test.js",
"test-unit": "jest --env node --verbose --runInBand --bail test/unit.*test.*",
"test-integration-once": "jest --env node --verbose --runInBand --bail test/integration.test.js",
"prepublishOnly": "./build.sh"
},
"devDependencies": {

View File

@@ -1,5 +1,7 @@
import { getPlatformEnv } from './';
export default function debug(message: string, ...additional: any[]) {
if (process.env.NOW_BUILDER_DEBUG) {
if (getPlatformEnv('BUILDER_DEBUG')) {
console.log(message, ...additional);
}
}

View File

@@ -1,8 +1,9 @@
import minimatch from 'minimatch';
import { valid as validSemver } from 'semver';
import { parse as parsePath, extname } from 'path';
import { Route, Source } from '@now/routing-utils';
import { Route, Source } from '@vercel/routing-utils';
import { PackageJson, Builder, Config, BuilderFunctions } from './types';
import { isOfficialRuntime } from './';
interface ErrorResponse {
code: string;
@@ -55,7 +56,7 @@ export function detectApiDirectory(builders: Builder[]): string | null {
function getPublicBuilder(builders: Builder[]): Builder | null {
const builder = builders.find(
builder =>
builder.use === '@now/static' &&
isOfficialRuntime('static', builder.use) &&
/^.*\/\*\*\/\*$/.test(builder.src) &&
builder.config &&
builder.config.zeroConfig === true
@@ -194,7 +195,8 @@ export async function detectBuilders(
!fallbackEntrypoint &&
buildCommand &&
!fileName.includes('/') &&
fileName !== 'now.json'
fileName !== 'now.json' &&
fileName !== 'vercel.json'
) {
fallbackEntrypoint = fileName;
}
@@ -389,11 +391,11 @@ function getApiMatches({ tag }: Options = {}) {
const config = { zeroConfig: true };
return [
{ src: 'api/**/*.js', use: `@now/node${withTag}`, config },
{ src: 'api/**/*.ts', use: `@now/node${withTag}`, config },
{ src: 'api/**/!(*_test).go', use: `@now/go${withTag}`, config },
{ src: 'api/**/*.py', use: `@now/python${withTag}`, config },
{ src: 'api/**/*.rb', use: `@now/ruby${withTag}`, config },
{ src: 'api/**/*.js', use: `@vercel/node${withTag}`, config },
{ src: 'api/**/*.ts', use: `@vercel/node${withTag}`, config },
{ src: 'api/**/!(*_test).go', use: `@vercel/go${withTag}`, config },
{ src: 'api/**/*.py', use: `@vercel/python${withTag}`, config },
{ src: 'api/**/*.rb', use: `@vercel/ruby${withTag}`, config },
];
}
@@ -455,7 +457,7 @@ function detectFrontBuilder(
}
if (framework === 'nextjs') {
return { src: 'package.json', use: `@now/next${withTag}`, config };
return { src: 'package.json', use: `@vercel/next${withTag}`, config };
}
// Entrypoints for other frameworks
@@ -478,7 +480,7 @@ function detectFrontBuilder(
return {
src: source || 'package.json',
use: `@now/static-build${withTag}`,
use: `@vercel/static-build${withTag}`,
config,
};
}
@@ -593,7 +595,7 @@ function checkUnusedFunctions(
}
// Next.js can use functions only for `src/pages` or `pages`
if (frontendBuilder && frontendBuilder.use.startsWith('@now/next')) {
if (frontendBuilder && isOfficialRuntime('next', frontendBuilder.use)) {
for (const fnKey of unusedFunctions.values()) {
if (fnKey.startsWith('pages/') || fnKey.startsWith('src/pages')) {
unusedFunctions.delete(fnKey);
@@ -958,7 +960,7 @@ function getRouteResult(
outputDirectory &&
frontendBuilder &&
!options.featHandleMiss &&
frontendBuilder.use === '@now/static'
isOfficialRuntime('static', frontendBuilder.use)
) {
defaultRoutes.push({
src: '/(.*)',

View File

@@ -1,4 +1,4 @@
import { Framework, FrameworkDetectionItem } from '@now/frameworks';
import { Framework, FrameworkDetectionItem } from '@vercel/frameworks';
import { DetectorFilesystem } from './detectors/filesystem';
export interface DetectFrameworkOptions {

View File

@@ -23,7 +23,7 @@ interface Props {
message: string;
/**
* A unique error code for this particular error.
* Should start with the builder name such as `NOW_NODE_`.
* Should start with the builder name such as `NODE_`.
*/
code: string;
/**

View File

@@ -54,7 +54,7 @@ export async function getSupportedNodeVersion(
engineRange +
'".';
throw new NowBuildError({
code: 'NOW_BUILD_UTILS_NODE_VERSION_INVALID',
code: 'BUILD_UTILS_NODE_VERSION_INVALID',
link:
'https://vercel.com/docs/runtimes#official-runtimes/node-js/node-js-version',
message: intro + '\n' + pleaseSet,
@@ -72,7 +72,7 @@ export async function getSupportedNodeVersion(
engineRange +
'".';
throw new NowBuildError({
code: 'NOW_BUILD_UTILS_NODE_VERSION_DISCONTINUED',
code: 'BUILD_UTILS_NODE_VERSION_DISCONTINUED',
link:
'https://vercel.com/docs/runtimes#official-runtimes/node-js/node-js-version',
message: intro + '\n' + pleaseSet + '\n' + upstreamProvider,

View File

@@ -39,7 +39,7 @@ export function spawnAsync(
: 'Command';
reject(
new NowBuildError({
code: `NOW_BUILD_UTILS_SPAWN_${code || signal}`,
code: `BUILD_UTILS_SPAWN_${code || signal}`,
message:
opts.stdio === 'inherit'
? `${cmd} exited with ${code || signal}`
@@ -81,7 +81,7 @@ export function execAsync(
return reject(
new NowBuildError({
code: `NOW_BUILD_UTILS_EXEC_${code || signal}`,
code: `BUILD_UTILS_EXEC_${code || signal}`,
message: `${cmd} exited with ${code || signal}`,
})
);

View File

@@ -80,3 +80,42 @@ export { readConfigFile } from './fs/read-config-file';
export * from './schemas';
export * from './types';
export * from './errors';
/**
* Helper function to support both `@vercel` and legacy `@now` official Runtimes.
*/
export const isOfficialRuntime = (desired: string, name?: string): boolean => {
if (typeof name !== 'string') {
return false;
}
return (
name === `@vercel/${desired}` ||
name === `@now/${desired}` ||
name.startsWith(`@vercel/${desired}@`) ||
name.startsWith(`@now/${desired}@`)
);
};
export const isStaticRuntime = (name?: string): boolean => {
return isOfficialRuntime('static', name);
};
/**
* Helper function to support both `VERCEL_` and legacy `NOW_` env vars.
* Throws an error if *both* env vars are defined.
*/
export const getPlatformEnv = (name: string): string | undefined => {
const vName = `VERCEL_${name}`;
const nName = `NOW_${name}`;
const v = process.env[vName];
const n = process.env[nName];
if (typeof v === 'string') {
if (typeof n === 'string') {
throw new Error(
`Both "${vName}" and "${nName}" env vars are defined. Please only define the "${vName}" env var`
);
}
return v;
}
return n;
};

View File

@@ -49,6 +49,7 @@ export interface Config {
export interface Meta {
isDev?: boolean;
devCacheDir?: string;
skipDownload?: boolean;
requestPath?: string | null;
filesChanged?: string[];
@@ -81,7 +82,7 @@ export interface AnalyzeOptions {
/**
* An arbitrary object passed by the user in the build definition defined
* in `now.json`.
* in `vercel.json`.
*/
config: Config;
}
@@ -108,7 +109,7 @@ export interface BuildOptions {
/**
* An arbitrary object passed by the user in the build definition defined
* in `now.json`.
* in `vercel.json`.
*/
config: Config;
@@ -148,7 +149,7 @@ export interface PrepareCacheOptions {
/**
* An arbitrary object passed by the user in the build definition defined
* in `now.json`.
* in `vercel.json`.
*/
config: Config;
}
@@ -182,27 +183,11 @@ export interface ShouldServeOptions {
/**
* An arbitrary object passed by the user in the build definition defined
* in `now.json`.
* in `vercel.json`.
*/
config: Config;
}
export interface StartDevServerOptions {
/**
* Name of entrypoint file for this particular build job. Value
* `files[entrypoint]` is guaranteed to exist and be a valid File reference.
* `entrypoint` is always a discrete file and never a glob, since globs are
* expanded into separate builds at deployment time.
*/
entrypoint: string;
/**
* A writable temporary directory where you are encouraged to perform your
* build process. This directory will be populated with the restored cache.
*/
workPath: string;
}
export interface StartDevServerSuccess {
/**
* Port number where the dev server can be connected to, assumed to be running
@@ -228,7 +213,7 @@ export type StartDevServerResult = StartDevServerSuccess | null;
* Source: https://gist.github.com/iainreid820/5c1cc527fe6b5b7dba41fec7fe54bf6e
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace PackageJson {
namespace PackageJson {
/**
* An author or contributor
*/
@@ -351,24 +336,3 @@ export interface BuilderFunctions {
excludeFiles?: string;
};
}
export interface NowRewrite {
source: string;
destination: string;
}
export interface NowRedirect {
source: string;
destination: string;
statusCode?: number;
}
export interface NowHeader {
source: string;
headers: NowHeaderKeyValue[];
}
export interface NowHeaderKeyValue {
key: string;
value: string;
}

View File

@@ -1,6 +1,6 @@
{
"version": 2,
"builds": [{ "src": "api/index.js", "use": "@now/node" }],
"builds": [{ "src": "api/index.js", "use": "@vercel/node" }],
"probes": [
{
"path": "/api/index.js",

View File

@@ -1,9 +1,9 @@
{
"version": 2,
"builds": [
{ "src": "with-npm/index.js", "use": "@now/node" },
{ "src": "with-yarn/index.js", "use": "@now/node" },
{ "src": "with-yarn-and-npm/index.js", "use": "@now/node" }
{ "src": "with-npm/index.js", "use": "@vercel/node" },
{ "src": "with-yarn/index.js", "use": "@vercel/node" },
{ "src": "with-yarn-and-npm/index.js", "use": "@vercel/node" }
],
"probes": [
{ "path": "/with-npm", "mustContain": "npm:RANDOMNESS_PLACEHOLDER" },

View File

@@ -3,7 +3,7 @@
"builds": [
{
"src": "index.js",
"use": "@now/node"
"use": "@vercel/node"
}
],
"probes": [{ "path": "/", "mustContain": "found:RANDOMNESS_PLACEHOLDER" }]

View File

@@ -1,6 +1,6 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/static-build" }],
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
"build": { "env": { "NODE_ENV": "production" } },
"probes": [{ "path": "/", "mustContain": "node-env:RANDOMNESS_PLACEHOLDER" }]
}

View File

@@ -1,6 +1,6 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@now/static-build" }],
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
"build": { "env": { "NODE_ENV": "custom-value:RANDOMNESS_PLACEHOLDER" } },
"probes": [
{ "path": "/", "mustContain": "custom-value:RANDOMNESS_PLACEHOLDER" }

View File

@@ -2,8 +2,8 @@
"version": 2,
"build": { "env": { "NPM_ONLY_PRODUCTION": "1" } },
"builds": [
{ "src": "npm/package.json", "use": "@now/static-build" },
{ "src": "yarn/package.json", "use": "@now/static-build" }
{ "src": "npm/package.json", "use": "@vercel/static-build" },
{ "src": "yarn/package.json", "use": "@vercel/static-build" }
],
"probes": [
{ "path": "/npm", "mustContain": "npm-prod:RANDOMNESS_PLACEHOLDER" },

View File

@@ -27,7 +27,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
}
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
it(`Should build "${fixture}"`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
@@ -53,7 +53,7 @@ for (const builder of buildersToTestWith) {
// don't run all foreign fixtures, just some
if (['01-cowsay', '01-cache-headers', '03-env-vars'].includes(fixture)) {
// eslint-disable-next-line no-loop-func
it(`should build ${builder}/${fixture}`, async () => {
it(`Should build "${builder}/${fixture}"`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
@@ -113,6 +113,7 @@ it('Test `detectBuilders` and `detectRoutes`', async () => {
const { builders, defaultRoutes } = await detectBuilders(files, pkg);
const nowConfig = { builds: builders, routes: defaultRoutes, probes };
await fs.writeFile(
path.join(fixture, 'now.json'),
JSON.stringify(nowConfig, null, 2)

View File

@@ -1,10 +1,10 @@
import { Source, Route, Handler } from '@now/routing-utils';
import { detectBuilders } from '../src';
import { Source, Route, Handler } from '@vercel/routing-utils';
import {
detectBuilders,
detectOutputDirectory,
detectApiDirectory,
detectApiExtensions,
} from '../';
} from '../src';
describe('Test `detectBuilders`', () => {
it('should never select now.json src', async () => {
@@ -35,7 +35,7 @@ describe('Test `detectBuilders`', () => {
};
const files = ['package.json', 'pages/index.js'];
const { builders, errors } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(errors).toBe(null);
});
@@ -46,7 +46,7 @@ describe('Test `detectBuilders`', () => {
};
const files = ['package.json', 'pages/index.js'];
const { builders, errors } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(errors).toBe(null);
});
@@ -75,7 +75,7 @@ describe('Test `detectBuilders`', () => {
it('no package.json + no build + raw static + api', async () => {
const files = ['api/users.js', 'index.html'];
const { builders, errors } = await detectBuilders(files);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/users.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -86,7 +86,7 @@ describe('Test `detectBuilders`', () => {
it('package.json + no build + root + api', async () => {
const files = ['index.html', 'api/[endpoint].js', 'static/image.png'];
const { builders, errors } = await detectBuilders(files);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint].js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -102,7 +102,7 @@ describe('Test `detectBuilders`', () => {
];
const { builders } = await detectBuilders(files);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint]/[id].js');
expect(builders!.length).toBe(1);
});
@@ -115,9 +115,9 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'api/endpoint.js', 'public/index.html'];
const { builders } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/next');
expect(builders![1].use).toBe('@vercel/next');
expect(builders![1].src).toBe('package.json');
expect(builders!.length).toBe(2);
});
@@ -130,9 +130,9 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'api/endpoint.js', 'index.html'];
const { builders } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/next');
expect(builders![1].use).toBe('@vercel/next');
expect(builders![1].src).toBe('package.json');
expect(builders!.length).toBe(2);
});
@@ -141,7 +141,7 @@ describe('Test `detectBuilders`', () => {
const files = ['api/endpoint.js', 'index.html', 'favicon.ico'];
const { builders } = await detectBuilders(files);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -157,7 +157,7 @@ describe('Test `detectBuilders`', () => {
];
const { builders } = await detectBuilders(files);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('public/**/*');
@@ -201,7 +201,7 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'public/index.html', 'README.md'];
const { builders } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -214,7 +214,7 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'pages/index.js'];
const { builders } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/static-build');
expect(builders![0].use).toBe('@vercel/static-build');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -227,7 +227,7 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'pages/index.js'];
const { builders } = await detectBuilders(files, pkg, { tag: 'canary' });
expect(builders![0].use).toBe('@now/static-build@canary');
expect(builders![0].use).toBe('@vercel/static-build@canary');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -237,7 +237,7 @@ describe('Test `detectBuilders`', () => {
const files = ['package.json', 'api/[endpoint].js'];
const { builders } = await detectBuilders(files, pkg);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint].js');
expect(builders!.length).toBe(1);
});
@@ -278,9 +278,9 @@ describe('Test `detectBuilders`', () => {
];
const { builders } = await detectBuilders(files, pkg, { tag: 'canary' });
expect(builders![0].use).toBe('@now/node@canary');
expect(builders![1].use).toBe('@now/node@canary');
expect(builders![2].use).toBe('@now/next@canary');
expect(builders![0].use).toBe('@vercel/node@canary');
expect(builders![1].use).toBe('@vercel/node@canary');
expect(builders![2].use).toBe('@vercel/next@canary');
expect(builders!.length).toBe(3);
});
@@ -296,9 +296,9 @@ describe('Test `detectBuilders`', () => {
];
const { builders } = await detectBuilders(files, pkg, { tag: 'latest' });
expect(builders![0].use).toBe('@now/node@latest');
expect(builders![1].use).toBe('@now/node@latest');
expect(builders![2].use).toBe('@now/next@latest');
expect(builders![0].use).toBe('@vercel/node@latest');
expect(builders![1].use).toBe('@vercel/node@latest');
expect(builders![2].use).toBe('@vercel/next@latest');
expect(builders!.length).toBe(3);
});
@@ -314,9 +314,9 @@ describe('Test `detectBuilders`', () => {
];
const { builders } = await detectBuilders(files, pkg, { tag: 'haha' });
expect(builders![0].use).toBe('@now/node@haha');
expect(builders![1].use).toBe('@now/node@haha');
expect(builders![2].use).toBe('@now/next@haha');
expect(builders![0].use).toBe('@vercel/node@haha');
expect(builders![1].use).toBe('@vercel/node@haha');
expect(builders![2].use).toBe('@vercel/next@haha');
expect(builders!.length).toBe(3);
});
@@ -334,8 +334,8 @@ describe('Test `detectBuilders`', () => {
expect(warnings[0].code).toBe('conflicting_files');
expect(builders).toBeDefined();
expect(builders!.length).toBe(2);
expect(builders![0].use).toBe('@now/node');
expect(builders![1].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![1].use).toBe('@vercel/next');
});
it('many static files + one api file', async () => {
@@ -344,7 +344,7 @@ describe('Test `detectBuilders`', () => {
const { builders } = await detectBuilders(files);
expect(builders!.length).toBe(2);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/index.ts');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -374,7 +374,7 @@ describe('Test `detectBuilders`', () => {
expect(builders!.length).toBe(1);
expect(builders![0]).toEqual({
src: 'package.json',
use: '@now/next',
use: '@vercel/next',
config: {
zeroConfig: true,
functions: {
@@ -412,7 +412,7 @@ describe('Test `detectBuilders`', () => {
expect(builders!.length).toBe(3);
expect(builders![0]).toEqual({
src: 'api/teams/members.ts',
use: '@now/node',
use: '@vercel/node',
config: {
zeroConfig: true,
functions: {
@@ -437,7 +437,7 @@ describe('Test `detectBuilders`', () => {
});
expect(builders![2]).toEqual({
src: 'package.json',
use: '@now/next',
use: '@vercel/next',
config: {
zeroConfig: true,
},
@@ -538,7 +538,7 @@ describe('Test `detectBuilders`', () => {
expect(errors![0].code).toBe('invalid_function');
});
it('Do not allow functions that are not used by @now/next', async () => {
it('Do not allow functions that are not used by @vercel/next', async () => {
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
@@ -564,7 +564,7 @@ describe('Test `detectBuilders`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -584,7 +584,7 @@ describe('Test `detectBuilders`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -607,7 +607,7 @@ describe('Test `detectBuilders`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -705,7 +705,7 @@ describe('Test `detectBuilders`', () => {
expect(builders).toEqual([
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'config.yaml',
config: {
zeroConfig: true,
@@ -727,7 +727,7 @@ describe('Test `detectBuilders`', () => {
expect(builders).toEqual([
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'package.json',
config: {
zeroConfig: true,
@@ -744,14 +744,14 @@ describe('Test `detectBuilders`', () => {
expect(builders).toEqual([
{
use: '@now/ruby',
use: '@vercel/ruby',
src: 'api/date.rb',
config: {
zeroConfig: true,
},
},
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'config.rb',
config: {
zeroConfig: true,
@@ -765,7 +765,7 @@ describe('Test `detectBuilders`', () => {
const files = ['server/hello.ts', 'public/index.html'];
const functions = {
'server/**/*.ts': {
runtime: '@now/node@1.3.1',
runtime: '@vercel/node@1.3.1',
},
};
@@ -868,7 +868,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(errors).toBe(null);
expect(defaultRoutes).toStrictEqual([]);
expect(redirectRoutes).toStrictEqual([]);
@@ -888,7 +888,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(errors).toBe(null);
expect(defaultRoutes).toStrictEqual([]);
expect(redirectRoutes).toStrictEqual([]);
@@ -950,7 +950,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/users.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -970,7 +970,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const { builders, errors } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint].js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -991,7 +991,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, undefined, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint]/[id].js');
expect(builders!.length).toBe(1);
@@ -1017,9 +1017,9 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/next');
expect(builders![1].use).toBe('@vercel/next');
expect(builders![1].src).toBe('package.json');
expect(builders!.length).toBe(2);
@@ -1044,9 +1044,9 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/next');
expect(builders![1].use).toBe('@vercel/next');
expect(builders![1].src).toBe('package.json');
expect(builders!.length).toBe(2);
@@ -1067,7 +1067,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -1094,7 +1094,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/version.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -1119,7 +1119,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const { builders } = await detectBuilders(files, undefined, {
featHandleMiss,
});
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/endpoint.js');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('public/**/*');
@@ -1167,7 +1167,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const files = ['package.json', 'public/index.html', 'README.md'];
const { builders } = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/next');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -1180,7 +1180,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const files = ['package.json', 'pages/index.js'];
const { builders } = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/static-build');
expect(builders![0].use).toBe('@vercel/static-build');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -1196,7 +1196,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
tag: 'canary',
featHandleMiss,
});
expect(builders![0].use).toBe('@now/static-build@canary');
expect(builders![0].use).toBe('@vercel/static-build@canary');
expect(builders![0].src).toBe('package.json');
expect(builders!.length).toBe(1);
});
@@ -1206,7 +1206,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const files = ['package.json', 'api/[endpoint].js'];
const { builders } = await detectBuilders(files, pkg, { featHandleMiss });
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/[endpoint].js');
expect(builders!.length).toBe(1);
});
@@ -1256,9 +1256,9 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
tag: 'canary',
featHandleMiss,
});
expect(builders![0].use).toBe('@now/node@canary');
expect(builders![1].use).toBe('@now/node@canary');
expect(builders![2].use).toBe('@now/next@canary');
expect(builders![0].use).toBe('@vercel/node@canary');
expect(builders![1].use).toBe('@vercel/node@canary');
expect(builders![2].use).toBe('@vercel/next@canary');
expect(builders!.length).toBe(3);
});
@@ -1277,9 +1277,9 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
tag: 'latest',
featHandleMiss,
});
expect(builders![0].use).toBe('@now/node@latest');
expect(builders![1].use).toBe('@now/node@latest');
expect(builders![2].use).toBe('@now/next@latest');
expect(builders![0].use).toBe('@vercel/node@latest');
expect(builders![1].use).toBe('@vercel/node@latest');
expect(builders![2].use).toBe('@vercel/next@latest');
expect(builders!.length).toBe(3);
});
@@ -1298,9 +1298,9 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
tag: 'haha',
featHandleMiss,
});
expect(builders![0].use).toBe('@now/node@haha');
expect(builders![1].use).toBe('@now/node@haha');
expect(builders![2].use).toBe('@now/next@haha');
expect(builders![0].use).toBe('@vercel/node@haha');
expect(builders![1].use).toBe('@vercel/node@haha');
expect(builders![2].use).toBe('@vercel/next@haha');
expect(builders!.length).toBe(3);
});
@@ -1320,8 +1320,8 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(warnings[0].code).toBe('conflicting_files');
expect(builders).toBeDefined();
expect(builders!.length).toBe(2);
expect(builders![0].use).toBe('@now/node');
expect(builders![1].use).toBe('@now/next');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![1].use).toBe('@vercel/next');
});
it('many static files + one api file', async () => {
@@ -1332,7 +1332,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
});
expect(builders!.length).toBe(2);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].src).toBe('api/index.ts');
expect(builders![1].use).toBe('@now/static');
expect(builders![1].src).toBe('!{api/**,package.json}');
@@ -1363,7 +1363,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(builders!.length).toBe(1);
expect(builders![0]).toEqual({
src: 'package.json',
use: '@now/next',
use: '@vercel/next',
config: {
zeroConfig: true,
functions: {
@@ -1404,7 +1404,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(builders!.length).toBe(3);
expect(builders![0]).toEqual({
src: 'api/teams/members.ts',
use: '@now/node',
use: '@vercel/node',
config: {
zeroConfig: true,
functions: {
@@ -1429,7 +1429,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
});
expect(builders![2]).toEqual({
src: 'package.json',
use: '@now/next',
use: '@vercel/next',
config: {
zeroConfig: true,
},
@@ -1538,7 +1538,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errors![0].code).toBe('invalid_function');
});
it('Do not allow functions that are not used by @now/next', async () => {
it('Do not allow functions that are not used by @vercel/next', async () => {
const pkg = {
scripts: { build: 'next build' },
dependencies: { next: '9.0.0' },
@@ -1568,7 +1568,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -1589,7 +1589,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -1613,7 +1613,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errors).toBe(null);
expect(builders).not.toBe(null);
expect(builders![0].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![0].config).toMatchObject({
functions,
zeroConfig: true,
@@ -1737,7 +1737,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(builders).toEqual([
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'config.yaml',
config: {
zeroConfig: true,
@@ -1759,7 +1759,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(builders).toEqual([
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'package.json',
config: {
zeroConfig: true,
@@ -1779,14 +1779,14 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(builders).toEqual([
{
use: '@now/ruby',
use: '@vercel/ruby',
src: 'api/date.rb',
config: {
zeroConfig: true,
},
},
{
use: '@now/static-build',
use: '@vercel/static-build',
src: 'config.rb',
config: {
zeroConfig: true,
@@ -1800,7 +1800,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
const files = ['server/hello.ts', 'public/index.html'];
const functions = {
'server/**/*.ts': {
runtime: '@now/node@1.3.1',
runtime: '@vercel/node@1.3.1',
},
};
@@ -2000,10 +2000,10 @@ it('Test `detectRoutes`', async () => {
const { builders, defaultRoutes } = await detectBuilders(files);
expect(builders!.length).toBe(4);
expect(builders![0].use).toBe('@now/node');
expect(builders![1].use).toBe('@now/node');
expect(builders![2].use).toBe('@now/node');
expect(builders![3].use).toBe('@now/node');
expect(builders![0].use).toBe('@vercel/node');
expect(builders![1].use).toBe('@vercel/node');
expect(builders![2].use).toBe('@vercel/node');
expect(builders![3].use).toBe('@vercel/node');
expect(defaultRoutes!.length).toBe(5);
}
@@ -2883,7 +2883,7 @@ describe('Test `detectOutputDirectory`', () => {
config: { zeroConfig: true },
},
{
use: '@now/node',
use: '@vercel/node',
src: 'api/index.js',
},
];
@@ -2896,7 +2896,7 @@ describe('Test `detectApiDirectory`', () => {
it('should be `null` with no config', async () => {
const builders = [
{
use: '@now/node',
use: '@vercel/node',
src: 'api/**/*.js',
},
];
@@ -2907,7 +2907,7 @@ describe('Test `detectApiDirectory`', () => {
it('should be `null` with no zero config builds', async () => {
const builders = [
{
use: '@now/node',
use: '@vercel/node',
src: 'api/**/*.js',
config: {},
},
@@ -2919,7 +2919,7 @@ describe('Test `detectApiDirectory`', () => {
it('should be `api` with one zero config', async () => {
const builders = [
{
use: '@now/node',
use: '@vercel/node',
src: 'api/**/*.js',
config: { zeroConfig: true },
},
@@ -2931,12 +2931,12 @@ describe('Test `detectApiDirectory`', () => {
it('should be `api` with one zero config and one without config', async () => {
const builders = [
{
use: '@now/node',
use: '@vercel/node',
src: 'api/**/*.js',
config: { zeroConfig: true },
},
{
use: '@now/php',
use: '@vercel/php',
src: 'api/**/*.php',
},
];
@@ -2947,7 +2947,7 @@ describe('Test `detectApiDirectory`', () => {
it('should be `null` with zero config but without api directory', async () => {
const builders = [
{
use: '@now/next',
use: '@vercel/next',
src: 'package.json',
config: { zeroConfig: true },
},
@@ -2961,28 +2961,28 @@ describe('Test `detectApiExtensions`', () => {
it('should have correct extensions', async () => {
const builders = [
{
use: '@now/node',
use: '@vercel/node',
src: 'api/**/*.js',
config: {
zeroConfig: true,
},
},
{
use: '@now/python',
use: '@vercel/python',
src: 'api/**/*.py',
config: {
zeroConfig: true,
},
},
{
use: '@now/go',
use: '@vercel/go',
src: 'api/**/*.go',
config: {
zeroConfig: true,
},
},
{
use: '@now/ruby',
use: '@vercel/ruby',
src: 'api/**/*.rb',
config: {
zeroConfig: true,
@@ -3002,7 +3002,7 @@ describe('Test `detectApiExtensions`', () => {
},
},
{
use: '@now/next',
use: '@vercel/next',
src: 'package.json',
// No api directory should not be added
config: {

View File

@@ -1,6 +1,6 @@
import path from 'path';
import { readFileSync } from 'fs-extra';
import { Framework } from '@now/frameworks';
import { Framework } from '@vercel/frameworks';
import { detectFramework, DetectorFilesystem } from '../src';
const frameworkList = JSON.parse(

View File

@@ -0,0 +1,45 @@
import assert from 'assert';
import { getPlatformEnv } from '../src';
describe('Test `getPlatformEnv()`', () => {
it('should support `VERCEL_` prefix', () => {
try {
assert.equal(undefined, getPlatformEnv('FOO'));
process.env.VERCEL_FOO = 'bar';
assert.equal('bar', getPlatformEnv('FOO'));
} finally {
delete process.env.VERCEL_FOO;
}
});
it('should support `NOW_` prefix', () => {
try {
assert.equal(undefined, getPlatformEnv('FOO'));
process.env.NOW_FOO = 'bar';
assert.equal('bar', getPlatformEnv('FOO'));
} finally {
delete process.env.NOW_FOO;
}
});
it('should throw an error if both env vars exist', () => {
let err: Error | null = null;
try {
process.env.NOW_FOO = 'bar';
process.env.VERCEL_FOO = 'baz';
getPlatformEnv('FOO');
} catch (_err) {
err = _err;
} finally {
delete process.env.NOW_FOO;
delete process.env.VERCEL_FOO;
}
assert(err);
assert.equal(
err!.message,
'Both "VERCEL_FOO" and "NOW_FOO" env vars are defined. Please only define the "VERCEL_FOO" env var'
);
});
});

View File

@@ -0,0 +1,40 @@
import assert from 'assert';
import { isOfficialRuntime, isStaticRuntime } from '../src';
describe('Test `isOfficialRuntime()`', () => {
it('should be correct', () => {
assert.equal(true, isOfficialRuntime('static', '@vercel/static'));
assert.equal(true, isOfficialRuntime('static', '@now/static'));
assert.equal(false, isOfficialRuntime('static', '@vercel/static-build'));
assert.equal(false, isOfficialRuntime('static', '@now/static-build'));
assert.equal(true, isOfficialRuntime('node', '@vercel/node'));
assert.equal(true, isOfficialRuntime('node', '@now/node'));
assert.equal(true, isOfficialRuntime('node', '@vercel/node@1.0.0'));
assert.equal(true, isOfficialRuntime('node', '@now/node@1.0.0'));
assert.equal(false, isOfficialRuntime('node', '@my-fork/node'));
assert.equal(false, isOfficialRuntime('node', '@now/node-server'));
assert.equal(
true,
isOfficialRuntime('static-build', '@vercel/static-build')
);
assert.equal(true, isOfficialRuntime('static-build', '@now/static-build'));
assert.equal(
true,
isOfficialRuntime('static-build', '@vercel/static-build@1.0.0')
);
assert.equal(false, isOfficialRuntime('static-build', '@vercel/static'));
assert.equal(false, isOfficialRuntime('static-build', '@now/static'));
});
});
describe('Test `isStaticRuntime()`', () => {
it('should be correct', () => {
assert.equal(true, isStaticRuntime('@vercel/static'));
assert.equal(true, isStaticRuntime('@now/static'));
assert.equal(false, isStaticRuntime('@vercel/static-build'));
assert.equal(false, isStaticRuntime('@now/static-build'));
assert.equal(false, isStaticRuntime('@now/node'));
});
});

View File

@@ -134,21 +134,21 @@ it('should throw for discontinued versions', async () => {
});
it('should support require by path for legacy builders', () => {
const index = require('@now/build-utils');
const index = require('@vercel/build-utils');
const download2 = require('@now/build-utils/fs/download.js');
const getWriteableDirectory2 = require('@now/build-utils/fs/get-writable-directory.js');
const glob2 = require('@now/build-utils/fs/glob.js');
const rename2 = require('@now/build-utils/fs/rename.js');
const download2 = require('@vercel/build-utils/fs/download.js');
const getWriteableDirectory2 = require('@vercel/build-utils/fs/get-writable-directory.js');
const glob2 = require('@vercel/build-utils/fs/glob.js');
const rename2 = require('@vercel/build-utils/fs/rename.js');
const {
runNpmInstall: runNpmInstall2,
} = require('@now/build-utils/fs/run-user-scripts.js');
const streamToBuffer2 = require('@now/build-utils/fs/stream-to-buffer.js');
} = require('@vercel/build-utils/fs/run-user-scripts.js');
const streamToBuffer2 = require('@vercel/build-utils/fs/stream-to-buffer.js');
const FileBlob2 = require('@now/build-utils/file-blob.js');
const FileFsRef2 = require('@now/build-utils/file-fs-ref.js');
const FileRef2 = require('@now/build-utils/file-ref.js');
const { Lambda: Lambda2 } = require('@now/build-utils/lambda.js');
const FileBlob2 = require('@vercel/build-utils/file-blob.js');
const FileFsRef2 = require('@vercel/build-utils/file-fs-ref.js');
const FileRef2 = require('@vercel/build-utils/file-ref.js');
const { Lambda: Lambda2 } = require('@vercel/build-utils/lambda.js');
expect(download2).toBe(index.download);
expect(getWriteableDirectory2).toBe(index.getWriteableDirectory);

View File

@@ -3,7 +3,6 @@ const { mkdirp, copyFile } = require('fs-extra');
const {
glob,
debug,
download,
shouldServe,
createLambda,
@@ -14,7 +13,7 @@ exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.version = 3;
exports.build = async ({ workPath, files, entrypoint, meta, config }) => {
exports.build = async ({ workPath, files, entrypoint, meta }) => {
const outDir = await getWritableDirectory();
await download(files, workPath, meta);

View File

@@ -1,6 +1,6 @@
{
"name": "@now/cgi",
"version": "1.0.4",
"name": "@vercel/cgi",
"version": "1.0.5",
"license": "MIT",
"repository": {
"type": "git",

View File

@@ -1,22 +1,27 @@
![now](https://assets.zeit.co/image/upload/v1581518533/repositories/now-cli/v4.png)
<p align="center">
<img src="https://assets.vercel.com/image/upload/v1588805858/repositories/vercel/logo.png" height="96">
<h3 align="center">Vercel</h3>
<p align="center">Develop. Preview. Ship.</p>
</p>
[![Join the community on GitHub Discussions](https://badgen.net/badge/join%20the%20discussion/on%20github/black?icon=github)](https://github.com/zeit/now/discussions)
## Usages
To install the latest version of Now CLI, visit [vercel.com/download](https://vercel.com/download) or run this command:
To install the latest version of Vercel CLI, visit [vercel.com/download](https://vercel.com/download) or run this command:
```sh
npm i -g now
npm i -g vercel
```
To quickly start a new project, run the following commands:
```
now init # Pick an example project
vercel init # Pick an example project
cd <PROJECT> # Change directory to the new project
now # Deploy to the cloud
vercel # Deploy to the cloud
```
## Documentation
For details on how to use Now CLI, check out our [documentation](https://vercel.com/docs).
For details on how to use Vercel CLI, check out our [documentation](https://vercel.com/docs).

View File

@@ -1,6 +1,6 @@
{
"name": "now",
"version": "18.0.1-canary.6",
"name": "vercel",
"version": "19.0.1",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",
@@ -19,8 +19,7 @@
"prepublishOnly": "yarn build",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
"build": "ts-node ./scripts/build.ts",
"build-dev": "ts-node ./scripts/build.ts --dev",
"test-lint": "eslint . --ext .ts,.js --ignore-path ../../.eslintignore"
"build-dev": "ts-node ./scripts/build.ts --dev"
},
"nyc": {
"include": [
@@ -42,7 +41,8 @@
"all": true
},
"bin": {
"now": "./dist/index.js"
"vc": "./dist/index.js",
"vercel": "./dist/index.js"
},
"files": [
"dist",
@@ -64,7 +64,6 @@
"devDependencies": {
"@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.11.0",
"@tootallnate/once": "1.1.2",
"@types/ansi-escapes": "3.0.0",
"@types/ansi-regex": "4.0.0",
"@types/async-retry": "1.2.1",
@@ -108,7 +107,7 @@
"ava": "2.2.0",
"bytes": "3.0.0",
"chalk": "2.4.2",
"chokidar": "2.1.6",
"chokidar": "3.3.1",
"clipboardy": "2.1.0",
"codecov": "3.6.5",
"cpy": "7.2.0",

View File

@@ -39,14 +39,11 @@ async function createBuildersTarball() {
}
}
await execa(
'npm',
['install', '--save-exact', '--no-package-lock', ...builders],
{
cwd: buildersDir,
stdio: 'inherit',
}
);
const yarn = join(dirRoot, '../../node_modules/yarn/bin/yarn.js');
await execa(process.execPath, [yarn, 'add', '--no-lockfile', ...builders], {
cwd: buildersDir,
stdio: 'inherit',
});
const packer = tar.pack(buildersDir);
await pipe(
@@ -104,13 +101,12 @@ async function main() {
// Do the initial `ncc` build
console.log();
const src = join(dirRoot, 'src');
const ncc = join(dirRoot, 'node_modules/@zeit/ncc/dist/ncc/cli.js');
const args = [ncc, 'build', '--source-map'];
const args = ['@zeit/ncc', 'build', '--source-map'];
if (!isDev) {
args.push('--minify');
}
args.push(src);
await execa(process.execPath, args, { stdio: 'inherit' });
await execa('npx', args, { stdio: 'inherit' });
// `ncc` has some issues with `@zeit/fun`'s runtime files:
// - Executable bits on the `bootstrap` files appear to be lost:

View File

@@ -1,15 +1,4 @@
#!/usr/bin/env node
const fs = require('fs');
const { promisify } = require('util');
const { join, delimiter } = require('path');
const { homedir } = require('os');
const stat = promisify(fs.stat);
const unlink = promisify(fs.unlink);
function cmd(command) {
return `\`${command}\``;
}
function error(command) {
console.error('> Error!', command);
@@ -36,51 +25,6 @@ function isGlobal() {
: Boolean(process.env.npm_config_global);
}
// Logic is from Now Desktop
// See: https://git.io/fj4jD
function getNowPath() {
if (process.platform === 'win32') {
const { LOCALAPPDATA, USERPROFILE, HOMEPATH } = process.env;
const home = homedir() || USERPROFILE || HOMEPATH;
let path;
if (LOCALAPPDATA) {
path = join(LOCALAPPDATA, 'now-cli', 'now.exe');
} else if (home) {
path = join(home, 'AppData', 'Local', 'now-cli', 'now.exe');
} else {
path = '';
}
return fs.existsSync(path) ? path : null;
}
const pathEnv = (process.env.PATH || '').split(delimiter);
const paths = [
join(process.env.HOME || '/', 'bin'),
'/usr/local/bin',
'/usr/bin',
];
for (const basePath of paths) {
if (!pathEnv.includes(basePath)) {
continue;
}
const nowPath = join(basePath, 'now');
if (fs.existsSync(nowPath)) {
return nowPath;
}
}
return null;
}
async function isBinary(nowPath) {
const stats = await stat(nowPath);
return !stats.isDirectory();
}
function validateNodeVersion() {
let semver = '>= 0';
let major = '1';
@@ -113,46 +57,6 @@ async function main() {
);
process.exit(1);
}
const nowPath = getNowPath();
if (nowPath === null) {
debug(`No now binary found`);
return;
}
debug(`Located now binary at ${nowPath}`);
try {
if ((await isBinary(nowPath)) === false) {
debug(
'Found file or directory named now but will not delete, ' +
'as it seems unrelated to Now CLI'
);
return;
}
await unlink(nowPath);
debug(`Removed ${nowPath}`);
} catch (err) {
if (process.platform !== 'win32') {
error(
`Could not remove your previous Now CLI installation.\n` +
`Please use this command to remove it: ${cmd(
`sudo rm ${nowPath}`
)}.\n` +
`Then try to install it again.`
);
} else {
error(
`Could not remove your previous Now CLI installation.\n` +
`Please remove ${cmd(nowPath)} manually and try to install it again.`
);
}
process.exit(1);
}
}
process.on('unhandledRejection', err => {

View File

@@ -7,6 +7,7 @@ import createOutput from '../../util/output';
import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
import logo from '../../util/output/logo';
import { getPkgName } from '../../util/pkg-name.ts';
import ls from './ls';
import rm from './rm';
@@ -14,7 +15,7 @@ import set from './set';
const help = () => {
console.log(`
${chalk.bold(`${logo} now alias`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} alias`)} [options] <command>
${chalk.dim('Commands:')}
@@ -27,10 +28,10 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-r ${chalk.bold.underline('RULES_FILE')}, --rules=${chalk.bold.underline(
'RULES_FILE'
)} Rules file
@@ -46,7 +47,7 @@ const help = () => {
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.now.sh')}
${chalk.cyan(
`$ now alias set ${chalk.underline(
`$ ${getPkgName()} alias set ${chalk.underline(
'api-ownv3nc9f8.now.sh'
)} ${chalk.underline('my-api.now.sh')}`
)}
@@ -54,7 +55,7 @@ const help = () => {
Custom domains work as alias targets
${chalk.cyan(
`$ now alias set ${chalk.underline(
`$ ${getPkgName()} alias set ${chalk.underline(
'api-ownv3nc9f8.now.sh'
)} ${chalk.underline('my-api.com')}`
)}
@@ -67,26 +68,28 @@ const help = () => {
)} in the URLs are unneeded and ignored.
${chalk.gray('')} Add and modify path based aliases for ${chalk.underline(
'zeit.ninja'
'example.com'
)}
${chalk.cyan(
`$ now alias ${chalk.underline('zeit.ninja')} -r ${chalk.underline(
'rules.json'
)}`
`$ ${getPkgName()} alias ${chalk.underline(
'example.com'
)} -r ${chalk.underline('rules.json')}`
)}
Export effective routing rules
${chalk.cyan(
`$ now alias ls aliasId --json > ${chalk.underline('rules.json')}`
`$ ${getPkgName()} alias ls aliasId --json > ${chalk.underline(
'rules.json'
)}`
)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ now alias ls --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} alias ls --next 1584722256178`)}
`);
};

View File

@@ -9,7 +9,7 @@ import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
import strlen from '../../util/strlen.ts';
import getCommandFlags from '../../util/get-command-flags';
import cmd from '../../util/output/cmd.ts';
import { getCommandName } from '../../util/pkg-name.ts';
export default async function ls(ctx, opts, args, output) {
const {
@@ -55,7 +55,7 @@ export default async function ls(ctx, opts, args, output) {
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now alias ls [alias]`'
`${getCommandName('alias ls [alias]')}`
)}`
);
return 1;
@@ -106,8 +106,8 @@ export default async function ls(ctx, opts, args, output) {
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
output.log(
`To display the next page run ${cmd(
`now alias ls${flags} --next ${pagination.next}`
`To display the next page run ${getCommandName(
`alias ls${flags} --next ${pagination.next}`
)}`
);
}

View File

@@ -2,7 +2,6 @@ import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import Now from '../../util';
import cmd from '../../util/output/cmd.ts';
import Client from '../../util/client.ts';
import getScope from '../../util/get-scope.ts';
import removeAliasById from '../../util/alias/remove-alias-by-id';
@@ -11,6 +10,7 @@ import strlen from '../../util/strlen.ts';
import promptBool from '../../util/prompt-bool';
import { isValidName } from '../../util/is-valid-name';
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
import { getCommandName } from '../../util/pkg-name.ts';
export default async function rm(ctx, opts, args, output) {
const {
@@ -46,14 +46,14 @@ export default async function rm(ctx, opts, args, output) {
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now alias rm <alias>`'
`${getCommandName('alias rm <alias>')}`
)}`
);
return 1;
}
if (!aliasOrId) {
output.error(`${cmd('now alias rm <alias>')} expects one argument`);
output.error(`${getCommandName('alias rm <alias>')} expects one argument`);
return 1;
}
@@ -68,7 +68,7 @@ export default async function rm(ctx, opts, args, output) {
output.error(
`Alias not found by "${aliasOrId}" under ${chalk.bold(contextName)}`
);
output.log(`Run ${cmd('now alias ls')} to see your aliases.`);
output.log(`Run ${getCommandName('alias ls')} to see your aliases.`);
return 1;
}

View File

@@ -7,7 +7,6 @@ import { Output } from '../../util/output';
import * as ERRORS from '../../util/errors-ts';
import assignAlias from '../../util/alias/assign-alias';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import formatDnsTable from '../../util/format-dns-table';
import formatNSTable from '../../util/format-ns-table';
import getDeploymentForAlias from '../../util/alias/get-deployment-for-alias';
@@ -23,6 +22,7 @@ import handleCertError from '../../util/certs/handle-cert-error';
import isWildcardAlias from '../../util/alias/is-wildcard-alias';
import link from '../../util/output/link';
import { User } from '../../types';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -77,7 +77,9 @@ export default async function set(
// If there are more than two args we have to error
if (args.length > 2) {
output.error(
`${cmd('now alias <deployment> <target>')} accepts at most two arguments`
`${getCommandName(
`alias <deployment> <target>`
)} accepts at most two arguments`
);
return 1;
}
@@ -126,7 +128,7 @@ export default async function set(
output.error(
`To ship to production, optionally configure your domains (${link(
'https://vercel.com/docs/v2/custom-domains'
)}) and run ${cmd('now --prod')}.`
)}) and run ${getCommandName(`--prod`)}.`
);
return 1;
}
@@ -301,8 +303,8 @@ function handleSetupDomainError<T>(
)}\n\n`
);
output.print(
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${cmd(
'now domains verify <domain>'
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${getCommandName(
'domains verify <domain>'
)}.\n`
);
output.print(
@@ -310,8 +312,8 @@ function handleSetupDomainError<T>(
);
} else {
output.print(
` Once your domain uses the nameservers from above, run again ${cmd(
'now domains verify <domain>'
` Once your domain uses the nameservers from above, run again ${getCommandName(
'domains verify <domain>'
)}.\n`
);
}
@@ -474,7 +476,7 @@ function handleCreateAliasError<T>(
output.log(
`Update the scale settings on ${chalk.dim(
error.meta.url
)} with \`now scale\` and try again`
)} with ${getCommandName('scale')} and try again`
);
output.log('Read more: https://err.sh/now/v2-no-min');
return 1;
@@ -490,7 +492,7 @@ function handleCreateAliasError<T>(
output.log(
`Update the scale settings on ${chalk.dim(
error.meta.url
)} with \`now scale\` and try again`
)} with ${getCommandName('scale')} and try again`
);
return 1;
}
@@ -510,7 +512,7 @@ function handleCreateAliasError<T>(
output.log(
`Update the scale settings on ${chalk.dim(
error.meta.url
)} with \`now scale\` and try again`
)} with ${getCommandName('scale')} and try again`
);
return 1;
}
@@ -520,8 +522,8 @@ function handleCreateAliasError<T>(
`There is no certificate for the domain ${error.meta.domain} and it could not be created.`
);
output.log(
`Please generate a new certificate manually with ${cmd(
`now certs issue ${error.meta.domain}`
`Please generate a new certificate manually with ${getCommandName(
`certs issue ${error.meta.domain}`
)}`
);
return 1;

View File

@@ -15,10 +15,11 @@ import exit from '../../util/exit';
import Client from '../../util/client.ts';
import getScope from '../../util/get-scope.ts';
import createOutput from '../../util/output';
import { getPkgName } from '../../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now billing`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} billing`)} [options] <command>
${chalk.dim('Options:')}
@@ -32,10 +33,10 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -46,7 +47,7 @@ const help = () => {
${chalk.gray('')} Add a new credit card (interactively)
${chalk.cyan(`$ now billing add`)}
${chalk.cyan(`$ ${getPkgName()} billing add`)}
`);
};

View File

@@ -9,6 +9,7 @@ import createCertFromFile from '../../util/certs/create-cert-from-file';
import createCertForCns from '../../util/certs/create-cert-for-cns';
import { NowContext } from '../../types';
import { Output } from '../../util/output';
import { getCommandName } from '../../util/pkg-name';
interface Options {
'--overwrite'?: boolean;
@@ -61,7 +62,6 @@ async function add(
throw err;
}
// $FlowFixMe
const now = new Now({ apiUrl, token, debug: debugEnabled, currentTeam });
if (overwite) {
@@ -77,7 +77,9 @@ async function add(
);
output.print(
` ${chalk.cyan(
`now certs add --crt <domain.crt> --key <domain.key> --ca <ca.crt>`
`${getCommandName(
'certs add --crt <domain.crt> --key <domain.key> --ca <ca.crt>'
)}`
)}\n`
);
now.close();
@@ -89,9 +91,9 @@ async function add(
} else {
output.warn(
`${chalk.cyan(
'now certs add'
getCommandName('certs add')
)} will be soon deprecated. Please use ${chalk.cyan(
'now certs issue <cn> <cns>'
getCommandName('certs issue <cn> <cns>')
)} instead`
);
@@ -99,7 +101,9 @@ async function add(
output.error(
`Invalid number of arguments to create a custom certificate entry. Usage:`
);
output.print(` ${chalk.cyan(`now certs add <cn>[, <cn>]`)}\n`);
output.print(
` ${chalk.cyan(getCommandName('certs add <cn>[, <cn>]'))}\n`
);
now.close();
return 1;
}

View File

@@ -13,13 +13,14 @@ import issue from './issue';
import ls from './ls';
import rm from './rm';
import { NowContext } from '../../types';
import { getPkgName } from '../../util/pkg-name';
const help = () => {
console.log(`
${chalk.bold(`${logo} now certs`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} certs`)} [options] <command>
${chalk.yellow('NOTE:')} This command is intended for advanced use only.
By default, Now manages your certificates automatically.
By default, Vercel manages your certificates automatically.
${chalk.dim('Commands:')}
@@ -32,10 +33,10 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -57,17 +58,17 @@ const help = () => {
''
)} Generate a certificate with the cnames "acme.com" and "www.acme.com"
${chalk.cyan('$ now certs issue acme.com www.acme.com')}
${chalk.cyan(`$ ${getPkgName()} certs issue acme.com www.acme.com`)}
${chalk.gray('')} Remove a certificate
${chalk.cyan('$ now certs rm id')}
${chalk.cyan(`$ ${getPkgName()} certs rm id`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ now certs ls --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} certs ls --next 1584722256178`)}
`);
};

View File

@@ -14,6 +14,7 @@ import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import startCertOrder from '../../util/certs/start-cert-order';
import handleCertError from '../../util/certs/handle-cert-error';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--ca': string;
@@ -80,7 +81,9 @@ export default async function issue(
);
output.print(
` ${chalk.cyan(
`now certs issue --crt <domain.crt> --key <domain.key> --ca <ca.crt>`
getCommandName(
'certs issue --crt <domain.crt> --key <domain.key> --ca <ca.crt>'
)
)}\n`
);
return 1;
@@ -107,7 +110,9 @@ export default async function issue(
output.error(
`Invalid number of arguments to create a custom certificate entry. Usage:`
);
output.print(` ${chalk.cyan(`now certs issue <cn>[, <cn>]`)}\n`);
output.print(
` ${chalk.cyan(getCommandName('certs issue <cn>[, <cn>]'))}\n`
);
return 1;
}
@@ -189,7 +194,9 @@ async function runStartOrder(
output.print(
` There are no pending challenges. Finish the issuance by running: \n`
);
output.print(` ${chalk.cyan(`now certs issue ${cns.join(' ')}`)}\n`);
output.print(
` ${chalk.cyan(getCommandName(`certs issue ${cns.join(' ')}`))}\n`
);
return 0;
}
@@ -220,7 +227,9 @@ async function runStartOrder(
output.print(`${header}\n`);
process.stdout.write(`${rows.join('\n')}\n\n`);
output.log(`To issue the certificate once the records are added, run:`);
output.print(` ${chalk.cyan(`now certs issue ${cns.join(' ')}`)}\n`);
output.print(
` ${chalk.cyan(getCommandName(`certs issue ${cns.join(' ')}`))}\n`
);
output.print(' Read more: https://err.sh/now/solve-challenges-manually\n');
return 0;
}

View File

@@ -3,7 +3,6 @@ import ms from 'ms';
import table from 'text-table';
// @ts-ignore
import Now from '../../util';
import cmd from '../../util/output/cmd';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
@@ -12,6 +11,7 @@ import strlen from '../../util/strlen';
import { Output } from '../../util/output';
import { NowContext, Cert } from '../../types';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
interface Options {
'--debug'?: boolean;
@@ -53,7 +53,9 @@ async function ls(
if (args.length !== 0) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan('`now certs ls`')}`
`Invalid number of arguments. Usage: ${chalk.cyan(
`${getCommandName('certs ls')}`
)}`
);
return 1;
}
@@ -76,8 +78,8 @@ async function ls(
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
output.log(
`To display the next page run ${cmd(
`now certs ls${flags} --next ${pagination.next}`
`To display the next page run ${getCommandName(
`certs ls${flags} --next ${pagination.next}`
)}`
);
}

View File

@@ -12,6 +12,7 @@ import Client from '../../util/client';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import param from '../../util/output/param';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -49,7 +50,7 @@ async function rm(
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now certs rm <id or cn>`'
`${getCommandName('certs rm <id or cn>')}`
)}`
);
return 1;

View File

@@ -2,9 +2,10 @@ import chalk from 'chalk';
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';
export const latestHelp = () => `
${chalk.bold(`${logo} now`)} [options] <command | path>
${chalk.bold(`${logo} ${getPkgName()}`)} [options] <command | path>
${chalk.dim('Commands:')}
@@ -41,10 +42,10 @@ export const latestHelp = () => `
-V, --platform-version Set the platform version to deploy to
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-f, --force Force a new deployment even if nothing has changed
--with-cache Retain build cache when using "--force"
@@ -71,7 +72,7 @@ export const latestHelp = () => `
${note(
`To view the usage information for Now 1.0, run ${code(
'now help deploy-v1'
`${getPkgName()} help deploy-v1`
)}`
)}
@@ -79,21 +80,23 @@ export const latestHelp = () => `
${chalk.gray('')} Deploy the current directory
${chalk.cyan('$ now')}
${chalk.cyan(`$ ${getPkgName()}`)}
${chalk.gray('')} Deploy a custom path
${chalk.cyan('$ now /usr/src/project')}
${chalk.cyan(`$ ${getPkgName()} /usr/src/project`)}
${chalk.gray('')} Deploy with Environment Variables
${chalk.cyan('$ now -e NODE_ENV=production -e SECRET=@mysql-secret')}
${chalk.cyan(
`$ ${getPkgName()} -e NODE_ENV=production -e SECRET=@mysql-secret`
)}
${chalk.gray('')} Show the usage information for the sub command ${chalk.dim(
'`list`'
)}
${chalk.cyan('$ now help list')}
${chalk.cyan(`$ ${getPkgName()} help list`)}
`;
@@ -237,10 +240,10 @@ export const legacyHelp = () => `
-n, --name Set the project name of the deployment
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-f, --force Force a new deployment even if nothing has changed
-t ${chalk.underline('TOKEN')}, --token=${chalk.underline(

View File

@@ -1,5 +1,6 @@
import fs from 'fs-extra';
import { resolve, basename, parse, join } from 'path';
import { fileNameSymbol } from '@vercel/client';
import Client from '../../util/client.ts';
import getScope from '../../util/get-scope.ts';
import createOutput from '../../util/output';
@@ -112,11 +113,10 @@ export default async ctx => {
}
}
const file = highlight('now.json');
const prop = code('version');
if (localConfig) {
const { version } = localConfig;
const file = highlight(localConfig[fileNameSymbol]);
const prop = code('version');
if (version) {
if (typeof version === 'number') {

View File

@@ -4,6 +4,7 @@ import { join } from 'path';
import { write as copy } from 'clipboardy';
import chalk from 'chalk';
import title from 'title';
import { fileNameSymbol } from '@vercel/client';
import Client from '../../util/client';
import { handleError } from '../../util/error';
import getArgs from '../../util/get-args';
@@ -54,6 +55,7 @@ import validatePaths, {
validateRootDirectory,
} from '../../util/validate-paths';
import { readLocalConfig } from '../../util/config/files';
import { getCommandName } from '../../util/pkg-name.ts';
const addProcessEnv = async (log, env) => {
let val;
@@ -101,9 +103,7 @@ const printDeploymentStatus = async (
if (readyState !== 'READY') {
output.error(
`${chalk.red(
'Error!'
)} Your deployment failed. Please retry later. More: https://err.sh/now/deployment-error`
`Your deployment failed. Please retry later. More: https://err.sh/now/deployment-error`
);
return 1;
}
@@ -123,7 +123,10 @@ const printDeploymentStatus = async (
// but fallback to the first alias in the list
const mainAlias =
aliasList.find(
alias => !alias.endsWith('.now.sh') && !isWildcardAlias(alias)
alias =>
!alias.endsWith('.now.sh') &&
!alias.endsWith('.vercel.app') &&
!isWildcardAlias(alias)
) || aliasList[0];
isWildcard = isWildcardAlias(mainAlias);
@@ -260,7 +263,7 @@ export default async function main(
debug: debugEnabled,
});
// retrieve `project` and `org` from .now
// retrieve `project` and `org` from .vercel
const link = await getLinkedProject(output, client, path);
if (link.status === 'error') {
@@ -302,7 +305,7 @@ export default async function main(
}
// We use `localConfig` here to read the name
// even though the `now.json` file can change
// even though the `vercel.json` file can change
// afterwards, this is fine since the property
// will be deprecated and can be replaced with
// user input.
@@ -371,7 +374,7 @@ export default async function main(
output.print(
`${prependEmoji(
`The ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} file should be inside of the provided root directory.`,
emoji('warning')
)}\n`
@@ -385,7 +388,7 @@ export default async function main(
output.print(
`${prependEmoji(
`The ${code('name')} property in ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} is deprecated (https://zeit.ink/5F)`,
emoji('warning')
)}\n`
@@ -402,7 +405,7 @@ export default async function main(
if (typeof localConfig.env !== 'undefined' && !isObject(localConfig.env)) {
error(
`The ${code('env')} property in ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} needs to be an object`
);
return 1;
@@ -412,7 +415,7 @@ export default async function main(
if (!isObject(localConfig.build)) {
error(
`The ${code('build')} property in ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} needs to be an object`
);
return 1;
@@ -424,7 +427,7 @@ export default async function main(
) {
error(
`The ${code('build.env')} property in ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} needs to be an object`
);
return 1;
@@ -438,14 +441,14 @@ export default async function main(
parseMeta(argv['--meta'])
);
// Merge dotenv config, `env` from now.json, and `--env` / `-e` arguments
// Merge dotenv config, `env` from vercel.json, and `--env` / `-e` arguments
const deploymentEnv = Object.assign(
{},
parseEnv(localConfig.env),
parseEnv(argv['--env'])
);
// Merge build env out of `build.env` from now.json, and `--build-env` args
// Merge build env out of `build.env` from vercel.json, and `--build-env` args
const deploymentBuildEnv = Object.assign(
{},
parseEnv(localConfig.build && localConfig.build.env),
@@ -635,11 +638,11 @@ export default async function main(
}
if (purchase === false || purchase instanceof UserAborted) {
handleCreateDeployError(output, deployment);
handleCreateDeployError(output, deployment, localConfig);
return 1;
}
handleCreateDeployError(output, purchase);
handleCreateDeployError(output, purchase, localConfig);
return 1;
}
@@ -659,15 +662,15 @@ export default async function main(
err instanceof ConflictingFilePath ||
err instanceof ConflictingPathSegment
) {
handleCreateDeployError(output, err);
handleCreateDeployError(output, err, localConfig);
return 1;
}
if (err instanceof BuildError) {
output.error('Build failed');
output.error(
`Check your logs at https://${now.url}/_logs or run ${code(
`now logs ${now.url}`,
`Check your logs at https://${now.url}/_logs or run ${getCommandName(
`logs ${now.url}`,
{
// Backticks are interpreted as part of the URL, causing CMD+Click
// behavior to fail in editors like VSCode.
@@ -705,7 +708,7 @@ export default async function main(
);
}
function handleCreateDeployError(output, error) {
function handleCreateDeployError(output, error, localConfig) {
if (error instanceof InvalidDomain) {
output.error(`The domain ${error.meta.domain} is not valid`);
return 1;
@@ -734,8 +737,8 @@ function handleCreateDeployError(output, error) {
output.error(
`The property ${code(prop)} is not allowed in ${highlight(
'now.json'
)} when using Now 2.0 please remove it.`
localConfig[fileNameSymbol]
)} please remove it.`
);
if (prop === 'build.env' || prop === 'builds.env') {
@@ -759,7 +762,7 @@ function handleCreateDeployError(output, error) {
output.error(
`The property ${code(prop)} in ${highlight(
'now.json'
localConfig[fileNameSymbol]
)} can only be of type ${code(title(params.type))}.`
);
@@ -770,7 +773,7 @@ function handleCreateDeployError(output, error) {
output.error(
`Failed to validate ${highlight(
'now.json'
localConfig[fileNameSymbol]
)}: ${message}\nDocumentation: ${link}`
);
@@ -797,7 +800,9 @@ function handleCreateDeployError(output, error) {
}
if (error instanceof BuildsRateLimited) {
output.error(error.message);
output.note(`Run ${code('now upgrade')} to increase your builds limit.`);
output.note(
`Run ${getCommandName('upgrade')} to increase your builds limit.`
);
return 1;
}
if (

View File

@@ -25,6 +25,8 @@ import link from '../../util/output/link';
import exit from '../../util/exit';
// @ts-ignore
import Now from '../../util';
// @ts-ignore
import NowSecrets from '../../util/secrets';
import uniq from '../../util/unique-strings';
import promptBool from '../../util/input/prompt-bool';
// @ts-ignore
@@ -633,20 +635,7 @@ async function sync({
nowConfig.build.env = deploymentBuildEnv;
}
const hasSecrets = Object.keys(deploymentEnv).some(key =>
(deploymentEnv[key] || '').startsWith('@')
);
const secretsPromise = hasSecrets ? now.listSecrets() : null;
const findSecret = async (uidOrName: string) => {
const secrets = await Promise.resolve(secretsPromise);
return secrets.filter(
(secret: { name: string; uid: string }) =>
secret.name === uidOrName || secret.uid === uidOrName
);
};
const nowSecrets = new NowSecrets({ apiUrl, token, debug, currentTeam });
const env_ = await Promise.all(
Object.keys(deploymentEnv).map(async (key: string) => {
@@ -673,36 +662,17 @@ async function sync({
if (val[0] === '@') {
const uidOrName = val.substr(1);
const _secrets = await findSecret(uidOrName);
const secret = await nowSecrets.getSecretByNameOrId(uidOrName);
if (_secrets.length === 0) {
if (uidOrName === '') {
error(
`Empty reference provided for env key ${chalk.bold(
`"${chalk.bold(key)}"`
)}`
);
} else {
error(
`No secret found by uid or name ${chalk.bold(
`"${uidOrName}"`
)}`,
'env-no-secret'
);
}
await exit(1);
} else if (_secrets.length > 1) {
if (!secret) {
error(
`Ambiguous secret ${chalk.bold(
`"${uidOrName}"`
)} (matches ${chalk.bold(_secrets.length)} secrets)`
`No secret found by uid or name ${chalk.bold(`"${uidOrName}"`)}`,
'env-no-secret'
);
await exit(1);
}
val = { uid: _secrets[0].uid };
val = { uid: secret.uid };
}
return [key, typeof val === 'string' ? val.replace(/^\\@/, '@') : val];

View File

@@ -1,5 +1,4 @@
import path from 'path';
import chalk from 'chalk';
import { resolve, join } from 'path';
import DevServer from '../../util/dev/server';
import parseListen from '../../util/dev/parse-listen';
@@ -9,7 +8,7 @@ import Client from '../../util/client';
import { getLinkedProject } from '../../util/projects/link';
import { getFrameworks } from '../../util/get-frameworks';
import { isSettingValue } from '../../util/is-setting-value';
import cmd from '../../util/output/cmd';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug'?: boolean;
@@ -23,7 +22,7 @@ export default async function dev(
output: Output
) {
const [dir = '.'] = args;
let cwd = path.resolve(dir);
let cwd = resolve(dir);
const listen = parseListen(opts['--listen'] || '3000');
const debug = opts['--debug'] || false;
@@ -44,13 +43,9 @@ export default async function dev(
return link.exitCode;
}
if (link.status === 'not_linked' && !process.env.__NOW_SKIP_DEV_COMMAND) {
output.print(
`${chalk.red(
'Error!'
)} Your codebase isnt linked to a project on Vercel. Run ${cmd(
'now'
)} to link it.\n`
if (link.status === 'not_linked' && !process.env.__VERCEL_SKIP_DEV_CMD) {
output.error(
`Your codebase isnt linked to a project on Vercel. Run ${getCommandName()} to link it.`
);
return 1;
}
@@ -58,7 +53,8 @@ export default async function dev(
let devCommand: undefined | string;
let frameworkSlug: null | string = null;
if (link.status === 'linked') {
const { project } = link;
const { project, org } = link;
client.currentTeam = org.type === 'team' ? org.id : undefined;
if (project.devCommand) {
devCommand = project.devCommand;
@@ -76,7 +72,7 @@ export default async function dev(
}
if (project.rootDirectory) {
cwd = path.join(cwd, project.rootDirectory);
cwd = join(cwd, project.rootDirectory);
}
}

View File

@@ -1,6 +1,6 @@
import path from 'path';
import chalk from 'chalk';
import { PackageJson } from '@now/build-utils';
import { PackageJson } from '@vercel/build-utils';
import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
@@ -13,6 +13,7 @@ import cmd from '../../util/output/cmd';
import dev from './dev';
import readPackage from '../../util/read-package';
import readConfig from '../../util/config/read-config';
import { getPkgName, getCommandName } from '../../util/pkg-name';
const COMMAND_CONFIG = {
dev: ['dev'],
@@ -20,9 +21,9 @@ const COMMAND_CONFIG = {
const help = () => {
console.log(`
${chalk.bold(`${logo} now dev`)} [options] <dir>
${chalk.bold(`${logo} ${getPkgName()} dev`)} [options] <dir>
Starts the \`now dev\` server.
Starts the \`${getPkgName()} dev\` server.
${chalk.dim('Options:')}
@@ -33,13 +34,13 @@ const help = () => {
${chalk.dim('Examples:')}
${chalk.gray('')} Start the \`now dev\` server on port 8080
${chalk.gray('')} Start the \`${getPkgName()} dev\` server on port 8080
${chalk.cyan('$ now dev --listen 8080')}
${chalk.cyan(`$ ${getPkgName()} dev --listen 8080`)}
${chalk.gray('')} Make the \`now dev\` server bind to localhost on port 5000
${chalk.cyan('$ now dev --listen 127.0.0.1:5000')}
${chalk.cyan(`$ ${getPkgName()} dev --listen 127.0.0.1:5000`)}
`);
};
@@ -77,7 +78,7 @@ export default async function main(ctx: NowContext) {
const [dir = '.'] = args;
const nowJson = await readConfig(path.join(dir, 'now.json'));
const nowJson = await readConfig(dir);
// @ts-ignore: Because `nowJson` could be one of three different types
const hasBuilds = nowJson && nowJson.builds && nowJson.builds.length > 0;
@@ -96,11 +97,20 @@ export default async function main(ctx: NowContext) {
output.error(`More details: http://err.sh/now/now-dev-as-dev-script`);
return 1;
}
if (scripts && scripts.dev && /\bvercel\b\W+\bdev\b/.test(scripts.dev)) {
output.error(
`The ${cmd('dev')} script in ${cmd(
'package.json'
)} must not contain ${cmd('vercel dev')}`
);
output.error(`More details: http://err.sh/now/now-dev-as-dev-script`);
return 1;
}
}
}
if (argv._.length > 2) {
output.error(`${cmd('now dev [dir]')} accepts at most one argument`);
output.error(`${getCommandName(`dev [dir]`)} accepts at most one argument`);
return 1;
}

View File

@@ -13,6 +13,7 @@ import getScope from '../../util/get-scope';
import parseAddDNSRecordArgs from '../../util/dns/parse-add-dns-record-args';
import stamp from '../../util/output/stamp';
import getDNSData from '../../util/dns/get-dns-data';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -49,7 +50,7 @@ export default async function add(
if (!parsedParams) {
output.error(
`Invalid number of arguments. See: ${chalk.cyan(
'`now dns --help`'
`${getCommandName('dns --help')}`
)} for usage.`
);
return 1;

View File

@@ -6,6 +6,7 @@ import getScope from '../../util/get-scope';
import { DomainNotFound, InvalidDomain } from '../../util/errors-ts';
import stamp from '../../util/output/stamp';
import importZonefile from '../../util/dns/import-zonefile';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -41,7 +42,7 @@ export default async function add(
if (args.length !== 2) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now dns import <domain> <zonefile>`'
`${getCommandName('dns import <domain> <zonefile>')}`
)}`
);
return 1;

View File

@@ -6,6 +6,7 @@ import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
import handleError from '../../util/handle-error';
import logo from '../../util/output/logo';
import { getPkgName } from '../../util/pkg-name';
import add from './add';
import importZone from './import';
@@ -14,7 +15,7 @@ import rm from './rm';
const help = () => {
console.log(`
${chalk.bold(`${logo} now dns`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} dns`)} [options] <command>
${chalk.dim('Commands:')}
@@ -28,50 +29,64 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add an A record for a subdomain
${chalk.cyan(
'$ now dns add <DOMAIN> <SUBDOMAIN> <A | AAAA | ALIAS | CNAME | TXT> <VALUE>'
`$ ${getPkgName()} dns add <DOMAIN> <SUBDOMAIN> <A | AAAA | ALIAS | CNAME | TXT> <VALUE>`
)}
${chalk.cyan('$ now dns add zeit.rocks api A 198.51.100.100')}
${chalk.cyan(`$ ${getPkgName()} dns add zeit.rocks api A 198.51.100.100`)}
${chalk.gray('')} Add an MX record (@ as a name refers to the domain)
${chalk.cyan(`$ now dns add <DOMAIN> '@' MX <RECORD VALUE> <PRIORITY>`)}
${chalk.cyan(`$ now dns add zeit.rocks '@' MX mail.zeit.rocks 10`)}
${chalk.cyan(
`$ ${getPkgName()} dns add <DOMAIN> '@' MX <RECORD VALUE> <PRIORITY>`
)}
${chalk.cyan(
`$ ${getPkgName()} dns add zeit.rocks '@' MX mail.zeit.rocks 10`
)}
${chalk.gray('')} Add an SRV record
${chalk.cyan(
'$ now dns add <DOMAIN> <NAME> SRV <PRIORITY> <WEIGHT> <PORT> <TARGET>'
`$ ${getPkgName()} dns add <DOMAIN> <NAME> SRV <PRIORITY> <WEIGHT> <PORT> <TARGET>`
)}
${chalk.cyan(
`$ ${getPkgName()} dns add zeit.rocks '@' SRV 10 0 389 zeit.party`
)}
${chalk.cyan(`$ now dns add zeit.rocks '@' SRV 10 0 389 zeit.party`)}
${chalk.gray('')} Add a CAA record
${chalk.cyan(
`$ now dns add <DOMAIN> <NAME> CAA '<FLAGS> <TAG> "<VALUE>"'`
`$ ${getPkgName()} dns add <DOMAIN> <NAME> CAA '<FLAGS> <TAG> "<VALUE>"'`
)}
${chalk.cyan(
`$ ${getPkgName()} dns add zeit.rocks '@' CAA '0 issue "example.com"'`
)}
${chalk.cyan(`$ now dns add zeit.rocks '@' CAA '0 issue "example.com"'`)}
${chalk.gray('')} Import a Zone file
${chalk.cyan('$ now dns import <DOMAIN> <FILE>')}
${chalk.cyan(`$ now dns import zeit.rocks ./zonefile.txt`)}
${chalk.cyan(`$ ${getPkgName()} dns import <DOMAIN> <FILE>`)}
${chalk.cyan(`$ ${getPkgName()} dns import zeit.rocks ./zonefile.txt`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${getPkgName()} dns ls --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} dns ls zeit.rocks --next 1584722256178`)}
`);
};
@@ -86,7 +101,7 @@ export default async function main(ctx: NowContext) {
let argv;
try {
argv = getArgs(ctx.argv.slice(2), {});
argv = getArgs(ctx.argv.slice(2), { '--next': Number, '-N': '--next' });
} catch (error) {
handleError(error);
return 1;

View File

@@ -1,20 +1,22 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import { Output } from '../../util/output';
import { DomainNotFound } from '../../util/errors-ts';
import { ThenArg, DNSRecord, NowContext } from '../../types';
import { DNSRecord, NowContext } from '../../types';
import Client from '../../util/client';
import formatTable from '../../util/format-table';
import getDNSRecords from '../../util/dns/get-dns-records';
import getDNSRecords, {
DomainRecordsItem,
} from '../../util/dns/get-dns-records';
import getDomainDNSRecords from '../../util/dns/get-domain-dns-records';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
type DNSRecords = ThenArg<ReturnType<typeof getDNSRecords>>;
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
'--next'?: number;
};
export default async function ls(
@@ -29,7 +31,7 @@ export default async function ls(
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const { '--debug': debug, '--next': nextTimestamp } = opts;
const client = new Client({ apiUrl, token, currentTeam, debug });
let contextName = null;
@@ -50,15 +52,26 @@ export default async function ls(
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now dns ls [domain]`'
`${getCommandName('dns ls [domain]')}`
)}`
);
return 1;
}
if (typeof nextTimestamp !== 'undefined' && Number.isNaN(nextTimestamp)) {
output.error('Please provide a number for flag --next');
return 1;
}
if (domainName) {
const records = await getDomainDNSRecords(output, client, domainName);
if (records instanceof DomainNotFound) {
const data = await getDomainDNSRecords(
output,
client,
domainName,
nextTimestamp,
4
);
if (data instanceof DomainNotFound) {
output.error(
`The domain ${domainName} can't be found under ${chalk.bold(
contextName
@@ -67,27 +80,52 @@ export default async function ls(
return 1;
}
const { records, pagination } = data;
output.log(
`${plural('Record', records.length, true)} found under ${chalk.bold(
contextName
)} ${chalk.gray(lsStamp())}`
`${
records.length > 0 ? 'Records' : 'No records'
} found under ${chalk.bold(contextName)} ${chalk.gray(lsStamp())}`
);
console.log(getDNSRecordsTable([{ domainName, records }]));
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
output.log(
`To display the next page run ${getCommandName(
`dns ls ${domainName}${flags} --next ${pagination.next}`
)}`
);
}
return 0;
}
const dnsRecords = await getDNSRecords(output, client, contextName);
const { records: dnsRecords, pagination } = await getDNSRecords(
output,
client,
contextName,
nextTimestamp
);
const nRecords = dnsRecords.reduce((p, r) => r.records.length + p, 0);
output.log(
`${plural('Record', nRecords, true)} found under ${chalk.bold(
`${nRecords > 0 ? 'Records' : 'No records'} found under ${chalk.bold(
contextName
)} ${chalk.gray(lsStamp())}`
);
console.log(getDNSRecordsTable(dnsRecords));
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
output.log(
`To display the next page run ${getCommandName(
`dns ls${flags} --next ${pagination.next}`
)}`
);
}
return 0;
}
function getDNSRecordsTable(dnsRecords: DNSRecords) {
function getDNSRecordsTable(dnsRecords: DomainRecordsItem[]) {
return formatTable(
['', 'id', 'name', 'type', 'value', 'created'],
['l', 'r', 'l', 'l', 'l', 'l'],
@@ -101,7 +139,7 @@ function getDNSRecordsTable(dnsRecords: DNSRecords) {
function getDNSRecordRow(record: DNSRecord) {
const isSystemRecord = record.creator === 'system';
const createdAt = `${ms(
Date.now() - new Date(Number(record.created)).getTime()
Date.now() - new Date(Number(record.createdAt)).getTime()
)} ago`;
const priority = record.mxPriority || record.priority || null;
return [

View File

@@ -8,6 +8,7 @@ import deleteDNSRecordById from '../../util/dns/delete-dns-record-by-id';
import getDNSRecordById from '../../util/dns/get-dns-record-by-id';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -19,15 +20,17 @@ export default async function rm(
args: string[],
output: Output
) {
const { authConfig: { token }, config } = ctx;
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const client = new Client({ apiUrl, token, currentTeam, debug });
let contextName = null;
try {
({ contextName } = await getScope(client));
await getScope(client);
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message);
@@ -40,24 +43,21 @@ export default async function rm(
const [recordId] = args;
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan('`now dns rm <id>`')}`
`Invalid number of arguments. Usage: ${chalk.cyan(
`${getCommandName('dns rm <id>')}`
)}`
);
return 1;
}
const domainRecord = await getDNSRecordById(
output,
client,
contextName,
recordId
);
const record = await getDNSRecordById(client, recordId);
if (!domainRecord) {
if (!record) {
output.error('DNS record not found');
return 1;
}
const { domainName, record } = domainRecord;
const { domain: domainName } = record;
const yes = await readConfirmation(
output,
'The following record will be removed permanently',
@@ -91,7 +91,7 @@ function readConfirmation(
output.print(
`${table([getDeleteTableRow(domainName, record)], {
align: ['l', 'r', 'l'],
hsep: ' '.repeat(6)
hsep: ' '.repeat(6),
}).replace(/^(.*)/gm, ' $1')}\n`
);
output.print(
@@ -112,12 +112,16 @@ function readConfirmation(
}
function getDeleteTableRow(domainName: string, record: DNSRecord) {
const recordName = `${record.name.length > 0
? `${record.name}.`
: ''}${domainName}`;
const recordName = `${
record.name.length > 0 ? `${record.name}.` : ''
}${domainName}`;
return [
record.id,
chalk.bold(`${recordName} ${record.type} ${record.value} ${record.mxPriority || ''}`),
chalk.gray(`${ms(Date.now() - new Date(Number(record.created)).getTime())} ago`)
chalk.bold(
`${recordName} ${record.type} ${record.value} ${record.mxPriority || ''}`
),
chalk.gray(
`${ms(Date.now() - new Date(Number(record.createdAt)).getTime())} ago`
),
];
}

View File

@@ -12,6 +12,7 @@ import formatNSTable from '../../util/format-ns-table';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import param from '../../util/output/param';
import { getCommandName, getTitleName } from '../../util/pkg-name';
type Options = {
'--cdn': boolean;
@@ -47,12 +48,14 @@ export default async function add(
}
if (opts['--cdn'] !== undefined || opts['--no-cdn'] !== undefined) {
output.error(`Toggling CF from Now CLI is deprecated.`);
output.error(`Toggling CF from ${getTitleName()} CLI is deprecated.`);
return 1;
}
if (args.length !== 1) {
output.error(`${cmd('now domains add <domain>')} expects one argument`);
output.error(
`${getCommandName('domains add <domain>')} expects one argument`
);
return 1;
}
@@ -73,7 +76,7 @@ export default async function add(
output.error(
`You are adding '${domainName}' as a domain name containing a subdomain part '${subdomain}'\n` +
` This feature is deprecated, please add just the root domain: ${chalk.cyan(
`now domain add ${domain}`
`${getCommandName(`domain add ${domain}`)}`
)}`
);
return 1;
@@ -139,7 +142,7 @@ export default async function add(
);
output.print(
` If you want to force running a verification, you can run ${cmd(
'now domains verify <domain>'
`${getCommandName('domains verify <domain>')}`
)}\n`
);
output.print(' Read more: https://err.sh/now/domain-verification\n\n');

View File

@@ -5,7 +5,6 @@ import { NowContext } from '../../types';
import { Output } from '../../util/output';
import * as ERRORS from '../../util/errors-ts';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import getDomainPrice from '../../util/domains/get-domain-price';
import getDomainStatus from '../../util/domains/get-domain-status';
import getScope from '../../util/get-scope';
@@ -13,6 +12,7 @@ import param from '../../util/output/param';
import promptBool from '../../util/input/prompt-bool';
import purchaseDomain from '../../util/domains/purchase-domain';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -47,7 +47,9 @@ export default async function buy(
const [domainName] = args;
if (!domainName) {
output.error(`Missing domain name. Run ${cmd('now domains --help')}`);
output.error(
`Missing domain name. Run ${getCommandName(`domains --help`)}`
);
return 1;
}
@@ -60,7 +62,9 @@ export default async function buy(
const { domain: rootDomain, subdomain } = parsedDomain;
if (subdomain || !rootDomain) {
output.error(
`Invalid domain name "${domainName}". Run ${cmd('now domains --help')}`
`Invalid domain name "${domainName}". Run ${getCommandName(
`domains --help`
)}`
);
return 1;
}
@@ -116,8 +120,8 @@ export default async function buy(
if (buyResult instanceof ERRORS.SourceNotFound) {
output.error(
`Could not purchase domain. Please add a payment method using ${cmd(
'now billing add'
`Could not purchase domain. Please add a payment method using ${getCommandName(
`billing add`
)}.`
);
return 1;
@@ -184,8 +188,8 @@ export default async function buy(
);
} else {
output.note(
`You may now use your domain as an alias to your deployments. Run ${cmd(
'now alias --help'
`You may now use your domain as an alias to your deployments. Run ${getCommandName(
`alias --help`
)}`
);
}

View File

@@ -15,10 +15,11 @@ import ls from './ls';
import rm from './rm';
import verify from './verify';
import move from './move';
import { getPkgName } from '../../util/pkg-name';
const help = () => {
console.log(`
${chalk.bold(`${logo} now domains`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} domains`)} [options] <command>
${chalk.dim('Commands:')}
@@ -28,7 +29,7 @@ const help = () => {
rm [name] Remove a domain
buy [name] Buy a domain that you don't yet own
move [name] [destination] Move a domain to another user or team.
transfer-in [name] Transfer in a domain to Zeit
transfer-in [name] Transfer in a domain to Vercel
verify [name] Run a verification for a domain
${chalk.dim('Options:')}
@@ -37,10 +38,10 @@ const help = () => {
-d, --debug Debug mode [off]
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
@@ -51,13 +52,15 @@ const help = () => {
${chalk.gray('')} Add a domain that you already own
${chalk.cyan(`$ now domains add ${chalk.underline('domain-name.com')}`)}
${chalk.cyan(
`$ ${getPkgName()} domains add ${chalk.underline('domain-name.com')}`
)}
Make sure the domain's DNS nameservers are at least 2 of the
ones listed on ${chalk.underline('https://zeit.world')}.
ones listed on ${chalk.underline('https://vercel.com/edge-network')}.
${chalk.yellow('NOTE:')} Running ${chalk.dim(
'`now alias`'
`${getPkgName()} alias`
)} will automatically register your domain
if it's configured with these nameservers (no need to ${chalk.dim(
'`domain add`'
@@ -67,7 +70,7 @@ const help = () => {
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ now domains ls --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} domains ls --next 1584722256178`)}
`);
};

View File

@@ -3,7 +3,6 @@ import { DomainNotFound, DomainPermissionDenied } from '../../util/errors-ts';
import { NowContext } from '../../types';
import { Output } from '../../util/output';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import stamp from '../../util/output/stamp';
import dnsTable from '../../util/format-dns-table';
import formatDate from '../../util/format-date';
@@ -11,6 +10,7 @@ import formatNSTable from '../../util/format-ns-table';
import getDomainByName from '../../util/domains/get-domain-by-name';
import getScope from '../../util/get-scope';
import getDomainPrice from '../../util/domains/get-domain-price';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -48,14 +48,16 @@ export default async function inspect(
const inspectStamp = stamp();
if (!domainName) {
output.error(`${cmd('now domains inspect <domain>')} expects one argument`);
output.error(
`${getCommandName(`domains inspect <domain>`)} expects one argument`
);
return 1;
}
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now domains inspect <domain>`'
`${getCommandName('domains inspect <domain>')}`
)}`
);
return 1;
@@ -72,7 +74,7 @@ export default async function inspect(
output.error(
`Domain not found by "${domainName}" under ${chalk.bold(contextName)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -82,7 +84,7 @@ export default async function inspect(
contextName
)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -169,8 +171,8 @@ export default async function inspect(
` We will run a verification for you and you will receive an email upon completion.\n`
);
output.print(
` If you want to force running a verification, you can run ${cmd(
'now domains verify <domain>'
` If you want to force running a verification, you can run ${getCommandName(
`domains verify <domain>`
)}\n`
);
output.print(' Read more: https://err.sh/now/domain-verification\n\n');

View File

@@ -10,7 +10,7 @@ import strlen from '../../util/strlen';
import { Output } from '../../util/output';
import { Domain, NowContext } from '../../types';
import getCommandFlags from '../../util/get-command-flags';
import cmd from '../../util/output/cmd';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -53,7 +53,9 @@ export default async function ls(
if (args.length !== 0) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan('`now domains ls`')}`
`Invalid number of arguments. Usage: ${chalk.cyan(
`${getCommandName('domains ls')}`
)}`
);
return 1;
}
@@ -73,8 +75,8 @@ export default async function ls(
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(opts, ['_', '--next']);
output.log(
`To display the next page run ${cmd(
`now domains ls${flags} --next ${pagination.next}`
`To display the next page run ${getCommandName(
`domains ls${flags} --next ${pagination.next}`
)}`
);
}

View File

@@ -5,7 +5,6 @@ import { NowContext, User, Team } from '../../types';
import { Output } from '../../util/output';
import * as ERRORS from '../../util/errors-ts';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import getScope from '../../util/get-scope';
import withSpinner from '../../util/with-spinner';
import moveOutDomain from '../../util/domains/move-out-domain';
@@ -16,6 +15,7 @@ import getDomainAliases from '../../util/alias/get-domain-aliases';
import getDomainByName from '../../util/domains/get-domain-by-name';
import promptBool from '../../util/input/prompt-bool';
import getTeams from '../../util/get-teams';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -53,7 +53,9 @@ export default async function move(
const { domainName, destination } = await getArgs(args);
if (!isRootDomain(domainName)) {
output.error(
`Invalid domain name "${domainName}". Run ${cmd('now domains --help')}`
`Invalid domain name "${domainName}". Run ${getCommandName(
`domains --help`
)}`
);
return 1;
}
@@ -61,7 +63,7 @@ export default async function move(
const domain = await getDomainByName(client, contextName, domainName);
if (domain instanceof ERRORS.DomainNotFound) {
output.error(`Domain not found under ${chalk.bold(contextName)}`);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
if (domain instanceof ERRORS.DomainPermissionDenied) {
@@ -100,7 +102,7 @@ export default async function move(
output.warn(
`This domain's ${chalk.bold(
plural('alias', aliases.length, true)
)} will be removed. Run ${chalk.dim('`now alias ls`')} to list them.`
)} will be removed. Run ${getCommandName(`alias ls`)} to list them.`
);
if (
!(await promptBool(
@@ -140,7 +142,7 @@ export default async function move(
}
if (moveTokenResult instanceof ERRORS.DomainNotFound) {
output.error(`Domain not found under ${chalk.bold(contextName)}`);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
if (moveTokenResult instanceof ERRORS.DomainPermissionDenied) {

View File

@@ -5,7 +5,6 @@ import { DomainNotFound, DomainPermissionDenied } from '../../util/errors-ts';
import { NowContext, Domain } from '../../types';
import { Output } from '../../util/output';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import deleteCertById from '../../util/certs/delete-cert-by-id';
import getDomainByName from '../../util/domains/get-domain-by-name';
import getScope from '../../util/get-scope';
@@ -16,6 +15,7 @@ import * as ERRORS from '../../util/errors-ts';
import param from '../../util/output/param';
import promptBool from '../../util/input/prompt-bool';
import setCustomSuffix from '../../util/domains/set-custom-suffix';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -51,14 +51,16 @@ export default async function rm(
}
if (!domainName) {
output.error(`${cmd('now domains rm <domain>')} expects one argument`);
output.error(
`${getCommandName(`domains rm <domain>`)} expects one argument`
);
return 1;
}
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now domains rm <domain>`'
`${getCommandName('domains rm <domain>')}`
)}`
);
return 1;
@@ -69,7 +71,7 @@ export default async function rm(
output.error(
`Domain not found by "${domainName}" under ${chalk.bold(contextName)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -79,7 +81,7 @@ export default async function rm(
contextName
)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -146,7 +148,7 @@ async function removeDomain(
if (removeResult instanceof ERRORS.DomainNotFound) {
output.error(`Domain not found under ${chalk.bold(contextName)}`);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -204,7 +206,7 @@ async function removeDomain(
output.warn(
`This domain's ${chalk.bold(
plural('alias', aliases.length, true)
)} will be removed. Run ${chalk.dim('`now alias ls`')} to list them.`
)} will be removed. Run ${getCommandName(`alias ls`)} to list them.`
);
}
@@ -212,7 +214,7 @@ async function removeDomain(
output.warn(
`This domain's ${chalk.bold(
plural('certificate', certs.length, true)
)} will be removed. Run ${chalk.dim('`now cert ls`')} to list them.`
)} will be removed. Run ${getCommandName(`cert ls`)} to list them.`
);
}

View File

@@ -4,7 +4,6 @@ import { NowContext } from '../../types';
import { Output } from '../../util/output';
import * as ERRORS from '../../util/errors-ts';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import getScope from '../../util/get-scope';
import param from '../../util/output/param';
import transferInDomain from '../../util/domains/transfer-in-domain';
@@ -15,6 +14,7 @@ import getDomainPrice from '../../util/domains/get-domain-price';
import checkTransfer from '../../util/domains/check-transfer';
import promptBool from '../../util/input/prompt-bool';
import isRootDomain from '../../util/is-root-domain';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -50,14 +50,16 @@ export default async function transferIn(
const [domainName] = args;
if (!domainName) {
output.error(`Missing domain name. Run ${cmd('now domains --help')}`);
output.error(
`Missing domain name. Run ${getCommandName(`domains --help`)}`
);
return 1;
}
if (!isRootDomain(domainName)) {
output.error(
`Invalid domain name ${param(domainName)}. Run ${cmd(
'now domains --help'
`Invalid domain name ${param(domainName)}. Run ${getCommandName(
`domains --help`
)}`
);
return 1;
@@ -127,8 +129,8 @@ export default async function transferIn(
if (transferInResult instanceof ERRORS.SourceNotFound) {
output.error(
`Could not purchase domain. Please add a payment method using ${cmd(
'now billing add'
`Could not purchase domain. Please add a payment method using ${getCommandName(
`billing add`
)}.`
);
return 1;
@@ -157,6 +159,8 @@ export default async function transferIn(
` To transfer with previous DNS records, export the zone file from your previous registrar.\n`
);
output.print(` Then import it to Vercel DNS by using:\n`);
output.print(` ${cmd(`now dns import ${domainName} <zonefile>`)}\n\n`);
output.print(
` ${getCommandName(`dns import ${domainName} <zonefile>`)}\n\n`
);
return 0;
}

View File

@@ -3,13 +3,13 @@ import { NowContext } from '../../types';
import { Output } from '../../util/output';
import * as ERRORS from '../../util/errors-ts';
import Client from '../../util/client';
import cmd from '../../util/output/cmd';
import formatDnsTable from '../../util/format-dns-table';
import formatNSTable from '../../util/format-ns-table';
import getDomainByName from '../../util/domains/get-domain-by-name';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import verifyDomain from '../../util/domains/verify-domain';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -46,14 +46,16 @@ export default async function verify(
const [domainName] = args;
if (!domainName) {
output.error(`${cmd('now domains verify <domain>')} expects one argument`);
output.error(
`${getCommandName(`domains verify <domain>`)} expects one argument`
);
return 1;
}
if (args.length !== 1) {
output.error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now domains verify <domain>`'
`${getCommandName('domains verify <domain>')}`
)}`
);
return 1;
@@ -64,7 +66,7 @@ export default async function verify(
output.error(
`Domain not found by "${domainName}" under ${chalk.bold(contextName)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -74,7 +76,7 @@ export default async function verify(
contextName
)}`
);
output.log(`Run ${cmd('now domains ls')} to see your domains.`);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
}
@@ -111,8 +113,8 @@ export default async function verify(
)}\n\n`
);
output.print(
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${cmd(
'now domains verify <domain>'
` Once your domain uses either the nameservers or the TXT DNS record from above, run again ${getCommandName(
`domains verify <domain>`
)}.\n`
);
output.print(
@@ -137,8 +139,8 @@ export default async function verify(
)} was verified using DNS TXT record. ${verifyStamp()}`
);
output.print(
` You can verify with nameservers too. Run ${cmd(
`now domains inspect ${domain.name}`
` You can verify with nameservers too. Run ${getCommandName(
`domains inspect ${domain.name}`
)} to find out the intended set.\n`
);
return 0;

View File

@@ -1,10 +1,9 @@
import chalk from 'chalk';
import inquirer from 'inquirer';
import { NowContext, ProjectEnvTarget } from '../../types';
import { ProjectEnvTarget, Project } from '../../types';
import { Output } from '../../util/output';
import Client from '../../util/client';
import stamp from '../../util/output/stamp';
import { getLinkedProject } from '../../util/projects/link';
import addEnvRecord from '../../util/env/add-env-record';
import getEnvVariables from '../../util/env/get-env-records';
import {
@@ -13,160 +12,143 @@ import {
getEnvTargetChoices,
} from '../../util/env/env-target';
import readStandardInput from '../../util/input/read-standard-input';
import cmd from '../../util/output/cmd';
import param from '../../util/output/param';
import withSpinner from '../../util/with-spinner';
import { emoji, prependEmoji } from '../../util/emoji';
import { isKnownError } from '../../util/env/known-error';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
};
export default async function add(
ctx: NowContext,
client: Client,
project: Project,
opts: Options,
args: string[],
output: Output
) {
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const client = new Client({ apiUrl, token, currentTeam, debug });
const link = await getLinkedProject(output, client);
const stdInput = await readStandardInput();
let [envName, envTarget] = args;
if (link.status === 'error') {
return link.exitCode;
} else if (link.status === 'not_linked') {
output.print(
`${chalk.red(
'Error!'
)} Your codebase isnt linked to a project on Vercel. Run ${cmd(
'now'
)} to link it.\n`
if (args.length > 2) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(
`env add <name> ${getEnvTargetPlaceholder()}`
)}`
);
return 1;
} else {
const { project } = link;
const stdInput = await readStandardInput();
let [envName, envTarget] = args;
if (args.length > 2) {
output.error(
`Invalid number of arguments. Usage: ${cmd(
`now env add <name> ${getEnvTargetPlaceholder()}`
)}`
);
return 1;
}
if (stdInput && (!envName || !envTarget)) {
output.error(
`Invalid number of arguments. Usage: ${cmd(
`now env add <name> <target> < <file>`
)}`
);
return 1;
}
let envTargets: ProjectEnvTarget[] = [];
if (envTarget) {
if (!isValidEnvTarget(envTarget)) {
output.error(
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
envTargets.push(envTarget);
}
while (!envName) {
const { inputName } = await inquirer.prompt({
type: 'input',
name: 'inputName',
message: `Whats the name of the variable?`,
});
envName = inputName;
if (!inputName) {
output.error('Name cannot be empty');
}
}
const envs = await getEnvVariables(output, client, project.id);
const existing = new Set(
envs.filter(r => r.key === envName).map(r => r.target)
);
const choices = getEnvTargetChoices().filter(c => !existing.has(c.value));
if (choices.length === 0) {
output.error(
`The variable ${param(
envName
)} has already been added to all Environments. To remove, run ${cmd(
`now env rm ${envName}`
)}.`
);
return 1;
}
let envValue: string;
if (stdInput) {
envValue = stdInput;
} else {
const { inputValue } = await inquirer.prompt({
type: 'password',
name: 'inputValue',
message: `Whats the value of ${envName}?`,
});
envValue = inputValue || '';
}
while (envTargets.length === 0) {
const { inputTargets } = await inquirer.prompt({
name: 'inputTargets',
type: 'checkbox',
message: `Add ${envName} to which Environments (select multiple)?`,
choices,
});
envTargets = inputTargets;
if (inputTargets.length === 0) {
output.error('Please select at least one Environment');
}
}
const addStamp = stamp();
try {
await withSpinner('Saving', () =>
addEnvRecord(output, client, project.id, envName, envValue, envTargets)
);
} catch (error) {
if (isKnownError(error) && error.serverMessage) {
output.error(error.serverMessage);
return 1;
}
throw error;
}
output.print(
`${prependEmoji(
`Added Environment Variable ${chalk.bold(
envName
)} to Project ${chalk.bold(project.name)} ${chalk.gray(addStamp())}`,
emoji('success')
)}\n`
);
return 0;
}
if (stdInput && (!envName || !envTarget)) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(
`env add <name> <target> < <file>`
)}`
);
return 1;
}
let envTargets: ProjectEnvTarget[] = [];
if (envTarget) {
if (!isValidEnvTarget(envTarget)) {
output.error(
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
envTargets.push(envTarget);
}
while (!envName) {
const { inputName } = await inquirer.prompt({
type: 'input',
name: 'inputName',
message: `Whats the name of the variable?`,
});
envName = inputName;
if (!inputName) {
output.error('Name cannot be empty');
}
}
const envs = await getEnvVariables(output, client, project.id, 4);
const existing = new Set(
envs.filter(r => r.key === envName).map(r => r.target)
);
const choices = getEnvTargetChoices().filter(c => !existing.has(c.value));
if (choices.length === 0) {
output.error(
`The variable ${param(
envName
)} has already been added to all Environments. To remove, run ${getCommandName(
`env rm ${envName}`
)}.`
);
return 1;
}
let envValue: string;
if (stdInput) {
envValue = stdInput;
} else if (isSystemEnvVariable(envName)) {
envValue = '';
} else {
const { inputValue } = await inquirer.prompt({
type: 'password',
name: 'inputValue',
message: `Whats the value of ${envName}?`,
});
envValue = inputValue || '';
}
while (envTargets.length === 0) {
const { inputTargets } = await inquirer.prompt({
name: 'inputTargets',
type: 'checkbox',
message: `Add ${envName} to which Environments (select multiple)?`,
choices,
});
envTargets = inputTargets;
if (inputTargets.length === 0) {
output.error('Please select at least one Environment');
}
}
const addStamp = stamp();
try {
await withSpinner('Saving', () =>
addEnvRecord(output, client, project.id, envName, envValue, envTargets)
);
} catch (error) {
if (isKnownError(error) && error.serverMessage) {
output.error(error.serverMessage);
return 1;
}
throw error;
}
output.print(
`${prependEmoji(
`Added Environment Variable ${chalk.bold(
envName
)} to Project ${chalk.bold(project.name)} ${chalk.gray(addStamp())}`,
emoji('success')
)}\n`
);
return 0;
}
function isSystemEnvVariable(envName: string) {
return envName.startsWith('VERCEL_');
}

View File

@@ -6,8 +6,11 @@ import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
import { getLinkedProject } from '../../util/projects/link';
import Client from '../../util/client';
import handleError from '../../util/handle-error';
import logo from '../../util/output/logo';
import { getCommandName, getPkgName } from '../../util/pkg-name';
import add from './add';
import pull from './pull';
@@ -17,7 +20,7 @@ import rm from './rm';
const help = () => {
const placeholder = getEnvTargetPlaceholder();
console.log(`
${chalk.bold(`${logo} now env`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} env`)} [options] <command>
${chalk.dim('Commands:')}
@@ -31,42 +34,51 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new variable to multiple Environments
${chalk.cyan('$ now env add <name>')}
${chalk.cyan('$ now env add API_TOKEN')}
${chalk.cyan(`$ ${getPkgName()} env add <name>`)}
${chalk.cyan(`$ ${getPkgName()} env add API_TOKEN`)}
${chalk.gray('')} Add a new variable for a specific Environment
${chalk.cyan(`$ now env add <name> ${placeholder}`)}
${chalk.cyan('$ now env add DB_CONNECTION production')}
${chalk.cyan(`$ ${getPkgName()} env add <name> ${placeholder}`)}
${chalk.cyan(`$ ${getPkgName()} env add DB_CONNECTION production`)}
${chalk.gray('')} Add a new Environment Variable from stdin
${chalk.cyan(`$ cat <file> | now env add <name> ${placeholder}`)}
${chalk.cyan('$ cat ~/.npmrc | now env add NPM_RC preview')}
${chalk.cyan('$ now env add DB_PASS production < secret.txt')}
${chalk.cyan(
`$ cat <file> | ${getPkgName()} env add <name> ${placeholder}`
)}
${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.cyan('$ now env rm <name>')}
${chalk.cyan('$ now env rm API_TOKEN')}
${chalk.cyan(`$ ${getPkgName()} env rm <name>`)}
${chalk.cyan(`$ ${getPkgName()} env rm API_TOKEN`)}
${chalk.gray('')} Remove a variable from a specific Environment
${chalk.cyan(`$ now env rm <name> ${placeholder}`)}
${chalk.cyan('$ now env rm NPM_RC preview')}
${chalk.cyan(`$ ${getPkgName()} env rm <name> ${placeholder}`)}
${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`)}
`);
};
@@ -84,6 +96,8 @@ export default async function main(ctx: NowContext) {
argv = getArgs(ctx.argv.slice(2), {
'--yes': Boolean,
'-y': '--yes',
'--next': Number,
'-N': '--next',
});
} catch (error) {
handleError(error);
@@ -95,20 +109,40 @@ export default async function main(ctx: NowContext) {
return 2;
}
const output = createOutput({ debug: argv['--debug'] });
const debug = argv['--debug'];
const output = createOutput({ debug });
const { subcommand, args } = getSubcommand(argv._.slice(1), COMMAND_CONFIG);
switch (subcommand) {
case 'ls':
return ls(ctx, argv, args, output);
case 'add':
return add(ctx, argv, args, output);
case 'rm':
return rm(ctx, argv, args, output);
case 'pull':
return pull(ctx, argv, args, output);
default:
output.error(getInvalidSubcommand(COMMAND_CONFIG));
help();
return 2;
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const client = new Client({ apiUrl, token, currentTeam, debug });
const link = await getLinkedProject(output, client);
if (link.status === 'error') {
return link.exitCode;
} else if (link.status === 'not_linked') {
output.error(
`Your codebase isnt linked to a project on Vercel. Run ${getCommandName()} to link it.`
);
return 1;
} else {
const { project, org } = link;
client.currentTeam = org.type === 'team' ? org.id : undefined;
switch (subcommand) {
case 'ls':
return ls(client, project, argv, args, output);
case 'add':
return add(client, project, argv, args, output);
case 'rm':
return rm(client, project, argv, args, output);
case 'pull':
return pull(client, project, argv, args, output);
default:
output.error(getInvalidSubcommand(COMMAND_CONFIG));
help();
return 2;
}
}
}

View File

@@ -1,8 +1,7 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import { Output } from '../../util/output';
import { ProjectEnvVariable, ProjectEnvTarget, NowContext } from '../../types';
import { ProjectEnvVariable, ProjectEnvTarget, Project } from '../../types';
import Client from '../../util/client';
import formatTable from '../../util/format-table';
import getEnvVariables from '../../util/env/get-env-records';
@@ -10,82 +9,78 @@ import {
isValidEnvTarget,
getEnvTargetPlaceholder,
} from '../../util/env/env-target';
import { getLinkedProject } from '../../util/projects/link';
import stamp from '../../util/output/stamp';
import cmd from '../../util/output/cmd';
import param from '../../util/output/param';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
'--next'?: number;
};
export default async function ls(
ctx: NowContext,
client: Client,
project: Project,
opts: Options,
args: string[],
output: Output
) {
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const client = new Client({ apiUrl, token, currentTeam, debug });
const link = await getLinkedProject(output, client);
const { '--next': nextTimestamp } = opts;
if (link.status === 'error') {
return link.exitCode;
} else if (link.status === 'not_linked') {
output.print(
`${chalk.red(
'Error!'
)} Your codebase isnt linked to a project on Vercel. Run ${cmd(
'now'
)} to link it.\n`
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(
`env ls ${getEnvTargetPlaceholder()}`
)}`
);
return 1;
} else {
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${cmd(
`now env ls ${getEnvTargetPlaceholder()}`
)}`
);
return 1;
}
const { project } = link;
const envTarget = args[0] as ProjectEnvTarget | undefined;
if (!isValidEnvTarget(envTarget)) {
output.error(
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
const lsStamp = stamp();
const records = await getEnvVariables(
output,
client,
project.id,
envTarget
);
output.log(
`${plural(
'Environment Variable',
records.length,
true
)} found in Project ${chalk.bold(project.name)} ${chalk.gray(lsStamp())}`
);
console.log(getTable(records));
return 0;
}
const envTarget = args[0] as ProjectEnvTarget | undefined;
if (!isValidEnvTarget(envTarget)) {
output.error(
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
const lsStamp = stamp();
if (typeof nextTimestamp !== 'undefined' && Number.isNaN(nextTimestamp)) {
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(
`${
records.length > 0 ? 'Environment Variables' : 'No Environment Variables'
} found in Project ${chalk.bold(project.name)} ${chalk.gray(lsStamp())}`
);
console.log(getTable(records));
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;
}
function getTable(records: ProjectEnvVariable[]) {

View File

@@ -1,18 +1,17 @@
import chalk from 'chalk';
import { NowContext, ProjectEnvTarget } from '../../types';
import { ProjectEnvTarget, Project } from '../../types';
import { Output } from '../../util/output';
import promptBool from '../../util/prompt-bool';
import Client from '../../util/client';
import stamp from '../../util/output/stamp';
import getEnvVariables from '../../util/env/get-env-records';
import getDecryptedSecret from '../../util/env/get-decrypted-secret';
import { getLinkedProject } from '../../util/projects/link';
import cmd from '../../util/output/cmd';
import param from '../../util/output/param';
import withSpinner from '../../util/with-spinner';
import { join } from 'path';
import { promises, existsSync } from 'fs';
import { emoji, prependEmoji } from '../../util/emoji';
import { getCommandName } from '../../util/pkg-name';
const { writeFile } = promises;
type Options = {
@@ -21,95 +20,72 @@ type Options = {
};
export default async function pull(
ctx: NowContext,
client: Client,
project: Project,
opts: Options,
args: string[],
output: Output
) {
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const client = new Client({ apiUrl, token, currentTeam, debug });
const link = await getLinkedProject(output, client);
if (link.status === 'error') {
return link.exitCode;
} else if (link.status === 'not_linked') {
output.print(
`${chalk.red(
'Error!'
)} Your codebase isnt linked to a project on Vercel. Run ${cmd(
'now'
)} to link it.\n`
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(`env pull <file>`)}`
);
return 1;
} else {
if (args.length > 1) {
output.error(
`Invalid number of arguments. Usage: ${cmd('now env pull <file>')}`
);
return 1;
}
}
const { project } = link;
const [filename = '.env'] = args;
const fullPath = join(process.cwd(), filename);
const exists = existsSync(fullPath);
const skipConfirmation = opts['--yes'];
const [filename = '.env'] = args;
const fullPath = join(process.cwd(), filename);
const exists = existsSync(fullPath);
const skipConfirmation = opts['--yes'];
if (
exists &&
!skipConfirmation &&
!(await promptBool(
output,
`Found existing file ${param(filename)}. Do you want to overwrite?`
))
) {
output.log('Aborted');
return 0;
}
output.print(
`Downloading Development Environment Variables for Project ${chalk.bold(
project.name
)}\n`
);
const pullStamp = stamp();
const records = await withSpinner('Downloading', async () => {
const dev = ProjectEnvTarget.Development;
const envs = await getEnvVariables(output, client, project.id, dev);
const values = await Promise.all(
envs.map(env => getDecryptedSecret(output, client, env.value))
);
const results: { key: string; value: string }[] = [];
for (let i = 0; i < values.length; i++) {
results.push({ key: envs[i].key, value: values[i] });
}
return results;
});
const contents =
records
.map(({ key, value }) => `${key}="${escapeValue(value)}"`)
.join('\n') + '\n';
await writeFile(fullPath, contents, 'utf8');
output.print(
`${prependEmoji(
`${exists ? 'Updated' : 'Created'} ${chalk.bold(
filename
)} file ${chalk.gray(pullStamp())}`,
emoji('success')
)}\n`
);
if (
exists &&
!skipConfirmation &&
!(await promptBool(
output,
`Found existing file ${param(filename)}. Do you want to overwrite?`
))
) {
output.log('Aborted');
return 0;
}
output.print(
`Downloading Development Environment Variables for Project ${chalk.bold(
project.name
)}\n`
);
const pullStamp = stamp();
const records = await withSpinner('Downloading', async () => {
const dev = ProjectEnvTarget.Development;
const envs = await getEnvVariables(output, client, project.id, 4, dev);
const values = await Promise.all(
envs.map(env => getDecryptedSecret(output, client, env.value))
);
const results: { key: string; value: string }[] = [];
for (let i = 0; i < values.length; i++) {
results.push({ key: envs[i].key, value: values[i] });
}
return results;
});
const contents =
records
.map(({ key, value }) => `${key}="${escapeValue(value)}"`)
.join('\n') + '\n';
await writeFile(fullPath, contents, 'utf8');
output.print(
`${prependEmoji(
`${exists ? 'Updated' : 'Created'} ${chalk.bold(
filename
)} file ${chalk.gray(pullStamp())}`,
emoji('success')
)}\n`
);
return 0;
}
function escapeValue(value: string) {

View File

@@ -1,9 +1,8 @@
import chalk from 'chalk';
import inquirer from 'inquirer';
import { NowContext, ProjectEnvTarget } from '../../types';
import { ProjectEnvTarget, Project } from '../../types';
import { Output } from '../../util/output';
import promptBool from '../../util/prompt-bool';
import { getLinkedProject } from '../../util/projects/link';
import removeEnvRecord from '../../util/env/remove-env-record';
import getEnvVariables from '../../util/env/get-env-records';
import {
@@ -13,11 +12,11 @@ import {
} from '../../util/env/env-target';
import Client from '../../util/client';
import stamp from '../../util/output/stamp';
import cmd from '../../util/output/cmd';
import param from '../../util/output/param';
import withSpinner from '../../util/with-spinner';
import { emoji, prependEmoji } from '../../util/emoji';
import { isKnownError } from '../../util/env/known-error';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -25,144 +24,119 @@ type Options = {
};
export default async function rm(
ctx: NowContext,
client: Client,
project: Project,
opts: Options,
args: string[],
output: Output
) {
const {
authConfig: { token },
config,
} = ctx;
const { currentTeam } = config;
const { apiUrl } = ctx;
const debug = opts['--debug'];
const client = new Client({ apiUrl, token, currentTeam, debug });
const link = await getLinkedProject(output, client);
if (link.status === 'error') {
return link.exitCode;
} else if (link.status === 'not_linked') {
output.print(
`${chalk.red(
'Error!'
)} Your codebase isnt linked to a project on Vercel. Run ${cmd(
'now'
)} to link it.\n`
if (args.length > 2) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(
`env rm <name> ${getEnvTargetPlaceholder()}`
)}`
);
return 1;
} else {
if (args.length > 2) {
}
let [envName, envTarget] = args;
let envTargets: ProjectEnvTarget[] = [];
if (envTarget) {
if (!isValidEnvTarget(envTarget)) {
output.error(
`Invalid number of arguments. Usage: ${cmd(
`now env rm <name> ${getEnvTargetPlaceholder()}`
)}`
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
envTargets.push(envTarget);
}
const { project } = link;
let [envName, envTarget] = args;
let envTargets: ProjectEnvTarget[] = [];
while (!envName) {
const { inputName } = await inquirer.prompt({
type: 'input',
name: 'inputName',
message: `Whats the name of the variable?`,
});
if (envTarget) {
if (!isValidEnvTarget(envTarget)) {
output.error(
`The Environment ${param(
envTarget
)} is invalid. It must be one of: ${getEnvTargetPlaceholder()}.`
);
return 1;
}
envTargets.push(envTarget);
if (!inputName) {
output.error(`Name cannot be empty`);
continue;
}
while (!envName) {
const { inputName } = await inquirer.prompt({
type: 'input',
name: 'inputName',
message: `Whats the name of the variable?`,
});
envName = inputName;
}
if (!inputName) {
output.error(`Name cannot be empty`);
continue;
}
const envs = await getEnvVariables(output, client, project.id, 4);
const existing = new Set(
envs.filter(r => r.key === envName).map(r => r.target)
);
envName = inputName;
}
if (existing.size === 0) {
output.error(`The Environment Variable ${param(envName)} was not found.\n`);
return 1;
}
const envs = await getEnvVariables(output, client, project.id);
const existing = new Set(
envs.filter(r => r.key === envName).map(r => r.target)
);
if (existing.size === 0) {
if (envTargets.length === 0) {
const choices = getEnvTargetChoices().filter(c => existing.has(c.value));
if (choices.length === 0) {
output.error(
`The Environment Variable ${param(envName)} was not found.\n`
);
return 1;
}
if (envTargets.length === 0) {
const choices = getEnvTargetChoices().filter(c => existing.has(c.value));
if (choices.length === 0) {
output.error(
`The Environment Variable ${param(
envName
)} was found but it is not assigned to any Environments.\n`
);
return 1;
} else if (choices.length === 1) {
envTargets = [choices[0].value];
} else {
const { inputTargets } = await inquirer.prompt({
name: 'inputTargets',
type: 'checkbox',
message: `Remove ${envName} from which Environments (select multiple)?`,
choices,
});
envTargets = inputTargets;
}
}
const skipConfirmation = opts['--yes'];
if (
!skipConfirmation &&
!(await promptBool(
output,
`Removing Environment Variable ${param(
`The Environment Variable ${param(
envName
)} from Project ${chalk.bold(project.name)}. Are you sure?`
))
) {
output.log('Aborted');
return 0;
}
const rmStamp = stamp();
try {
await withSpinner('Removing', async () => {
for (const target of envTargets) {
await removeEnvRecord(output, client, project.id, envName, target);
}
)} was found but it is not assigned to any Environments.\n`
);
return 1;
} else if (choices.length === 1) {
envTargets = [choices[0].value];
} else {
const { inputTargets } = await inquirer.prompt({
name: 'inputTargets',
type: 'checkbox',
message: `Remove ${envName} from which Environments (select multiple)?`,
choices,
});
} catch (error) {
if (isKnownError(error) && error.serverMessage) {
output.error(error.serverMessage);
return 1;
}
throw error;
envTargets = inputTargets;
}
}
output.print(
`${prependEmoji(
`Removed Environment Variable ${chalk.gray(rmStamp())}`,
emoji('success')
)}\n`
);
const skipConfirmation = opts['--yes'];
if (
!skipConfirmation &&
!(await promptBool(
output,
`Removing Environment Variable ${param(
envName
)} from Project ${chalk.bold(project.name)}. Are you sure?`
))
) {
output.log('Aborted');
return 0;
}
const rmStamp = stamp();
try {
await withSpinner('Removing', async () => {
for (const target of envTargets) {
await removeEnvRecord(output, client, project.id, envName, target);
}
});
} catch (error) {
if (isKnownError(error) && error.serverMessage) {
output.error(error.serverMessage);
return 1;
}
throw error;
}
output.print(
`${prependEmoji(
`Removed Environment Variable ${chalk.gray(rmStamp())}`,
emoji('success')
)}\n`
);
return 0;
}

View File

@@ -8,14 +8,15 @@ import createOutput from '../../util/output/create-output';
import logo from '../../util/output/logo';
import error from '../../util/output/error';
import init from './init';
import { getPkgName } from '../../util/pkg-name';
const COMMAND_CONFIG = {
init: ['init']
init: ['init'],
};
const help = () => {
console.log(`
${chalk.bold(`${logo} now init`)} [example] [dir] [-f | --force]
${chalk.bold(`${logo} ${getPkgName()} init`)} [example] [dir] [-f | --force]
${chalk.dim('Options:')}
@@ -27,19 +28,19 @@ const help = () => {
${chalk.gray('')} Choose from all available examples
${chalk.cyan(`$ now init`)}
${chalk.cyan(`$ ${getPkgName()} init`)}
${chalk.gray('')} Initialize example project into a new directory
${chalk.cyan(`$ now init <example>`)}
${chalk.cyan(`$ ${getPkgName()} init <example>`)}
${chalk.gray('')} Initialize example project into specified directory
${chalk.cyan(`$ now init <example> <dir>`)}
${chalk.cyan(`$ ${getPkgName()} init <example> <dir>`)}
${chalk.gray('')} Initialize example project without checking
${chalk.cyan(`$ now init <example> --force`)}
${chalk.cyan(`$ ${getPkgName()} init <example> --force`)}
`);
};
@@ -51,7 +52,7 @@ export default async function main(ctx: NowContext) {
try {
argv = getArgs(ctx.argv.slice(2), {
'--force': Boolean,
'-f': Boolean
'-f': Boolean,
});
args = getSubcommand(argv._.slice(1), COMMAND_CONFIG).args;
output = createOutput({ debug: argv['--debug'] });

View File

@@ -15,6 +15,7 @@ import success from '../../util/output/success';
import info from '../../util/output/info';
import cmd from '../../util/output/cmd';
import didYouMean from '../../util/init/did-you-mean';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--debug': boolean;
@@ -152,9 +153,11 @@ async function extractExample(
const folderRel = path.relative(process.cwd(), folder);
const deployHint =
folderRel === ''
? listItem(`To deploy, run ${cmd('now')}.`)
? listItem(`To deploy, run ${getCommandName()}.`)
: listItem(
`To deploy, ${cmd(`cd ${folderRel}`)} and run ${cmd('now')}.`
`To deploy, ${cmd(
`cd ${folderRel}`
)} and run ${getCommandName()}.`
);
console.log(success(`${successLog}\n${deployHint}`));
return 0;
@@ -204,8 +207,8 @@ function prepareFolder(cwd: string, folder: string, force?: boolean) {
*/
async function guess(exampleList: string[], name: string) {
const GuessError = new Error(
`No example found for ${chalk.bold(name)}, run ${cmd(
`now init`
`No example found for ${chalk.bold(name)}, run ${getCommandName(
`init`
)} to see the list of available examples.`
);

View File

@@ -4,7 +4,6 @@ import getArgs from '../util/get-args';
import buildsList from '../util/output/builds';
import routesList from '../util/output/routes';
import indent from '../util/output/indent';
import cmd from '../util/output/cmd.ts';
import createOutput from '../util/output';
import Now from '../util';
import logo from '../util/output/logo';
@@ -13,22 +12,23 @@ import { handleError } from '../util/error';
import strlen from '../util/strlen.ts';
import Client from '../util/client.ts';
import getScope from '../util/get-scope.ts';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
const STATIC = 'STATIC';
const help = () => {
console.log(`
${chalk.bold(`${logo} now inspect`)} <url>
${chalk.bold(`${logo} ${getPkgName()} inspect`)} <url>
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
@@ -39,11 +39,11 @@ const help = () => {
${chalk.gray('')} Get information about a deployment by its unique URL
${chalk.cyan('$ now inspect my-deployment-ji2fjij2.now.sh')}
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment-ji2fjij2.now.sh`)}
${chalk.gray('-')} Get information about the deployment an alias points to
${chalk.cyan('$ now inspect my-deployment.now.sh')}
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment.now.sh`)}
`);
};
@@ -73,7 +73,7 @@ export default async function main(ctx) {
id = argv._[1];
if (argv._.length !== 2) {
error(`${cmd('now inspect <url>')} expects exactly one argument`);
error(`${getCommandName('inspect <url>')} expects exactly one argument`);
help();
return 1;
}

View File

@@ -18,20 +18,21 @@ import toHost from '../util/to-host';
import parseMeta from '../util/parse-meta';
import { isValidName } from '../util/is-valid-name';
import getCommandFlags from '../util/get-command-flags';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now list`)} [app]
${chalk.bold(`${logo} ${getPkgName()} list`)} [app]
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -47,27 +48,27 @@ const help = () => {
${chalk.gray('')} List all deployments
${chalk.cyan('$ now ls')}
${chalk.cyan(`$ ${getPkgName()} ls`)}
${chalk.gray('')} List all deployments for the app ${chalk.dim('`my-app`')}
${chalk.cyan('$ now ls my-app')}
${chalk.cyan(`$ ${getPkgName()} ls my-app`)}
${chalk.gray(
''
)} List all deployments and all instances for the app ${chalk.dim('`my-app`')}
${chalk.cyan('$ now ls my-app --all')}
${chalk.cyan(`$ ${getPkgName()} ls my-app --all`)}
${chalk.gray('')} Filter deployments by metadata
${chalk.cyan('$ now ls -m key1=value1 -m key2=value2')}
${chalk.cyan(`$ ${getPkgName()} ls -m key1=value1 -m key2=value2`)}
${chalk.gray('')} Paginate deployments for a project, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ now ls my-app --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} ls my-app --next 1584722256178`)}
`);
};
@@ -97,7 +98,7 @@ export default async function main(ctx) {
});
if (argv._.length > 2) {
error(`${cmd('now ls [app]')} accepts at most one argument`);
error(`${getCommandName('ls [app]')} accepts at most one argument`);
return 1;
}
@@ -162,12 +163,14 @@ export default async function main(ctx) {
// Some people are using entire domains as app names, so
// we need to account for this here
if (app && toHost(app).endsWith('.now.sh')) {
const asHost = app ? toHost(app) : '';
if (asHost.endsWith('.now.sh') || asHost.endsWith('.vercel.app')) {
note(
'We suggest using `now inspect <deployment>` for retrieving details about a single deployment'
`We suggest using ${getCommandName(
'inspect <deployment>'
)} for retrieving details about a single deployment`
);
const asHost = toHost(app);
const hostParts = asHost.split('-');
if (hostParts < 2) {
@@ -233,7 +236,7 @@ export default async function main(ctx) {
now.close();
stopSpinner();
log(`Found matching path alias: ${chalk.cyan(item.alias)}`);
log(`Please run ${cmd(`now alias ls ${item.alias}`)} instead`);
log(`Please run ${getCommandName(`alias ls ${item.alias}`)} instead`);
return 0;
}
@@ -283,10 +286,16 @@ export default async function main(ctx) {
// information to help the user find other deployments or instances
if (app == null) {
log(
`To list more deployments for a project run ${cmd('now ls [project]')}`
`To list more deployments for a project run ${cmd(
`${getCommandName('ls [project]')}`
)}`
);
} else if (!argv['--all']) {
log(`To list deployment instances run ${cmd('now ls --all [project]')}`);
log(
`To list deployment instances run ${cmd(
`${getCommandName('ls --all [project]')}`
)}`
);
}
print('\n');
@@ -339,8 +348,8 @@ export default async function main(ctx) {
if (pagination && pagination.count === 20) {
const flags = getCommandFlags(argv, ['_', '--next']);
log(
`To display the next page run ${cmd(
`now ls${app ? ' ' + app : ''}${flags} --next ${pagination.next}`
`To display the next page run ${getCommandName(
`ls${app ? ' ' + app : ''}${flags} --next ${pagination.next}`
)}`
);
}

View File

@@ -10,45 +10,45 @@ import getArgs from '../util/get-args';
import error from '../util/output/error';
import highlight from '../util/output/highlight';
import ok from '../util/output/ok';
import cmd from '../util/output/cmd.ts';
import param from '../util/output/param.ts';
import eraseLines from '../util/output/erase-lines';
import sleep from '../util/sleep';
import { handleError } from '../util/error';
import { writeToAuthConfigFile, writeToConfigFile } from '../util/config/files';
import getNowDir from '../util/config/global-path';
import getGlobalPathConfig from '../util/config/global-path';
import hp from '../util/humanize-path';
import logo from '../util/output/logo';
import exit from '../util/exit';
import createOutput from '../util/output';
import executeLogin from '../util/login/login.ts';
import { prependEmoji, emoji } from '../util/emoji';
import { getCommandName, getPkgName } from '../util/pkg-name.ts';
const debug = debugFactory('now:sh:login');
const debug = debugFactory(`${getPkgName()}:login`);
const help = () => {
console.log(`
${chalk.bold(`${logo} now login`)} <email>
${chalk.bold(`${logo} ${getPkgName()} login`)} <email>
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
${chalk.dim('Examples:')}
${chalk.gray('')} Log into the Now platform
${chalk.gray('')} Log into the Vercel platform
${chalk.cyan('$ now login')}
${chalk.cyan(`$ ${getPkgName()} login`)}
${chalk.gray('')} Log in using a specific email address
${chalk.cyan('$ now login john@doe.com')}
${chalk.cyan(`$ ${getPkgName()} login john@doe.com`)}
`);
};
@@ -114,8 +114,8 @@ const readEmail = async () => {
if (err.message === 'stdin lacks setRawMode support') {
throw new Error(
error(
`Interactive mode not supported please run ${cmd(
'now login you@domain.com'
`Interactive mode not supported please run ${getCommandName(
`login you@domain.com`
)}`
)
);
@@ -248,11 +248,11 @@ const login = async ctx => {
writeToAuthConfigFile(ctx.authConfig);
writeToConfigFile(ctx.config);
output.debug(`Saved credentials in "${hp(getNowDir())}"`);
output.debug(`Saved credentials in "${hp(getGlobalPathConfig())}"`);
console.log(
`${chalk.cyan('Congratulations!')} ` +
`You are now logged in. In order to deploy something, run ${cmd('now')}.`
`You are now logged in. In order to deploy something, run ${getCommandName()}.`
);
output.print(

View File

@@ -12,26 +12,27 @@ import {
import getArgs from '../util/get-args';
import { NowContext } from '../types';
import createOutput, { Output } from '../util/output';
import { getPkgName } from '../util/pkg-name';
const help = () => {
console.log(`
${chalk.bold(`${logo} now logout`)}
${chalk.bold(`${logo} ${getPkgName()} logout`)}
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
${chalk.dim('Examples:')}
${chalk.gray('')} Logout from the CLI:
${chalk.cyan('$ now logout')}
${chalk.cyan(`$ ${getPkgName()} logout`)}
`);
};

View File

@@ -8,20 +8,21 @@ import { maybeURL, normalizeURL } from '../util/url';
import printEvents from '../util/events';
import Client from '../util/client.ts';
import getScope from '../util/get-scope.ts';
import { getPkgName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now logs`)} <url|deploymentId>
${chalk.bold(`${logo} ${getPkgName()} logs`)} <url|deploymentId>
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-f, --follow Wait for additional data [off]
-n ${chalk.bold.underline(
@@ -49,7 +50,7 @@ const help = () => {
'`deploymentId`'
)}
${chalk.cyan('$ now logs deploymentId')}
${chalk.cyan(`$ ${getPkgName()} logs deploymentId`)}
`);
};

View File

@@ -2,7 +2,6 @@ import chalk from 'chalk';
import table from 'text-table';
import mri from 'mri';
import ms from 'ms';
import plural from 'pluralize';
import strlen from '../util/strlen';
import { handleError, error } from '../util/error';
import exit from '../util/exit';
@@ -10,12 +9,16 @@ import Client from '../util/client.ts';
import logo from '../util/output/logo';
import getScope from '../util/get-scope';
import createOutput from '../util/output';
import getCommandFlags from '../util/get-command-flags';
import wait from '../util/output/wait';
import getPrefixedFlags from '../util/get-prefixed-flags';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
const e = encodeURIComponent;
const help = () => {
console.log(`
${chalk.bold(`${logo} now projects`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} projects`)} [options] <command>
${chalk.dim('Commands:')}
@@ -30,12 +33,19 @@ const help = () => {
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new project
${chalk.cyan('$ now projects add my-project')}
${chalk.cyan(`$ ${getPkgName()} projects add my-project`)}
${chalk.gray('')} Paginate projects, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${getPkgName()} projects ls --next 1584722256178`)}
`);
};
@@ -50,6 +60,7 @@ const main = async ctx => {
boolean: ['help'],
alias: {
help: 'h',
next: 'N',
},
});
@@ -111,20 +122,33 @@ async function run({ client, contextName }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now projects ls`'
`${getCommandName('projects ls')}`
)}`
)
);
return exit(1);
}
const list = await client.fetch('/v2/projects/', { method: 'GET' });
const stopSpinner = wait(`Fetching projects in ${chalk.bold(contextName)}`);
let projectsUrl = '/v4/projects/?limit=20';
if (argv.next) {
projectsUrl += `&until=${argv.next}`;
}
const { projects: list, pagination } = await client.fetch(projectsUrl, {
method: 'GET',
});
stopSpinner();
const elapsed = ms(new Date() - start);
console.log(
`> ${plural('project', list.length, true)} found under ${chalk.bold(
contextName
)} ${chalk.gray(`[${elapsed}]`)}`
`> ${
list.length > 0 ? 'Projects' : 'No projects'
} found under ${chalk.bold(contextName)} ${chalk.gray(`[${elapsed}]`)}`
);
if (list.length > 0) {
@@ -149,6 +173,19 @@ async function run({ client, contextName }) {
if (out) {
console.log(`\n${out}\n`);
}
if (pagination && pagination.count === 20) {
const prefixedArgs = getPrefixedFlags(argv);
const flags = getCommandFlags(prefixedArgs, [
'_',
'--next',
'-N',
'-d',
'-y',
]);
const nextCmd = `projects ls${flags} --next ${pagination.next}`;
console.log(`To display the next page run ${getCommandName(nextCmd)}`);
}
}
return;
}
@@ -158,7 +195,7 @@ async function run({ client, contextName }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now project rm <name>`'
`${getCommandName('project rm <name>')}`
)}`
)
);
@@ -200,13 +237,15 @@ async function run({ client, contextName }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now projects add <name>`'
`${getCommandName('projects add <name>')}`
)}`
)
);
if (args.length > 1) {
const example = chalk.cyan(`$ now projects add "${args.join(' ')}"`);
const example = chalk.cyan(
`${getCommandName(`projects add "${args.join(' ')}"`)}`
);
console.log(
`> If your project name has spaces, make sure to wrap it in quotes. Example: \n ${example} `
);

View File

@@ -7,7 +7,6 @@ import Now from '../util';
import getAliases from '../util/alias/get-aliases';
import createOutput from '../util/output';
import logo from '../util/output/logo';
import cmd from '../util/output/cmd.ts';
import elapsed from '../util/output/elapsed.ts';
import { normalizeURL } from '../util/url';
import Client from '../util/client.ts';
@@ -18,20 +17,23 @@ import removeProject from '../util/projects/remove-project';
import getProjectByIdOrName from '../util/projects/get-project-by-id-or-name';
import getDeploymentByIdOrHost from '../util/deploy/get-deployment-by-id-or-host';
import getDeploymentsByProjectId from '../util/deploy/get-deployments-by-project-id';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now remove`)} [...deploymentId|deploymentName]
${chalk.bold(
`${logo} ${getPkgName()} remove`
)} [...deploymentId|deploymentName]
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -46,17 +48,17 @@ const help = () => {
'`deploymentId`'
)}
${chalk.cyan('$ now rm deploymentId')}
${chalk.cyan(`$ ${getPkgName()} rm deploymentId`)}
${chalk.gray('')} Remove all deployments with name ${chalk.dim('`my-app`')}
${chalk.cyan('$ now rm my-app')}
${chalk.cyan(`$ ${getPkgName()} rm my-app`)}
${chalk.gray('')} Remove two deployments with IDs ${chalk.dim(
'`eyWt6zuSdeus`'
)} and ${chalk.dim('`uWHoA9RQ1d1o`')}
${chalk.cyan('$ now rm eyWt6zuSdeus uWHoA9RQ1d1o')}
${chalk.cyan(`$ ${getPkgName()} rm eyWt6zuSdeus uWHoA9RQ1d1o`)}
`);
};
@@ -91,7 +93,7 @@ export default async function main(ctx) {
}
if (ids.length < 1) {
error(`${cmd('now rm')} expects at least one argument`);
error(`${getCommandName('rm')} expects at least one argument`);
help();
return 1;
}
@@ -212,9 +214,9 @@ export default async function main(ctx) {
log(
`Could not find ${argv.safe ? 'unaliased' : 'any'} deployments ` +
`or projects matching ` +
`${ids.map(id => chalk.bold(`"${id}"`)).join(', ')}. Run ${cmd(
'now ls'
)} to list.`
`${ids
.map(id => chalk.bold(`"${id}"`))
.join(', ')}. Run ${getCommandName('ls')} to list.`
);
client.close();
return 1;

View File

@@ -35,20 +35,21 @@ import {
} from '../util/errors-ts';
import { InvalidAllForScale, InvalidRegionOrDCForScale } from '../util/errors';
import handleCertError from '../util/certs/handle-cert-error';
import { getPkgName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now scale`)} <url> <dc> [min] [max]
${chalk.bold(`${logo} ${getPkgName()} scale`)} <url> <dc> [min] [max]
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
@@ -63,25 +64,25 @@ const help = () => {
''
)} Enable your deployment in all datacenters (min: 0, max: auto)
${chalk.cyan('$ now scale my-deployment-123.now.sh all')}
${chalk.cyan(`$ ${getPkgName()} scale my-deployment-123.now.sh all`)}
${chalk.gray(
'-'
)} Enable your deployment in the SFO datacenter (min: 0, max: auto)
${chalk.cyan('$ now scale my-deployment-123.now.sh sfo')}
${chalk.cyan(`$ ${getPkgName()} scale my-deployment-123.now.sh sfo`)}
${chalk.gray(
''
)} Scale a deployment in all datacenters to 3 instances at all times (no sleep)
${chalk.cyan('$ now scale my-deployment-123.now.sh all 3')}
${chalk.cyan(`$ ${getPkgName()} scale my-deployment-123.now.sh all 3`)}
${chalk.gray(
''
)} Enable your deployment in all datacenters, with auto-scaling
${chalk.cyan('$ now scale my-deployment-123.now.sh all auto')}
${chalk.cyan(`$ ${getPkgName()} scale my-deployment-123.now.sh all auto`)}
`);
};
@@ -133,9 +134,9 @@ export default async function main(ctx) {
// Fail if the user is providing an old command
if (argv._[1] === 'ls') {
output.error(
`${cmd('now scale ls')} has been deprecated. Use ${cmd(
`${cmd(`${getPkgName()} scale ls`)} has been deprecated. Use ${cmd(
'now ls'
)} and ${cmd('now inspect <url>')}`
)} and ${cmd(`${getPkgName()} inspect <url>`)}`
);
now.close();
return 1;
@@ -145,7 +146,7 @@ export default async function main(ctx) {
if (argv._.length < 3 || argv._.length > 5) {
output.error(
`${cmd(
'now scale <url> <dc> [min] [max]'
`${getPkgName()} scale <url> <dc> [min] [max]`
)} expects at least two arguments`
);
help();

View File

@@ -12,11 +12,12 @@ import getScope from '../util/get-scope.ts';
import createOutput from '../util/output';
import confirm from '../util/input/confirm';
import getCommandFlags from '../util/get-command-flags';
import cmd from '../util/output/cmd.ts';
import getPrefixedFlags from '../util/get-prefixed-flags';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now secrets`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} secrets`)} [options] <command>
${chalk.dim('Commands:')}
@@ -30,10 +31,10 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -45,7 +46,7 @@ const help = () => {
${chalk.gray('')} Add a new secret
${chalk.cyan('$ now secrets add my-secret "my value"')}
${chalk.cyan(`$ ${getPkgName()} secrets add my-secret "my value"`)}
${chalk.gray(
''
@@ -61,13 +62,13 @@ const help = () => {
'`@`'
)} symbol)
${chalk.cyan(`$ now -e MY_SECRET=${chalk.bold('@my-secret')}`)}
${chalk.cyan(`$ ${getPkgName()} -e MY_SECRET=${chalk.bold('@my-secret')}`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ now secrets ls --next 1584722256178`)}
${chalk.cyan(`$ ${getPkgName()} secrets ls --next 1584722256178`)}
`);
};
@@ -146,7 +147,9 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
if (args.length > 1) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan('`now secret ls`')}`
`Invalid number of arguments. Usage: ${chalk.cyan(
`${getCommandName('secret ls')}`
)}`
)
);
return exit(1);
@@ -193,8 +196,8 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
'-d',
'-y',
]);
const nextCmd = `now secrets ${subcommand}${flags} --next ${pagination.next}`;
output.log(`To display the next page run ${cmd(nextCmd)}`);
const nextCmd = `secrets ${subcommand}${flags} --next ${pagination.next}`;
output.log(`To display the next page run ${getCommandName(nextCmd)}`);
}
return secrets.close();
}
@@ -204,7 +207,7 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now secret rm <name>`'
`${getCommandName('secret rm <name>')}`
)}`
)
);
@@ -246,7 +249,7 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now secret rename <old-name> <new-name>`'
`${getCommandName('secret rename <old-name> <new-name>')}`
)}`
)
);
@@ -269,13 +272,15 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
console.error(
error(
`Invalid number of arguments. Usage: ${chalk.cyan(
'`now secret add <name> <value>`'
`${getCommandName('secret add <name> <value>')}`
)}`
)
);
if (args.length > 2) {
const example = chalk.cyan(`$ now secret add -- "${args[0]}"`);
const example = chalk.cyan(
`$ ${getCommandName('secret add -- "${args[0]}"')}`
);
console.log(
`If your secret has spaces or starts with '-', make sure to terminate command options with double dash and wrap it in quotes. Example: \n ${example} `
);
@@ -299,7 +304,9 @@ async function run({ output, token, contextName, currentTeam, ctx }) {
}
if (typeof value === 'boolean') {
const example = chalk.cyan(`$ now secret add -- "${name}"`);
const example = chalk.cyan(
`$ ${getCommandName('secret add -- "${name}"')}`
);
console.log(
`If your secret starts with '-', make sure to terminate command options with double dash and wrap it in quotes. Example: \n ${example} `
);
@@ -349,28 +356,3 @@ async function readConfirmation(output, secret, contextName) {
return confirm(`${chalk.bold.red('Are you sure?')}`, false);
}
/**
* This function adds a prefix `-` or `--` to the flags
* passed from the command line, because the package `mri`
* used to extract the args removes them for some reason.
*/
function getPrefixedFlags(args) {
const prefixedArgs = {};
for (const arg in args) {
if (arg === '_') {
prefixedArgs[arg] = argv[arg];
} else {
let prefix = '-';
// Full form flags need two dashes, whereas one letter
// flags need only one.
if (arg.length > 1) {
prefix = '--';
}
prefixedArgs[`${prefix}${arg}`] = argv[arg];
}
}
return prefixedArgs;
}

View File

@@ -9,10 +9,11 @@ import list from './teams/list';
import add from './teams/add';
import change from './teams/switch';
import invite from './teams/invite';
import { getPkgName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now teams`)} [options] <command>
${chalk.bold(`${logo} ${getPkgName()} teams`)} [options] <command>
${chalk.dim('Commands:')}
@@ -26,17 +27,18 @@ const help = () => {
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Switch to a team
${chalk.cyan(`$ now switch <slug>`)}
${chalk.cyan(`$ ${getPkgName()} switch <slug>`)}
${chalk.gray(
''
@@ -49,7 +51,13 @@ const help = () => {
${chalk.gray('')} Invite new members (interactively)
${chalk.cyan(`$ now teams invite`)}
${chalk.cyan(`$ ${getPkgName()} teams invite`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${getPkgName()} teams ls --next 1584722256178`)}
`);
};
@@ -64,8 +72,9 @@ const main = async ctx => {
alias: {
help: 'h',
debug: 'd',
switch: 'change'
}
switch: 'change',
next: 'N',
},
});
debug = argv.debug;
@@ -86,7 +95,10 @@ const main = async ctx => {
await exit(0);
}
const { authConfig: { token }, config } = ctx;
const {
authConfig: { token },
config,
} = ctx;
return run({ token, config });
};
@@ -113,7 +125,8 @@ async function run({ token, config }) {
teams,
config,
apiUrl,
token
token,
argv,
});
break;
}
@@ -124,7 +137,7 @@ async function run({ token, config }) {
config,
apiUrl,
token,
debug
debug,
});
break;
}
@@ -140,7 +153,7 @@ async function run({ token, config }) {
args,
config,
apiUrl,
token
token,
});
break;
}

View File

@@ -7,11 +7,11 @@ import rightPad from '../../util/output/right-pad';
import eraseLines from '../../util/output/erase-lines';
import chars from '../../util/output/chars';
import success from '../../util/output/success';
import cmd from '../../util/output/cmd.ts';
import note from '../../util/output/note';
import textInput from '../../util/input/text';
import invite from './invite';
import { writeToConfigFile } from '../../util/config/files';
import { getPkgName, getCommandName } from '../../util/pkg-name.ts';
const validateSlugKeypress = (data, value) =>
// TODO: the `value` here should contain the current value + the keypress
@@ -26,8 +26,8 @@ const validateNameKeypress = (data, value) =>
const gracefulExit = () => {
console.log(); // Blank line
note(
`Your team is now active for all ${cmd('now')} commands!\n Run ${cmd(
'now switch'
`Your team is now active for all ${getPkgName()} commands!\n Run ${getCommandName(
`switch`
)} to change it in the future.`
);
return 0;
@@ -151,8 +151,8 @@ export default async function({ apiUrl, token, teams, config }) {
apiUrl,
config,
introMsg: 'Invite your teammates! When done, press enter on an empty field',
noopMsg: `You can invite teammates later by running ${cmd(
'now teams invite'
noopMsg: `You can invite teammates later by running ${getCommandName(
`teams invite`
)}`,
});

View File

@@ -14,6 +14,7 @@ import eraseLines from '../../util/output/erase-lines';
import success from '../../util/output/success';
import getUser from '../../util/get-user.ts';
import Client from '../../util/client.ts';
import { getCommandName } from '../../util/pkg-name.ts';
const validateEmail = data => regexEmail.test(data.trim()) || data.length === 0;
@@ -96,9 +97,9 @@ export default async function({
// We specifically need a team scope here
let err = `You can't run this command under ${param(
user.username || user.email
)}.\nPlease select a team scope using ${cmd('now switch')} or use ${cmd(
'--scope'
)}`;
)}.\nPlease select a team scope using ${getCommandName(
`switch`
)} or use ${cmd('--scope')}`;
return fatalError(err);
}

View File

@@ -8,12 +8,28 @@ import info from '../../util/output/info';
import error from '../../util/output/error';
import chars from '../../util/output/chars';
import table from '../../util/output/table';
import createOutput from '../../util/output';
import getUser from '../../util/get-user.ts';
import Client from '../../util/client.ts';
import getPrefixedFlags from '../../util/get-prefixed-flags';
import { getPkgName } from '../../util/pkg-name.ts';
import getCommandFlags from '../../util/get-command-flags';
import cmd from '../../util/output/cmd.ts';
export default async function({ teams, config, apiUrl, token, argv }) {
const { next } = argv;
const output = createOutput({ debug: argv['--debug'] });
if (typeof next !== 'undefined' && !Number.isInteger(next)) {
output.error('Please provide a number for flag --next');
return 1;
}
export default async function({ teams, config, apiUrl, token }) {
const stopSpinner = wait('Fetching teams');
const list = (await teams.ls()).teams;
const { teams: list, pagination } = await teams.ls({
next,
apiVersion: 2,
});
let { currentTeam } = config;
const accountIsCurrent = !currentTeam;
@@ -78,4 +94,14 @@ export default async function({ teams, config, apiUrl, token }) {
teamList.map(team => [team.current, team.value, team.name]),
[1, 5]
);
if (pagination && pagination.count === 20) {
const prefixedArgs = getPrefixedFlags(argv);
const flags = getCommandFlags(prefixedArgs, ['_', '--next', '-N', '-d']);
const nextCmd = `${getPkgName()} teams ls${flags} --next ${
pagination.next
}`;
console.log(); // empty line
output.log(`To display the next page run ${cmd(nextCmd)}`);
}
}

View File

@@ -7,10 +7,11 @@ import getArgs from '../util/get-args';
import { NowContext } from '../types';
import createOutput from '../util/output';
import getUpdateCommand from '../util/get-update-command';
import { getPkgName, getTitleName } from '../util/pkg-name';
const help = () => {
console.log(`
${chalk.bold(`${logo} now update`)} [options]
${chalk.bold(`${logo} ${getPkgName()} update`)} [options]
${chalk.dim('Options:')}
@@ -26,9 +27,9 @@ const help = () => {
${chalk.dim('Examples:')}
${chalk.gray('')} Update Now CLI to the latest "canary" version
${chalk.gray('')} Update ${getTitleName()} CLI to the latest "canary" version
${chalk.cyan(`$ now update --channel=canary`)}
${chalk.cyan(`$ ${getPkgName()} update --channel=canary`)}
`);
};
@@ -42,7 +43,7 @@ export default async function main(ctx: NowContext): Promise<number> {
'--release': String,
'-V': '--release',
'--yes': Boolean,
'-y': '--yes'
'-y': '--yes',
});
} catch (err) {
handleError(err);
@@ -56,6 +57,10 @@ export default async function main(ctx: NowContext): Promise<number> {
const debugEnabled = argv['--debug'];
const output = createOutput({ debug: debugEnabled });
output.log(`Please run ${cmd(await getUpdateCommand())} to update Now CLI`);
output.log(
`Please run ${cmd(
await getUpdateCommand()
)} to update ${getTitleName()} CLI`
);
return 0;
}

View File

@@ -5,20 +5,21 @@ import { handleError } from '../util/error';
import Client from '../util/client.ts';
import getScope from '../util/get-scope.ts';
import createOutput from '../util/output';
import { getPkgName } from '../util/pkg-name.ts';
const help = () => {
console.log(`
${chalk.bold(`${logo} now whoami`)}
${chalk.bold(`${logo} ${getPkgName()} whoami`)}
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`now.json`'} file
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.now`'} directory
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
@@ -28,7 +29,7 @@ const help = () => {
${chalk.gray('')} Shows the username of the currently logged in user
${chalk.cyan('$ now whoami')}
${chalk.cyan(`$ ${getPkgName()} whoami`)}
`);
};

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