Compare commits

..

70 Commits

Author SHA1 Message Date
JJ Kasper
8f7c2f6385 Publish Canary
- @vercel/build-utils@2.11.2-canary.5
 - vercel@23.0.2-canary.10
 - @vercel/client@10.1.2-canary.6
 - @vercel/frameworks@0.4.2-canary.4
 - @vercel/routing-utils@1.11.3-canary.1
2021-07-26 13:02:53 -05:00
JJ Kasper
232f55df22 Fix has segment validation in destination (#6521)
This ensures we validate segments being used from `has` in the `destination` correctly

### Related Issues

x-ref: https://vercel.slack.com/archives/CLDDX2Y0G/p1627285500281300

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-07-26 17:22:27 +00:00
Lee Robinson
43d365c73d Publish Canary
- @vercel/build-utils@2.11.2-canary.4
 - vercel@23.0.2-canary.9
 - @vercel/client@10.1.2-canary.5
 - @vercel/frameworks@0.4.2-canary.3
2021-07-23 09:21:24 -05:00
Lee Robinson
8950cd9685 [frameworks][examples] Add support for zero-config SvelteKit (#6482)
While we already have support for [SvelteKit](https://sveltekit-delta.vercel.app) on Vercel with the [File System API](https://vercel.com/docs/more/adding-your-framework), this makes the Svelte logo show up and adds an example. I also updated the Svelte example to match their default template and guide the user to use SvelteKit if they want functions.

https://sveltekit.examples.vercel.com
2021-07-23 14:17:22 +00:00
Nathan Rajlich
868fc6159c Publish Canary
- vercel@23.0.2-canary.8
2021-07-22 17:33:30 -07:00
Nathan Rajlich
7cadbc3989 [cli] Add request counter to --debug logs (#6510)
Follow up to #6508. Adds a request "counter" that increments for every API request, matching how `front` does it.

Also tweaks the `output.time()` output a bit by rendering the timestamp in gray, and with `[]` brackets. If the time diff is < 1000ms then the full milliseconds will be printed intstead of the seconds.

<img width="710" alt="Screen Shot 2021-07-22 at 2 45 39 PM" src="https://user-images.githubusercontent.com/71256/126713843-db70ed9c-4752-4ca9-8f54-313c4cb44914.png">
2021-07-22 22:36:01 +00:00
Kaitlyn
89553e6015 [cli] Add "x-vercel-id" response header to --debug logs (#6508) 2021-07-22 14:26:21 -07:00
Nathan Rajlich
181f1d60b6 [cli] Allow dynamic label in output.time() function (#6492)
Updates the `output.time()` function to accept a function as the "label" parameter. When a function is passed, it will be invoked twice, once at the beginning of the promise being executed, and a second time after the promise has resolved. The second time, the return value of the promise is passed to the label function, so that the resolved value may be used to create the label.

Drops usage of Node's `console.time()` and `console.timeEnd()` since we were using it in a hacky and unnecessary way.
2021-07-19 20:48:02 +00:00
Nathan Rajlich
8cc72a6872 [cli] Remove "now" from variable names in vc dev (#6483) 2021-07-19 10:32:21 -07:00
Nathan Rajlich
e37e558674 Publish Canary
- vercel@23.0.2-canary.7
2021-07-16 09:35:15 -07:00
Markoz Peña
e0a62dabaa [cli] Convert vc ls and vc rm commands to TypeScript (#6460) 2021-07-15 01:33:15 -07:00
Nathan Rajlich
c23473df49 [cli] Handle the ssoUserId being pasted in "out-of-band" login mode (#6476)
Handles the edge case where a SAML login is executed for an unconnected user, so they have to complete a two-step login.
2021-07-14 18:58:36 +00:00
Nathan Rajlich
0569b268e6 [cli] Add "Local Development" section to README (#6472)
Adds a section to the CLI readme explaining how to check out the source code and use `ts-eager` for local development.
2021-07-14 07:24:57 +00:00
ernestd
db955473d9 Add billing to list of commands (#6471) 2021-07-13 14:15:56 -04:00
Steven
311ef26f60 Publish Canary
- @vercel/build-utils@2.11.2-canary.3
 - vercel@23.0.2-canary.6
 - @vercel/client@10.1.2-canary.4
 - @vercel/frameworks@0.4.2-canary.2
2021-07-13 12:34:37 -04:00
Stephanie Dietz
c08462a46b [examples][frameworks] Add support for vite (#6445)
Co-authored-by: Lee Robinson <me@leerob.io>
Co-authored-by: Steven <steven@ceriously.com>
2021-07-13 12:33:57 -04:00
Nathan Rajlich
24b2f16afb Publish Canary
- vercel@23.0.2-canary.5
 - @vercel/client@10.1.2-canary.3
2021-07-12 15:00:14 -07:00
Nathan Rajlich
919c667ff1 [cli] Add "out-of-band" mode to vc login (#6455)
Adds an "out-of-band" login mode to the `vc login` command, for use in headless environments like inside a Docker container or an SSH session. In these situations, spawning a localhost HTTP server won't work, because the HTTP server will not be accessible to the web browser that is doing the authentication.

In "out-of-band" mode, the login URL is simply presented to the user, and they must visit the login URL in their web browser and complete the authentication. The callback URL is a page on front that shows the verification token to the user and instructs them to copy + paste the token back into the CLI, at which point the login can complete.

Docker/SSH sessions are attempted to be automatically detected, and "out-of-band" mode is enabled implicitly. But there is also an `--oob` flag in case that detection logic were to fail (or if you'd like to run OOB mode locally).

This PR also adds shortcut flags for the Git provider login mechanisms, i.e. `vc login --github`.


https://user-images.githubusercontent.com/71256/125129304-1f5f3380-e0b4-11eb-8139-d1109811bd86.mov
2021-07-12 20:29:54 +00:00
Mark Glagola
ab3f99bfea [cli][client] Printable link from deployment.aliasWarning (#6454)
* Ability to print `links` from `aliasWarning`

* Update latest.ts

* Add link style
2021-07-08 18:58:22 -05:00
Markoz Peña
a8615d3c34 [cli] Convert vc projects to TypeScript (#6452) 2021-07-08 14:46:37 -07:00
Nathan Rajlich
0a09a5232c Publish Canary
- vercel@23.0.2-canary.4
 - @vercel/node-bridge@2.0.1-canary.2
 - @vercel/node@1.11.2-canary.4
2021-07-07 19:35:35 -07:00
Nathan Rajlich
f3190b7f74 [node] Use require() when source is TypeScript in vc dev (#6448) 2021-07-07 19:33:45 -07:00
JJ Kasper
cf827a8b91 Publish Canary
- @vercel/build-utils@2.11.2-canary.2
 - vercel@23.0.2-canary.3
 - @vercel/client@10.1.2-canary.2
 - @vercel/frameworks@0.4.2-canary.1
 - @vercel/go@1.2.3-canary.0
 - @vercel/node-bridge@2.0.1-canary.1
 - @vercel/node@1.11.2-canary.3
 - @vercel/python@2.0.5-canary.0
 - @vercel/routing-utils@1.11.3-canary.0
 - @vercel/ruby@1.2.7-canary.0
2021-07-06 22:43:13 -05:00
Steven
bed83e829c [routing-utils] Fix rewrites with query string array in destination (#6441)
Related to https://github.com/vercel/next.js/pull/26619
2021-07-06 22:24:40 +00:00
Markoz Peña
0f0ee4e845 [cli] Convert vc whoami to TypeScript (#6435) 2021-07-06 15:10:00 -04:00
Steven
2d70c6c811 [test] Update publish-canary script (#6432) 2021-07-02 11:54:53 -04:00
Nathan Rajlich
887309f0a5 [cli] Convert vc deploy to TypeScript (#6413)
This is a continuation of https://github.com/vercel/vercel/pull/6382 (thank you @markozxuu!) with merge conflicts addressed and pushed to a local branch, so that CI tests run.
2021-06-30 18:26:29 +00:00
Nathan Rajlich
8a7657c80b [cli] Use output.spinner() instead of wait() (#6414) 2021-06-29 18:48:50 -07:00
Nathan Rajlich
279d0bf988 [cli] Set current scope to proper team after SSO login (#6415) 2021-06-29 16:42:40 -07:00
Nathan Rajlich
d2b31d03da [cli] Use Client instead of LoginParams for login (#6409)
* [cli] Use `Client` instead of `LoginParams`

* Use `client.fetch()`

* Fix email verify

* Remove redundant "user-agent" header

* Fix test
2021-06-29 01:48:36 -07:00
Nathan Rajlich
16acf906fc Update to TypeScript 4.3.4 (#6397)
Also updates eslint and related packages to work with the new TypeScript version.
2021-06-25 23:45:53 +00:00
Nathan Rajlich
0127d17703 Fix Ruby E2E tests (#6401)
Currently the `06-rails` test is failing at build time with:

```
16:27:09.550  	    'Your bundle is locked to mimemagic (0.3.3) from rubygems repository\n' +
16:27:09.550  	    'https://rubygems.org/ or installed locally, but that version can no longer be\n' +
16:27:09.550  	    'found in that source. That means the author of mimemagic (0.3.3) has removed it.\n' +
16:27:09.550  	    "You'll need to update your bundle to a version other than mimemagic (0.3.3) that\n" +
16:27:09.550  	    "hasn't been removed in order to install.",
```

So I ran `bundler update` in the "06-rails" Ruby test fixture to update the deps in the Gemfile.lock file.
2021-06-25 14:41:52 -07:00
Steven
0bfc2a3693 Publish Canary
- @vercel/build-utils@2.11.2-canary.1
 - vercel@23.0.2-canary.2
 - @vercel/client@10.1.2-canary.1
 - @vercel/frameworks@0.4.2-canary.0
 - @vercel/node@1.11.2-canary.2
2021-06-25 11:22:56 -04:00
Steven
b9809b140c [node] Fix ESM when package.json type: module (#6399)
* [node] Fix ESM when package.json `type: module`

* Fix cjs and add test fixture
2021-06-25 11:14:05 -04:00
Steven
faaccc1f9f [frameworks] Add missing cachePattern to Next.js (#6396) 2021-06-24 15:31:16 -04:00
Nathan Rajlich
4b61f1dd61 [cli] Set proper currentTeam in vc deploy (#6394)
Fixes an edge case bug when the user has a current scope that is
different than the owner of the project that is being deployed.

When this was the case, the API call to get the certs for a domain at
the end of the `vc deploy` command was using the incorrect `teamId`,
potentially causing a 403 error (when the current auth token does not
have access to the selected scope).
2021-06-24 12:06:27 -07:00
Steven
cdd417455f [frameworks] Add cachePattern to API response (#6395) 2021-06-24 14:44:38 -04:00
Leonardo Merlin
fe671f56c5 chore(examples): update nuxtjs (#6383)
* chore: update nuxtjs example

* fix: remove @nuxtjs/pwa

Co-authored-by: Leonardo Merlin <lmerlin@schubergphilis.com>
2021-06-23 19:19:04 -07:00
Nathan Rajlich
ddf9e6cf3f [cli] Make vc deploy not load current "scope" (#6388)
`vc deploy` doesn't care about the current "scope" that the CLI has selected, since it uses the `.vercel` directory to determine the ownerId and projectId.

Therefore, it should not be fetching the team details of the selected scope during `vc deploy`, since it's possible that the token might not have access to the current scope and returns a 403, even though that API call is unnecessary for the `vc deploy` command to complete.
2021-06-23 12:32:43 -07:00
Steven
13b03c6abd Publish Canary
- @vercel/build-utils@2.11.2-canary.0
 - vercel@23.0.2-canary.1
 - @vercel/client@10.1.2-canary.0
 - @vercel/node@1.11.2-canary.1
2021-06-23 10:54:17 -04:00
Steven
7dd4c629ad [node] Add support for ESM to vc dev (#6385)
Follow up to #6121
2021-06-23 14:48:47 +00:00
Nathan Rajlich
81b3d7f5f1 [cli] Fix vc login hanging for a few seconds before exiting (#6387)
Closing keep-alive HTTP connections was causing the `server.close()` call
to take a few seconds before completing, so set the `Connection: close`
response header in order to make the connections close immediately,
so that `server.close()` is fast.
2021-06-22 20:57:15 -07:00
Steven
3566c32209 [build-utils] Add support for .mjs with zero config (#6386)
Follow up to #6121
2021-06-23 02:21:16 +00:00
Nathan Rajlich
267ca7b379 [cli] Print timestamp for each line for multi-line log entries (#6384) 2021-06-22 16:46:03 -07:00
Steven
7b9d9954b8 Publish Canary
- vercel@23.0.2-canary.0
 - @vercel/node-bridge@2.0.1-canary.0
 - @vercel/node@1.11.2-canary.0
2021-06-22 15:46:21 -04:00
Steven
79675db241 [node][node-bridge] Add support for ESM (#6121) 2021-06-22 15:44:30 -04:00
Nathan Rajlich
3ac8a3f67f [cli] Make vercel dev command exit quickly (#6365)
Considering that it's a development environment, it's not important to wait for ongoing HTTP request connections to complete. Sometimes it takes a long time for all the shutdown operations to complete, which makes the command feel sluggish. So let's just `process.exit()` and exit quickly.
2021-06-18 23:33:37 +00:00
Nathan Rajlich
2f19949133 [cli] Finish executing the original command after login with no credentials (#6364) 2021-06-18 13:10:30 -07:00
Paco
85fd2aed7e Update Next.js example favicon (#6367) 2021-06-18 12:35:01 -07:00
Steven
e659eecf48 Publish Stable
- @vercel/build-utils@2.11.1
 - vercel@23.0.1
 - @vercel/client@10.1.1
 - @vercel/frameworks@0.4.1
 - @vercel/node@1.11.1
 - @vercel/python@2.0.4
 - @vercel/routing-utils@1.11.2
2021-06-15 17:29:53 -04:00
Steven
b428f7ff83 Publish Canary
- vercel@23.0.1-canary.4
2021-06-15 16:37:28 -04:00
Nathan Rajlich
5eb133283d Remove utils/go (#6362)
This code now lives in its own repository, so the code in this repo is not being used.

https://github.com/vercel/go-bridge
2021-06-15 12:49:18 +00:00
Nathan Rajlich
646c29600e [cgi] Remove @vercel/cgi Runtime (#6361)
This Runtime is very old, outdated, unmaintained, and has never been documented.

Additionally, it no longer compiles with the latest version of Go. So
rather than fixing it, let's just remove it since we don't want to
invest any more time into it.
2021-06-14 20:49:05 -07:00
Nathan Rajlich
469eb4315d [cli] Update "open" to v8.2.0 (#6348)
Fixes an issue where the bundled `xdg-open` script would not be used.
2021-06-10 19:14:57 -07:00
JJ Kasper
6dc54d0d64 Publish Canary
- @vercel/build-utils@2.11.1-canary.1
 - vercel@23.0.1-canary.3
 - @vercel/client@10.1.1-canary.1
 - @vercel/frameworks@0.4.1-canary.1
 - @vercel/routing-utils@1.11.2-canary.1
2021-06-08 11:38:01 -05:00
JJ Kasper
adc84d5148 Fix check: true beforeFiles order (#6337) 2021-06-08 11:35:31 -05:00
Nathan Rajlich
88642b1ce8 [cli] Print login URL to terminal (#6336)
In some cases (i.e. when SSH'd to a remote machine) the `open` command will not work reliably. So we need to print the URL to the user as a fallback for those cases when the web browser is not automatically opened.

This also moves where `tokenName` is specified to be in the "verify" endpoint, so that it does not need to be part of the URL that gets printed to the user.

<img width="738" alt="Screen Shot 2021-06-07 at 2 12 47 PM" src="https://user-images.githubusercontent.com/71256/121089239-b5452d00-c79b-11eb-85b2-0e45b817dff0.png">
2021-06-07 22:13:58 +00:00
Steven
4b8d207533 [cli] Warn when vercel.json uses has (#6327) 2021-06-07 14:45:36 -04:00
Steven
36fe5cc4d1 [test] Fix corrupt bmp test (#6328) 2021-06-07 09:31:51 -04:00
JJ Kasper
370b0dbed2 Publish Canary
- vercel@23.0.1-canary.2
 - @vercel/node@1.11.1-canary.0
2021-06-06 15:24:50 -05:00
JJ Kasper
cc7a82fb0a [node] Update nft to 0.13.1 (#6333) 2021-06-06 16:22:56 -04:00
Markoz Peña
6eea26c39e [cli] Convert vc alias to TS (#6325)
* refactor: Remove unncessary file

* feat(cli/alias): Migration to TS

* refactor(cli/alias): Add a line break

* refactor(cli/alias): Remove unnecesary code

* feat(cli): Add `Paginationoptions` type to `pagination`

* feat(cli/commands): Rewrite th `alias ls` command to TS

* refactor: Remove unncessary code

* feat: Create helper function for `getSafeAlias`

* refactor: Remove unnecessary code

* feat: Remove parameter generic, "null" for the fetch

* feat(cli/alias): Rewritten in full TS

* feat: Add Partial to opts

* refactor: Remove comment @ts-ignore

* feat: Add Partial to opts

* feat: Only should be return `alias.uid`

* refactor: Remove `Alias` type from of the parameter `id`

* refactor: Remove destructuring from alias object

* refactor: Remove unnecessary code

* feat: Rename `created` property to `createdAt` of number type

* refactor: Move getSafeAlias function in the same file

* refactor: Simplifying code

* refactor: Intentation did not affect diff on git

* Add null back to type

Co-authored-by: Steven <steven@ceriously.com>
2021-06-04 16:43:39 -04:00
Nathan Rajlich
b8bfae7840 [cli] Fix vc logout command when using Team scope (#6322)
Fixes logout command not working when switched to a Team scope:

```
$ vc login
$ vc switch $some_team
$ vc logout
Failed during logout
```
2021-06-04 19:48:03 +00:00
Nathan Rajlich
dc6a0a1cbb [cli] Upgrade token scopes in vc switch command (#6323)
Pass the `Authorization` request header to the verify endpoint so that the current auth token will be upgraded with the new scope.

[ch22273]
2021-06-04 18:33:49 +00:00
Steven
a6807c9d21 Publish Canary
- vercel@23.0.1-canary.1
 - @vercel/python@2.0.4-canary.0
2021-06-01 14:35:09 -04:00
Steven
c628090d08 [cli] Fix vc projects rm race condition (#6306)
The call to `GET /projects/info` is used to check existence but it can cause a race condition if the project was removed before the `DELETE /v2/projects` is called.

Instead, we rely on the response from `DELETE /v2/projects` to determine if the project exists or not.

This will also allow us to remove a legacy API endpoint in the future (see related API PR)
2021-06-01 18:31:20 +00:00
Hydrophobefireman
4e0b291ed1 [python] Remove imports from werkzeug._compat (#6283) 2021-06-01 09:15:06 -04:00
JJ Kasper
ee0bc9b0c8 Publish Canary
- @vercel/build-utils@2.11.1-canary.0
 - vercel@23.0.1-canary.0
 - @vercel/client@10.1.1-canary.0
 - @vercel/frameworks@0.4.1-canary.0
 - @vercel/routing-utils@1.11.2-canary.0
2021-05-26 13:44:39 -05:00
JJ Kasper
e516c1f49f Ensure beforeFiles rewrites come after redirects when continuing (#6289) 2021-05-26 12:50:51 -05:00
JJ Kasper
01f53f36fc [routing-utils] Ensure header key value casing is normalized (#6284)
This ensures we normalize header `key` values in `has` items to be lower-case as the proxy currently only matches against the lower-case variant. Updated superstatic tests to ensure the header key is normalized correctly. 

### Related Issues

[related thread](https://vercel.slack.com/archives/C01N3RWTE5V/p1621937306006400)

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-05-25 22:46:28 +00:00
187 changed files with 5218 additions and 4083 deletions

View File

@@ -1,14 +1,7 @@
node_modules
dist
examples
# gatsby-plugin-now
packages/gatsby-plugin-now/test/fixtures
# build-utils
packages/build-utils/test/fixtures
# cli
packages/cli/@types
packages/cli/download
packages/cli/dist
@@ -17,24 +10,9 @@ packages/cli/test/dev/fixtures
packages/cli/bin
packages/cli/link
packages/cli/src/util/dev/templates/*.ts
# client
packages/client/tests/fixtures
packages/client/lib
# next
packages/next/test/fixtures
# node
packages/node/src/bridge.ts
packages/node/test/fixtures
# node-bridge
packages/node-bridge/bridge.*
# static-build
packages/static-build/test/fixtures
packages/static-build/test/build-fixtures
# redwood
packages/redwood/test/fixtures
packages/node-bridge/bridge.js
packages/node-bridge/launcher.js

View File

@@ -14,7 +14,6 @@ const frameworks = (_frameworks as Framework[])
sort: undefined,
dependency: undefined,
defaultRoutes: undefined,
cachePattern: undefined,
devCommand: undefined,
buildCommand: undefined,
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -80,11 +80,15 @@ dist
# IDE / Editor
.idea
.editorconfig
# Service worker
sw.*
# Mac OSX
# macOS
.DS_Store
# Vim swap files
*.swp
# Vercel
.vercel

View File

@@ -1 +1,4 @@
README.md
.nuxt
node_modules
*.log

View File

@@ -8,7 +8,7 @@ Deploy your own Nuxt.js project with Vercel.
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/vercel/tree/main/examples/nuxtjs)
_Live Example: https://nuxtjs.now-examples.now.sh_
_Live Example: https://nuxtjs.now-examples.vercel.app/_
### How We Created This Example
@@ -17,5 +17,3 @@ To get started with Nuxt.js deployed with Vercel, you can use the [Create-Nuxt-A
```shell
$ npx create-nuxt-app my-app
```
> The only change made is to amend the output directory in `nuxt.config.js` to `"/public"`.

View File

@@ -1,44 +1,37 @@
export default {
mode: 'spa',
/*
** Headers of the page
*/
// Target: https://go.nuxtjs.dev/config-target
target: 'static',
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: process.env.npm_package_name || '',
title: 'nuxtjs',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || '',
content: 'My astonishing Nuxt.js project',
},
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
/*
** Plugins to load before mounting the App
*/
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [],
/*
** Nuxt.js modules
*/
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [],
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {},
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {}
};

View File

@@ -10,9 +10,8 @@
"start": "nuxt start"
},
"dependencies": {
"nuxt": "^2.0.0"
"core-js": "^3.15.0",
"nuxt": "^2.15.7"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
"devDependencies": {}
}

View File

@@ -12,6 +12,7 @@
<a
href="https://nuxtjs.org/"
target="_blank"
rel="noopener"
class="button--green"
>
Documentation
@@ -19,6 +20,7 @@
<a
href="https://github.com/nuxt/nuxt.js"
target="_blank"
rel="noopener"
class="button--grey"
>
GitHub

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,24 @@
# Svelte Example
This directory is a brief example of a [Svelte](https://svelte.dev/) app with [Serverless Functions](https://vercel.com/docs/v2/serverless-functions/introduction) that can be deployed with Vercel and zero configuration.
This directory is a brief example of a [Svelte](https://svelte.dev/) site that can be deployed with Vercel and zero-configuration. If you need to use API Routes, we recommend using our [SvelteKit example](https://github.com/vercel/vercel/tree/main/examples/sveltekit).
## Deploy Your Own
Deploy your own Svelte project, along with Serverless Functions, with Vercel.
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/vercel/tree/main/examples/svelte)
_Live Example: https://svelte.now-examples.now.sh_
_Live Example: https://svelte.examples.vercel.com_
### How We Created This Example
## Getting Started
To get started with Svelte, along with [Serverless Functions](https://vercel.com/docs/v2/serverless-functions/introduction), deployed with Vercel, you can use [degit](https://github.com/Rich-Harris/degit) to initialize the project:
```shell
$ npx degit sveltejs/template my-svelte-project
```bash
npx degit sveltejs/template svelte-app
npm install
```
Then, start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.

View File

@@ -1,4 +0,0 @@
module.exports = (req, res) => {
const date = new Date().toString();
res.status(200).send(date);
};

View File

@@ -1,17 +1,19 @@
{
"name": "svelte-app",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public"
"start": "sirv public --no-clear"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^14.0.0",
"@rollup/plugin-node-resolve": "^8.0.0",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^6.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0"
},

View File

@@ -1,44 +1,63 @@
main {
align-content: center;
box-sizing: border-box;
display: grid;
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', 'Helvetica',
'Arial', sans-serif;
hyphens: auto;
line-height: 1.65;
margin: 0 auto;
max-width: 680px;
min-height: 100vh;
padding: 72px 0;
text-align: center;
html, body {
position: relative;
width: 100%;
height: 100%;
}
h1 {
font-size: 45px;
}
h2 {
margin-top: 1.5em;
}
p {
font-size: 16px;
body {
color: #333;
margin: 0;
padding: 8px;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
a {
border-bottom: 1px solid white;
color: #0076ff;
cursor: pointer;
text-decoration: none;
transition: all 0.2s ease;
color: rgb(0,100,200);
text-decoration: none;
}
a:hover {
border-bottom: 1px solid #0076ff;
text-decoration: underline;
}
code,
pre {
color: #d400ff;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace, serif;
font-size: 0.92em;
a:visited {
color: rgb(0,80,160);
}
code:before,
code:after {
content: '\`';
label {
display: block;
}
input, button, select, textarea {
font-family: inherit;
font-size: inherit;
-webkit-padding: 0.4em 0;
padding: 0.4em;
margin: 0 0 0.5em 0;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 2px;
}
input:disabled {
color: #ccc;
}
button {
color: #333;
background-color: #f4f4f4;
outline: none;
}
button:disabled {
color: #999;
}
button:not(:disabled):active {
background-color: #ddd;
}
button:focus {
border-color: #666;
}

View File

@@ -4,7 +4,7 @@
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte + Node.js API</title>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>

View File

@@ -1,14 +1,15 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
@@ -37,14 +38,14 @@ export default {
},
plugins: [
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file - better for performance
css: css => {
css.write('bundle.css');
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In

View File

@@ -22,17 +22,17 @@ const projectRoot = argv[2] || path.join(__dirname, "..")
// Add deps to pkg.json
const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
"svelte-check": "^1.0.0",
"svelte-check": "^2.0.0",
"svelte-preprocess": "^4.0.0",
"@rollup/plugin-typescript": "^6.0.0",
"typescript": "^3.9.3",
"@rollup/plugin-typescript": "^8.0.0",
"typescript": "^4.0.0",
"tslib": "^2.0.0",
"@tsconfig/svelte": "^1.0.0"
"@tsconfig/svelte": "^2.0.0"
})
// Add script for checking
packageJSON.scripts = Object.assign(packageJSON.scripts, {
"validate": "svelte-check"
"check": "svelte-check --tsconfig ./tsconfig.json"
})
// Write the package JSON
@@ -62,22 +62,11 @@ import typescript from '@rollup/plugin-typescript';`)
// Replace name of entry point
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
// Instead we look for `css:` then the next `}` and add the preprocessor to that
let foundCSS = false
let match
// https://regex101.com/r/OtNjwo/1
const configEditor = new RegExp(/css:.|\n*}/gmi)
while (( match = configEditor.exec(rollupConfig)) != null) {
if (foundCSS) {
const endOfCSSIndex = match.index + 1
rollupConfig = rollupConfig.slice(0, endOfCSSIndex) + ",\n preprocess: sveltePreprocess()," + rollupConfig.slice(endOfCSSIndex);
break
}
if (match[0].includes("css:")) foundCSS = true
}
// Add preprocessor
rollupConfig = rollupConfig.replace(
'compilerOptions:',
'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:'
);
// Add TypeScript
rollupConfig = rollupConfig.replace(
@@ -96,6 +85,10 @@ const tsconfig = `{
const tsconfigPath = path.join(projectRoot, "tsconfig.json")
fs.writeFileSync(tsconfigPath, tsconfig)
// Add global.d.ts
const dtsPath = path.join(projectRoot, "src", "global.d.ts")
fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`)
// Delete this script, but not during testing
if (!argv[2]) {
// Remove the script
@@ -115,7 +108,7 @@ if (!argv[2]) {
}
// Adds the extension recommendation
fs.mkdirSync(path.join(projectRoot, ".vscode"))
fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true })
fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
"recommendations": ["svelte.svelte-vscode"]
}

View File

@@ -1,48 +1,30 @@
<script>
import { onMount } from "svelte";
export let date;
onMount(async () => {
const res = await fetch("/api/date");
const newDate = await res.text();
date = newDate;
});
export let name;
</script>
<main>
<h1>Svelte + Node.js API</h1>
<h2>
Deployed with
<a href="https://vercel.com/docs" target="_blank" rel="noreferrer noopener">
Vercel
</a>
!
</h2>
<p>
<a
href="https://github.com/vercel/vercel/tree/main/examples/svelte"
target="_blank"
rel="noreferrer noopener">
This project
</a>
is a
<a href="https://svelte.dev/">Svelte</a>
app with three directories,
<code>/public</code>
for static assets,
<code>/src</code>
for components and content, and
<code>/api</code>
which contains a serverless
<a href="https://nodejs.org/en/">Node.js</a>
function. See
<a href="/api/date">
<code>api/date</code>
for the Date API with Node.js
</a>
.
</p>
<br />
<h2>The date according to Node.js is:</h2>
<p>{date ? date : 'Loading date...'}</p>
<h1>Hello {name}!</h1>
<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>

View File

@@ -3,58 +3,65 @@
"@babel/code-frame@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
dependencies:
"@babel/highlight" "^7.10.4"
"@babel/highlight" "^7.14.5"
"@babel/helper-validator-identifier@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
"@babel/helper-validator-identifier@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
"@babel/highlight@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
"@babel/highlight@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
"@babel/helper-validator-identifier" "^7.14.5"
chalk "^2.0.0"
js-tokens "^4.0.0"
"@polka/url@^1.0.0-next.9":
version "1.0.0-next.11"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.11.tgz#aeb16f50649a91af79dbe36574b66d0f9e4d9f71"
integrity sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==
"@polka/url@^1.0.0-next.15":
version "1.0.0-next.15"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.15.tgz#6a9d143f7f4f49db2d782f9e1c8839a29b43ae23"
integrity sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==
"@rollup/plugin-commonjs@^14.0.0":
version "14.0.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-14.0.0.tgz#4285f9ec2db686a31129e5a2b415c94aa1f836f0"
integrity sha512-+PSmD9ePwTAeU106i9FRdc+Zb3XUWyW26mo5Atr2mk82hor8+nPwkztEjFo8/B1fJKfaQDg9aM2bzQkjhi7zOw==
"@rollup/plugin-commonjs@^17.0.0":
version "17.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz#757ec88737dffa8aa913eb392fade2e45aef2a2d"
integrity sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==
dependencies:
"@rollup/pluginutils" "^3.0.8"
"@rollup/pluginutils" "^3.1.0"
commondir "^1.0.1"
estree-walker "^1.0.1"
glob "^7.1.2"
is-reference "^1.1.2"
magic-string "^0.25.2"
resolve "^1.11.0"
estree-walker "^2.0.1"
glob "^7.1.6"
is-reference "^1.2.1"
magic-string "^0.25.7"
resolve "^1.17.0"
"@rollup/plugin-node-resolve@^8.0.0":
version "8.4.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz#261d79a680e9dc3d86761c14462f24126ba83575"
integrity sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==
"@rollup/plugin-node-resolve@^11.0.0":
version "11.2.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60"
integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==
dependencies:
"@rollup/pluginutils" "^3.1.0"
"@types/resolve" "1.17.1"
builtin-modules "^3.1.0"
deep-freeze "^0.0.1"
deepmerge "^4.2.2"
is-module "^1.0.0"
resolve "^1.17.0"
resolve "^1.19.0"
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
"@rollup/pluginutils@4":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec"
integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==
dependencies:
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
@@ -64,9 +71,9 @@
picomatch "^2.2.2"
"@types/estree@*":
version "0.0.45"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
version "0.0.50"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
"@types/estree@0.0.39":
version "0.0.39"
@@ -74,9 +81,9 @@
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/node@*":
version "14.14.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
version "16.3.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.3.3.tgz#0c30adff37bbbc7a50eb9b58fae2a504d0d88038"
integrity sha512-8h7k1YgQKxKXWckzFCMfsIwn0Y61UK6tlD6y2lOb3hTOIMlK3t9/QwHOhc81TwU+RMf0As5fj7NPjroERCnejQ==
"@types/resolve@1.17.1":
version "1.17.1"
@@ -92,28 +99,23 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
anymatch@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
binary-extensions@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
brace-expansion@^1.1.7:
version "1.1.11"
@@ -136,9 +138,9 @@ buffer-from@^1.0.0:
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
builtin-modules@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484"
integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==
version "3.2.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"
integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==
chalk@^2.0.0:
version "2.4.2"
@@ -149,20 +151,20 @@ chalk@^2.0.0:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chokidar@^3.3.0:
version "3.4.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b"
integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==
chokidar@^3.5.0:
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
dependencies:
anymatch "~3.1.1"
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.0"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.5.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.1.2"
fsevents "~2.3.2"
color-convert@^1.9.0:
version "1.9.3"
@@ -196,11 +198,6 @@ console-clear@^1.1.0:
resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7"
integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==
deep-freeze@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84"
integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
@@ -221,6 +218,11 @@ estree-walker@^1.0.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
estree-walker@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@@ -233,10 +235,10 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@~2.1.2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
@@ -248,17 +250,17 @@ get-port@^3.2.0:
resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob@^7.1.2:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
glob@^7.1.6:
version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -304,10 +306,10 @@ is-binary-path@~2.1.0:
dependencies:
binary-extensions "^2.0.0"
is-core-module@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946"
integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==
is-core-module@^2.2.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491"
integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==
dependencies:
has "^1.0.3"
@@ -333,7 +335,7 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-reference@^1.1.2:
is-reference@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
@@ -359,27 +361,27 @@ kleur@^3.0.0:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
livereload-js@^3.1.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.1.tgz#61f887468086762e61fb2987412cf9d1dda99202"
integrity sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==
livereload-js@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-3.3.2.tgz#c88b009c6e466b15b91faa26fd7c99d620e12651"
integrity sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==
livereload@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.1.tgz#65125dabdf2db4fd3f1169e953fe56e3bcc6f477"
integrity sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==
version "0.9.3"
resolved "https://registry.yarnpkg.com/livereload/-/livereload-0.9.3.tgz#a714816375ed52471408bede8b49b2ee6a0c55b1"
integrity sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==
dependencies:
chokidar "^3.3.0"
livereload-js "^3.1.0"
chokidar "^3.5.0"
livereload-js "^3.3.1"
opts ">= 1.2.0"
ws "^6.2.1"
ws "^7.4.3"
local-access@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.0.1.tgz#5121258146d64e869046c642ea4f1dd39ff942bb"
integrity sha512-ykt2pgN0aqIy6KQC1CqdWTWkmUwNgaOS6dcpHVjyBJONA+Xi7AtSB1vuxC/U/0tjIP3wcRudwQk1YYzUvzk2bA==
version "1.1.0"
resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.1.0.tgz#e007c76ba2ca83d5877ba1a125fc8dfe23ba4798"
integrity sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==
magic-string@^0.25.2:
magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
@@ -392,9 +394,9 @@ merge-stream@^2.0.0:
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
mime@^2.3.1:
version "2.4.6"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
version "2.5.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
minimatch@^3.0.4:
version "3.0.4"
@@ -431,14 +433,14 @@ path-is-absolute@^1.0.0:
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
randombytes@^2.1.0:
version "2.1.0"
@@ -447,10 +449,10 @@ randombytes@^2.1.0:
dependencies:
safe-buffer "^5.1.0"
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
@@ -459,29 +461,35 @@ require-relative@^0.8.7:
resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
resolve@^1.11.0, resolve@^1.17.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
resolve@^1.17.0, resolve@^1.19.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
dependencies:
is-core-module "^2.1.0"
is-core-module "^2.2.0"
path-parse "^1.0.6"
rollup-plugin-css-only@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz#6a701cc5b051c6b3f0961e69b108a9a118e1b1df"
integrity sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==
dependencies:
"@rollup/pluginutils" "4"
rollup-plugin-livereload@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.0.tgz#d3928d74e8cf2ae4286c5dd46b770fd3f3b82313"
integrity sha512-oC/8NqumGYuphkqrfszOHUUIwzKsaHBICw6QRwT5uD07gvePTS+HW+GFwu6f9K8W02CUuTvtIM9AWJrbj4wE1A==
version "2.0.5"
resolved "https://registry.yarnpkg.com/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz#4747fa292a2cceb0c972c573d71b3d66b4252b37"
integrity sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==
dependencies:
livereload "^0.9.1"
rollup-plugin-svelte@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-6.1.1.tgz#66362cf0500fb7a848283ebcf19d289a60ef0871"
integrity sha512-ijnm0pH1ScrY4uxwaNXBpNVejVzpL2769hIEbAlnqNUWZrffLspu5/k9/l/Wsj3NrEHLQ6wCKGagVJonyfN7ow==
rollup-plugin-svelte@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz#d45f2b92b1014be4eb46b55aa033fb9a9c65f04d"
integrity sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==
dependencies:
require-relative "^0.8.7"
rollup-pluginutils "^2.8.2"
sourcemap-codec "^1.4.8"
rollup-plugin-terser@^7.0.0:
version "7.0.2"
@@ -501,11 +509,11 @@ rollup-pluginutils@^2.8.2:
estree-walker "^0.6.1"
rollup@^2.3.4:
version "2.33.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.1.tgz#802795164164ee63cd47769d8879c33ec8ae0c40"
integrity sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==
version "2.53.2"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.53.2.tgz#3279f9bfba1fe446585560802e418c5fbcaefa51"
integrity sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==
optionalDependencies:
fsevents "~2.1.2"
fsevents "~2.3.2"
sade@^1.6.0:
version "1.7.4"
@@ -532,9 +540,9 @@ serialize-javascript@^4.0.0:
randombytes "^2.1.0"
sirv-cli@^1.0.0:
version "1.0.8"
resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-1.0.8.tgz#150c3f62694203a86cf5d71ec60e6ff4c34064a9"
integrity sha512-bJI+kkzQvMKfAOfgLzv09kWsdymLm39LgKmGjacB19GHIAQLCvXXg8e8HzcofTjDZlA8zVv4dQjU9SWkNzkJhw==
version "1.0.12"
resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-1.0.12.tgz#10c5240831879422dba42bdcdf9c09dcc3314615"
integrity sha512-Rs5PvF3a48zuLmrl8vcqVv9xF/WWPES19QawVkpdzqx7vD5SMZS07+ece1gK4umbslXN43YeIksYtQM5csgIzQ==
dependencies:
console-clear "^1.1.0"
get-port "^3.2.0"
@@ -542,15 +550,15 @@ sirv-cli@^1.0.0:
local-access "^1.0.1"
sade "^1.6.0"
semiver "^1.0.0"
sirv "^1.0.7"
sirv "^1.0.12"
tinydate "^1.0.0"
sirv@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.7.tgz#ad8ca1f84430777a59162592626c2b8e9b9f1384"
integrity sha512-QMT2OTD3CTr8de9VByPmvSEeyt6k8/Cxg0J2kQJ5HNhIWfhFg9ypcIWWzez9rPWnGj+WtJ7AZD/MdT/vdilV/A==
sirv@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.12.tgz#d816c882b35489b3c63290e2f455ae3eccd5f652"
integrity sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==
dependencies:
"@polka/url" "^1.0.0-next.9"
"@polka/url" "^1.0.0-next.15"
mime "^2.3.1"
totalist "^1.0.0"
@@ -572,7 +580,7 @@ source-map@~0.7.2:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
sourcemap-codec@^1.4.4:
version "1.4.8"
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
@@ -592,14 +600,14 @@ supports-color@^7.0.0:
has-flag "^4.0.0"
svelte@^3.0.0:
version "3.29.7"
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.29.7.tgz#e254eb2d0d609ce0fd60f052d444ac4a66d90f7d"
integrity sha512-rx0g311kBODvEWUU01DFBUl3MJuJven04bvTVFUG/w0On/wuj0PajQY/QlXcJndFxG+W1s8iXKaB418tdHWc3A==
version "3.38.3"
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.3.tgz#e15a1da98ee4b10162a6c8cb4c80aa86b2b589ed"
integrity sha512-N7bBZJH0iF24wsalFZF+fVYMUOigaAUQMIcEKHO3jstK/iL8VmP9xE+P0/a76+FkNcWt+TDv2Gx1taUoUscrvw==
terser@^5.0.0:
version "5.3.8"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.8.tgz#991ae8ba21a3d990579b54aa9af11586197a75dd"
integrity sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ==
version "5.7.1"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784"
integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==
dependencies:
commander "^2.20.0"
source-map "~0.7.2"
@@ -627,9 +635,7 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
dependencies:
async-limiter "~1.0.0"
ws@^7.4.3:
version "7.5.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==

6
examples/sveltekit/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.DS_Store
node_modules
/.svelte-kit
/package
.vercel_build_output
.vercel

View File

@@ -0,0 +1 @@
engine-strict=true

View File

@@ -0,0 +1,28 @@
# SvelteKit
Example project using SvelteKit with the [SpaceX GraphQL API](https://api.spacex.land/graphql/), deployed to [Vercel](https://vercel.com).
## Deploy Your Own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fsveltekit&project-name=sveltekit-vercel&repository-name=sveltekit-vercel&demo-title=SvelteKit%20%2B%20Vercel&demo-description=SvelteKit%20app%20fetching%20data%20from%20the%20SpaceX%20GraphQL%20API.&demo-url=https%3A%2F%2Fsveltekit.examples.vercel.com%2F&demo-image=https%3A%2F%2Fsveltekit.examples.vercel.com%2Ftwitter.png)
_Live Example: https://sveltekit.examples.vercel.com_
## Developing
Once you've created a project and installed dependencies with `npm install`, start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
This uses the [Vercel Adapter](https://github.com/sveltejs/kit/tree/master/packages/adapter-vercel) for SvelteKit.
```bash
npm run build
```

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
}

View File

@@ -0,0 +1,24 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build --verbose",
"preview": "svelte-kit preview"
},
"devDependencies": {
"@sveltejs/adapter-vercel": "next",
"@sveltejs/kit": "next",
"svelte": "^3.38.3"
},
"dependencies": {
"prettier": "^2.3.2",
"prettier-plugin-svelte": "^2.3.1"
},
"prettier": {
"arrowParens": "always",
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none"
}
}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="follow, index" />
<title>SpaceX Launches | SvelteKit and Vercel</title>
<meta
content="SvelteKit app fetching data from the SpaceX GraphQL API, deployed to Vercel."
name="description"
/>
<meta
property="og:title"
content="SpaceX Launches | SvelteKit and Vercel"
/>
<meta property="og:image" content="/twitter.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@vercel" />
<meta
name="twitter:title"
content="SpaceX Launches | SvelteKit and Vercel"
/>
<meta
name="twitter:description"
content="SvelteKit app fetching data from the SpaceX GraphQL API, deployed to Vercel."
/>
<meta name="twitter:image" content="/twitter.png" />
%svelte.head%
</head>
<body>
<div id="svelte">%svelte.body%</div>
</body>
</html>

1
examples/sveltekit/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="@sveltejs/kit" />

View File

@@ -0,0 +1,143 @@
<script context="module">
export async function load({ fetch }) {
const res = await fetch('https://api.spacex.land/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: `{
launchesPast(limit: 10) {
mission_name
launch_date_local
links {
video_link
}
}
}`
})
});
if (res.ok) {
const { data } = await res.json();
return {
props: {
launches: data.launchesPast
}
};
}
return {
status: res.status,
error: new Error(`Error fetching GraphQL data`)
};
}
</script>
<script>
export let launches;
</script>
<h1>SpaceX Launches</h1>
<p>
This is an example <a
class="link"
target="_blank"
rel="noopener"
href="https://svelte.dev">SvelteKit</a
>
application fetching GraphQL data from the public
<a
class="link"
target="_blank"
rel="noopener"
href="https://api.spacex.land/graphql">SpaceX API</a
>. View source on
<a
class="link"
target="_blank"
rel="noopener"
href="https://github.com/leerob/sveltekit-graphql">GitHub</a
>.
</p>
<ul>
{#each launches as launch}
<li>
<a
class="card-link"
target="_blank"
rel="noopener"
href={launch.links.video_link}
>
<h2>{launch.mission_name}</h2>
<p>{new Date(launch.launch_date_local).toLocaleString()}</p>
</a>
</li>
{/each}
</ul>
<footer>
<p>
Created with <a
class="link"
target="_blank"
rel="noopener"
href="https://svelte.dev">SvelteKit</a
>
and deployed with
<a class="link" target="_blank" rel="noopener" href="https://vercel.com"
>▲ Vercel</a
>.
</p>
</footer>
<style>
:global(body) {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,
monospace;
background-color: #fafafa;
max-width: 650px;
margin: 32px auto;
padding: 0 16px;
}
h1 {
letter-spacing: -0.025em;
}
h2 {
font-size: 18px;
}
ul {
list-style: none;
padding: 0;
margin-top: 32px;
}
li {
border: 1px solid #eaeaea;
border-radius: 8px;
margin-bottom: 16px;
background-color: white;
transition: 0.15s box-shadow ease-in-out;
}
li:hover {
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
}
p {
color: #666;
font-size: 14px;
line-height: 1.75;
}
a {
color: #0070f3;
text-decoration: none;
}
.card-link {
padding: 8px 24px;
display: block;
}
.link {
transition: 0.15s text-decoration ease-in-out;
color: #0761d1;
}
.link:hover {
text-decoration: underline;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

View File

@@ -0,0 +1,8 @@
import vercel from '@sveltejs/adapter-vercel';
export default {
kit: {
adapter: vercel(),
target: '#svelte',
},
};

View File

@@ -0,0 +1,206 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@rollup/pluginutils@^4.1.0":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec"
integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==
dependencies:
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@sveltejs/adapter-vercel@next":
version "1.0.0-next.24"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.24.tgz#0b6c1d7e75eb6207bc07ec1c2e8392811269ce44"
integrity sha512-fTJptAA+UPF6HloAeRgfRNR85i2EDCaGN4XS028aXp9qwZ8X7Dhh9mFxRV4hko5USzj3j/HsH672Mp8OsAu12A==
dependencies:
esbuild "^0.12.5"
"@sveltejs/kit@next":
version "1.0.0-next.131"
resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.131.tgz#1ebc6d83b84fbd84a556c75baae14b180eda6172"
integrity sha512-izTzzUbxTVuW+uwzCg5ltaCF4DZaD8fGI88IGb3fQ3qcmfRQi/vQUZuyfKc1CYxRDVohvaBSMQUQYie4AM6jGQ==
dependencies:
"@sveltejs/vite-plugin-svelte" "^1.0.0-next.12"
cheap-watch "^1.0.3"
sade "^1.7.4"
vite "^2.4.1"
"@sveltejs/vite-plugin-svelte@^1.0.0-next.12":
version "1.0.0-next.12"
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.12.tgz#5ab9cc2bc361d2d6fc9abbbd73fcd2803bf8f00c"
integrity sha512-cuyNkJ6leptfv+7qL/fWQ7EpGWdguosFOUI0z93oQUmFTcX7QxJ5h+QI3NQyktBzlKL/761L8BbG2hHNkVbLIQ==
dependencies:
"@rollup/pluginutils" "^4.1.0"
debug "^4.3.2"
kleur "^4.1.4"
magic-string "^0.25.7"
require-relative "^0.8.7"
svelte-hmr "^0.14.5"
cheap-watch@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/cheap-watch/-/cheap-watch-1.0.3.tgz#3c4265718bcf8f1ae08f5e450f9f4693432e028e"
integrity sha512-xC5CruMhLzjPwJ5ecUxGu1uGmwJQykUhqd2QrCrYbwvsFYdRyviu6jG9+pccwDXJR/OpmOTOJ9yLFunVgQu9wg==
colorette@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
debug@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
dependencies:
ms "2.1.2"
esbuild@^0.12.5, esbuild@^0.12.8:
version "0.12.15"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.15.tgz#9d99cf39aeb2188265c5983e983e236829f08af0"
integrity sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==
estree-walker@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
is-core-module@^2.2.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491"
integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==
dependencies:
has "^1.0.3"
kleur@^4.1.4:
version "4.1.4"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d"
integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==
magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
dependencies:
sourcemap-codec "^1.4.4"
mri@^1.1.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nanoid@^3.1.23:
version "3.1.23"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
path-parse@^1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
picomatch@^2.2.2:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
postcss@^8.3.5:
version "8.3.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.23"
source-map-js "^0.6.2"
prettier-plugin-svelte@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.3.1.tgz#926184a490549688dbea0a8d61c1b1ae20218368"
integrity sha512-F1/r6OYoBq8Zgurhs1MN25tdrhPw0JW5JjioPRqpxbYdmrZ3gY/DzHGs0B6zwd4DLyRsfGB2gqhxUCbHt/D1fw==
prettier@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d"
integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==
require-relative@^0.8.7:
version "0.8.7"
resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
resolve@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
rollup@^2.38.5:
version "2.53.2"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.53.2.tgz#3279f9bfba1fe446585560802e418c5fbcaefa51"
integrity sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==
optionalDependencies:
fsevents "~2.3.2"
sade@^1.7.4:
version "1.7.4"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691"
integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==
dependencies:
mri "^1.1.0"
source-map-js@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
sourcemap-codec@^1.4.4:
version "1.4.8"
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
svelte-hmr@^0.14.5:
version "0.14.6"
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.14.6.tgz#d3f3be88bebb50ef2fb1ed4ebfb8ba4f03874098"
integrity sha512-0oXQmRiEh3uNjyVQiGmIE7imbKO4dYc1WL6XRXTC0X9XbSacJgj9MOLguqqbZygPsNnlglhlk4eB0pCmM6nQAA==
svelte@^3.38.3:
version "3.38.3"
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.3.tgz#e15a1da98ee4b10162a6c8cb4c80aa86b2b589ed"
integrity sha512-N7bBZJH0iF24wsalFZF+fVYMUOigaAUQMIcEKHO3jstK/iL8VmP9xE+P0/a76+FkNcWt+TDv2Gx1taUoUscrvw==
vite@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/vite/-/vite-2.4.2.tgz#07d00615775c808530bc9f65641062b349b67929"
integrity sha512-2MifxD2I9fjyDmmEzbULOo3kOUoqX90A58cT6mECxoVQlMYFuijZsPQBuA14mqSwvV3ydUsqnq+BRWXyO9Qa+w==
dependencies:
esbuild "^0.12.8"
postcss "^8.3.5"
resolve "^1.20.0"
rollup "^2.38.5"
optionalDependencies:
fsevents "~2.3.2"

6
examples/vite/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
.vercel

View File

@@ -0,0 +1 @@
README.md

29
examples/vite/README.md Normal file
View File

@@ -0,0 +1,29 @@
![Vite Logo](https://vitejs.dev/logo.svg)
# Vite Example
This directory is a brief example of a Vite/Vue.js site that can be deployed with Vercel and zero configuration.
While this project uses Vue.js, Vite supports many popular JS frameworks. See all the supported frameworks here: https://vitejs.dev/guide/#scaffolding-your-first-vite-project
## Deploy Your Own
Deploy your own Vite project with Vercel.
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/vercel/tree/main/examples/vite)
### How We Created This Example
To get started with Vue.js deployed with Vercel, you can use Vite (https://vitejs.dev/guide/#scaffolding-your-first-vite-project) to initialize the project:
```shell
$ yarn create @vitejs/app
```
### Deploying From Your Terminal
You can deploy your new Vite project with a single command from your terminal using [Vercel CLI](https://vercel.com/download):
```shell
$ vercel
```

13
examples/vite/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@@ -0,0 +1,17 @@
{
"name": "vite",
"version": "0.1.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"vue": "^3.0.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.2.4",
"@vue/compiler-sfc": "^3.0.5",
"vite": "^2.4.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

22
examples/vite/src/App.vue Normal file
View File

@@ -0,0 +1,22 @@
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
// This starter template is using Vue 3 experimental <script setup> SFCs
// Check out https://github.com/vuejs/rfcs/blob/script-setup-2/active-rfcs/0000-script-setup.md
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,33 @@
<template>
<h1>{{ msg }}</h1>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
Vite Documentation
</a>
|
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
</p>
<button type="button" @click="state.count++">count is: {{ state.count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<script setup>
import { defineProps, reactive } from 'vue'
defineProps({
msg: String
})
const state = reactive({ count: 0 })
</script>
<style scoped>
a {
color: #42b983;
}
</style>

View File

@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()]
})

395
examples/vite/yarn.lock Normal file
View File

@@ -0,0 +1,395 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/helper-validator-identifier@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==
"@babel/parser@^7.12.0", "@babel/parser@^7.13.9":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595"
integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==
"@babel/types@^7.12.0", "@babel/types@^7.13.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff"
integrity sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==
dependencies:
"@babel/helper-validator-identifier" "^7.14.5"
to-fast-properties "^2.0.0"
"@types/estree@^0.0.48":
version "0.0.48"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.48.tgz#18dc8091b285df90db2f25aa7d906cfc394b7f74"
integrity sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==
"@vitejs/plugin-vue@^1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-1.2.4.tgz#a7aa6e6a31c556a8b781de730316deeecf7f56f2"
integrity sha512-D/3H9plevPQGgQGwmV6eecvOnooLTecPR63HPffVVWPEhbfvmtYLWgznzs456NBb2DItiRTCIa1yWxvGqC+I8A==
"@vue/compiler-core@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.1.4.tgz#a3a74cf52e8f01af386d364ac8a099cbeb260424"
integrity sha512-TnUz+1z0y74O/A4YKAbzsdUfamyHV73MihrEfvettWpm9bQKVoZd1nEmR1cGN9LsXWlwAvVQBetBlWdOjmQO5Q==
dependencies:
"@babel/parser" "^7.12.0"
"@babel/types" "^7.12.0"
"@vue/shared" "3.1.4"
estree-walker "^2.0.1"
source-map "^0.6.1"
"@vue/compiler-dom@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.1.4.tgz#bf3795e1449f32c965d38c4ea6d808ca05fdfc97"
integrity sha512-3tG2ScHkghhUBuFwl9KgyZhrS8CPFZsO7hUDekJgIp5b1OMkROr4AvxHu6rRMl4WkyvYkvidFNBS2VfOnwa6Kw==
dependencies:
"@vue/compiler-core" "3.1.4"
"@vue/shared" "3.1.4"
"@vue/compiler-sfc@^3.0.5":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.1.4.tgz#93e87db950e0711339c18baa7bb7d28d3522d7bc"
integrity sha512-4KDQg60Khy3SgnF+V/TB2NZqzmM4TyGRmzsxqG1SebGdMSecCweFDSlI/F1vDYk6dKiCHgmpoT9A1sLxswkJ0A==
dependencies:
"@babel/parser" "^7.13.9"
"@babel/types" "^7.13.0"
"@types/estree" "^0.0.48"
"@vue/compiler-core" "3.1.4"
"@vue/compiler-dom" "3.1.4"
"@vue/compiler-ssr" "3.1.4"
"@vue/shared" "3.1.4"
consolidate "^0.16.0"
estree-walker "^2.0.1"
hash-sum "^2.0.0"
lru-cache "^5.1.1"
magic-string "^0.25.7"
merge-source-map "^1.1.0"
postcss "^8.1.10"
postcss-modules "^4.0.0"
postcss-selector-parser "^6.0.4"
source-map "^0.6.1"
"@vue/compiler-ssr@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.1.4.tgz#7f6eaac5b1851fc15c82c083e8179eb1216b303c"
integrity sha512-Box8fCuCFPp0FuimIswjDkjwiSDCBkHvt/xVALyFkYCiIMWv2eR53fIjmlsnEHhcBuZ+VgRC+UanCTcKvSA1gA==
dependencies:
"@vue/compiler-dom" "3.1.4"
"@vue/shared" "3.1.4"
"@vue/reactivity@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.1.4.tgz#d926ed46fb0d48582ccf8665b062d37b5d35ba99"
integrity sha512-YDlgii2Cr9yAoKVZFzgY4j0mYlVT73986X3e5SPp6ifqckSEoFSUWXZK2Tb53TB/9qO29BEEbspnKD3m3wAwkA==
dependencies:
"@vue/shared" "3.1.4"
"@vue/runtime-core@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.1.4.tgz#3e30ae6ecbfff06df5adc9414491143191a375ba"
integrity sha512-qmVJgJuFxfT7M4qHQ4M6KqhKC66fjuswK+aBivE8dWiZ2rtIGl9gtJGpwqwjQEcKEBTOfvvrtrwBncYArJUO8Q==
dependencies:
"@vue/reactivity" "3.1.4"
"@vue/shared" "3.1.4"
"@vue/runtime-dom@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.1.4.tgz#acfeee200d5c45fc2cbdf7058cda1498f9b45849"
integrity sha512-vbmwgTxku1BU87Kw7r29adv0OIrDXCW0PslOPQT0O/9R5SqcXgS94Yj6zsztDjvghegenwIAPNLlDR1Auh5s+w==
dependencies:
"@vue/runtime-core" "3.1.4"
"@vue/shared" "3.1.4"
csstype "^2.6.8"
"@vue/shared@3.1.4":
version "3.1.4"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.1.4.tgz#c14c461ec42ea2c1556e86f60b0354341d91adc3"
integrity sha512-6O45kZAmkLvzGLToBxEz4lR2W6kXohCtebV2UxjH9GXjd8X9AhEn68FN9eNanFtWNzvgw1hqd6HkPRVQalqf7Q==
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
bluebird@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
colorette@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
consolidate@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16"
integrity sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==
dependencies:
bluebird "^3.7.2"
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
csstype@^2.6.8:
version "2.6.17"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.17.tgz#4cf30eb87e1d1a005d8b6510f95292413f6a1c0e"
integrity sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
esbuild@^0.12.8:
version "0.12.15"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.15.tgz#9d99cf39aeb2188265c5983e983e236829f08af0"
integrity sha512-72V4JNd2+48eOVCXx49xoSWHgC3/cCy96e7mbXKY+WOWghN00cCmlGnwVLRhRHorvv0dgCyuMYBZlM2xDM5OQw==
estree-walker@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
generic-names@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872"
integrity sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==
dependencies:
loader-utils "^1.1.0"
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
hash-sum@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
icss-utils@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
is-core-module@^2.2.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==
dependencies:
has "^1.0.3"
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
dependencies:
minimist "^1.2.0"
loader-utils@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
dependencies:
big.js "^5.2.2"
emojis-list "^3.0.0"
json5 "^1.0.1"
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
dependencies:
yallist "^3.0.2"
magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
dependencies:
sourcemap-codec "^1.4.4"
merge-source-map@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
dependencies:
source-map "^0.6.1"
minimist@^1.2.0:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
nanoid@^3.1.23:
version "3.1.23"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
path-parse@^1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
postcss-modules-extract-imports@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
postcss-modules-local-by-default@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
dependencies:
icss-utils "^5.0.0"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.1.0"
postcss-modules-scope@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
dependencies:
postcss-selector-parser "^6.0.4"
postcss-modules-values@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
dependencies:
icss-utils "^5.0.0"
postcss-modules@^4.0.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-4.1.3.tgz#c4c4c41d98d97d24c70e88dacfc97af5a4b3e21d"
integrity sha512-dBT39hrXe4OAVYJe/2ZuIZ9BzYhOe7t+IhedYeQ2OxKwDpAGlkEN/fR0fGnrbx4BvgbMReRX4hCubYK9cE/pJQ==
dependencies:
generic-names "^2.0.1"
icss-replace-symbols "^1.1.0"
lodash.camelcase "^4.3.0"
postcss-modules-extract-imports "^3.0.0"
postcss-modules-local-by-default "^4.0.0"
postcss-modules-scope "^3.0.0"
postcss-modules-values "^4.0.0"
string-hash "^1.1.1"
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
version "6.0.6"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea"
integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==
dependencies:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss@^8.1.10, postcss@^8.3.5:
version "8.3.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.23"
source-map-js "^0.6.2"
resolve@^1.20.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
rollup@^2.38.5:
version "2.52.7"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.52.7.tgz#e15a8bf734f6e4c204b7cdf33521151310250cb2"
integrity sha512-55cSH4CCU6MaPr9TAOyrIC+7qFCHscL7tkNsm1MBfIJRRqRbCEY0mmeFn4Wg8FKsHtEH8r389Fz38r/o+kgXLg==
optionalDependencies:
fsevents "~2.3.2"
source-map-js@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
sourcemap-codec@^1.4.4:
version "1.4.8"
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
string-hash@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
vite@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/vite/-/vite-2.4.1.tgz#2e48b8dbfc69e4edbf7f4d1c0798d621585cb8da"
integrity sha512-4BpKRis9uxIqPfIEcJ18LTBsamqnDFxTx45CXwagHjNltHa6PFEvf8Pe6OpgIHb0OyWT30OXOSSQvdOaX4OBiQ==
dependencies:
esbuild "^0.12.8"
postcss "^8.3.5"
resolve "^1.20.0"
rollup "^2.38.5"
optionalDependencies:
fsevents "~2.3.2"
vue@^3.0.5:
version "3.1.4"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.1.4.tgz#120d6818c51eaa35d0879e5bc1cff60135bc69fd"
integrity sha512-p8dcdyeCgmaAiZsbLyDkmOLcFGZb/jEVdCLW65V68LRCXTNX8jKsgah2F7OZ/v/Ai2V0Fb1MNO0vz/GFqsPVMA==
dependencies:
"@vue/compiler-dom" "3.1.4"
"@vue/runtime-dom" "3.1.4"
"@vue/shared" "3.1.4"
yallist@^3.0.2:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==

View File

@@ -15,27 +15,27 @@
"lerna": "3.16.4"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "2.0.0",
"@typescript-eslint/parser": "2.0.0",
"@typescript-eslint/eslint-plugin": "4.28.0",
"@typescript-eslint/parser": "4.28.0",
"@vercel/ncc": "0.24.0",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"cheerio": "1.0.0-rc.3",
"eslint": "6.2.2",
"eslint-config-prettier": "6.1.0",
"eslint-plugin-jest": "23.8.2",
"eslint": "7.29.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "24.3.6",
"husky": "6.0.0",
"json5": "2.1.1",
"lint-staged": "9.2.5",
"node-fetch": "2.6.1",
"npm-package-arg": "6.1.0",
"prettier": "2.0.5"
"prettier": "2.3.1"
},
"scripts": {
"lerna": "lerna",
"bootstrap": "lerna bootstrap",
"publish-stable": "echo 'Run `yarn changelog` for instructions'",
"publish-canary": "git pull && lerna version prerelease --preid canary --message 'Publish Canary' --exact",
"publish-canary": "git checkout main && git pull && lerna version prerelease --preid canary --message 'Publish Canary' --exact",
"publish-from-github": "./utils/publish.sh",
"changelog": "node utils/changelog.js",
"build": "node utils/run.js build all",
@@ -79,8 +79,7 @@
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
"prettier"
],
"env": {
"node": true,
@@ -89,26 +88,19 @@
},
"rules": {
"require-atomic-updates": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-module-boundary-types": 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-var-requires": 0,
"jest/no-disabled-tests": 2,
"jest/no-focused-tests": 2
},
"overrides": [
{
"files": [
"**/*.js"
],
"rules": {
"@typescript-eslint/no-var-requires": "off"
}
},
{
"files": [
"packages/cli/**/*"
@@ -125,8 +117,7 @@
"@typescript-eslint/member-delimiter-style": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-var-requires": 0
"@typescript-eslint/no-inferrable-types": 0
}
},
{

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.11.0",
"version": "2.11.2-canary.5",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.4.0",
"@vercel/frameworks": "0.4.2-canary.4",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",
@@ -47,7 +47,7 @@
"node-fetch": "2.6.1",
"semver": "6.1.1",
"ts-jest": "24.1.0",
"typescript": "3.9.3",
"typescript": "4.3.4",
"yazl": "2.4.3"
}
}

View File

@@ -424,6 +424,7 @@ function getApiMatches() {
return [
{ src: 'api/**/*.js', use: `@vercel/node`, config },
{ src: 'api/**/*.mjs', use: `@vercel/node`, config },
{ src: 'api/**/*.ts', use: `@vercel/node`, config },
{ src: 'api/**/!(*_test).go', use: `@vercel/go`, config },
{ src: 'api/**/*.py', use: `@vercel/python`, config },

View File

@@ -1346,6 +1346,25 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect((errorRoutes![0] as Source).status).toBe(404);
});
it('api detect node mjs files', async () => {
const files = [
'api/index.mjs',
'api/users.mjs',
'api/config/staging.mjs',
'api/config/production.mjs',
'api/src/controllers/health.mjs',
'api/src/controllers/user.module.mjs',
];
const { builders, errorRoutes } = await detectBuilders(files, undefined, {
featHandleMiss,
});
expect(builders!.length).toBe(6);
expect(builders!.every(b => b.src!.endsWith('.mjs'))).toBe(true);
expect(errorRoutes!.length).toBe(1);
expect((errorRoutes![0] as Source).status).toBe(404);
});
it('just public', async () => {
const files = ['public/index.html', 'public/favicon.ico', 'README.md'];

View File

@@ -1 +0,0 @@
handler

View File

@@ -1,25 +0,0 @@
#!/usr/bin/env node
const execa = require('execa');
const { join } = require('path');
const { homedir } = require('os');
async function main() {
process.env.GOOS = 'linux';
process.env.GOARCH = 'amd64';
process.env.GOPATH = join(homedir(), 'go');
await execa('go', ['get', 'github.com/aws/aws-lambda-go/events'], {
stdio: 'inherit',
});
await execa('go', ['get', 'github.com/aws/aws-lambda-go/lambda'], {
stdio: 'inherit',
});
await execa('go', ['build', '-o', 'handler', 'main.go'], {
stdio: 'inherit',
});
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View File

@@ -1,45 +0,0 @@
const path = require('path');
const { mkdirp, copyFile } = require('fs-extra');
const {
glob,
download,
shouldServe,
createLambda,
getWritableDirectory,
} = require('@vercel/build-utils');
exports.analyze = ({ files, entrypoint }) => files[entrypoint].digest;
exports.version = 3;
exports.build = async ({ workPath, files, entrypoint, meta }) => {
const outDir = await getWritableDirectory();
await download(files, workPath, meta);
const handlerPath = path.join(__dirname, 'handler');
await copyFile(handlerPath, path.join(outDir, 'handler'));
const entrypointOutDir = path.join(outDir, path.dirname(entrypoint));
await mkdirp(entrypointOutDir);
// For now only the entrypoint file is copied into the lambda
await copyFile(
path.join(workPath, entrypoint),
path.join(outDir, entrypoint)
);
const lambda = await createLambda({
files: await glob('**', outDir),
handler: 'handler',
runtime: 'go1.x',
environment: {
SCRIPT_FILENAME: entrypoint,
},
});
return { output: lambda };
};
exports.shouldServe = shouldServe;

View File

@@ -1,36 +0,0 @@
package main
import (
now "../../utils/go/bridge"
"net/http"
"net/http/cgi"
"os"
"path/filepath"
)
type CgiHandler struct {
http.Handler
Dir string
Script string
}
func (h *CgiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
handler := cgi.Handler{
Path: h.Script,
Root: "/" + h.Script,
Dir: h.Dir,
Env: []string{
"HTTPS=on",
"SERVER_PORT=443",
"SERVER_SOFTWARE=@vercel/cgi",
},
}
handler.ServeHTTP(w, r)
}
func main() {
workdir, _ := filepath.Abs(".")
script := os.Getenv("SCRIPT_FILENAME")
handler := &CgiHandler{nil, workdir, script}
now.Start(handler)
}

View File

@@ -1,24 +0,0 @@
{
"name": "@vercel/cgi",
"version": "1.0.7",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/vercel/vercel.git",
"directory": "packages/cgi"
},
"scripts": {
"build": "node build",
"prepublishOnly": "node build"
},
"files": [
"index.js",
"handler"
],
"dependencies": {
"fs-extra": "7.0.0"
},
"devDependencies": {
"rmfr": "2.0.0"
}
}

View File

@@ -14,13 +14,13 @@ Vercel is the optimal workflow for frontend teams. All-in-one: Static and Jamsta
To install the latest version of Vercel CLI, visit [vercel.com/download](https://vercel.com/download) or run this command:
```sh
```bash
npm i -g vercel
```
To quickly start a new project, run the following commands:
```
```bash
vercel init # Pick an example project
cd <PROJECT> # Change directory to the new project
vercel # Deploy to the cloud
@@ -29,3 +29,31 @@ vercel # Deploy to the cloud
## Documentation
For details on how to use Vercel CLI, check out our [documentation](https://vercel.com/docs).
## Local Development
To develop Vercel CLI, first check out the source code, install dependencies, and build all packages:
```bash
git clone https://github.com/vercel/vercel.git
cd vercel
yarn
yarn build
```
At this point you can make modifications to the CLI source code and test them out locally. The CLI source code is located in the `packages/cli` directory.
```bash
cd packages/cli
```
From within the `packages/cli` directory, you can use the `ts-eager` command line tool to quickly excute Vercel CLI from its TypeScript source code directly (without having to manually compile first). For example:
```bash
npx ts-eager src
npx ts-eager src login
npx ts-eager src switch --debug
npx ts-eager src dev
```
When you are satisfied with your changes, make a commit and create a pull request!

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "23.0.0",
"version": "23.0.2-canary.10",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -61,11 +61,11 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.11.0",
"@vercel/go": "1.2.2",
"@vercel/node": "1.11.0",
"@vercel/python": "2.0.3",
"@vercel/ruby": "1.2.6",
"@vercel/build-utils": "2.11.2-canary.5",
"@vercel/go": "1.2.3-canary.0",
"@vercel/node": "1.11.2-canary.4",
"@vercel/python": "2.0.5-canary.0",
"@vercel/ruby": "1.2.7-canary.0",
"update-notifier": "4.1.0"
},
"devDependencies": {
@@ -100,7 +100,7 @@
"@types/universal-analytics": "0.4.2",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.4.0",
"@vercel/frameworks": "0.4.2-canary.4",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",
@@ -136,6 +136,7 @@
"glob": "7.1.2",
"http-proxy": "1.18.1",
"inquirer": "7.0.4",
"is-docker": "2.2.1",
"is-port-reachable": "3.0.0",
"is-url": "1.2.2",
"jaro-winkler": "0.2.8",
@@ -148,7 +149,7 @@
"node-fetch": "2.6.1",
"npm-package-arg": "6.1.0",
"nyc": "13.2.0",
"open": "8.0.2",
"open": "8.2.0",
"ora": "3.4.0",
"pcre-to-regexp": "1.0.0",
"pluralize": "7.0.0",
@@ -171,7 +172,7 @@
"tree-kill": "1.2.2",
"ts-eager": "2.0.2",
"ts-node": "8.3.0",
"typescript": "3.9.3",
"typescript": "4.3.4",
"universal-analytics": "0.4.20",
"utility-types": "2.1.0",
"which": "2.0.2",

View File

@@ -2,10 +2,11 @@ import chalk from 'chalk';
import { handleError } from '../../util/error';
import Client from '../../util/client';
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 { getPkgName } from '../../util/pkg-name';
import ls from './ls';
import rm from './rm';
@@ -36,6 +37,7 @@ const help = () => {
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.vercel.app')}
@@ -64,13 +66,13 @@ const help = () => {
};
const COMMAND_CONFIG = {
default: 'set',
default: ['set'],
ls: ['ls', 'list'],
rm: ['rm', 'remove'],
set: ['set'],
};
export default async function main(client) {
export default async function main(client: Client) {
let argv;
try {

View File

@@ -1,21 +1,26 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import Now from '../../util';
import Client from '../../util/client';
import getAliases from '../../util/alias/get-aliases';
import getScope from '../../util/get-scope.ts';
import stamp from '../../util/output/stamp.ts';
import strlen from '../../util/strlen.ts';
import getScope from '../../util/get-scope';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name.ts';
import { getCommandName } from '../../util/pkg-name';
export default async function ls(client, opts, args) {
const {
apiUrl,
authConfig: { token },
output,
config: { currentTeam },
} = client;
import { Alias } from '../../types';
interface Options {
'--next'?: number;
}
export default async function ls(
client: Client,
opts: Options,
args: string[]
) {
const { output } = client;
const { '--next': nextTimestamp } = opts;
let contextName = null;
@@ -36,13 +41,6 @@ export default async function ls(client, opts, args) {
return 1;
}
const now = new Now({
apiUrl,
token,
debug: client.output.isDebugEnabled(),
currentTeam,
output,
});
const lsStamp = stamp();
if (args.length > 0) {
@@ -56,8 +54,9 @@ export default async function ls(client, opts, args) {
output.spinner(`Fetching aliases under ${chalk.bold(contextName)}`);
// Get the list of alias
const { aliases, pagination } = await getAliases(
now,
client,
undefined,
nextTimestamp
);
@@ -73,21 +72,20 @@ export default async function ls(client, opts, args) {
);
}
now.close();
return 0;
}
function printAliasTable(aliases) {
function printAliasTable(aliases: Alias[]) {
return `${table(
[
['source', 'url', 'age'].map(h => chalk.gray(h)),
['source', 'url', 'age'].map(header => chalk.gray(header)),
...aliases.map(a => [
// for legacy reasons, we might have situations
// where the deployment was deleted and the alias
// not collected appropriately, and we need to handle it
a.deployment && a.deployment.url ? a.deployment.url : chalk.gray(''),
a.alias,
ms(Date.now() - new Date(a.createdAt)),
ms(Date.now() - a.createdAt),
]),
],
{

View File

@@ -1,23 +1,29 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import Now from '../../util';
import getScope from '../../util/get-scope.ts';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import removeAliasById from '../../util/alias/remove-alias-by-id';
import stamp from '../../util/output/stamp.ts';
import strlen from '../../util/strlen.ts';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import confirm from '../../util/input/confirm';
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(client, opts, args) {
const {
apiUrl,
authConfig: { token },
output,
config: { currentTeam },
} = client;
import { Alias } from '../../types';
import { Output } from '../../util/output';
import { isValidName } from '../../util/is-valid-name';
import { getCommandName } from '../../util/pkg-name';
type Options = {
'--yes': boolean;
};
export default async function rm(
client: Client,
opts: Partial<Options>,
args: string[]
) {
const { output } = client;
let contextName = null;
@@ -32,13 +38,6 @@ export default async function rm(client, opts, args) {
throw err;
}
const now = new Now({
apiUrl,
token,
debug: client.output.isDebugEnabled(),
currentTeam,
output,
});
const [aliasOrId] = args;
if (args.length !== 1) {
@@ -61,7 +60,8 @@ export default async function rm(client, opts, args) {
return 1;
}
const alias = await findAliasByAliasOrId(output, now, aliasOrId);
const alias = await findAliasByAliasOrId(output, client, aliasOrId);
if (!alias) {
output.error(
`Alias not found by "${aliasOrId}" under ${chalk.bold(contextName)}`
@@ -76,7 +76,7 @@ export default async function rm(client, opts, args) {
return 0;
}
await removeAliasById(now, alias.uid);
await removeAliasById(client, alias.uid);
console.log(
`${chalk.cyan('> Success!')} Alias ${chalk.bold(
alias.alias
@@ -85,7 +85,7 @@ export default async function rm(client, opts, args) {
return 0;
}
async function confirmAliasRemove(output, alias) {
async function confirmAliasRemove(output: Output, alias: Alias) {
const srcUrl = alias.deployment
? chalk.underline(alias.deployment.url)
: null;
@@ -94,7 +94,7 @@ async function confirmAliasRemove(output, alias) {
[
...(srcUrl ? [srcUrl] : []),
chalk.underline(alias.alias),
chalk.gray(`${ms(new Date() - new Date(alias.created))} ago`),
chalk.gray(`${ms(Date.now() - alias.createdAt)} ago`),
],
],
{

View File

@@ -28,7 +28,7 @@ type Options = {
export default async function set(
client: Client,
opts: Options,
opts: Partial<Options>,
args: string[]
) {
const { output, localConfig } = client;

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import logo from '../../util/output/logo';
import { getPkgName } from '../../util/pkg-name.ts';
import { getPkgName } from '../../util/pkg-name';
export const help = () => `
${chalk.bold(`${logo} ${getPkgName()}`)} [options] <command | path>
@@ -9,6 +9,7 @@ export const help = () => `
${chalk.dim('Basic')}
billing Manages the account payment methods
deploy [path] Performs a deployment ${chalk.bold(
'(default)'
)}
@@ -27,6 +28,7 @@ export const help = () => `
rm | remove [id] Removes a deployment
domains [name] Manages your domain names
projects Manages your Projects
dns [name] Manages your DNS records
certs [cmd] Manages your SSL certificates
secrets [name] Manages your global Secrets, for use in Environment Variables
@@ -92,30 +94,3 @@ export const help = () => `
${chalk.cyan(`$ ${getPkgName()} help list`)}
`;
export const args = {
'--force': Boolean,
'--with-cache': Boolean,
'--public': Boolean,
'--no-clipboard': Boolean,
'--env': [String],
'--build-env': [String],
'--meta': [String],
// This is not an array in favor of matching
// the config property name.
'--regions': String,
'--prod': Boolean,
'--confirm': Boolean,
'-f': '--force',
'-p': '--public',
'-e': '--env',
'-b': '--build-env',
'-C': '--no-clipboard',
'-m': '--meta',
'-c': '--confirm',
// deprecated
'--name': String,
'-n': '--name',
'--target': String,
};

View File

@@ -1,37 +1,62 @@
import fs from 'fs-extra';
import { resolve, basename } from 'path';
import { fileNameSymbol } from '@vercel/client';
import getScope from '../../util/get-scope.ts';
import { VercelConfig, fileNameSymbol } from '@vercel/client';
import code from '../../util/output/code';
import highlight from '../../util/output/highlight';
import { readLocalConfig } from '../../util/config/files';
import getArgs from '../../util/get-args';
import { handleError } from '../../util/error';
import { help, args } from './args';
import { help } from './args';
import deploy from './latest';
import Client from '../../util/client';
export default async client => {
const {
output,
config: { currentTeam },
} = client;
export default async (client: Client) => {
const { output } = client;
let contextName = currentTeam || 'current user';
let argv = null;
try {
argv = getArgs(client.argv.slice(2), args);
argv = getArgs(client.argv.slice(2), {
'--force': Boolean,
'--with-cache': Boolean,
'--public': Boolean,
'--no-clipboard': Boolean,
'--env': [String],
'--build-env': [String],
'--meta': [String],
// This is not an array in favor of matching
// the config property name.
'--regions': String,
'--prod': Boolean,
'--confirm': Boolean,
'-f': '--force',
'-p': '--public',
'-e': '--env',
'-b': '--build-env',
'-C': '--no-clipboard',
'-m': '--meta',
'-c': '--confirm',
// deprecated
'--name': String,
'-n': '--name',
'--target': String,
});
} catch (error) {
handleError(error);
return 1;
}
if (argv['--help']) {
output.print(help());
return 2;
}
if (argv._[0] === 'deploy') {
argv._.shift();
}
let paths = [];
let paths;
if (argv._.length > 0) {
// If path is relative: resolve
// if path is absolute: clear up strange `/` etc
@@ -40,20 +65,14 @@ export default async client => {
paths = [process.cwd()];
}
let { localConfig } = client;
let localConfig: VercelConfig | null = client.localConfig;
if (!localConfig || localConfig instanceof Error) {
localConfig = readLocalConfig(paths[0]);
}
const stats = {};
if (argv['--help']) {
output.print(help());
return 2;
}
for (const path of paths) {
try {
stats[path] = await fs.lstat(path);
await fs.stat(path);
} catch (err) {
output.error(
`The specified file or directory "${basename(path)}" does not exist.`
@@ -62,26 +81,15 @@ export default async client => {
}
}
try {
({ contextName } = await getScope(client));
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message);
return 1;
}
throw err;
}
if (localConfig) {
const { version } = localConfig;
const file = highlight(localConfig[fileNameSymbol]);
const file = highlight(localConfig[fileNameSymbol]!);
const prop = code('version');
if (version) {
if (typeof version === 'number') {
if (version !== 2) {
const two = code(2);
const two = code(String(2));
output.error(
`The value of the ${prop} property within ${file} can only be ${two}.`
@@ -97,5 +105,5 @@ export default async client => {
}
}
return deploy(client, contextName, output, stats, localConfig, args);
return deploy(client, paths, localConfig, argv);
};

View File

@@ -3,17 +3,17 @@ import bytes from 'bytes';
import { join } from 'path';
import { write as copy } from 'clipboardy';
import chalk from 'chalk';
import { fileNameSymbol } from '@vercel/client';
import { Dictionary, fileNameSymbol, VercelConfig } from '@vercel/client';
import { getPrettyError } from '@vercel/build-utils';
import { handleError } from '../../util/error';
import getArgs from '../../util/get-args';
import toHumanPath from '../../util/humanize-path';
import Now from '../../util';
import stamp from '../../util/output/stamp.ts';
import stamp from '../../util/output/stamp';
import createDeploy from '../../util/deploy/create-deploy';
import getDeploymentByIdOrHost from '../../util/deploy/get-deployment-by-id-or-host';
import parseMeta from '../../util/parse-meta';
import code from '../../util/output/code';
import linkStyle from '../../util/output/link';
import param from '../../util/output/param';
import highlight from '../../util/output/highlight';
import {
@@ -53,10 +53,15 @@ import validatePaths, {
validateRootDirectory,
} from '../../util/validate-paths';
import { readLocalConfig } from '../../util/config/files';
import { getCommandName } from '../../util/pkg-name.ts';
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url.ts';
import { getCommandName } from '../../util/pkg-name';
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url';
import { Output } from '../../util/output';
import Client from '../../util/client';
const addProcessEnv = async (log, env) => {
const addProcessEnv = async (
log: (str: string) => void,
env: typeof process.env
) => {
let val;
for (const key of Object.keys(env)) {
@@ -85,8 +90,8 @@ const addProcessEnv = async (log, env) => {
};
const printDeploymentStatus = async (
output,
client,
output: Output,
client: Client,
{
readyState,
alias: aliasList,
@@ -94,11 +99,26 @@ const printDeploymentStatus = async (
target,
indications,
url: deploymentUrl,
aliasWarning,
}: {
readyState: string;
alias: string[];
aliasError: Error;
target: string;
indications: any;
url: string;
aliasWarning?: {
code: string;
message: string;
link?: string;
action?: string;
};
},
deployStamp,
isClipboardEnabled,
isFile
deployStamp: () => string,
isClipboardEnabled: boolean,
isFile: boolean
) => {
indications = indications || [];
const isProdDeployment = target === 'production';
if (readyState !== 'READY') {
@@ -116,8 +136,8 @@ const printDeploymentStatus = async (
);
} else {
// print preview/production url
let previewUrl;
let isWildcard;
let previewUrl: string;
let isWildcard: boolean;
if (!isFile && Array.isArray(aliasList) && aliasList.length > 0) {
const previewUrlInfo = await getPreferredPreviewURL(client, aliasList);
if (previewUrlInfo) {
@@ -136,11 +156,12 @@ const printDeploymentStatus = async (
// copy to clipboard
let isCopiedToClipboard = false;
if (isClipboardEnabled && !isWildcard) {
await copy(previewUrl)
.then(() => {
isCopiedToClipboard = true;
})
.catch(error => output.debug(`Error copying to clipboard: ${error}`));
try {
await copy(previewUrl);
isCopiedToClipboard = true;
} catch (err) {
output.debug(`Error copyind to clipboard: ${err}`);
}
}
output.print(
@@ -155,28 +176,32 @@ const printDeploymentStatus = async (
);
}
if (indications) {
const indent = process.stdout.isTTY ? ' ' : ''; // if using emojis
const newline = '\n';
for (let indication of indications) {
const message =
prependEmoji(chalk.dim(indication.payload), emoji(indication.type)) +
newline;
let link = '';
if (indication.link)
link =
indent +
chalk.dim(
`${indication.action || 'Learn More'}: ${indication.link}`
) +
newline;
output.print(message + link);
}
if (aliasWarning?.message) {
indications.push({
type: 'warning',
payload: aliasWarning.message,
link: aliasWarning.link,
action: aliasWarning.action,
});
}
const newline = '\n';
for (let indication of indications) {
const message =
prependEmoji(chalk.dim(indication.payload), emoji(indication.type)) +
newline;
let link = '';
if (indication.link)
link =
chalk.dim(
`${indication.action || 'Learn More'}: ${linkStyle(indication.link)}`
) + newline;
output.print(message + link);
}
};
// Converts `env` Arrays, Strings and Objects into env Objects.
const parseEnv = env => {
const parseEnv = (env?: string[] | Dictionary<string>) => {
if (!env) {
return {};
}
@@ -201,35 +226,25 @@ const parseEnv = env => {
o[key] = value;
return o;
}, {});
}, {} as Dictionary<string | undefined>);
}
// assume it's already an Object
return env;
};
export default async function main(
client,
contextName,
output,
stats,
localConfig,
args
client: Client,
paths: string[],
localConfig: VercelConfig | null,
argv: any
) {
let argv = null;
try {
argv = getArgs(client.argv.slice(2), args);
} catch (error) {
handleError(error);
return 1;
}
const {
apiUrl,
output,
authConfig: { token },
} = client;
const { log, debug, error, warn } = output;
const paths = Object.keys(stats);
const debugEnabled = argv['--debug'];
const { isTTY } = process.stdout;
@@ -265,6 +280,7 @@ export default async function main(
}
let { org, project, status } = link;
let newProjectName = null;
let rootDirectory = project ? project.rootDirectory : null;
let sourceFilesOutsideRootDirectory = true;
@@ -340,6 +356,16 @@ export default async function main(
}
}
// At this point `org` should be populated
if (!org) {
throw new Error(`"org" is not defined`);
}
// Set the `contextName` and `currentTeam` as specified by the
// Project Settings, so that API calls happen with the proper scope
const contextName = org.slug;
client.config.currentTeam = org.type === 'team' ? org.id : undefined;
// if we have `sourceFilesOutsideRootDirectory` set to `true`, we use the current path
// and upload the entire directory.
const sourcePath =
@@ -354,7 +380,7 @@ export default async function main(
path,
sourcePath,
project
? `To change your Project Settings, go to https://vercel.com/${org.slug}/${project.name}/settings`
? `To change your Project Settings, go to https://vercel.com/${org?.slug}/${project.name}/settings`
: ''
)) === false
) {
@@ -373,7 +399,7 @@ export default async function main(
output.print(
`${prependEmoji(
`The ${highlight(
localConfig[fileNameSymbol]
localConfig[fileNameSymbol]!
)} file should be inside of the provided root directory.`,
emoji('warning')
)}\n`
@@ -387,7 +413,7 @@ export default async function main(
output.print(
`${prependEmoji(
`The ${code('name')} property in ${highlight(
localConfig[fileNameSymbol]
localConfig[fileNameSymbol]!
)} is deprecated (https://vercel.link/name-prop)`,
emoji('warning')
)}\n`
@@ -395,7 +421,7 @@ export default async function main(
}
// build `env`
const isObject = item =>
const isObject = (item: any) =>
Object.prototype.toString.call(item) === '[object Object]';
// This validation needs to happen on the client side because
@@ -404,7 +430,7 @@ export default async function main(
if (typeof localConfig.env !== 'undefined' && !isObject(localConfig.env)) {
error(
`The ${code('env')} property in ${highlight(
localConfig[fileNameSymbol]
localConfig[fileNameSymbol]!
)} needs to be an object`
);
return 1;
@@ -414,7 +440,7 @@ export default async function main(
if (!isObject(localConfig.build)) {
error(
`The ${code('build')} property in ${highlight(
localConfig[fileNameSymbol]
localConfig[fileNameSymbol]!
)} needs to be an object`
);
return 1;
@@ -426,7 +452,7 @@ export default async function main(
) {
error(
`The ${code('build.env')} property in ${highlight(
localConfig[fileNameSymbol]
localConfig[fileNameSymbol]!
)} needs to be an object`
);
return 1;
@@ -466,7 +492,7 @@ export default async function main(
// build `regions`
const regionFlag = (argv['--regions'] || '')
.split(',')
.map(s => s.trim())
.map((s: string) => s.trim())
.filter(Boolean);
const regions = regionFlag.length > 0 ? regionFlag : localConfig.regions;
@@ -497,13 +523,13 @@ export default async function main(
target = 'production';
}
const currentTeam = org.type === 'team' ? org.id : undefined;
const currentTeam = org?.type === 'team' ? org.id : undefined;
const now = new Now({ apiUrl, token, debug: debugEnabled, currentTeam });
let deployStamp = stamp();
let deployment = null;
try {
const createArgs = {
const createArgs: any = {
name: project ? project.name : newProjectName,
env: deploymentEnv,
build: { env: deploymentBuildEnv },
@@ -527,7 +553,7 @@ export default async function main(
}
deployment = await createDeploy(
output,
client,
now,
contextName,
[sourcePath],
@@ -537,18 +563,15 @@ export default async function main(
path
);
if (
deployment instanceof Error &&
deployment.code === 'missing_project_settings'
) {
if (deployment.code === 'missing_project_settings') {
let { projectSettings, framework } = deployment;
if (rootDirectory) {
projectSettings.rootDirectory = rootDirectory;
}
if (typeof sourceFilesOutsideRootDirectory !== 'undefined') {
projectSettings.sourceFilesOutsideRootDirectory = sourceFilesOutsideRootDirectory;
projectSettings.sourceFilesOutsideRootDirectory =
sourceFilesOutsideRootDirectory;
}
const settings = await editProjectSettings(
@@ -563,7 +586,7 @@ export default async function main(
deployStamp = stamp();
createArgs.deployStamp = deployStamp;
deployment = await createDeploy(
output,
client,
now,
contextName,
[sourcePath],
@@ -575,7 +598,7 @@ export default async function main(
}
if (deployment instanceof NotDomainOwner) {
output.error(deployment);
output.error(deployment.message);
return 1;
}
@@ -583,7 +606,7 @@ export default async function main(
output.error(
deployment.message ||
'An unexpected error occurred while deploying your project',
null,
undefined,
'https://vercel.link/help',
'Contact Support'
);
@@ -596,7 +619,7 @@ export default async function main(
}
const deploymentResponse = await getDeploymentByIdOrHost(
now,
client,
contextName,
deployment.id,
'v10'
@@ -676,12 +699,7 @@ export default async function main(
output.error(err.message || 'Build failed');
output.error(
`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.
backticks: false,
}
`logs ${now.url}`
)}`
);
@@ -715,7 +733,11 @@ export default async function main(
);
}
function handleCreateDeployError(output, error, localConfig) {
function handleCreateDeployError(
output: Output,
error: Error,
localConfig: VercelConfig
) {
if (error instanceof InvalidDomain) {
output.error(`The domain ${error.meta.domain} is not valid`);
return 1;

View File

@@ -108,8 +108,5 @@ export default async function dev(
systemEnvValues,
});
process.once('SIGINT', () => devServer.stop());
process.once('SIGTERM', () => devServer.stop());
await devServer.start(...listen);
}

View File

@@ -13,7 +13,6 @@ import getDomainPrice from '../../util/domains/get-domain-price';
import { getCommandName } from '../../util/pkg-name';
import { getDomainConfig } from '../../util/domains/get-domain-config';
import code from '../../util/output/code';
import wait from '../../util/output/wait';
import { getDomainRegistrar } from '../../util/domains/get-domain-registrar';
type Options = {};
@@ -59,7 +58,7 @@ export default async function inspect(
output.debug(`Fetching domain info`);
const cancelWait = wait(
output.spinner(
`Fetching Domain ${domainName} under ${chalk.bold(contextName)}`
);
@@ -68,9 +67,6 @@ export default async function inspect(
client,
contextName,
domainName,
cancelWait,
}).finally(() => {
cancelWait();
});
if (typeof information === 'number') {
@@ -207,13 +203,11 @@ async function fetchInformation({
client,
contextName,
domainName,
cancelWait,
}: {
output: Output;
client: Client;
contextName: string;
domainName: string;
cancelWait: () => void;
}) {
const [domain, renewalPrice] = await Promise.all([
getDomainByName(client, contextName, domainName, { ignoreWait: true }),
@@ -223,13 +217,11 @@ async function fetchInformation({
]);
if (domain instanceof DomainNotFound) {
cancelWait();
output.prettyError(domain);
return 1;
}
if (domain instanceof DomainPermissionDenied) {
cancelWait();
output.prettyError(domain);
output.log(`Run ${getCommandName(`domains ls`)} to see your domains.`);
return 1;
@@ -238,7 +230,6 @@ async function fetchInformation({
const projects = await findProjectsForDomain(client, domainName);
if (projects instanceof Error) {
cancelWait();
output.prettyError(projects);
return 1;
}

View File

@@ -2,7 +2,6 @@ import ms from 'ms';
import chalk from 'chalk';
import plural from 'pluralize';
import wait from '../../util/output/wait';
import Client from '../../util/client';
import getDomains from '../../util/domains/get-domains';
import getScope from '../../util/get-scope';
@@ -55,14 +54,9 @@ export default async function ls(
return 1;
}
const cancelWait = wait(`Fetching Domains under ${chalk.bold(contextName)}`);
output.spinner(`Fetching Domains under ${chalk.bold(contextName)}`);
const { domains, pagination } = await getDomains(
client,
nextTimestamp
).finally(() => {
cancelWait();
});
const { domains, pagination } = await getDomains(client, nextTimestamp);
output.log(
`${plural('Domain', domains.length, true)} found under ${chalk.bold(

View File

@@ -4,16 +4,18 @@ import table from 'text-table';
import Now from '../util';
import getArgs from '../util/get-args';
import { handleError } from '../util/error';
import cmd from '../util/output/cmd.ts';
import cmd from '../util/output/cmd';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import strlen from '../util/strlen.ts';
import getScope from '../util/get-scope.ts';
import elapsed from '../util/output/elapsed';
import strlen from '../util/strlen';
import getScope from '../util/get-scope';
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';
import { getPkgName, getCommandName } from '../util/pkg-name';
import Client from '../util/client';
import { Deployment } from '../types';
const help = () => {
console.log(`
@@ -60,7 +62,7 @@ const help = () => {
`);
};
export default async function main(client) {
export default async function main(client: Client) {
let argv;
try {
@@ -90,8 +92,8 @@ export default async function main(client) {
return 1;
}
let app = argv._[1];
let host = null;
let app: string | null = argv._[1];
let host: string | null = null;
if (argv['--help']) {
help();
@@ -130,7 +132,7 @@ export default async function main(client) {
output,
currentTeam,
});
const start = new Date();
const start = Date.now();
if (app && !isValidName(app)) {
error(`The provided argument "${app}" is not a valid project name`);
@@ -147,9 +149,9 @@ export default async function main(client) {
)} for retrieving details about a single deployment`
);
const hostParts = asHost.split('-');
const hostParts: string[] = asHost.split('-');
if (hostParts < 2) {
if (hostParts.length < 2) {
error('Only deployment hostnames are allowed, no aliases');
return 1;
}
@@ -165,7 +167,13 @@ export default async function main(client) {
nextTimestamp,
});
let { deployments, pagination } = response;
let {
deployments,
pagination,
}: {
deployments: Deployment[];
pagination: { count: number; next: number };
} = response;
if (app && !deployments.length) {
debug(
@@ -220,8 +228,8 @@ export default async function main(client) {
console.log(
`${table(
[
['project', 'latest deployment', 'state', 'age', 'username'].map(s =>
chalk.dim(s)
['project', 'latest deployment', 'state', 'age', 'username'].map(
header => chalk.dim(header)
),
...deployments
.sort(sortRecent())
@@ -230,23 +238,21 @@ export default async function main(client) {
getProjectName(dep),
chalk.bold((includeScheme ? 'https://' : '') + dep.url),
stateString(dep.state),
chalk.gray(ms(Date.now() - new Date(dep.createdAt))),
chalk.gray(ms(Date.now() - dep.createdAt)),
dep.creator.username,
],
])
// flatten since the previous step returns a nested
// array of the deployment and (optionally) its instances
.reduce((ac, c) => ac.concat(c), [])
.filter(
app == null
? // if an app wasn't supplied to filter by,
// we only want to render one deployment per app
filterUniqueApps()
: () => true
.flat()
.filter(app =>
// if an app wasn't supplied to filter by,
// we only want to render one deployment per app
app === null ? filterUniqueApps() : () => true
),
],
{
align: ['l', 'l', 'r', 'l', 'b'],
align: ['l', 'l', 'r', 'l', 'l'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
@@ -263,7 +269,7 @@ export default async function main(client) {
}
}
function getProjectName(d) {
function getProjectName(d: Deployment) {
// We group both file and files into a single project
if (d.name === 'file') {
return 'files';
@@ -273,7 +279,7 @@ function getProjectName(d) {
}
// renders the state string
function stateString(s) {
function stateString(s: string) {
switch (s) {
case 'INITIALIZING':
return chalk.yellow(s);
@@ -291,7 +297,7 @@ function stateString(s) {
// sorts by most recent deployment
function sortRecent() {
return function recencySort(a, b) {
return function recencySort(a: Deployment, b: Deployment) {
return b.createdAt - a.createdAt;
};
}
@@ -301,7 +307,7 @@ function sortRecent() {
// this mode can be bypassed by supplying an app name
function filterUniqueApps() {
const uniqueApps = new Set();
return function uniqueAppFilter([appName]) {
return function uniqueAppFilter([appName]: [appName: string]) {
if (uniqueApps.has(appName)) {
return false;
}

View File

@@ -5,14 +5,17 @@ import getArgs from '../util/get-args';
import handleError from '../util/handle-error';
import logo from '../util/output/logo';
import prompt from '../util/login/prompt';
import doSsoLogin from '../util/login/sso';
import doSamlLogin from '../util/login/saml';
import doEmailLogin from '../util/login/email';
import doGithubLogin from '../util/login/github';
import doGitlabLogin from '../util/login/gitlab';
import doBitbucketLogin from '../util/login/bitbucket';
import { prependEmoji, emoji } from '../util/emoji';
import { getCommandName, getPkgName } from '../util/pkg-name';
import getGlobalPathConfig from '../util/config/global-path';
import { writeToAuthConfigFile, writeToConfigFile } from '../util/config/files';
import Client from '../util/client';
import { LoginParams } from '../util/login/types';
import { LoginResult } from '../util/login/types';
const help = () => {
console.log(`
@@ -41,15 +44,24 @@ const help = () => {
${chalk.gray('')} Log in using a specific team "slug" for SAML Single Sign-On
${chalk.cyan(`$ ${getPkgName()} login acme`)}
${chalk.gray('')} Log in using GitHub in "out-of-band" mode
${chalk.cyan(`$ ${getPkgName()} login --github --oob`)}
`);
};
export default async function login(client: Client): Promise<number> {
let argv;
const { apiUrl, output } = client;
const { output } = client;
try {
argv = getArgs(client.argv.slice(2));
argv = getArgs(client.argv.slice(2), {
'--oob': Boolean,
'--github': Boolean,
'--gitlab': Boolean,
'--bitbucket': Boolean,
});
} catch (err) {
handleError(err);
return 1;
@@ -67,19 +79,24 @@ export default async function login(client: Client): Promise<number> {
const input = argv._[1];
let result: number | string = 1;
const params: LoginParams = { output, apiUrl };
let result: LoginResult = 1;
if (input) {
// Email or Team slug was provided via command line
if (validateEmail(input)) {
result = await doEmailLogin(params, input);
result = await doEmailLogin(client, input);
} else {
result = await doSsoLogin(params, input);
result = await doSamlLogin(client, input, argv['--oob']);
}
} else if (argv['--github']) {
result = await doGithubLogin(client, argv['--oob']);
} else if (argv['--gitlab']) {
result = await doGitlabLogin(client, argv['--oob']);
} else if (argv['--bitbucket']) {
result = await doBitbucketLogin(client, argv['--oob']);
} else {
// Interactive mode
result = await prompt(params);
result = await prompt(client, undefined, argv['--oob']);
}
// The login function failed, so it returned an exit code
@@ -87,12 +104,20 @@ export default async function login(client: Client): Promise<number> {
return result;
}
// If the token was upgraded (not a new login), then don't modify
// the current scope.
if (!client.authConfig.token) {
if (result.teamId) {
// SSO login, so set the current scope to the appropriate Team
client.config.currentTeam = result.teamId;
} else {
delete client.config.currentTeam;
}
}
// When `result` is a string it's the user's authentication token.
// It needs to be saved to the configuration file.
client.authConfig.token = result;
// New user, so we can't keep the team
delete client.config.currentTeam;
client.authConfig.token = result.token;
writeToAuthConfigFile(client.authConfig);
writeToConfigFile(client.config);

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import logo from '../util/output/logo';
// @ts-ignore
import { handleError } from '../util/error';
import { writeToConfigFile, writeToAuthConfigFile } from '../util/config/files';
import getArgs from '../util/get-args';
@@ -62,6 +61,7 @@ export default async function main(client: Client): Promise<number> {
try {
await client.fetch(`/v3/user/tokens/current`, {
method: 'DELETE',
useCurrentTeam: false,
});
} catch (err) {
if (err.status === 403) {

View File

@@ -243,7 +243,7 @@ function printLogShort(log: any) {
const date = new Date(log.created).toISOString();
data.split('\n').forEach((line, i) => {
data.split('\n').forEach(line => {
if (
line.includes('START RequestId:') ||
line.includes('END RequestId:') ||
@@ -260,18 +260,9 @@ function printLogShort(log: any) {
}
}
if (i === 0) {
console.log(
`${chalk.dim(date)} ${line.replace('[now-builder-debug] ', '')}`
);
} else {
console.log(
`${' '.repeat(date.length)} ${line.replace(
'[now-builder-debug] ',
''
)}`
);
}
console.log(
`${chalk.dim(date)} ${line.replace('[now-builder-debug] ', '')}`
);
});
return 0;

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import table from 'text-table';
import ms from 'ms';
import table from 'text-table';
import strlen from '../util/strlen';
import getArgs from '../util/get-args';
import { handleError, error } from '../util/error';
@@ -8,8 +8,8 @@ import exit from '../util/exit';
import logo from '../util/output/logo';
import getScope from '../util/get-scope';
import getCommandFlags from '../util/get-command-flags';
import wait from '../util/output/wait';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
import { getPkgName, getCommandName } from '../util/pkg-name';
import Client from '../util/client';
const e = encodeURIComponent;
@@ -46,11 +46,10 @@ const help = () => {
`);
};
// Options
let argv;
let subcommand;
let argv: any;
let subcommand: string | string[];
const main = async client => {
const main = async (client: Client) => {
try {
argv = getArgs(client.argv.slice(2), {
'--next': Number,
@@ -93,7 +92,7 @@ const main = async client => {
}
};
export default async client => {
export default async (client: Client) => {
try {
await main(client);
} catch (err) {
@@ -102,8 +101,16 @@ export default async client => {
}
};
async function run({ client, contextName }) {
async function run({
client,
contextName,
}: {
client: Client;
contextName: string;
}) {
const { output } = client;
const args = argv._.slice(1);
const start = Date.now();
if (subcommand === 'ls' || subcommand === 'list') {
@@ -118,7 +125,7 @@ async function run({ client, contextName }) {
return exit(2);
}
const stopSpinner = wait(`Fetching projects in ${chalk.bold(contextName)}`);
output.spinner(`Fetching projects in ${chalk.bold(contextName)}`);
let projectsUrl = '/v4/projects/?limit=20';
@@ -127,13 +134,19 @@ async function run({ client, contextName }) {
projectsUrl += `&until=${next}`;
}
const { projects: list, pagination } = await client.fetch(projectsUrl, {
const {
projects: list,
pagination,
}: {
projects: [{ name: string; updatedAt: number }];
pagination: { count: number; next: number };
} = await client.fetch(projectsUrl, {
method: 'GET',
});
stopSpinner();
output.stopSpinner();
const elapsed = ms(new Date() - start);
const elapsed = ms(Date.now() - start);
console.log(
`> ${
@@ -143,14 +156,14 @@ async function run({ client, contextName }) {
if (list.length > 0) {
const cur = Date.now();
const header = [['', 'name', 'updated'].map(s => chalk.dim(s))];
const header = [['', 'name', 'updated'].map(title => chalk.dim(title))];
const out = table(
header.concat(
list.map(secret => [
'',
chalk.bold(secret.name),
chalk.gray(`${ms(cur - new Date(secret.updatedAt))} ago`),
chalk.gray(`${ms(cur - secret.updatedAt)} ago`),
])
),
{
@@ -187,26 +200,23 @@ async function run({ client, contextName }) {
const name = args[0];
// Check the existence of the project
try {
await client.fetch(`/projects/info/${e(name)}`);
} catch (err) {
if (err.status === 404) {
console.error(error('No such project exists'));
return exit(1);
}
}
const yes = await readConfirmation(name);
if (!yes) {
console.error(error('User abort'));
return exit(0);
}
await client.fetch(`/v2/projects/${name}`, {
method: 'DELETE',
});
const elapsed = ms(new Date() - start);
try {
await client.fetch(`/v2/projects/${e(name)}`, {
method: 'DELETE',
});
} catch (err) {
if (err.status === 404) {
console.error(error('No such project exists'));
return exit(1);
}
}
const elapsed = ms(Date.now() - start);
console.log(
`${chalk.cyan('> Success!')} Project ${chalk.bold(
name
@@ -251,7 +261,7 @@ async function run({ client, contextName }) {
throw error;
}
}
const elapsed = ms(new Date() - start);
const elapsed = ms(Date.now() - start);
console.log(
`${chalk.cyan('> Success!')} Project ${chalk.bold(
@@ -271,7 +281,7 @@ process.on('uncaughtException', err => {
exit(1);
});
function readConfirmation(projectName) {
function readConfirmation(projectName: string) {
return new Promise(resolve => {
process.stdout.write(
`The project: ${chalk.bold(projectName)} will be removed permanently.\n` +

View File

@@ -5,18 +5,23 @@ import table from 'text-table';
import Now from '../util';
import getAliases from '../util/alias/get-aliases';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import elapsed from '../util/output/elapsed';
import { normalizeURL } from '../util/url';
import getScope from '../util/get-scope.ts';
import { NowError } from '../util/now-error';
import getScope from '../util/get-scope';
import { isValidName } from '../util/is-valid-name';
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';
import getArgs from '../util/get-args.ts';
import handleError from '../util/handle-error.ts';
import getDeploymentsByProjectId, {
DeploymentPartial,
} from '../util/deploy/get-deployments-by-project-id';
import { getPkgName, getCommandName } from '../util/pkg-name';
import getArgs from '../util/get-args';
import handleError from '../util/handle-error';
import Client from '../util/client';
import { Output } from '../util/output';
import { Alias, Project } from '../types';
import { NowError } from '../util/now-error';
const help = () => {
console.log(`
@@ -61,7 +66,7 @@ const help = () => {
`);
};
export default async function main(client) {
export default async function main(client: Client) {
let argv;
try {
@@ -87,7 +92,8 @@ export default async function main(client) {
} = client;
const hard = argv['--hard'];
const skipConfirmation = argv['--yes'];
const ids = argv._;
const safe = argv['--safe'];
const ids: string[] = argv._;
const { success, error, log } = output;
if (argv['--help'] || ids[0] === 'help') {
@@ -110,7 +116,7 @@ export default async function main(client) {
return 1;
}
let contextName = null;
let contextName: string | null = null;
try {
({ contextName } = await getScope(client));
@@ -129,13 +135,13 @@ export default async function main(client) {
.join(' ')} in ${chalk.bold(contextName)}`
);
let aliases;
let projects;
let deployments;
let aliases: Alias[][];
let projects: Project[];
let deployments: DeploymentPartial[];
const findStart = Date.now();
try {
const searchFilter = d =>
const searchFilter = (d: DeploymentPartial) =>
ids.some(
id =>
d &&
@@ -143,23 +149,27 @@ export default async function main(client) {
(d.uid === id || d.name === id || d.url === normalizeURL(id))
);
const [deploymentList, projectList] = await Promise.all([
const [deploymentList, projectList] = await Promise.all<any>([
Promise.all(
ids.map(idOrHost =>
getDeploymentByIdOrHost(client, contextName, idOrHost)
)
ids.map(idOrHost => {
if (!contextName) {
throw new Error('Context name is not defined');
}
return getDeploymentByIdOrHost(client, contextName, idOrHost);
})
),
Promise.all(
ids.map(async idOrName => getProjectByIdOrName(client, idOrName))
),
]);
deployments = deploymentList.filter(searchFilter);
projects = projectList.filter(searchFilter);
deployments = deploymentList.filter((d: any) => searchFilter(d));
projects = projectList.filter((d: any) => searchFilter(d));
// When `--safe` is set we want to replace all projects
// with deployments to verify the aliases
if (argv['--safe']) {
if (safe) {
const projectDeployments = await Promise.all(
projects.map(project => {
return getDeploymentsByProjectId(client, project.id, {
@@ -192,7 +202,7 @@ export default async function main(client) {
}
deployments = deployments.filter((match, i) => {
if (argv['--safe'] && aliases[i].length > 0) {
if (safe && aliases[i].length > 0) {
return false;
}
@@ -241,9 +251,9 @@ export default async function main(client) {
currentTeam,
output,
});
const start = new Date();
const start = Date.now();
await Promise.all([
await Promise.all<any>([
...deployments.map(depl => now.remove(depl.uid, { hard })),
...projects.map(project => removeProject(client, project.id)),
]);
@@ -257,14 +267,18 @@ export default async function main(client) {
console.log(`${chalk.gray('-')} ${chalk.bold(depl.url)}`);
});
projects.forEach(project => {
projects.forEach((project: Project) => {
console.log(`${chalk.gray('-')} ${chalk.bold(project.name)}`);
});
return 0;
}
function readConfirmation(deployments, projects, output) {
function readConfirmation(
deployments: DeploymentPartial[],
projects: Project[],
output: Output
): Promise<string> {
return new Promise(resolve => {
if (deployments.length > 0) {
output.log(
@@ -277,7 +291,7 @@ function readConfirmation(deployments, projects, output) {
const deploymentTable = table(
deployments.map(depl => {
const time = chalk.gray(`${ms(new Date() - depl.created)} ago`);
const time = chalk.gray(`${ms(Date.now() - depl.created)} ago`);
const url = depl.url ? chalk.underline(`https://${depl.url}`) : '';
return [` ${depl.uid}`, url, time];
}),
@@ -326,8 +340,8 @@ function readConfirmation(deployments, projects, output) {
}
function deploymentsAndProjects(
deployments = [],
projects = [],
deployments: DeploymentPartial[],
projects: Project[],
conjunction = 'and'
) {
if (!projects || projects.length === 0) {

View File

@@ -1,12 +1,9 @@
import chalk from 'chalk';
import stamp from '../../util/output/stamp.ts';
import info from '../../util/output/info';
import error from '../../util/output/error';
import wait from '../../util/output/wait';
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 note from '../../util/output/note';
import textInput from '../../util/input/text';
import invite from './invite';
@@ -40,14 +37,12 @@ export default async function add(client, teams) {
let slug;
let team;
let elapsed;
let stopSpinner;
const { output } = client;
console.log(
info(
`Pick a team identifier for its url (e.g.: ${chalk.cyan(
'`vercel.com/acme`'
)})`
)
output.log(
`Pick a team identifier for its url (e.g.: ${chalk.cyan(
'`vercel.com/acme`'
)})`
);
do {
try {
@@ -61,7 +56,7 @@ export default async function add(client, teams) {
});
} catch (err) {
if (err.message === 'USER_ABORT') {
console.log(info('Aborted'));
output.log('Aborted');
return 0;
}
@@ -69,26 +64,26 @@ export default async function add(client, teams) {
}
elapsed = stamp();
stopSpinner = wait(teamUrlPrefix + slug);
output.spinner(teamUrlPrefix + slug);
let res;
try {
// eslint-disable-next-line no-await-in-loop
res = await teams.create({ slug });
stopSpinner();
team = res;
} catch (err) {
stopSpinner();
output.stopSpinner();
process.stdout.write(eraseLines(2));
console.error(error(err.message));
output.error(err.message);
}
} while (!team);
output.stopSpinner();
process.stdout.write(eraseLines(2));
console.log(success(`Team created ${elapsed()}`));
console.log(`${chalk.cyan(`${chars.tick} `) + teamUrlPrefix + slug}\n`);
console.log(info('Pick a display name for your team'));
output.success(`Team created ${elapsed()}`);
output.log(`${chalk.cyan(`${chars.tick} `) + teamUrlPrefix + slug}\n`);
output.log('Pick a display name for your team');
let name;
@@ -107,17 +102,16 @@ export default async function add(client, teams) {
}
elapsed = stamp();
stopSpinner = wait(teamNamePrefix + name);
output.spinner(teamNamePrefix + name);
const res = await teams.edit({ id: team.id, name });
stopSpinner();
output.stopSpinner();
process.stdout.write(eraseLines(2));
if (res.error) {
console.error(error(res.error.message));
console.log(`${chalk.red(`${teamNamePrefix}`)}${name}`);
output.error(res.error.message);
output.log(`${chalk.red(`${teamNamePrefix}`)}${name}`);
return 1;
// TODO: maybe we want to ask the user to retry? not sure if
@@ -126,10 +120,10 @@ export default async function add(client, teams) {
team = Object.assign(team, res);
console.log(success(`Team name saved ${elapsed()}`));
console.log(`${chalk.cyan(`${chars.tick} `) + teamNamePrefix + team.name}\n`);
output.success(`Team name saved ${elapsed()}`);
output.log(`${chalk.cyan(`${chars.tick} `) + teamNamePrefix + team.name}\n`);
stopSpinner = wait('Saving');
output.spinner('Saving');
// Update config file
const configCopy = Object.assign({}, client.config);
@@ -142,7 +136,7 @@ export default async function add(client, teams) {
writeToConfigFile(configCopy);
stopSpinner();
output.stopSpinner();
await invite(client, { _: [] }, teams, {
introMsg: 'Invite your teammates! When done, press enter on an empty field',

View File

@@ -1,11 +1,3 @@
// Packages
import chalk from 'chalk';
// Utilities
import wait from '../../util/output/wait';
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 getUser from '../../util/get-user.ts';
@@ -23,7 +15,7 @@ export default async function list(client, argv, teams) {
return 1;
}
const stopSpinner = wait('Fetching teams');
output.spinner('Fetching teams');
const { teams: list, pagination } = await teams.ls({
next,
apiVersion: 2,
@@ -31,23 +23,19 @@ export default async function list(client, argv, teams) {
let { currentTeam } = config;
const accountIsCurrent = !currentTeam;
stopSpinner();
const stopUserSpinner = wait('Fetching user information');
output.spinner('Fetching user information');
let user;
try {
user = await getUser(client);
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
console.error(error(err.message));
output.error(err.message);
return 1;
}
throw err;
}
stopUserSpinner();
if (accountIsCurrent) {
currentTeam = {
slug: user.username || user.email,
@@ -79,12 +67,12 @@ export default async function list(client, argv, teams) {
const count = teamList.length;
if (!count) {
// Maybe should not happen
console.error(error(`No team found`));
output.error(`No teams found`);
return 1;
}
info(`${chalk.bold(count)} team${count > 1 ? 's' : ''} found`);
console.log();
output.stopSpinner();
console.log(); // empty line
table(
['', 'id', 'email / name'],

View File

@@ -1,9 +1,10 @@
import chalk from 'chalk';
import logo from '../util/output/logo';
import getScope from '../util/get-scope.ts';
import { getPkgName } from '../util/pkg-name.ts';
import getArgs from '../util/get-args.ts';
import handleError from '../util/handle-error.ts';
import getScope from '../util/get-scope';
import { getPkgName } from '../util/pkg-name';
import getArgs from '../util/get-args';
import handleError from '../util/handle-error';
import Client from '../util/client';
const help = () => {
console.log(`
@@ -31,7 +32,7 @@ const help = () => {
`);
};
export default async client => {
export default async (client: Client) => {
const { output } = client;
let argv;
try {

View File

@@ -50,6 +50,7 @@ import { SENTRY_DSN } from './util/constants.ts';
import getUpdateCommand from './util/get-update-command';
import { metrics, shouldCollectMetrics } from './util/metrics.ts';
import { getCommandName, getTitleName } from './util/pkg-name.ts';
import doLoginPrompt from './util/login/prompt.ts';
const isCanary = pkg.version.includes('canary');
@@ -422,13 +423,24 @@ const main = async () => {
) {
if (isTTY) {
output.log(info(`No existing credentials found. Please log in:`));
const result = await doLoginPrompt(client);
subcommand = 'login';
client.argv[2] = 'login';
// The login function failed, so it returned an exit code
if (typeof result === 'number') {
return result;
}
// Ensure that subcommands lead to login as well, if
// no credentials are defined
client.argv = client.argv.splice(0, 3);
// When `result` is a string it's the user's authentication token.
// It needs to be saved to the configuration file.
client.authConfig.token = result;
// New user, so we can't keep the team
delete client.config.currentTeam;
configFiles.writeToAuthConfigFile(client.authConfig);
configFiles.writeToConfigFile(client.config);
output.debug(`Saved credentials in "${hp(VERCEL_DIR)}"`);
} else {
output.prettyError({
message:

View File

@@ -16,12 +16,13 @@ export interface JSONObject {
}
export interface AuthConfig {
token: string;
token?: string;
skipWrite?: boolean;
}
export interface GlobalConfig {
currentTeam?: string;
includeScheme?: string;
collectMetrics?: boolean;
api?: string;
@@ -139,13 +140,14 @@ export type Deployment = {
| 'CANCELED';
version?: number;
created: number;
creator: { uid: string };
createdAt: number;
creator: { uid: string; username: string };
};
export type Alias = {
uid: string;
alias: string;
created: string;
createdAt: number;
deployment: {
id: string;
url: string;
@@ -270,6 +272,7 @@ export interface Project extends ProjectSettings {
rootDirectory?: string | null;
latestDeployments?: Partial<Deployment>[];
autoExposeSystemEnvs?: boolean;
sourceFilesOutsideRootDirectory: boolean;
}
export interface Org {

View File

@@ -1,5 +1,6 @@
import { Output } from '../output';
import { Alias } from '../../types';
import Client from '../client';
export default async function findAliasByAliasOrId(
@@ -11,7 +12,6 @@ export default async function findAliasByAliasOrId(
`/now/aliases/${encodeURIComponent(getSafeAlias(aliasOrId))}`
);
}
function getSafeAlias(alias: string) {
return alias
.replace(/^https:\/\//i, '')

View File

@@ -1,8 +1,9 @@
import { Alias } from '../../types';
import { Alias, PaginationOptions } from '../../types';
import Client from '../client';
type Response = {
aliases: Alias[];
pagination: PaginationOptions;
};
export default async function getAliases(

View File

@@ -2,6 +2,6 @@ import Client from '../client';
export default async function removeAliasById(client: Client, id: string) {
return client.fetch(`/now/aliases/${id}`, {
method: 'DELETE'
method: 'DELETE',
});
}

View File

@@ -1,6 +1,5 @@
import { readFileSync } from 'fs';
import { resolve } from 'path';
import wait from '../output/wait';
import Client from '../client';
import { Cert } from '../../types';
@@ -10,7 +9,7 @@ export default async function createCertFromFile(
certPath: string,
caPath: string
) {
const cancelWait = wait('Adding your custom certificate');
client.output.spinner('Adding your custom certificate');
try {
const cert = readFileSync(resolve(certPath), 'utf8');
@@ -36,7 +35,5 @@ export default async function createCertFromFile(
}
throw error;
} finally {
cancelWait();
}
}

View File

@@ -3,7 +3,6 @@ import chalk from 'chalk';
import { Cert } from '../../types';
import * as ERRORS from '../errors-ts';
import Client from '../client';
import wait from '../output/wait';
import mapCertError from './map-cert-error';
export default async function startCertOrder(
@@ -11,7 +10,7 @@ export default async function startCertOrder(
cns: string[],
context: string // eslint-disable-line
) {
const cancelWait = wait(
client.output.spinner(
`Issuing a certificate for ${chalk.bold(cns.join(', '))}`
);
try {
@@ -22,10 +21,8 @@ export default async function startCertOrder(
domains: cns,
},
});
cancelWait();
return cert;
} catch (error) {
cancelWait();
if (error.code === 'cert_order_not_found') {
return new ERRORS.CertOrderNotFound(cns);
}

View File

@@ -1,5 +1,4 @@
import chalk from 'chalk';
import wait from '../output/wait';
import Client from '../client';
export type CertificateChallenge = {
@@ -24,23 +23,17 @@ export default async function startCertOrder(
cns: string[],
contextName: string
) {
const cancelWait = wait(
client.output.spinner(
`Starting certificate issuance for ${chalk.bold(
cns.join(', ')
)} under ${chalk.bold(contextName)}`
);
try {
const order = await client.fetch<CertificateOrder>('/v3/now/certs', {
method: 'PATCH',
body: {
op: 'startOrder',
domains: cns
}
});
cancelWait();
return order;
} catch (error) {
cancelWait();
throw error;
}
const order = await client.fetch<CertificateOrder>('/v3/now/certs', {
method: 'PATCH',
body: {
op: 'startOrder',
domains: cns,
},
});
return order;
}

View File

@@ -48,6 +48,7 @@ export default class Client extends EventEmitter {
output: Output;
config: GlobalConfig;
localConfig: VercelConfig;
private requestIdCounter: number;
constructor(opts: ClientOptions) {
super();
@@ -57,6 +58,7 @@ export default class Client extends EventEmitter {
this.output = opts.output;
this.config = opts.config;
this.localConfig = opts.localConfig;
this.requestIdCounter = 1;
}
retry<T>(fn: RetryFunction<T>, { retries = 3, maxTimeout = Infinity } = {}) {
@@ -90,8 +92,10 @@ export default class Client extends EventEmitter {
}
const headers = new Headers(opts.headers);
headers.set('authorization', `Bearer ${this.authConfig.token}`);
headers.set('user-agent', ua);
if (this.authConfig.token) {
headers.set('authorization', `Bearer ${this.authConfig.token}`);
}
let body;
if (isJSONObject(opts.body)) {
@@ -102,10 +106,16 @@ export default class Client extends EventEmitter {
}
const url = `${apiUrl ? '' : this.apiUrl}${_url}`;
return this.output.time(
`${opts.method || 'GET'} ${url} ${JSON.stringify(opts.body) || ''}`,
fetch(url, { ...opts, headers, body })
);
const requestId = this.requestIdCounter++;
return this.output.time(res => {
if (res) {
return `#${requestId}${res.status} ${
res.statusText
}: ${res.headers.get('x-vercel-id')}`;
} else {
return `#${requestId}${opts.method || 'GET'} ${url}`;
}
}, fetch(url, { ...opts, headers, body }));
}
fetch(url: string, opts: { json: false }): Promise<Response>;
@@ -163,7 +173,7 @@ export default class Client extends EventEmitter {
process.exit(1);
}
this.authConfig.token = result;
this.authConfig.token = result.token;
writeToAuthConfigFile(this.authConfig);
});

View File

@@ -3,17 +3,21 @@ import * as ERRORS_TS from '../errors-ts';
import * as ERRORS from '../errors';
import { NowError } from '../now-error';
import mapCertError from '../certs/map-cert-error';
import { Org } from '../../types';
import Now from '..';
import Client from '../client';
import { DeploymentError } from '../../../../client/dist';
export default async function createDeploy(
output,
now,
contextName,
paths,
createArgs,
org,
isSettingUpProject,
cwd
) {
client: Client,
now: Now,
contextName: string,
paths: string[],
createArgs: any,
org: Org | null,
isSettingUpProject: boolean,
cwd?: string
): Promise<any | DeploymentError> {
try {
return await now.create(paths, createArgs, org, isSettingUpProject, cwd);
} catch (error) {
@@ -83,16 +87,17 @@ export default async function createDeploy(
// If the cert is missing we try to generate a new one and the retry
if (error.code === 'cert_missing') {
const result = await generateCertForDeploy(
output,
now,
client,
contextName,
error.value
);
if (result instanceof NowError) {
return result;
}
return createDeploy(
output,
client,
now,
contextName,
paths,

View File

@@ -1,17 +1,16 @@
import psl from 'psl';
import { NowError } from '../now-error';
import { Output } from '../output';
import Client from '../client';
import createCertForCns from '../certs/create-cert-for-cns';
import setupDomain from '../domains/setup-domain';
import { InvalidDomain } from '../errors-ts';
export default async function generateCertForDeploy(
output: Output,
client: Client,
contextName: string,
deployURL: string
) {
const { output } = client;
const parsedDomain = psl.parse(deployURL);
if (parsedDomain.error) {
return new InvalidDomain(deployURL, parsedDomain.error.message);

View File

@@ -1,25 +1,31 @@
import { URLSearchParams } from 'url';
import { Alias } from '../../types';
import Client from '../client';
type Response = {
deployments: Array<{
uid: string;
name: string;
url: string;
created: number;
state: 'INITIALIZING' | 'FROZEN' | 'READY' | 'ERROR';
creator: { uid: string };
instanceCount: number;
scale: {
[key: string]: number;
};
}>;
deployments: DeploymentPartial[];
};
export interface DeploymentPartial {
uid: string;
name: string;
url: string;
created: number;
createdAt: number;
aliases: Alias[];
state:
| 'BUILDING'
| 'ERROR'
| 'INITIALIZING'
| 'QUEUED'
| 'READY'
| 'CANCELED';
creator: { uid: string };
}
interface Options {
from: number | null;
limit: number | null;
continue: boolean;
from?: number | null;
limit?: number | null;
continue?: boolean;
max?: number;
}
@@ -28,7 +34,7 @@ export default async function getDeploymentsByProjectId(
projectId: string,
options: Options = { from: null, limit: 100, continue: false },
total: number = 0
) {
): Promise<DeploymentPartial[]> {
const limit = options.limit || 100;
const query = new URLSearchParams();

View File

@@ -96,7 +96,7 @@ async function createBuildProcess(
}
export async function executeBuild(
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
devServer: DevServer,
files: BuilderInputs,
match: BuildMatch,
@@ -263,7 +263,7 @@ export async function executeBuild(
}
const { output } = result;
const { cleanUrls } = nowConfig;
const { cleanUrls } = vercelConfig;
// Mimic fmeta-util and perform file renaming
Object.entries(output).forEach(([path, value]) => {
@@ -359,7 +359,7 @@ export async function executeBuild(
MemorySize: asset.memory || 3008,
Environment: {
Variables: {
...nowConfig.env,
...vercelConfig.env,
...asset.environment,
...envConfigs.runEnv,
},
@@ -383,7 +383,7 @@ export async function executeBuild(
}
export async function getBuildMatches(
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
cwd: string,
output: Output,
devServer: DevServer,
@@ -398,7 +398,7 @@ export async function getBuildMatches(
}
const noMatches: Builder[] = [];
const builds = nowConfig.builds || [{ src: '**', use: '@vercel/static' }];
const builds = vercelConfig.builds || [{ src: '**', use: '@vercel/static' }];
for (const buildConfig of builds) {
let { src = '**', use, config = {} } = buildConfig;

View File

@@ -50,7 +50,7 @@ export async function devRouter(
reqMethod?: string,
routes?: Route[],
devServer?: DevServer,
nowConfig?: VercelConfig,
vercelConfig?: VercelConfig,
previousHeaders?: HttpHeadersConfig,
missRoutes?: Route[],
phase?: HandleValue | null
@@ -124,14 +124,14 @@ export async function devRouter(
if (
routeConfig.check &&
devServer &&
nowConfig &&
vercelConfig &&
phase !== 'hit' &&
!isDestUrl
) {
const { pathname = '/' } = url.parse(destPath);
const hasDestFile = await devServer.hasFilesystem(
pathname,
nowConfig
vercelConfig
);
if (!hasDestFile) {
@@ -144,7 +144,7 @@ export async function devRouter(
reqMethod,
missRoutes,
devServer,
nowConfig,
vercelConfig,
combinedHeaders,
[],
'miss'

View File

@@ -145,6 +145,7 @@ export default class DevServer {
private devServerPids: Set<number>;
private projectSettings?: ProjectSettings;
private vercelConfigWarning: boolean;
private getVercelConfigPromise: Promise<VercelConfig> | null;
private blockingBuildsPromise: Promise<void> | null;
private updateBuildersPromise: Promise<void> | null;
@@ -181,6 +182,7 @@ export default class DevServer {
this.inProgressBuilds = new Map();
this.devCacheDir = join(getVercelDirectory(cwd), 'cache');
this.vercelConfigWarning = false;
this.getVercelConfigPromise = null;
this.blockingBuildsPromise = null;
this.updateBuildersPromise = null;
@@ -244,20 +246,18 @@ export default class DevServer {
}
}
const nowConfig = await this.getVercelConfig();
const vercelConfig = await this.getVercelConfig();
// Update the build matches in case an entrypoint was created or deleted
await this.updateBuildMatches(nowConfig);
await this.updateBuildMatches(vercelConfig);
const filesChangedArray = [...filesChanged];
const filesRemovedArray = [...filesRemoved];
// Trigger rebuilds of any existing builds that are dependent
// on one of the files that has changed
const needsRebuild: Map<
BuildResult,
[string | null, BuildMatch]
> = new Map();
const needsRebuild: Map<BuildResult, [string | null, BuildMatch]> =
new Map();
for (const match of this.buildMatches.values()) {
for (const [requestPath, result] of match.buildResults) {
@@ -290,13 +290,19 @@ export default class DevServer {
for (const [result, [requestPath, match]] of needsRebuild) {
if (
requestPath === null ||
(await shouldServe(match, this.files, requestPath, this, nowConfig))
(await shouldServe(
match,
this.files,
requestPath,
this,
vercelConfig
))
) {
this.triggerBuild(
match,
requestPath,
null,
nowConfig,
vercelConfig,
result,
filesChangedArray,
filesRemovedArray
@@ -375,12 +381,12 @@ export default class DevServer {
}
async updateBuildMatches(
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
isInitial = false
): Promise<void> {
const fileList = this.resolveBuildFiles(this.files);
const matches = await getBuildMatches(
nowConfig,
vercelConfig,
this.cwd,
this.output,
this,
@@ -417,7 +423,7 @@ export default class DevServer {
this.buildMatches.set(match.src, match);
if (!isInitial && needsBlockingBuild(match)) {
const buildPromise = executeBuild(
nowConfig,
vercelConfig,
this,
this.files,
match,
@@ -460,7 +466,7 @@ export default class DevServer {
}
async invalidateBuildMatches(
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
updatedBuilders: string[]
): Promise<void> {
if (updatedBuilders.length === 0) {
@@ -483,7 +489,7 @@ export default class DevServer {
}
// Re-add the build matches that were just removed, but with the new builder
await this.updateBuildMatches(nowConfig);
await this.updateBuildMatches(vercelConfig);
}
async getLocalEnv(fileName: string, base?: Env): Promise<Env> {
@@ -540,26 +546,26 @@ export default class DevServer {
pkg = null,
// The default empty `vercel.json` is used to serve all
// files as static when no `vercel.json` is present
config = { version: 2, [fileNameSymbol]: 'vercel.json' },
vercelConfig = { version: 2, [fileNameSymbol]: 'vercel.json' },
] = await Promise.all([
this.readJsonFile<PackageJson>('package.json'),
this.readJsonFile<VercelConfig>(configPath),
]);
await this.validateVercelConfig(config);
await this.validateVercelConfig(vercelConfig);
const { error: routeError, routes: maybeRoutes } = getTransformedRoutes({
nowConfig: config,
nowConfig: vercelConfig,
});
if (routeError) {
this.output.prettyError(routeError);
await this.exit();
}
config.routes = maybeRoutes || [];
vercelConfig.routes = maybeRoutes || [];
// no builds -> zero config
if (!config.builds || config.builds.length === 0) {
if (!vercelConfig.builds || vercelConfig.builds.length === 0) {
const featHandleMiss = true; // enable for zero config
const { projectSettings, cleanUrls, trailingSlash } = config;
const { projectSettings, cleanUrls, trailingSlash } = vercelConfig;
const opts = { output: this.output };
const files = (await getFiles(this.cwd, opts)).map(f =>
@@ -576,7 +582,7 @@ export default class DevServer {
errorRoutes,
} = await detectBuilders(files, pkg, {
tag: getDistTag(cliPkg.version) === 'canary' ? 'canary' : 'latest',
functions: config.functions,
functions: vercelConfig.functions,
projectSettings: projectSettings || this.projectSettings,
featHandleMiss,
cleanUrls,
@@ -599,18 +605,17 @@ export default class DevServer {
builders = builders.filter(filterFrontendBuilds);
}
config.builds = config.builds || [];
config.builds.push(...builders);
vercelConfig.builds = vercelConfig.builds || [];
vercelConfig.builds.push(...builders);
delete config.functions;
delete vercelConfig.functions;
}
let routes: Route[] = [];
const { routes: nowConfigRoutes } = config;
routes.push(...(redirectRoutes || []));
routes.push(
...appendRoutesToPhase({
routes: nowConfigRoutes,
routes: vercelConfig.routes,
newRoutes: rewriteRoutes,
phase: 'filesystem',
})
@@ -621,29 +626,43 @@ export default class DevServer {
phase: 'error',
});
routes.push(...(defaultRoutes || []));
config.routes = routes;
vercelConfig.routes = routes;
}
if (Array.isArray(config.builds)) {
if (Array.isArray(vercelConfig.builds)) {
if (this.devCommand) {
config.builds = config.builds.filter(filterFrontendBuilds);
vercelConfig.builds = vercelConfig.builds.filter(filterFrontendBuilds);
}
// `@vercel/static-build` needs to be the last builder
// since it might catch all other requests
config.builds.sort(sortBuilders);
vercelConfig.builds.sort(sortBuilders);
}
await this.validateVercelConfig(config);
await this.validateVercelConfig(vercelConfig);
this.caseSensitive = hasNewRoutingProperties(config);
this.apiDir = detectApiDirectory(config.builds || []);
this.apiExtensions = detectApiExtensions(config.builds || []);
// TODO: temporarily strip and warn since `has` is not implemented yet
vercelConfig.routes = (vercelConfig.routes || []).filter(route => {
if ('has' in route) {
if (!this.vercelConfigWarning) {
this.vercelConfigWarning = true;
this.output.warn(
`The "has" property in ${vercelConfig[fileNameSymbol]} will be ignored during development. Deployments will work as expected.`
);
}
return false;
}
return true;
});
this.caseSensitive = hasNewRoutingProperties(vercelConfig);
this.apiDir = detectApiDirectory(vercelConfig.builds || []);
this.apiExtensions = detectApiExtensions(vercelConfig.builds || []);
// Update the env vars configuration
let [runEnv, buildEnv] = await Promise.all([
this.getLocalEnv('.env', config.env),
this.getLocalEnv('.env.build', config.build?.env),
this.getLocalEnv('.env', vercelConfig.env),
this.getLocalEnv('.env.build', vercelConfig.build?.env),
]);
let allEnv = { ...buildEnv, ...runEnv };
@@ -675,7 +694,7 @@ export default class DevServer {
}
this.envConfigs = { buildEnv, runEnv, allEnv };
return config;
return vercelConfig;
}
async readJsonFile<T>(
@@ -855,7 +874,7 @@ export default class DevServer {
.replace('[::]', 'localhost')
.replace('127.0.0.1', 'localhost');
const nowConfig = await this.getVercelConfig();
const vercelConfig = await this.getVercelConfig();
const devCommandPromise = this.runDevCommand();
const files = await getFiles(this.cwd, { output: this.output });
@@ -871,13 +890,13 @@ export default class DevServer {
}
const builders = new Set<string>(
(nowConfig.builds || [])
(vercelConfig.builds || [])
.filter((b: Builder) => b.use)
.map((b: Builder) => b.use)
);
await installBuilders(builders, this.output);
await this.updateBuildMatches(nowConfig, true);
await this.updateBuildMatches(vercelConfig, true);
// Updating builders happens lazily, and any builders that were updated
// get their "build matches" invalidated so that the new version is used.
@@ -885,7 +904,7 @@ export default class DevServer {
this.updateBuildersPromise = updateBuilders(builders, this.output)
.then(updatedBuilders => {
this.updateBuildersPromise = null;
this.invalidateBuildMatches(nowConfig, updatedBuilders);
this.invalidateBuildMatches(vercelConfig, updatedBuilders);
})
.catch(err => {
this.updateBuildersPromise = null;
@@ -906,7 +925,7 @@ export default class DevServer {
);
for (const match of blockingBuilds) {
await executeBuild(nowConfig, this, this.files, match, null, true);
await executeBuild(vercelConfig, this, this.files, match, null, true);
}
this.output.success('Build completed');
@@ -1046,21 +1065,21 @@ export default class DevServer {
async send404(
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string
requestId: string
): Promise<void> {
return this.sendError(req, res, nowRequestId, 'NOT_FOUND', 404);
return this.sendError(req, res, requestId, 'NOT_FOUND', 404);
}
async sendError(
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string,
requestId: string,
errorCode?: string,
statusCode: number = 500,
headers: HttpHeadersConfig = {}
): Promise<void> {
res.statusCode = statusCode;
this.setResponseHeaders(res, nowRequestId, headers);
this.setResponseHeaders(res, requestId, headers);
const http_status_description = generateHttpStatusDescription(statusCode);
const error_code = errorCode || http_status_description;
@@ -1087,7 +1106,7 @@ export default class DevServer {
http_status_code: statusCode,
http_status_description,
error_code,
now_id: nowRequestId,
request_id: requestId,
});
} else if (statusCode === 502) {
view = errorTemplate502({
@@ -1095,13 +1114,13 @@ export default class DevServer {
http_status_code: statusCode,
http_status_description,
error_code,
now_id: nowRequestId,
request_id: requestId,
});
} else {
view = errorTemplate({
http_status_code: statusCode,
http_status_description,
now_id: nowRequestId,
request_id: requestId,
});
}
body = errorTemplateBase({
@@ -1119,14 +1138,14 @@ export default class DevServer {
async sendRedirect(
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string,
requestId: string,
location: string,
statusCode: number = 302
): Promise<void> {
this.output.debug(`Redirect ${statusCode}: ${location}`);
res.statusCode = statusCode;
this.setResponseHeaders(res, nowRequestId, { location });
this.setResponseHeaders(res, requestId, { location });
let body: string;
const { accept = 'text/plain' } = req.headers;
@@ -1157,14 +1176,14 @@ export default class DevServer {
*/
setResponseHeaders(
res: http.ServerResponse,
nowRequestId: string,
requestId: string,
headers: http.OutgoingHttpHeaders = {}
): void {
const allHeaders = {
'cache-control': 'public, max-age=0, must-revalidate',
...headers,
server: 'Vercel',
'x-vercel-id': nowRequestId,
'x-vercel-id': requestId,
'x-vercel-cache': 'MISS',
};
for (const [name, value] of Object.entries(allHeaders)) {
@@ -1175,9 +1194,9 @@ export default class DevServer {
/**
* Returns the request `headers` that will be sent to the Lambda.
*/
getNowProxyHeaders(
getProxyHeaders(
req: http.IncomingMessage,
nowRequestId: string,
requestId: string,
xfwd: boolean
): http.IncomingHttpHeaders {
const ip = this.getRequestIp(req);
@@ -1187,7 +1206,7 @@ export default class DevServer {
'x-real-ip': ip,
'x-vercel-deployment-url': host,
'x-vercel-forwarded-for': ip,
'x-vercel-id': nowRequestId,
'x-vercel-id': requestId,
};
if (xfwd) {
headers['x-forwarded-host'] = host;
@@ -1201,7 +1220,7 @@ export default class DevServer {
match: BuildMatch,
requestPath: string | null,
req: http.IncomingMessage | null,
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
previousBuildResult?: BuildResult,
filesChanged?: string[],
filesRemoved?: string[]
@@ -1237,7 +1256,7 @@ export default class DevServer {
}
this.output.debug(msg);
buildPromise = executeBuild(
nowConfig,
vercelConfig,
this,
this.files,
match,
@@ -1278,11 +1297,11 @@ export default class DevServer {
) => {
await this.startPromise;
let nowRequestId = generateRequestId(this.podId);
let requestId = generateRequestId(this.podId);
if (this.stopping) {
res.setHeader('Connection', 'close');
await this.send404(req, res, nowRequestId);
await this.send404(req, res, requestId);
return;
}
@@ -1290,8 +1309,8 @@ export default class DevServer {
this.output.debug(`${chalk.bold(method)} ${req.url}`);
try {
const nowConfig = await this.getVercelConfig();
await this.serveProjectAsNowV2(req, res, nowRequestId, nowConfig);
const vercelConfig = await this.getVercelConfig();
await this.serveProjectAsNowV2(req, res, requestId, vercelConfig);
} catch (err) {
console.error(err);
this.output.debug(err.stack);
@@ -1312,20 +1331,20 @@ export default class DevServer {
phase: HandleValue | null,
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string
requestId: string
): Promise<boolean> => {
const { status, headers, dest } = routeResult;
const location = headers['location'] || dest;
if (status && location && 300 <= status && status <= 399) {
this.output.debug(`Route found with redirect status code ${status}`);
await this.sendRedirect(req, res, nowRequestId, location, status);
await this.sendRedirect(req, res, requestId, location, status);
return true;
}
if (!match && status && phase !== 'miss') {
this.output.debug(`Route found with with status code ${status}`);
await this.sendError(req, res, nowRequestId, '', status, headers);
await this.sendError(req, res, requestId, '', status, headers);
return true;
}
@@ -1338,9 +1357,9 @@ export default class DevServer {
serveProjectAsNowV2 = async (
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string,
nowConfig: VercelConfig,
routes: Route[] | undefined = nowConfig.routes,
requestId: string,
vercelConfig: VercelConfig,
routes: Route[] | undefined = vercelConfig.routes,
callLevel: number = 0
) => {
const { debug } = this.output;
@@ -1357,7 +1376,7 @@ export default class DevServer {
// Only `GET` requests are redirected.
// Other methods are normalized without redirecting.
if (req.method === 'GET') {
await this.sendRedirect(req, res, nowRequestId, location, 301);
await this.sendRedirect(req, res, requestId, location, 301);
return;
}
@@ -1366,7 +1385,7 @@ export default class DevServer {
}
if (callLevel === 0) {
await this.updateBuildMatches(nowConfig);
await this.updateBuildMatches(vercelConfig);
}
if (this.blockingBuildsPromise) {
@@ -1408,7 +1427,7 @@ export default class DevServer {
req.method,
phaseRoutes,
this,
nowConfig,
vercelConfig,
prevHeaders,
missRoutes,
phase
@@ -1428,8 +1447,8 @@ export default class DevServer {
const destUrl = url.format(destParsed);
debug(`ProxyPass: ${destUrl}`);
this.setResponseHeaders(res, nowRequestId);
return proxyPass(req, res, destUrl, this, nowRequestId);
this.setResponseHeaders(res, requestId);
return proxyPass(req, res, destUrl, this, requestId);
}
match = await findBuildMatch(
@@ -1437,7 +1456,7 @@ export default class DevServer {
this.files,
routeResult.dest,
this,
nowConfig
vercelConfig
);
if (
@@ -1447,7 +1466,7 @@ export default class DevServer {
phase,
req,
res,
nowRequestId
requestId
)
) {
return;
@@ -1460,7 +1479,7 @@ export default class DevServer {
req.method,
missRoutes,
this,
nowConfig,
vercelConfig,
routeResult.headers,
[],
'miss'
@@ -1471,7 +1490,7 @@ export default class DevServer {
this.files,
routeResult.dest,
this,
nowConfig
vercelConfig
);
if (
await this.exitWithStatus(
@@ -1480,7 +1499,7 @@ export default class DevServer {
phase,
req,
res,
nowRequestId
requestId
)
) {
return;
@@ -1494,7 +1513,7 @@ export default class DevServer {
req.method,
hitRoutes,
this,
nowConfig,
vercelConfig,
routeResult.headers,
[],
'hit'
@@ -1522,7 +1541,7 @@ export default class DevServer {
req.method,
errorRoutes,
this,
nowConfig,
vercelConfig,
routeResult.headers,
[],
'error'
@@ -1534,7 +1553,7 @@ export default class DevServer {
this.files,
routeResultForError.dest,
this,
nowConfig
vercelConfig
);
if (matchForError) {
@@ -1553,7 +1572,7 @@ export default class DevServer {
'error',
req,
res,
nowRequestId
requestId
)
) {
return;
@@ -1595,25 +1614,25 @@ export default class DevServer {
debug(`Proxying to frontend dev server: ${upstream}`);
// Add the Vercel platform proxy request headers
const headers = this.getNowProxyHeaders(req, nowRequestId, false);
const headers = this.getProxyHeaders(req, requestId, false);
for (const [name, value] of Object.entries(headers)) {
req.headers[name] = value;
}
this.setResponseHeaders(res, nowRequestId);
this.setResponseHeaders(res, requestId);
const origUrl = url.parse(req.url || '/', true);
delete origUrl.search;
origUrl.pathname = dest;
Object.assign(origUrl.query, uri_args);
req.url = url.format(origUrl);
return proxyPass(req, res, upstream, this, nowRequestId, false);
return proxyPass(req, res, upstream, this, requestId, false);
}
if (
(statusCode === 404 && routeResult.phase === 'miss') ||
!this.renderDirectoryListing(req, res, requestPath, nowRequestId)
!this.renderDirectoryListing(req, res, requestPath, requestId)
) {
await this.send404(req, res, nowRequestId);
await this.send404(req, res, requestId);
}
return;
}
@@ -1639,7 +1658,7 @@ export default class DevServer {
req.method,
buildResult.routes,
this,
nowConfig
vercelConfig
);
if (matchedRoute.found && callLevel === 0) {
debug(`Found matching route ${matchedRoute.dest} for ${newUrl}`);
@@ -1647,8 +1666,8 @@ export default class DevServer {
await this.serveProjectAsNowV2(
req,
res,
nowRequestId,
nowConfig,
requestId,
vercelConfig,
buildResult.routes,
callLevel + 1
);
@@ -1697,7 +1716,7 @@ export default class DevServer {
await this.sendError(
req,
res,
nowRequestId,
requestId,
'NO_RESPONSE_FROM_FUNCTION',
502
);
@@ -1707,7 +1726,7 @@ export default class DevServer {
if (devServerResult) {
// When invoking lambda functions, the region where the lambda was invoked
// is also included in the request ID. So use the same `dev1` fake region.
nowRequestId = generateRequestId(this.podId, true);
requestId = generateRequestId(this.podId, true);
const { port, pid } = devServerResult;
this.devServerPids.add(pid);
@@ -1729,31 +1748,31 @@ export default class DevServer {
});
// Add the Vercel platform proxy request headers
const headers = this.getNowProxyHeaders(req, nowRequestId, false);
const headers = this.getProxyHeaders(req, requestId, false);
for (const [name, value] of Object.entries(headers)) {
req.headers[name] = value;
}
this.setResponseHeaders(res, nowRequestId);
this.setResponseHeaders(res, requestId);
return proxyPass(
req,
res,
`http://localhost:${port}`,
this,
nowRequestId,
requestId,
false
);
} else {
debug(`Skipping \`startDevServer()\` for ${match.entrypoint}`);
}
}
let foundAsset = findAsset(match, requestPath, nowConfig);
let foundAsset = findAsset(match, requestPath, vercelConfig);
if (!foundAsset && callLevel === 0) {
await this.triggerBuild(match, buildRequestPath, req, nowConfig);
await this.triggerBuild(match, buildRequestPath, req, vercelConfig);
// Since the `asset` was just built, resolve again to get the new asset
foundAsset = findAsset(match, requestPath, nowConfig);
foundAsset = findAsset(match, requestPath, vercelConfig);
}
// Proxy to the dev server:
@@ -1766,24 +1785,24 @@ export default class DevServer {
debug('Proxying to frontend dev server');
// Add the Vercel platform proxy request headers
const headers = this.getNowProxyHeaders(req, nowRequestId, false);
const headers = this.getProxyHeaders(req, requestId, false);
for (const [name, value] of Object.entries(headers)) {
req.headers[name] = value;
}
this.setResponseHeaders(res, nowRequestId);
this.setResponseHeaders(res, requestId);
return proxyPass(
req,
res,
`http://localhost:${this.devProcessPort}`,
this,
nowRequestId,
requestId,
false
);
}
if (!foundAsset) {
await this.send404(req, res, nowRequestId);
await this.send404(req, res, requestId);
return;
}
@@ -1797,7 +1816,7 @@ export default class DevServer {
/* eslint-disable no-case-declarations */
switch (asset.type) {
case 'FileFsRef':
this.setResponseHeaders(res, nowRequestId);
this.setResponseHeaders(res, requestId);
req.url = `/${basename(asset.fsPath)}`;
return serveStaticFile(req, res, dirname(asset.fsPath), {
headers: [
@@ -1818,7 +1837,7 @@ export default class DevServer {
'Content-Length': asset.data.length,
'Content-Type': asset.contentType || getMimeType(assetKey),
};
this.setResponseHeaders(res, nowRequestId, headers);
this.setResponseHeaders(res, requestId, headers);
res.end(asset.data);
return;
@@ -1830,7 +1849,7 @@ export default class DevServer {
await this.sendError(
req,
res,
nowRequestId,
requestId,
'INTERNAL_LAMBDA_NOT_FOUND'
);
return;
@@ -1838,7 +1857,7 @@ export default class DevServer {
// When invoking lambda functions, the region where the lambda was invoked
// is also included in the request ID. So use the same `dev1` fake region.
nowRequestId = generateRequestId(this.podId, true);
requestId = generateRequestId(this.podId, true);
// Mix the `routes` result dest query params into the req path
const parsed = url.parse(req.url || '/', true);
@@ -1855,7 +1874,7 @@ export default class DevServer {
path,
headers: {
...req.headers,
...this.getNowProxyHeaders(req, nowRequestId, true),
...this.getProxyHeaders(req, requestId, true),
},
encoding: 'base64',
body: body.toString('base64'),
@@ -1874,7 +1893,7 @@ export default class DevServer {
await this.sendError(
req,
res,
nowRequestId,
requestId,
'NO_RESPONSE_FROM_FUNCTION',
502
);
@@ -1884,7 +1903,7 @@ export default class DevServer {
if (!statusCode) {
res.statusCode = result.statusCode;
}
this.setResponseHeaders(res, nowRequestId, result.headers);
this.setResponseHeaders(res, requestId, result.headers);
let resBody: Buffer | string | undefined;
if (result.encoding === 'base64' && typeof result.body === 'string') {
@@ -1896,15 +1915,15 @@ export default class DevServer {
default:
// This shouldn't really ever happen...
await this.sendError(req, res, nowRequestId, 'UNKNOWN_ASSET_TYPE');
await this.sendError(req, res, requestId, 'UNKNOWN_ASSET_TYPE');
}
};
renderDirectoryListing(
req: http.IncomingMessage,
_req: http.IncomingMessage,
res: http.ServerResponse,
requestPath: string,
nowRequestId: string
requestId: string
): boolean {
// If the "directory listing" feature is disabled in the
// Project's settings, then don't render the directory listing
@@ -1982,7 +2001,7 @@ export default class DevServer {
paths,
directory,
});
this.setResponseHeaders(res, nowRequestId);
this.setResponseHeaders(res, requestId);
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader(
'Content-Length',
@@ -1992,14 +2011,17 @@ export default class DevServer {
return true;
}
async hasFilesystem(dest: string, nowConfig: VercelConfig): Promise<boolean> {
async hasFilesystem(
dest: string,
vercelConfig: VercelConfig
): Promise<boolean> {
if (
await findBuildMatch(
this.buildMatches,
this.files,
dest,
this,
nowConfig,
vercelConfig,
true
)
) {
@@ -2105,7 +2127,7 @@ function proxyPass(
res: http.ServerResponse,
dest: string,
devServer: DevServer,
nowRequestId: string,
requestId: string,
ignorePath: boolean = true
): void {
return devServer.proxy.web(
@@ -2120,7 +2142,7 @@ function proxyPass(
devServer.sendError(
req,
res,
nowRequestId,
requestId,
'NO_RESPONSE_FROM_FUNCTION',
502
);
@@ -2181,7 +2203,7 @@ async function findBuildMatch(
files: BuilderInputs,
requestPath: string,
devServer: DevServer,
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
isFilesystem = false
): Promise<BuildMatch | null> {
requestPath = requestPath.replace(/^\//, '');
@@ -2194,7 +2216,7 @@ async function findBuildMatch(
files,
requestPath,
devServer,
nowConfig,
vercelConfig,
isFilesystem
)
) {
@@ -2219,7 +2241,7 @@ async function shouldServe(
files: BuilderInputs,
requestPath: string,
devServer: DevServer,
nowConfig: VercelConfig,
vercelConfig: VercelConfig,
isFilesystem = false
): Promise<boolean> {
const {
@@ -2233,22 +2255,22 @@ async function shouldServe(
: requestPath;
if (
nowConfig.cleanUrls &&
nowConfig.trailingSlash &&
vercelConfig.cleanUrls &&
vercelConfig.trailingSlash &&
cleanSrc === trimmedPath
) {
// Mimic fmeta-util and convert cleanUrls and trailingSlash
return true;
} else if (
nowConfig.cleanUrls &&
!nowConfig.trailingSlash &&
vercelConfig.cleanUrls &&
!vercelConfig.trailingSlash &&
cleanSrc === requestPath
) {
// Mimic fmeta-util and convert cleanUrls
return true;
} else if (
!nowConfig.cleanUrls &&
nowConfig.trailingSlash &&
!vercelConfig.cleanUrls &&
vercelConfig.trailingSlash &&
src === trimmedPath
) {
// Mimic fmeta-util and convert trailingSlash
@@ -2264,13 +2286,13 @@ async function shouldServe(
if (shouldServe) {
return true;
}
} else if (findAsset(match, requestPath, nowConfig)) {
} else if (findAsset(match, requestPath, vercelConfig)) {
// If there's no `shouldServe()` function, then look up if there's
// a matching build asset on the `match` that has already been built.
return true;
} else if (
!isFilesystem &&
(await findMatchingRoute(match, requestPath, devServer, nowConfig))
(await findMatchingRoute(match, requestPath, devServer, vercelConfig))
) {
// If there's no `shouldServe()` function and no matched asset, then look
// up if there's a matching build route on the `match` that has already
@@ -2284,7 +2306,7 @@ async function findMatchingRoute(
match: BuildMatch,
requestPath: string,
devServer: DevServer,
nowConfig: VercelConfig
vercelConfig: VercelConfig
): Promise<RouteResult | void> {
const reqUrl = `/${requestPath}`;
for (const buildResult of match.buildResults.values()) {
@@ -2294,7 +2316,7 @@ async function findMatchingRoute(
undefined,
buildResult.routes,
devServer,
nowConfig
vercelConfig
);
if (route.found) {
return route;
@@ -2305,7 +2327,7 @@ async function findMatchingRoute(
function findAsset(
match: BuildMatch,
requestPath: string,
nowConfig: VercelConfig
vercelConfig: VercelConfig
): { asset: BuilderOutput; assetKey: string } | void {
if (!match.buildOutput) {
return;
@@ -2313,7 +2335,7 @@ function findAsset(
let assetKey: string = requestPath.replace(/\/$/, '');
let asset = match.buildOutput[requestPath];
if (nowConfig.trailingSlash && requestPath.endsWith('/')) {
if (vercelConfig.trailingSlash && requestPath.endsWith('/')) {
asset = match.buildOutput[requestPath.slice(0, -1)];
}
@@ -2397,13 +2419,13 @@ function filterFrontendBuilds(build: Builder) {
return !frontendRuntimeSet.has(name || '');
}
function hasNewRoutingProperties(nowConfig: VercelConfig) {
function hasNewRoutingProperties(vercelConfig: VercelConfig) {
return (
typeof nowConfig.cleanUrls !== undefined ||
typeof nowConfig.headers !== undefined ||
typeof nowConfig.redirects !== undefined ||
typeof nowConfig.rewrites !== undefined ||
typeof nowConfig.trailingSlash !== undefined
typeof vercelConfig.cleanUrls !== undefined ||
typeof vercelConfig.headers !== undefined ||
typeof vercelConfig.redirects !== undefined ||
typeof vercelConfig.rewrites !== undefined ||
typeof vercelConfig.trailingSlash !== undefined
);
}

View File

@@ -4,6 +4,6 @@
{{? it.error_code }}
<span class="devinfo-line">Code: <code>{{! it.error_code }}</code></span>
{{?}}
<span class="devinfo-line">ID: <code>{{! it.now_id }}</code>
<span class="devinfo-line">ID: <code>{{! it.request_id }}</code>
</p>
</main>

View File

@@ -2,5 +2,5 @@ interface Inputs {
http_status_code: number;
http_status_description: string;
error_code?: string;
now_id: string;
request_id: string;
}

View File

@@ -4,6 +4,6 @@
{{? it.error_code }}
<span class="devinfo-line">Code: <code>{{! it.error_code }}</code></span>
{{?}}
<span class="devinfo-line">ID: <code>{{! it.now_id }}</code>
<span class="devinfo-line">ID: <code>{{! it.request_id }}</code>
</p>
</main>

View File

@@ -5,5 +5,5 @@ interface Inputs {
http_status_code: number;
http_status_description: string;
error_code?: string;
now_id: string;
request_id: string;
}

View File

@@ -38,7 +38,7 @@
{{? it.error_code }}
<span class="devinfo-line">Code: <code>{{! it.error_code }}</code></span>
{{?}}
<span class="devinfo-line">ID: <code>{{! it.now_id }}</code>
<span class="devinfo-line">ID: <code>{{! it.request_id }}</code>
</p>
{{? it.app_error }}
<p>

View File

@@ -5,5 +5,5 @@ interface Inputs {
http_status_code: number;
http_status_description: string;
error_code?: string;
now_id: string;
request_id: string;
}

View File

@@ -4,7 +4,6 @@ import { Output } from '../output';
import Client from '../client';
import getDomainDNSRecords from './get-domain-dns-records';
import getDomains from '../domains/get-domains';
import wait from '../output/wait';
import chalk from 'chalk';
export type DomainRecordsItem = {
@@ -60,11 +59,7 @@ async function getDomainNames(
contextName: string,
next?: number
) {
const cancelWait = wait(`Fetching domains under ${chalk.bold(contextName)}`);
try {
const { domains, pagination } = await getDomains(client, next);
return { domainNames: domains.map(domain => domain.name), pagination };
} finally {
cancelWait();
}
client.output.spinner(`Fetching domains under ${chalk.bold(contextName)}`);
const { domains, pagination } = await getDomains(client, next);
return { domainNames: domains.map(domain => domain.name), pagination };
}

View File

@@ -4,7 +4,6 @@ import { resolve } from 'path';
import { Response } from 'node-fetch';
import { DomainNotFound, InvalidDomain } from '../errors-ts';
import Client from '../client';
import wait from '../output/wait';
type JSONResponse = {
recordIds: string[];
@@ -16,7 +15,7 @@ export default async function importZonefile(
domain: string,
zonefilePath: string
) {
const cancelWait = wait(
client.output.spinner(
`Importing Zone file for domain ${domain} under ${chalk.bold(contextName)}`
);
const zonefile = readFileSync(resolve(zonefilePath), 'utf8');
@@ -33,10 +32,8 @@ export default async function importZonefile(
);
const { recordIds } = (await res.json()) as JSONResponse;
cancelWait();
return recordIds;
} catch (error) {
cancelWait();
if (error.code === 'not_found') {
return new DomainNotFound(domain, contextName);
}

View File

@@ -3,7 +3,6 @@ import retry from 'async-retry';
import { DomainAlreadyExists, InvalidDomain } from '../errors-ts';
import { Domain } from '../../types';
import Client from '../client';
import wait from '../output/wait';
type Response = {
domain: Domain;
@@ -14,17 +13,11 @@ export default async function addDomain(
domain: string,
contextName: string
) {
const cancelWait = wait(
client.output.spinner(
`Adding domain ${domain} under ${chalk.bold(contextName)}`
);
try {
const addedDomain = await performAddRequest(client, domain);
cancelWait();
return addedDomain;
} catch (error) {
cancelWait();
throw error;
}
const addedDomain = await performAddRequest(client, domain);
return addedDomain;
}
async function performAddRequest(client: Client, domainName: string) {

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import Client from '../client';
import wait from '../output/wait';
import { Domain } from '../../types';
import { DomainPermissionDenied, DomainNotFound } from '../errors-ts';
@@ -16,14 +15,15 @@ export default async function getDomainByName(
ignoreWait?: boolean;
} = {}
) {
const cancelWait = options.ignoreWait
? null
: wait(`Fetching domain ${domainName} under ${chalk.bold(contextName)}`);
if (!options.ignoreWait) {
client.output.spinner(
`Fetching domain ${domainName} under ${chalk.bold(contextName)}`
);
}
try {
const { domain } = await client.fetch<Response>(
`/v4/domains/${encodeURIComponent(domainName)}`
);
return domain;
} catch (error) {
if (error.status === 404) {
@@ -35,7 +35,5 @@ export default async function getDomainByName(
}
throw error;
} finally {
cancelWait?.();
}
}

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import Client from '../client';
import wait from '../output/wait';
import { Domain } from '../../types';
type Response = {
@@ -12,7 +11,7 @@ export async function getDomain(
contextName: string,
domainName: string
) {
const cancelWait = wait(
client.output.spinner(
`Fetching domain ${domainName} under ${chalk.bold(contextName)}`
);
try {
@@ -27,7 +26,5 @@ export async function getDomain(
}
throw error;
} finally {
cancelWait();
}
}

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