mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 21:07:47 +00:00
Compare commits
60 Commits
@vercel/py
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15c7ad241a | ||
|
|
ec57654b5b | ||
|
|
3b9a9878bc | ||
|
|
70b7db1a15 | ||
|
|
41d6666139 | ||
|
|
2857219f89 | ||
|
|
246c2a0f5d | ||
|
|
d91bca7d6b | ||
|
|
be54fce67b | ||
|
|
7753bb8d89 | ||
|
|
ce17ac5c35 | ||
|
|
8006fc32b8 | ||
|
|
8038a90db1 | ||
|
|
f88c862e9d | ||
|
|
9170820371 | ||
|
|
c881546e0e | ||
|
|
fa21db98e4 | ||
|
|
8eabbfc666 | ||
|
|
6783f7afc9 | ||
|
|
a400b9b29d | ||
|
|
b549c37149 | ||
|
|
30d5e64291 | ||
|
|
47c2c361d2 | ||
|
|
438576fc7c | ||
|
|
b30343ef7b | ||
|
|
2dc0dfa572 | ||
|
|
9ee54b3dd6 | ||
|
|
9d67e0bc06 | ||
|
|
466135cf84 | ||
|
|
eab2e229dc | ||
|
|
698b89a2ba | ||
|
|
bae2a2e4df | ||
|
|
57916bb712 | ||
|
|
12bbd4e8eb | ||
|
|
4e4c7023dc | ||
|
|
41805790e7 | ||
|
|
6ad77ae8e1 | ||
|
|
e8daf36cd7 | ||
|
|
c319a2c499 | ||
|
|
a410baa797 | ||
|
|
625568e659 | ||
|
|
41868c1fe0 | ||
|
|
1b644f1218 | ||
|
|
29ea0fb06b | ||
|
|
b61f049f11 | ||
|
|
16e28f326b | ||
|
|
276397c940 | ||
|
|
85d7311199 | ||
|
|
b8114b8b39 | ||
|
|
d63e8d3187 | ||
|
|
11d3dd04aa | ||
|
|
46bf95ee36 | ||
|
|
92252468c2 | ||
|
|
71b83d5587 | ||
|
|
d9e5fdc5e4 | ||
|
|
58f479c603 | ||
|
|
d62461d952 | ||
|
|
e7f524defb | ||
|
|
bdefd0d05d | ||
|
|
ca522fc9f1 |
@@ -6,6 +6,7 @@
|
|||||||
!.yarnrc
|
!.yarnrc
|
||||||
!yarn.lock
|
!yarn.lock
|
||||||
!package.json
|
!package.json
|
||||||
|
!turbo.json
|
||||||
|
|
||||||
# api
|
# api
|
||||||
!api/
|
!api/
|
||||||
@@ -14,4 +15,4 @@
|
|||||||
# packages
|
# packages
|
||||||
!packages/
|
!packages/
|
||||||
!packages/frameworks
|
!packages/frameworks
|
||||||
!packages/frameworks/**
|
!packages/frameworks/**
|
||||||
@@ -307,15 +307,15 @@ This is a [class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere
|
|||||||
|
|
||||||
This is an abstract enumeration type that is implemented by one of the following possible `String` values:
|
This is an abstract enumeration type that is implemented by one of the following possible `String` values:
|
||||||
|
|
||||||
|
- `nodejs14.x`
|
||||||
- `nodejs12.x`
|
- `nodejs12.x`
|
||||||
- `nodejs10.x`
|
|
||||||
- `go1.x`
|
- `go1.x`
|
||||||
- `java11`
|
- `java11`
|
||||||
- `python3.9`
|
- `python3.9`
|
||||||
- `python3.6`
|
- `dotnet6`
|
||||||
- `dotnetcore2.1`
|
- `dotnetcore3.1`
|
||||||
- `ruby2.5`
|
- `ruby2.7`
|
||||||
- `provided`
|
- `provided.al2`
|
||||||
|
|
||||||
## `@vercel/build-utils` Helper Functions
|
## `@vercel/build-utils` Helper Functions
|
||||||
|
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ If you would not like to verify your domain, you can remove it from your account
|
|||||||
|
|
||||||
#### Resources
|
#### Resources
|
||||||
|
|
||||||
- [Vercel Custom Domains Documentation](https://vercel.com/docs/v2/custom-domains)
|
- [Vercel Custom Domains Documentation](https://vercel.com/docs/concepts/projects/custom-domains)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#### Why This Error Occurred
|
#### Why This Error Occurred
|
||||||
|
|
||||||
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/v2/build-step#environment-variables).
|
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||||
|
|
||||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
|
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
|
||||||
|
|
||||||
@@ -24,4 +24,4 @@ TEST=value
|
|||||||
|
|
||||||
In the above example, `TEST` represents the name of the environment variable and `value` its value.
|
In the above example, `TEST` represents the name of the environment variable and `value` its value.
|
||||||
|
|
||||||
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/v2/build-step#environment-variables).
|
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||||
|
|||||||
1
examples/amp/.gitignore
vendored
1
examples/amp/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
.env
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# AMP Example
|
|
||||||
|
|
||||||
This directory is a brief example of an [AMP](https://amp.dev/) site that can be deployed to Vercel with zero configuration.
|
|
||||||
|
|
||||||
## Deploy Your Own
|
|
||||||
|
|
||||||
Deploy your own AMP project with Vercel.
|
|
||||||
|
|
||||||
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/amp)
|
|
||||||
|
|
||||||
_Live Example: https://amp-template.vercel.app_
|
|
||||||
|
|
||||||
### How We Created This Example
|
|
||||||
|
|
||||||
To get started deploying AMP with Vercel, you can use the [Vercel CLI](https://vercel.com/download) to initialize the project:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ vercel init amp
|
|
||||||
```
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,72 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html ⚡>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width,minimum-scale=1" />
|
|
||||||
<link rel="shortcut icon" href="favicon.png">
|
|
||||||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
|
|
||||||
<link rel="canonical" href="index.html" />
|
|
||||||
<title>AMP Website</title>
|
|
||||||
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
|
||||||
<style amp-custom>
|
|
||||||
body > * {
|
|
||||||
margin: 3rem 1rem;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
||||||
color: #525252;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.links {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin-bottom: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.links a {
|
|
||||||
margin: 0 10px;
|
|
||||||
font-size: 1rem;
|
|
||||||
color: #005af0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<center>
|
|
||||||
<amp-img width=150 height=150 layout="fixed" class="logo" src="logo.png"></amp-img>
|
|
||||||
<h3>Welcome to your AMP page</h3>
|
|
||||||
<p>AMP is a web component framework to <br> easily create user-first websites, stories, ads and emails.</p>
|
|
||||||
|
|
||||||
<h4>Links</h4>
|
|
||||||
<div class="links">
|
|
||||||
<a href="https://amp.dev/">Homepage</a>
|
|
||||||
<a href="https://amp.dev/documentation/guides-and-tutorials/?format=websites">Tutorials</a>
|
|
||||||
<a href="https://amp.dev/documentation/examples/">Examples</a>
|
|
||||||
<a href="https://blog.amp.dev">Blog</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>Ready to get started?</h4>
|
|
||||||
<div class="links">
|
|
||||||
<a href="https://amp.dev/documentation/guides-and-tutorials/start/create/?format=websites">Create your first AMP page</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>Get involved</h4>
|
|
||||||
<div class="links">
|
|
||||||
<a href="https://twitter.com/amphtml">Twitter</a>
|
|
||||||
<a href="https://amphtml.slack.com">Slack</a>
|
|
||||||
<a href="https://amp.dev/events/amp-conf-2019">AMP Conf</a>
|
|
||||||
<a href="https://amp.dev/events/amp-roadshow">AMP Roadshow</a>
|
|
||||||
</div>
|
|
||||||
</center>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
20
examples/astro/.gitignore
vendored
Normal file
20
examples/astro/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# build output
|
||||||
|
dist/
|
||||||
|
.output/
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
|
||||||
|
# environment variables
|
||||||
|
.env
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# macOS-specific files
|
||||||
|
.DS_Store
|
||||||
2
examples/astro/.npmrc
Normal file
2
examples/astro/.npmrc
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Expose Astro dependencies for `pnpm` users
|
||||||
|
shamefully-hoist=true
|
||||||
1
examples/astro/.vercelignore
Normal file
1
examples/astro/.vercelignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
README.md
|
||||||
42
examples/astro/README.md
Normal file
42
examples/astro/README.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Welcome to [Astro](https://astro.build)
|
||||||
|
|
||||||
|
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/starter)
|
||||||
|
|
||||||
|
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||||
|
|
||||||
|
## 🚀 Project Structure
|
||||||
|
|
||||||
|
Inside of your Astro project, you'll see the following folders and files:
|
||||||
|
|
||||||
|
```
|
||||||
|
/
|
||||||
|
├── public/
|
||||||
|
│ └── favicon.ico
|
||||||
|
├── src/
|
||||||
|
│ ├── components/
|
||||||
|
│ │ └── Layout.astro
|
||||||
|
│ └── pages/
|
||||||
|
│ └── index.astro
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||||
|
|
||||||
|
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components or layouts.
|
||||||
|
|
||||||
|
Any static assets, like images, can be placed in the `public/` directory.
|
||||||
|
|
||||||
|
## 🧞 Commands
|
||||||
|
|
||||||
|
All commands are run from the root of the project, from a terminal:
|
||||||
|
|
||||||
|
| Command | Action |
|
||||||
|
| :---------------- | :------------------------------------------- |
|
||||||
|
| `npm install` | Installs dependencies |
|
||||||
|
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||||
|
| `npm run build` | Build your production site to `./dist/` |
|
||||||
|
| `npm run preview` | Preview your build locally, before deploying |
|
||||||
|
|
||||||
|
## 👀 Want to learn more?
|
||||||
|
|
||||||
|
Feel free to check [our documentation](https://github.com/withastro/astro) or jump into our [Discord server](https://astro.build/chat).
|
||||||
4
examples/astro/astro.config.mjs
Normal file
4
examples/astro/astro.config.mjs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
|
// https://astro.build/config
|
||||||
|
export default defineConfig({});
|
||||||
14
examples/astro/package.json
Normal file
14
examples/astro/package.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "@example/basics",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"start": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"astro": "^1.0.0-beta.20"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
examples/astro/public/favicon.ico
Normal file
BIN
examples/astro/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
55
examples/astro/src/components/Layout.astro
Normal file
55
examples/astro/src/components/Layout.astro
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title } = Astro.props as Props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<slot />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--font-size-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
|
||||||
|
--font-size-lg: clamp(1.2rem, 0.7vw + 1.2rem, 1.5rem);
|
||||||
|
--font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);
|
||||||
|
|
||||||
|
--color-text: hsl(12, 5%, 4%);
|
||||||
|
--color-bg: hsl(10, 21%, 95%);
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(h1) {
|
||||||
|
font-size: var(--font-size-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(h2) {
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(code) {
|
||||||
|
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||||
|
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
174
examples/astro/src/pages/index.astro
Normal file
174
examples/astro/src/pages/index.astro
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
import Layout from '../components/Layout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Welcome to Astro.">
|
||||||
|
<main>
|
||||||
|
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
|
||||||
|
<p class="instructions"><strong>Your first mission:</strong> tweak this message to try our hot module reloading. Check the <code>src/pages</code> directory!</p>
|
||||||
|
<ul role="list" class="link-card-grid">
|
||||||
|
<li class="link-card">
|
||||||
|
<a href="https://astro.build/integrations/">
|
||||||
|
<h2>Integrations <span>→</span></h2>
|
||||||
|
<p>Add component frameworks, Tailwind, Partytown, and more!</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="link-card">
|
||||||
|
<a href="https://astro.build/themes/">
|
||||||
|
<h2>Themes <span>→</span></h2>
|
||||||
|
<p>Explore a galaxy of community-built starters.</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="link-card">
|
||||||
|
<a href="https://docs.astro.build/">
|
||||||
|
<h2>Docs <span>→</span></h2>
|
||||||
|
<p>Learn our complete feature set and explore the API.</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="link-card">
|
||||||
|
<a href="https://astro.build/chat/">
|
||||||
|
<h2>Chat <span>→</span></h2>
|
||||||
|
<p>
|
||||||
|
Ask, contribute, and have fun on our community Discord
|
||||||
|
<svg
|
||||||
|
class="heart"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<title>heart</title>
|
||||||
|
<path d="M256 448l-30.164-27.211C118.718 322.442 48 258.61 48 179.095 48 114.221 97.918 64 162.4 64c36.399 0 70.717 16.742 93.6 43.947C278.882 80.742 313.199 64 349.6 64 414.082 64 464 114.221 464 179.095c0 79.516-70.719 143.348-177.836 241.694L256 448z" />
|
||||||
|
</svg>
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--color-border: hsl(17, 24%, 90%);
|
||||||
|
--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4);
|
||||||
|
--link-gradient: linear-gradient(45deg, #4F39FA, #DA62C4 30%, var(--color-border) 60%);
|
||||||
|
--night-sky-gradient: linear-gradient(0deg, #392362 -33%, #431f69 10%, #30216b 50%, #1f1638 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0;
|
||||||
|
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 span {
|
||||||
|
display: inline-block;
|
||||||
|
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.875em;
|
||||||
|
border: 0.1em solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.15em 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
margin: auto;
|
||||||
|
padding: 1em;
|
||||||
|
max-width: 60ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gradient {
|
||||||
|
font-weight: 900;
|
||||||
|
background-image: var(--astro-gradient);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-size: 100% 200%;
|
||||||
|
background-position-y: 100%;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
animation: pulse 4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
background-position-y: 0%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position-y: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions {
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
background-image: var(--night-sky-gradient);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
color: var(--color-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
padding: 0.15rem;
|
||||||
|
background-image: var(--link-gradient);
|
||||||
|
background-size: 400%;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background-position: 100%;
|
||||||
|
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card > a {
|
||||||
|
width: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding: 1em 1.3em;
|
||||||
|
border-radius: 0.35rem;
|
||||||
|
color: var(--text-color);
|
||||||
|
background-color: white;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card:is(:hover, :focus-within) {
|
||||||
|
background-position: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card:is(:hover, :focus-within) h2 {
|
||||||
|
color: #4F39FA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-card:is(:hover, :focus-within) h2 span {
|
||||||
|
transform: translateX(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heart {
|
||||||
|
display: inline-block;
|
||||||
|
color: #DA62C4;
|
||||||
|
animation: heartbeat 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes heartbeat {
|
||||||
|
0%,
|
||||||
|
50%,
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
5% {
|
||||||
|
transform: scale(1.125);
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
15% {
|
||||||
|
transform: scale(1.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
15
examples/astro/tsconfig.json
Normal file
15
examples/astro/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// Enable top-level await, and other modern ESM features.
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
// Enable node-style module resolution, for things like npm package imports.
|
||||||
|
"moduleResolution": "node",
|
||||||
|
// Enable JSON imports.
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
// Enable stricter transpilation for better output.
|
||||||
|
"isolatedModules": true,
|
||||||
|
// Add type definitions for our Vite runtime.
|
||||||
|
"types": ["vite/client"]
|
||||||
|
}
|
||||||
|
}
|
||||||
3457
examples/astro/yarn.lock
Normal file
3457
examples/astro/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ This directory is a brief example of a [Dojo](https://dojo.io) site that can be
|
|||||||
|
|
||||||
Deploy your own Dojo project with Vercel.
|
Deploy your own Dojo project with Vercel.
|
||||||
|
|
||||||
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/dojo&template=dojo)
|
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/dojo&template=dojo)
|
||||||
|
|
||||||
### How We Created This Example
|
### How We Created This Example
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ cache:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
# See https://git.io/vdao3 for details.
|
# See https://github.com/ember-cli/ember-cli/blob/master/docs/build-concurrency.md
|
||||||
- JOBS=1
|
- JOBS=1
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
|||||||
33
package.json
33
package.json
@@ -14,37 +14,24 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lerna": "3.16.4"
|
"lerna": "3.16.4"
|
||||||
},
|
},
|
||||||
"turbo": {
|
|
||||||
"baseBranch": "origin/main",
|
|
||||||
"pipeline": {
|
|
||||||
"build": {
|
|
||||||
"dependsOn": [
|
|
||||||
"^build"
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
"dist/**"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "4.28.0",
|
"@typescript-eslint/eslint-plugin": "5.21.0",
|
||||||
"@typescript-eslint/parser": "4.28.0",
|
"@typescript-eslint/parser": "5.21.0",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
"buffer-replace": "1.0.0",
|
"buffer-replace": "1.0.0",
|
||||||
"eslint": "7.29.0",
|
"eslint": "8.14.0",
|
||||||
"eslint-config-prettier": "8.3.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
"eslint-plugin-jest": "24.3.6",
|
"eslint-plugin-jest": "26.1.5",
|
||||||
"husky": "6.0.0",
|
"husky": "7.0.4",
|
||||||
"jest": "27.3.1",
|
"jest": "28.0.2",
|
||||||
"json5": "2.1.1",
|
"json5": "2.1.1",
|
||||||
"lint-staged": "9.2.5",
|
"lint-staged": "9.2.5",
|
||||||
"node-fetch": "2.6.1",
|
"node-fetch": "2.6.1",
|
||||||
"npm-package-arg": "6.1.0",
|
"npm-package-arg": "6.1.0",
|
||||||
"prettier": "2.3.1",
|
"prettier": "2.6.2",
|
||||||
"ts-eager": "2.0.2",
|
"ts-eager": "2.0.2",
|
||||||
"ts-jest": "27.0.4",
|
"ts-jest": "28.0.0-next.1",
|
||||||
"turbo": "1.1.9"
|
"turbo": "1.2.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lerna": "lerna",
|
"lerna": "lerna",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/build-utils",
|
"name": "@vercel/build-utils",
|
||||||
"version": "2.15.1",
|
"version": "2.17.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.js",
|
"types": "./dist/index.d.js",
|
||||||
@@ -23,14 +23,14 @@
|
|||||||
"@types/end-of-stream": "^1.4.0",
|
"@types/end-of-stream": "^1.4.0",
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
"@types/glob": "^7.1.1",
|
"@types/glob": "^7.1.1",
|
||||||
"@types/jest": "27.0.1",
|
"@types/jest": "27.4.1",
|
||||||
"@types/js-yaml": "3.12.1",
|
"@types/js-yaml": "3.12.1",
|
||||||
"@types/ms": "0.7.31",
|
"@types/ms": "0.7.31",
|
||||||
"@types/multistream": "2.1.1",
|
"@types/multistream": "2.1.1",
|
||||||
"@types/node-fetch": "^2.1.6",
|
"@types/node-fetch": "^2.1.6",
|
||||||
"@types/semver": "6.0.0",
|
"@types/semver": "6.0.0",
|
||||||
"@types/yazl": "^2.4.1",
|
"@types/yazl": "2.4.2",
|
||||||
"@vercel/frameworks": "0.7.1",
|
"@vercel/frameworks": "0.9.0",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"aggregate-error": "3.0.1",
|
"aggregate-error": "3.0.1",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
@@ -47,6 +47,6 @@
|
|||||||
"node-fetch": "2.6.1",
|
"node-fetch": "2.6.1",
|
||||||
"semver": "6.1.1",
|
"semver": "6.1.1",
|
||||||
"typescript": "4.3.4",
|
"typescript": "4.3.4",
|
||||||
"yazl": "2.4.3"
|
"yazl": "2.5.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ function getMissingBuildScriptError() {
|
|||||||
code: 'missing_build_script',
|
code: 'missing_build_script',
|
||||||
message:
|
message:
|
||||||
'Your `package.json` file is missing a `build` property inside the `scripts` property.' +
|
'Your `package.json` file is missing a `build` property inside the `scripts` property.' +
|
||||||
'\nLearn More: https://vercel.com/docs/v2/platform/frequently-asked-questions#missing-build-script',
|
'\nLearn More: https://vercel.link/missing-build-script',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { NowBuildError } from '../errors';
|
|||||||
import debug from '../debug';
|
import debug from '../debug';
|
||||||
|
|
||||||
const allOptions = [
|
const allOptions = [
|
||||||
|
{ major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||||
{ major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
{ major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||||
{ major: 12, range: '12.x', runtime: 'nodejs12.x' },
|
{ major: 12, range: '12.x', runtime: 'nodejs12.x' },
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import debug from '../debug';
|
import Sema from 'async-sema';
|
||||||
import spawn from 'cross-spawn';
|
import spawn from 'cross-spawn';
|
||||||
import { SpawnOptions } from 'child_process';
|
import { SpawnOptions } from 'child_process';
|
||||||
import { deprecate } from 'util';
|
import { deprecate } from 'util';
|
||||||
|
import debug from '../debug';
|
||||||
import { NowBuildError } from '../errors';
|
import { NowBuildError } from '../errors';
|
||||||
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
||||||
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
||||||
import { readConfigFile } from './read-config-file';
|
import { readConfigFile } from './read-config-file';
|
||||||
|
|
||||||
|
// Only allow one `runNpmInstall()` invocation to run concurrently
|
||||||
|
const runNpmInstallSema = new Sema(1);
|
||||||
|
|
||||||
export type CliType = 'yarn' | 'npm' | 'pnpm';
|
export type CliType = 'yarn' | 'npm' | 'pnpm';
|
||||||
|
|
||||||
export interface ScanParentDirsResult {
|
export interface ScanParentDirsResult {
|
||||||
@@ -17,6 +21,11 @@ export interface ScanParentDirsResult {
|
|||||||
* "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
|
* "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
|
||||||
*/
|
*/
|
||||||
cliType: CliType;
|
cliType: CliType;
|
||||||
|
/**
|
||||||
|
* The file path of found `package.json` file, or `undefined` if none was
|
||||||
|
* found.
|
||||||
|
*/
|
||||||
|
packageJsonPath?: string;
|
||||||
/**
|
/**
|
||||||
* The contents of found `package.json` file, when the `readPackageJson`
|
* The contents of found `package.json` file, when the `readPackageJson`
|
||||||
* option is enabled.
|
* option is enabled.
|
||||||
@@ -237,12 +246,13 @@ export async function scanParentDirs(
|
|||||||
|
|
||||||
let cliType: CliType = 'yarn';
|
let cliType: CliType = 'yarn';
|
||||||
let packageJson: PackageJson | undefined;
|
let packageJson: PackageJson | undefined;
|
||||||
|
let packageJsonPath: string | undefined;
|
||||||
let currentDestPath = destPath;
|
let currentDestPath = destPath;
|
||||||
let lockfileVersion: number | undefined;
|
let lockfileVersion: number | undefined;
|
||||||
|
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
const packageJsonPath = path.join(currentDestPath, 'package.json');
|
packageJsonPath = path.join(currentDestPath, 'package.json');
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
if (await fs.pathExists(packageJsonPath)) {
|
if (await fs.pathExists(packageJsonPath)) {
|
||||||
// Only read the contents of the *first* `package.json` file found,
|
// Only read the contents of the *first* `package.json` file found,
|
||||||
@@ -269,15 +279,17 @@ export async function scanParentDirs(
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (packageLockJson && !hasYarnLock && !pnpmLockYaml) {
|
// Priority order is Yarn > pnpm > npm
|
||||||
cliType = 'npm';
|
// - find highest priority lock file and use that
|
||||||
lockfileVersion = packageLockJson.lockfileVersion;
|
if (hasYarnLock) {
|
||||||
}
|
cliType = 'yarn';
|
||||||
|
} else if (pnpmLockYaml) {
|
||||||
if (!packageLockJson && !hasYarnLock && pnpmLockYaml) {
|
|
||||||
cliType = 'pnpm';
|
cliType = 'pnpm';
|
||||||
// just ensure that it is read as a number and not a string
|
// just ensure that it is read as a number and not a string
|
||||||
lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
|
lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
|
||||||
|
} else if (packageLockJson) {
|
||||||
|
cliType = 'npm';
|
||||||
|
lockfileVersion = packageLockJson.lockfileVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only stop iterating if a lockfile was found, because it's possible
|
// Only stop iterating if a lockfile was found, because it's possible
|
||||||
@@ -293,7 +305,7 @@ export async function scanParentDirs(
|
|||||||
currentDestPath = newDestPath;
|
currentDestPath = newDestPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { cliType, packageJson, lockfileVersion };
|
return { cliType, packageJson, lockfileVersion, packageJsonPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function walkParentDirs({
|
export async function walkParentDirs({
|
||||||
@@ -319,55 +331,87 @@ export async function walkParentDirs({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSet<T>(v: any): v is Set<T> {
|
||||||
|
return v?.constructor?.name === 'Set';
|
||||||
|
}
|
||||||
|
|
||||||
export async function runNpmInstall(
|
export async function runNpmInstall(
|
||||||
destPath: string,
|
destPath: string,
|
||||||
args: string[] = [],
|
args: string[] = [],
|
||||||
spawnOpts?: SpawnOptions,
|
spawnOpts?: SpawnOptions,
|
||||||
meta?: Meta,
|
meta?: Meta,
|
||||||
nodeVersion?: NodeVersion
|
nodeVersion?: NodeVersion
|
||||||
) {
|
): Promise<boolean> {
|
||||||
if (meta?.isDev) {
|
if (meta?.isDev) {
|
||||||
debug('Skipping dependency installation because dev mode is enabled');
|
debug('Skipping dependency installation because dev mode is enabled');
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(path.isAbsolute(destPath));
|
assert(path.isAbsolute(destPath));
|
||||||
debug(`Installing to ${destPath}`);
|
|
||||||
|
|
||||||
const { cliType, lockfileVersion } = await scanParentDirs(destPath);
|
try {
|
||||||
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
await runNpmInstallSema.acquire();
|
||||||
const env = opts.env ? { ...opts.env } : { ...process.env };
|
const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(
|
||||||
delete env.NODE_ENV;
|
destPath
|
||||||
opts.env = getEnvForPackageManager({
|
);
|
||||||
cliType,
|
|
||||||
lockfileVersion,
|
|
||||||
nodeVersion,
|
|
||||||
env,
|
|
||||||
});
|
|
||||||
let commandArgs: string[];
|
|
||||||
|
|
||||||
if (cliType === 'npm') {
|
// Only allow `runNpmInstall()` to run once per `package.json`
|
||||||
opts.prettyCommand = 'npm install';
|
// when doing a default install (no additional args)
|
||||||
commandArgs = args
|
if (meta && packageJsonPath && args.length === 0) {
|
||||||
.filter(a => a !== '--prefer-offline')
|
if (!isSet<string>(meta.runNpmInstallSet)) {
|
||||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
meta.runNpmInstallSet = new Set<string>();
|
||||||
} else if (cliType === 'pnpm') {
|
}
|
||||||
// PNPM's install command is similar to NPM's but without the audit nonsense
|
if (isSet<string>(meta.runNpmInstallSet)) {
|
||||||
// @see options https://pnpm.io/cli/install
|
if (meta.runNpmInstallSet.has(packageJsonPath)) {
|
||||||
opts.prettyCommand = 'pnpm install';
|
return false;
|
||||||
commandArgs = args
|
} else {
|
||||||
.filter(a => a !== '--prefer-offline')
|
meta.runNpmInstallSet.add(packageJsonPath);
|
||||||
.concat(['install', '--unsafe-perm']);
|
}
|
||||||
} else {
|
}
|
||||||
opts.prettyCommand = 'yarn install';
|
}
|
||||||
commandArgs = ['install', ...args];
|
|
||||||
|
const installTime = Date.now();
|
||||||
|
console.log('Installing dependencies...');
|
||||||
|
debug(`Installing to ${destPath}`);
|
||||||
|
|
||||||
|
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
||||||
|
const env = opts.env ? { ...opts.env } : { ...process.env };
|
||||||
|
delete env.NODE_ENV;
|
||||||
|
opts.env = getEnvForPackageManager({
|
||||||
|
cliType,
|
||||||
|
lockfileVersion,
|
||||||
|
nodeVersion,
|
||||||
|
env,
|
||||||
|
});
|
||||||
|
let commandArgs: string[];
|
||||||
|
|
||||||
|
if (cliType === 'npm') {
|
||||||
|
opts.prettyCommand = 'npm install';
|
||||||
|
commandArgs = args
|
||||||
|
.filter(a => a !== '--prefer-offline')
|
||||||
|
.concat(['install', '--no-audit', '--unsafe-perm']);
|
||||||
|
} else if (cliType === 'pnpm') {
|
||||||
|
// PNPM's install command is similar to NPM's but without the audit nonsense
|
||||||
|
// @see options https://pnpm.io/cli/install
|
||||||
|
opts.prettyCommand = 'pnpm install';
|
||||||
|
commandArgs = args
|
||||||
|
.filter(a => a !== '--prefer-offline')
|
||||||
|
.concat(['install', '--unsafe-perm']);
|
||||||
|
} else {
|
||||||
|
opts.prettyCommand = 'yarn install';
|
||||||
|
commandArgs = ['install', ...args];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.NPM_ONLY_PRODUCTION) {
|
||||||
|
commandArgs.push('--production');
|
||||||
|
}
|
||||||
|
|
||||||
|
await spawnAsync(cliType, commandArgs, opts);
|
||||||
|
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
runNpmInstallSema.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NPM_ONLY_PRODUCTION) {
|
|
||||||
commandArgs.push('--production');
|
|
||||||
}
|
|
||||||
|
|
||||||
return spawnAsync(cliType, commandArgs, opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnvForPackageManager({
|
export function getEnvForPackageManager({
|
||||||
@@ -392,6 +436,16 @@ export function getEnvForPackageManager({
|
|||||||
newEnv.PATH = `/node16/bin-npm7:${env.PATH}`;
|
newEnv.PATH = `/node16/bin-npm7:${env.PATH}`;
|
||||||
console.log('Detected `package-lock.json` generated by npm 7...');
|
console.log('Detected `package-lock.json` generated by npm 7...');
|
||||||
}
|
}
|
||||||
|
} else if (cliType === 'pnpm') {
|
||||||
|
if (
|
||||||
|
typeof lockfileVersion === 'number' &&
|
||||||
|
lockfileVersion === 5.4 &&
|
||||||
|
(nodeVersion?.major || 0) > 12
|
||||||
|
) {
|
||||||
|
// Ensure that pnpm 7 is at the beginning of the `$PATH`
|
||||||
|
newEnv.PATH = `/pnpm7/pnpm:${env.PATH}`;
|
||||||
|
console.log('Detected `pnpm-lock.yaml` generated by pnpm 7...');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
|
||||||
if (!env.YARN_NODE_LINKER) {
|
if (!env.YARN_NODE_LINKER) {
|
||||||
@@ -502,7 +556,7 @@ export async function runPipInstall(
|
|||||||
meta?: Meta
|
meta?: Meta
|
||||||
) {
|
) {
|
||||||
if (meta && meta.isDev) {
|
if (meta && meta.isDev) {
|
||||||
debug('Skipping dependency installation because dev mode is enabled');
|
debug('Skipping dependency installation because dev mode is enabled');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import {
|
|||||||
getDiscontinuedNodeVersions,
|
getDiscontinuedNodeVersions,
|
||||||
} from './fs/node-version';
|
} from './fs/node-version';
|
||||||
import streamToBuffer from './fs/stream-to-buffer';
|
import streamToBuffer from './fs/stream-to-buffer';
|
||||||
import shouldServe from './should-serve';
|
|
||||||
import debug from './debug';
|
import debug from './debug';
|
||||||
import getIgnoreFilter from './get-ignore-filter';
|
import getIgnoreFilter from './get-ignore-filter';
|
||||||
import { getPlatformEnv } from './get-platform-env';
|
import { getPlatformEnv } from './get-platform-env';
|
||||||
@@ -73,7 +72,6 @@ export {
|
|||||||
getSpawnOptions,
|
getSpawnOptions,
|
||||||
getPlatformEnv,
|
getPlatformEnv,
|
||||||
streamToBuffer,
|
streamToBuffer,
|
||||||
shouldServe,
|
|
||||||
debug,
|
debug,
|
||||||
isSymbolicLink,
|
isSymbolicLink,
|
||||||
getLambdaOptionsFromFunction,
|
getLambdaOptionsFromFunction,
|
||||||
@@ -94,6 +92,7 @@ export { DetectorFilesystem } from './detectors/filesystem';
|
|||||||
export { readConfigFile } from './fs/read-config-file';
|
export { readConfigFile } from './fs/read-config-file';
|
||||||
export { normalizePath } from './fs/normalize-path';
|
export { normalizePath } from './fs/normalize-path';
|
||||||
|
|
||||||
|
export * from './should-serve';
|
||||||
export * from './schemas';
|
export * from './schemas';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './errors';
|
export * from './errors';
|
||||||
@@ -116,3 +115,5 @@ export const isOfficialRuntime = (desired: string, name?: string): boolean => {
|
|||||||
export const isStaticRuntime = (name?: string): boolean => {
|
export const isStaticRuntime = (name?: string): boolean => {
|
||||||
return isOfficialRuntime('static', name);
|
return isOfficialRuntime('static', name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { workspaceManagers } from './workspaces/workspace-managers';
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { parse } from 'path';
|
import { parse } from 'path';
|
||||||
import { ShouldServeOptions } from './types';
|
import type FileFsRef from './file-fs-ref';
|
||||||
import FileFsRef from './file-fs-ref';
|
import type { ShouldServe } from './types';
|
||||||
|
|
||||||
export default function shouldServe({
|
export const shouldServe: ShouldServe = ({
|
||||||
entrypoint,
|
entrypoint,
|
||||||
files,
|
files,
|
||||||
requestPath,
|
requestPath,
|
||||||
}: ShouldServeOptions): boolean {
|
}) => {
|
||||||
requestPath = requestPath.replace(/\/$/, ''); // sanitize trailing '/'
|
requestPath = requestPath.replace(/\/$/, ''); // sanitize trailing '/'
|
||||||
entrypoint = entrypoint.replace(/\\/, '/'); // windows compatibility
|
entrypoint = entrypoint.replace(/\\/, '/'); // windows compatibility
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export default function shouldServe({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
function hasProp(obj: { [path: string]: FileFsRef }, key: string): boolean {
|
function hasProp(obj: { [path: string]: FileFsRef }, key: string): boolean {
|
||||||
return Object.hasOwnProperty.call(obj, key);
|
return Object.hasOwnProperty.call(obj, key);
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ export interface ProjectSettings {
|
|||||||
sourceFilesOutsideRootDirectory?: boolean;
|
sourceFilesOutsideRootDirectory?: boolean;
|
||||||
directoryListing?: boolean;
|
directoryListing?: boolean;
|
||||||
gitForkProtection?: boolean;
|
gitForkProtection?: boolean;
|
||||||
|
commandForIgnoringBuildStep?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BuilderV2 {
|
export interface BuilderV2 {
|
||||||
@@ -344,6 +345,7 @@ export interface BuilderV3 {
|
|||||||
version: 3;
|
version: 3;
|
||||||
build: BuildV3;
|
build: BuildV3;
|
||||||
prepareCache?: PrepareCache;
|
prepareCache?: PrepareCache;
|
||||||
|
shouldServe?: ShouldServe;
|
||||||
startDevServer?: StartDevServer;
|
startDevServer?: StartDevServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +358,29 @@ export interface Images {
|
|||||||
formats?: ImageFormat[];
|
formats?: ImageFormat[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BuildResultV2 {
|
/**
|
||||||
|
* If a Builder ends up creating filesystem outputs conforming to
|
||||||
|
* the Build Output API, then the Builder should return this type.
|
||||||
|
*/
|
||||||
|
export interface BuildResultBuildOutput {
|
||||||
|
/**
|
||||||
|
* Version number of the Build Output API that was created.
|
||||||
|
* Currently only `3` is a valid value.
|
||||||
|
* @example 3
|
||||||
|
*/
|
||||||
|
buildOutputVersion: 3;
|
||||||
|
/**
|
||||||
|
* Filesystem path to the Build Output directory.
|
||||||
|
* @example "/path/to/.vercel/output"
|
||||||
|
*/
|
||||||
|
buildOutputPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a Builder implements `version: 2`, the `build()` function is expected
|
||||||
|
* to return this type.
|
||||||
|
*/
|
||||||
|
export interface BuildResultV2Typical {
|
||||||
// TODO: use proper `Route` type from `routing-utils` (perhaps move types to a common package)
|
// TODO: use proper `Route` type from `routing-utils` (perhaps move types to a common package)
|
||||||
routes?: any[];
|
routes?: any[];
|
||||||
images?: Images;
|
images?: Images;
|
||||||
@@ -369,6 +393,8 @@ export interface BuildResultV2 {
|
|||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
||||||
|
|
||||||
export interface BuildResultV3 {
|
export interface BuildResultV3 {
|
||||||
output: Lambda;
|
output: Lambda;
|
||||||
}
|
}
|
||||||
@@ -376,6 +402,9 @@ export interface BuildResultV3 {
|
|||||||
export type BuildV2 = (options: BuildOptions) => Promise<BuildResultV2>;
|
export type BuildV2 = (options: BuildOptions) => Promise<BuildResultV2>;
|
||||||
export type BuildV3 = (options: BuildOptions) => Promise<BuildResultV3>;
|
export type BuildV3 = (options: BuildOptions) => Promise<BuildResultV3>;
|
||||||
export type PrepareCache = (options: PrepareCacheOptions) => Promise<Files>;
|
export type PrepareCache = (options: PrepareCacheOptions) => Promise<Files>;
|
||||||
|
export type ShouldServe = (
|
||||||
|
options: ShouldServeOptions
|
||||||
|
) => boolean | Promise<boolean>;
|
||||||
export type StartDevServer = (
|
export type StartDevServer = (
|
||||||
options: StartDevServerOptions
|
options: StartDevServerOptions
|
||||||
) => Promise<StartDevServerResult>;
|
) => Promise<StartDevServerResult>;
|
||||||
|
|||||||
129
packages/build-utils/src/workspaces/workspace-managers.ts
Normal file
129
packages/build-utils/src/workspaces/workspace-managers.ts
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import type { Framework } from '@vercel/frameworks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported list of workspace managers.
|
||||||
|
*
|
||||||
|
* This list is designed to work with the @see {@link detectFramework} function.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import { workspaceManagers as frameworkList } from '@vercel/build-utils/workspaces'
|
||||||
|
* import { detectFramework } from '@vercel/build-utils'
|
||||||
|
*
|
||||||
|
* const fs = new GitDetectorFilesystem(...)
|
||||||
|
* detectFramwork({ fs, frameworkList }) // returns the 'slug' field if detected, otherwise null
|
||||||
|
*
|
||||||
|
* @todo Will be used by the detect-eligible-projects API endpoint for a given git url.
|
||||||
|
*/
|
||||||
|
export const workspaceManagers: Array<Framework> = [
|
||||||
|
{
|
||||||
|
name: 'Yarn',
|
||||||
|
slug: 'yarn',
|
||||||
|
detectors: {
|
||||||
|
every: [
|
||||||
|
{
|
||||||
|
path: 'package.json',
|
||||||
|
matchContent:
|
||||||
|
'"workspaces":\\s*(?:\\[[^\\]]*]|{[^}]*"packages":[^}]*})',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'yarn.lock',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// unused props - needed for typescript
|
||||||
|
description: '',
|
||||||
|
logo: '',
|
||||||
|
settings: {
|
||||||
|
buildCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
devCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
installCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
outputDirectory: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getOutputDirName: () => Promise.resolve(''),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pnpm',
|
||||||
|
slug: 'pnpm',
|
||||||
|
detectors: {
|
||||||
|
every: [
|
||||||
|
{
|
||||||
|
path: 'pnpm-workspace.yaml',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// unused props - needed for typescript
|
||||||
|
description: '',
|
||||||
|
logo: '',
|
||||||
|
settings: {
|
||||||
|
buildCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
devCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
installCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
outputDirectory: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getOutputDirName: () => Promise.resolve(''),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'npm',
|
||||||
|
slug: 'npm',
|
||||||
|
detectors: {
|
||||||
|
every: [
|
||||||
|
{
|
||||||
|
path: 'package.json',
|
||||||
|
matchContent:
|
||||||
|
'"workspaces":\\s*(?:\\[[^\\]]*]|{[^}]*"packages":[^}]*})',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'package-lock.json',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// unused props - needed for typescript
|
||||||
|
description: '',
|
||||||
|
logo: '',
|
||||||
|
settings: {
|
||||||
|
buildCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
devCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
installCommand: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
outputDirectory: {
|
||||||
|
value: '',
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getOutputDirName: () => Promise.resolve(''),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default workspaceManagers;
|
||||||
4
packages/build-utils/test/fixtures/02-zero-config-api/yarn.lock
vendored
Normal file
4
packages/build-utils/test/fixtures/02-zero-config-api/yarn.lock
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
7789
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/package-lock.json
generated
vendored
Normal file
7789
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
14
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/package.json
vendored
Normal file
14
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/package.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"private": "true",
|
||||||
|
"name": "25-multiple-lock-files-yarn",
|
||||||
|
"workspaces": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "mkdir -p public && (printf \"yarn version: \" && yarn -v) > public/index.txt"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/pnpm-lock.yaml
generated
vendored
Normal file
19
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/pnpm-lock.yaml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
lockfileVersion: 5.3
|
||||||
|
|
||||||
|
specifiers:
|
||||||
|
once: ^1.4.0
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
once: 1.4.0
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/once/1.4.0:
|
||||||
|
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
||||||
|
dependencies:
|
||||||
|
wrappy: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/wrappy/1.0.2:
|
||||||
|
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
||||||
|
dev: false
|
||||||
11
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/vercel.json
vendored
Normal file
11
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"mustContain": "yarn version: 1",
|
||||||
|
"logMustContain": "yarn run build"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/yarn.lock
vendored
Normal file
15
packages/build-utils/test/fixtures/25-multiple-lock-files-yarn/yarn.lock
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
once@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
|
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||||
|
dependencies:
|
||||||
|
wrappy "1"
|
||||||
|
|
||||||
|
wrappy@1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||||
44
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/package-lock.json
generated
vendored
Normal file
44
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "26-multiple-lock-files-pnpm",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "26-multiple-lock-files-pnpm",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/package.json
vendored
Normal file
14
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/package.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"private": "true",
|
||||||
|
"name": "26-multiple-lock-files-pnpm",
|
||||||
|
"workspaces": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "mkdir -p public && (printf \"pnpm version: \" && pnpm -v) > public/index.txt"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/pnpm-lock.yaml
generated
vendored
Normal file
19
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/pnpm-lock.yaml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
lockfileVersion: 5.3
|
||||||
|
|
||||||
|
specifiers:
|
||||||
|
once: ^1.4.0
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
once: 1.4.0
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/once/1.4.0:
|
||||||
|
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
||||||
|
dependencies:
|
||||||
|
wrappy: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/wrappy/1.0.2:
|
||||||
|
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
||||||
|
dev: false
|
||||||
3
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/pnpm-workspace.yaml
vendored
Normal file
3
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/pnpm-workspace.yaml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
packages:
|
||||||
|
- 'a'
|
||||||
|
- 'b'
|
||||||
11
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/vercel.json
vendored
Normal file
11
packages/build-utils/test/fixtures/26-multiple-lock-files-pnpm/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"mustContain": "pnpm version: 6",
|
||||||
|
"logMustContain": "pnpm run build"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
15
packages/build-utils/test/fixtures/27-yarn-workspaces/a/package.json
vendored
Normal file
15
packages/build-utils/test/fixtures/27-yarn-workspaces/a/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "a",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
packages/build-utils/test/fixtures/27-yarn-workspaces/b/package.json
vendored
Normal file
15
packages/build-utils/test/fixtures/27-yarn-workspaces/b/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"cowsay": "^1.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
9
packages/build-utils/test/fixtures/27-yarn-workspaces/package.json
vendored
Normal file
9
packages/build-utils/test/fixtures/27-yarn-workspaces/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "21-npm-workspaces",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"workspaces": [
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
]
|
||||||
|
}
|
||||||
232
packages/build-utils/test/fixtures/27-yarn-workspaces/yarn.lock
vendored
Normal file
232
packages/build-utils/test/fixtures/27-yarn-workspaces/yarn.lock
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
ansi-regex@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
|
||||||
|
integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
|
||||||
|
|
||||||
|
ansi-regex@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||||
|
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||||
|
|
||||||
|
ansi-styles@^4.0.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||||
|
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||||
|
dependencies:
|
||||||
|
color-convert "^2.0.1"
|
||||||
|
|
||||||
|
camelcase@^5.0.0:
|
||||||
|
version "5.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
|
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||||
|
|
||||||
|
cliui@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||||
|
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||||
|
dependencies:
|
||||||
|
string-width "^4.2.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
wrap-ansi "^6.2.0"
|
||||||
|
|
||||||
|
color-convert@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||||
|
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||||
|
dependencies:
|
||||||
|
color-name "~1.1.4"
|
||||||
|
|
||||||
|
color-name@~1.1.4:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
|
cowsay@^1.5.0:
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cowsay/-/cowsay-1.5.0.tgz#4a2a453b8b59383c7d7a50e44d765c5de0bf615f"
|
||||||
|
integrity sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==
|
||||||
|
dependencies:
|
||||||
|
get-stdin "8.0.0"
|
||||||
|
string-width "~2.1.1"
|
||||||
|
strip-final-newline "2.0.0"
|
||||||
|
yargs "15.4.1"
|
||||||
|
|
||||||
|
debug@^4.3.2:
|
||||||
|
version "4.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||||
|
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||||
|
dependencies:
|
||||||
|
ms "2.1.2"
|
||||||
|
|
||||||
|
decamelize@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||||
|
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||||
|
|
||||||
|
emoji-regex@^8.0.0:
|
||||||
|
version "8.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||||
|
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||||
|
|
||||||
|
find-up@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||||
|
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||||
|
dependencies:
|
||||||
|
locate-path "^5.0.0"
|
||||||
|
path-exists "^4.0.0"
|
||||||
|
|
||||||
|
get-caller-file@^2.0.1:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
|
|
||||||
|
get-stdin@8.0.0:
|
||||||
|
version "8.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
|
||||||
|
integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
|
||||||
|
|
||||||
|
is-fullwidth-code-point@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||||
|
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||||
|
|
||||||
|
is-fullwidth-code-point@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||||
|
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||||
|
|
||||||
|
locate-path@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||||
|
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
|
||||||
|
dependencies:
|
||||||
|
p-locate "^4.1.0"
|
||||||
|
|
||||||
|
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==
|
||||||
|
|
||||||
|
p-limit@^2.2.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||||
|
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
|
||||||
|
dependencies:
|
||||||
|
p-try "^2.0.0"
|
||||||
|
|
||||||
|
p-locate@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||||
|
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
|
||||||
|
dependencies:
|
||||||
|
p-limit "^2.2.0"
|
||||||
|
|
||||||
|
p-try@^2.0.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||||
|
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
|
|
||||||
|
path-exists@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||||
|
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||||
|
|
||||||
|
require-directory@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||||
|
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
|
||||||
|
|
||||||
|
require-main-filename@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||||
|
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||||
|
|
||||||
|
set-blocking@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||||
|
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||||
|
|
||||||
|
string-width@^4.1.0, string-width@^4.2.0:
|
||||||
|
version "4.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
dependencies:
|
||||||
|
emoji-regex "^8.0.0"
|
||||||
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
strip-ansi "^6.0.1"
|
||||||
|
|
||||||
|
string-width@~2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||||
|
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
|
||||||
|
dependencies:
|
||||||
|
is-fullwidth-code-point "^2.0.0"
|
||||||
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
|
strip-ansi@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||||
|
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^3.0.0"
|
||||||
|
|
||||||
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
|
strip-final-newline@2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
|
||||||
|
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
|
||||||
|
|
||||||
|
which-module@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||||
|
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||||
|
|
||||||
|
wrap-ansi@^6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||||
|
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.0.0"
|
||||||
|
string-width "^4.1.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
y18n@^4.0.0:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||||
|
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||||
|
|
||||||
|
yargs-parser@^18.1.2:
|
||||||
|
version "18.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||||
|
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||||
|
dependencies:
|
||||||
|
camelcase "^5.0.0"
|
||||||
|
decamelize "^1.2.0"
|
||||||
|
|
||||||
|
yargs@15.4.1:
|
||||||
|
version "15.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
|
||||||
|
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||||
|
dependencies:
|
||||||
|
cliui "^6.0.0"
|
||||||
|
decamelize "^1.2.0"
|
||||||
|
find-up "^4.1.0"
|
||||||
|
get-caller-file "^2.0.1"
|
||||||
|
require-directory "^2.1.1"
|
||||||
|
require-main-filename "^2.0.0"
|
||||||
|
set-blocking "^2.0.0"
|
||||||
|
string-width "^4.2.0"
|
||||||
|
which-module "^2.0.0"
|
||||||
|
y18n "^4.0.0"
|
||||||
|
yargs-parser "^18.1.2"
|
||||||
9
packages/build-utils/test/fixtures/28-pnpm-7/package.json
vendored
Normal file
9
packages/build-utils/test/fixtures/28-pnpm-7/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"private": "true",
|
||||||
|
"scripts": {
|
||||||
|
"build": "mkdir -p public && (printf \"pnpm version: \" && pnpm -v) > public/index.txt"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
packages/build-utils/test/fixtures/28-pnpm-7/pnpm-lock.yaml
generated
vendored
Normal file
19
packages/build-utils/test/fixtures/28-pnpm-7/pnpm-lock.yaml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
lockfileVersion: 5.4
|
||||||
|
|
||||||
|
specifiers:
|
||||||
|
once: ^1.4.0
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
once: 1.4.0
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/once/1.4.0:
|
||||||
|
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
|
||||||
|
dependencies:
|
||||||
|
wrappy: 1.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/wrappy/1.0.2:
|
||||||
|
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
|
||||||
|
dev: false
|
||||||
11
packages/build-utils/test/fixtures/28-pnpm-7/vercel.json
vendored
Normal file
11
packages/build-utils/test/fixtures/28-pnpm-7/vercel.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
|
||||||
|
"probes": [
|
||||||
|
{
|
||||||
|
"path": "/",
|
||||||
|
"mustContain": "pnpm version: 7",
|
||||||
|
"logMustContain": "pnpm run build"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ const skipFixtures: string[] = [
|
|||||||
'08-zero-config-middleman',
|
'08-zero-config-middleman',
|
||||||
'21-npm-workspaces',
|
'21-npm-workspaces',
|
||||||
'23-pnpm-workspaces',
|
'23-pnpm-workspaces',
|
||||||
|
'27-yarn-workspaces',
|
||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
|||||||
31
packages/build-utils/test/unit.detect-workspace-managers.test.ts
vendored
Normal file
31
packages/build-utils/test/unit.detect-workspace-managers.test.ts
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { detectFramework } from '../src/detect-framework';
|
||||||
|
import workspaceManagers from '../src/workspaces/workspace-managers';
|
||||||
|
import { FixtureFilesystem } from './utils/fixture-filesystem';
|
||||||
|
|
||||||
|
describe('workspace-managers', () => {
|
||||||
|
describe.each([
|
||||||
|
['npm', '21-npm-workspaces'],
|
||||||
|
['pnpm', '23-pnpm-workspaces'],
|
||||||
|
['yarn', '27-yarn-workspaces'],
|
||||||
|
['yarn', '25-multiple-lock-files-yarn'],
|
||||||
|
['pnpm', '26-multiple-lock-files-pnpm'],
|
||||||
|
[null, '22-pnpm'],
|
||||||
|
])('with detectFramework', (frameworkSlug, fixturePath) => {
|
||||||
|
const testName = frameworkSlug
|
||||||
|
? `should detect a ${frameworkSlug} workspace for ${fixturePath}`
|
||||||
|
: `should not detect framework for ${fixturePath}`;
|
||||||
|
|
||||||
|
it(testName, async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', fixturePath);
|
||||||
|
const fs = new FixtureFilesystem(fixture);
|
||||||
|
|
||||||
|
const result = await detectFramework({
|
||||||
|
fs,
|
||||||
|
frameworkList: workspaceManagers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toBe(frameworkSlug);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { getEnvForPackageManager, NodeVersion } from '../src';
|
import { getEnvForPackageManager } from '../src';
|
||||||
import { CliType } from '../src/fs/run-user-scripts';
|
|
||||||
|
|
||||||
describe('Test `getEnvForPackageManager()`', () => {
|
describe('Test `getEnvForPackageManager()`', () => {
|
||||||
const cases = [
|
const cases: Array<{
|
||||||
|
name: string;
|
||||||
|
args: Parameters<typeof getEnvForPackageManager>[0];
|
||||||
|
want: unknown;
|
||||||
|
}> = [
|
||||||
{
|
{
|
||||||
name: 'should do nothing to env for npm < 6 and node < 16',
|
name: 'should do nothing to env for npm < 6 and node < 16',
|
||||||
args: {
|
args: {
|
||||||
cliType: 'npm' as CliType,
|
cliType: 'npm',
|
||||||
nodeVersion: {
|
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||||
major: 14,
|
|
||||||
} as NodeVersion,
|
|
||||||
lockfileVersion: 1,
|
lockfileVersion: 1,
|
||||||
env: {
|
env: {
|
||||||
FOO: 'bar',
|
FOO: 'bar',
|
||||||
@@ -23,10 +24,8 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
{
|
{
|
||||||
name: 'should set path if npm 7+ is detected and node < 16',
|
name: 'should set path if npm 7+ is detected and node < 16',
|
||||||
args: {
|
args: {
|
||||||
cliType: 'npm' as CliType,
|
cliType: 'npm',
|
||||||
nodeVersion: {
|
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||||
major: 14,
|
|
||||||
} as NodeVersion,
|
|
||||||
lockfileVersion: 2,
|
lockfileVersion: 2,
|
||||||
env: {
|
env: {
|
||||||
FOO: 'bar',
|
FOO: 'bar',
|
||||||
@@ -41,10 +40,8 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
{
|
{
|
||||||
name: 'should not set path if node is 16 and npm 7+ is detected',
|
name: 'should not set path if node is 16 and npm 7+ is detected',
|
||||||
args: {
|
args: {
|
||||||
cliType: 'npm' as CliType,
|
cliType: 'npm',
|
||||||
nodeVersion: {
|
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||||
major: 16,
|
|
||||||
} as NodeVersion,
|
|
||||||
lockfileVersion: 2,
|
lockfileVersion: 2,
|
||||||
env: {
|
env: {
|
||||||
FOO: 'bar',
|
FOO: 'bar',
|
||||||
@@ -59,10 +56,8 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
{
|
{
|
||||||
name: 'should set YARN_NODE_LINKER w/yarn if it is not already defined',
|
name: 'should set YARN_NODE_LINKER w/yarn if it is not already defined',
|
||||||
args: {
|
args: {
|
||||||
cliType: 'yarn' as CliType,
|
cliType: 'yarn',
|
||||||
nodeVersion: {
|
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||||
major: 16,
|
|
||||||
} as NodeVersion,
|
|
||||||
lockfileVersion: 2,
|
lockfileVersion: 2,
|
||||||
env: {
|
env: {
|
||||||
FOO: 'bar',
|
FOO: 'bar',
|
||||||
@@ -76,10 +71,8 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
{
|
{
|
||||||
name: 'should not set YARN_NODE_LINKER if it already exists',
|
name: 'should not set YARN_NODE_LINKER if it already exists',
|
||||||
args: {
|
args: {
|
||||||
cliType: 'yarn' as CliType,
|
cliType: 'yarn',
|
||||||
nodeVersion: {
|
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||||
major: 16,
|
|
||||||
} as NodeVersion,
|
|
||||||
lockfileVersion: 2,
|
lockfileVersion: 2,
|
||||||
env: {
|
env: {
|
||||||
FOO: 'bar',
|
FOO: 'bar',
|
||||||
@@ -91,6 +84,50 @@ describe('Test `getEnvForPackageManager()`', () => {
|
|||||||
YARN_NODE_LINKER: 'exists',
|
YARN_NODE_LINKER: 'exists',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'should set path if pnpm 7+ is detected and Node version is greater than 12',
|
||||||
|
args: {
|
||||||
|
cliType: 'pnpm',
|
||||||
|
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||||
|
lockfileVersion: 5.4,
|
||||||
|
env: {
|
||||||
|
FOO: 'bar',
|
||||||
|
PATH: 'foo',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: {
|
||||||
|
FOO: 'bar',
|
||||||
|
PATH: '/pnpm7/pnpm:foo',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'should not set path if pnpm 7+ is detected and Node version is less than or equal to 12',
|
||||||
|
args: {
|
||||||
|
cliType: 'pnpm',
|
||||||
|
nodeVersion: { major: 12, range: '12.x', runtime: 'nodejs12.x' },
|
||||||
|
lockfileVersion: 5.4,
|
||||||
|
env: {
|
||||||
|
FOO: 'bar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: {
|
||||||
|
FOO: 'bar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'should not set path if pnpm 6 is detected',
|
||||||
|
args: {
|
||||||
|
cliType: 'pnpm',
|
||||||
|
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||||
|
lockfileVersion: 5.3,
|
||||||
|
env: {
|
||||||
|
FOO: 'bar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: {
|
||||||
|
FOO: 'bar',
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const { name, want, args } of cases) {
|
for (const { name, want, args } of cases) {
|
||||||
|
|||||||
67
packages/build-utils/test/unit.test.ts
vendored
67
packages/build-utils/test/unit.test.ts
vendored
@@ -15,6 +15,7 @@ import {
|
|||||||
runPackageJsonScript,
|
runPackageJsonScript,
|
||||||
scanParentDirs,
|
scanParentDirs,
|
||||||
FileBlob,
|
FileBlob,
|
||||||
|
Meta,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
|
|
||||||
async function expectBuilderError(promise: Promise<any>, pattern: string) {
|
async function expectBuilderError(promise: Promise<any>, pattern: string) {
|
||||||
@@ -175,9 +176,13 @@ it('should only match supported node versions, otherwise throw an error', async
|
|||||||
'major',
|
'major',
|
||||||
14
|
14
|
||||||
);
|
);
|
||||||
|
expect(await getSupportedNodeVersion('16.x', false)).toHaveProperty(
|
||||||
|
'major',
|
||||||
|
16
|
||||||
|
);
|
||||||
|
|
||||||
const autoMessage =
|
const autoMessage =
|
||||||
'Please set Node.js Version to 14.x in your Project Settings to use Node.js 14.';
|
'Please set Node.js Version to 16.x in your Project Settings to use Node.js 16.';
|
||||||
await expectBuilderError(
|
await expectBuilderError(
|
||||||
getSupportedNodeVersion('8.11.x', true),
|
getSupportedNodeVersion('8.11.x', true),
|
||||||
autoMessage
|
autoMessage
|
||||||
@@ -195,9 +200,13 @@ it('should only match supported node versions, otherwise throw an error', async
|
|||||||
'major',
|
'major',
|
||||||
14
|
14
|
||||||
);
|
);
|
||||||
|
expect(await getSupportedNodeVersion('16.x', true)).toHaveProperty(
|
||||||
|
'major',
|
||||||
|
16
|
||||||
|
);
|
||||||
|
|
||||||
const foundMessage =
|
const foundMessage =
|
||||||
'Please set "engines": { "node": "14.x" } in your `package.json` file to use Node.js 14.';
|
'Please set "engines": { "node": "16.x" } in your `package.json` file to use Node.js 16.';
|
||||||
await expectBuilderError(
|
await expectBuilderError(
|
||||||
getSupportedNodeVersion('8.11.x', false),
|
getSupportedNodeVersion('8.11.x', false),
|
||||||
foundMessage
|
foundMessage
|
||||||
@@ -218,8 +227,8 @@ it('should match all semver ranges', async () => {
|
|||||||
// See https://docs.npmjs.com/files/package.json#engines
|
// See https://docs.npmjs.com/files/package.json#engines
|
||||||
expect(await getSupportedNodeVersion('12.0.0')).toHaveProperty('major', 12);
|
expect(await getSupportedNodeVersion('12.0.0')).toHaveProperty('major', 12);
|
||||||
expect(await getSupportedNodeVersion('12.x')).toHaveProperty('major', 12);
|
expect(await getSupportedNodeVersion('12.x')).toHaveProperty('major', 12);
|
||||||
expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 14);
|
expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 16);
|
||||||
expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 14);
|
expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 16);
|
||||||
expect(await getSupportedNodeVersion('11.5.0 - 12.5.0')).toHaveProperty(
|
expect(await getSupportedNodeVersion('11.5.0 - 12.5.0')).toHaveProperty(
|
||||||
'major',
|
'major',
|
||||||
12
|
12
|
||||||
@@ -230,6 +239,10 @@ it('should match all semver ranges', async () => {
|
|||||||
);
|
);
|
||||||
expect(await getSupportedNodeVersion('~12.5.0')).toHaveProperty('major', 12);
|
expect(await getSupportedNodeVersion('~12.5.0')).toHaveProperty('major', 12);
|
||||||
expect(await getSupportedNodeVersion('^12.5.0')).toHaveProperty('major', 12);
|
expect(await getSupportedNodeVersion('^12.5.0')).toHaveProperty('major', 12);
|
||||||
|
expect(await getSupportedNodeVersion('12.5.0 - 14.5.0')).toHaveProperty(
|
||||||
|
'major',
|
||||||
|
14
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore node version in vercel dev getNodeVersion()', async () => {
|
it('should ignore node version in vercel dev getNodeVersion()', async () => {
|
||||||
@@ -245,8 +258,8 @@ it('should ignore node version in vercel dev getNodeVersion()', async () => {
|
|||||||
|
|
||||||
it('should select project setting from config when no package.json is found', async () => {
|
it('should select project setting from config when no package.json is found', async () => {
|
||||||
expect(
|
expect(
|
||||||
await getNodeVersion('/tmp', undefined, { nodeVersion: '14.x' }, {})
|
await getNodeVersion('/tmp', undefined, { nodeVersion: '16.x' }, {})
|
||||||
).toHaveProperty('range', '14.x');
|
).toHaveProperty('range', '16.x');
|
||||||
expect(warningMessages).toStrictEqual([]);
|
expect(warningMessages).toStrictEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -277,7 +290,7 @@ it('should not warn when package.json engines matches project setting from confi
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should get latest node version', async () => {
|
it('should get latest node version', async () => {
|
||||||
expect(getLatestNodeVersion()).toHaveProperty('major', 14);
|
expect(getLatestNodeVersion()).toHaveProperty('major', 16);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw for discontinued versions', async () => {
|
it('should throw for discontinued versions', async () => {
|
||||||
@@ -312,8 +325,8 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
|
|||||||
10
|
10
|
||||||
);
|
);
|
||||||
expect(warningMessages).toStrictEqual([
|
expect(warningMessages).toStrictEqual([
|
||||||
'Error: Node.js version 10.x is deprecated. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "14.x" } in your `package.json` file to use Node.js 14. This change is the result of a decision made by an upstream infrastructure provider (AWS).',
|
'Error: Node.js version 10.x is deprecated. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "16.x" } in your `package.json` file to use Node.js 16. This change is the result of a decision made by an upstream infrastructure provider (AWS).',
|
||||||
'Error: Node.js version 10.x is deprecated. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 14.x in your Project Settings to use Node.js 14. This change is the result of a decision made by an upstream infrastructure provider (AWS).',
|
'Error: Node.js version 10.x is deprecated. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 16.x in your Project Settings to use Node.js 16. This change is the result of a decision made by an upstream infrastructure provider (AWS).',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
global.Date.now = realDateNow;
|
global.Date.now = realDateNow;
|
||||||
@@ -413,3 +426,39 @@ it('should detect pnpm Workspaces', async () => {
|
|||||||
expect(result.cliType).toEqual('pnpm');
|
expect(result.cliType).toEqual('pnpm');
|
||||||
expect(result.lockfileVersion).toEqual(5.3);
|
expect(result.lockfileVersion).toEqual(5.3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
||||||
|
const meta: Meta = {};
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||||
|
const apiDir = path.join(fixture, 'api');
|
||||||
|
const run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||||
|
expect(run1).toEqual(true);
|
||||||
|
expect(
|
||||||
|
(meta.runNpmInstallSet as Set<string>).has(
|
||||||
|
path.join(fixture, 'package.json')
|
||||||
|
)
|
||||||
|
).toEqual(true);
|
||||||
|
const run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||||
|
expect(run2).toEqual(false);
|
||||||
|
const run3 = await runNpmInstall(fixture, [], undefined, meta);
|
||||||
|
expect(run3).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
||||||
|
const meta: Meta = {};
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||||
|
const apiDir = path.join(fixture, 'api');
|
||||||
|
const [run1, run2, run3] = await Promise.all([
|
||||||
|
runNpmInstall(apiDir, [], undefined, meta),
|
||||||
|
runNpmInstall(apiDir, [], undefined, meta),
|
||||||
|
runNpmInstall(fixture, [], undefined, meta),
|
||||||
|
]);
|
||||||
|
expect(run1).toEqual(true);
|
||||||
|
expect(run2).toEqual(false);
|
||||||
|
expect(run3).toEqual(false);
|
||||||
|
expect(
|
||||||
|
(meta.runNpmInstallSet as Set<string>).has(
|
||||||
|
path.join(fixture, 'package.json')
|
||||||
|
)
|
||||||
|
).toEqual(true);
|
||||||
|
});
|
||||||
|
|||||||
35
packages/build-utils/test/utils/fixture-filesystem.ts
Normal file
35
packages/build-utils/test/utils/fixture-filesystem.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { promises } from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
import { DetectorFilesystem } from '../../src';
|
||||||
|
|
||||||
|
const { stat, readFile } = promises;
|
||||||
|
|
||||||
|
export class FixtureFilesystem extends DetectorFilesystem {
|
||||||
|
private rootPath: string;
|
||||||
|
|
||||||
|
constructor(fixturePath: string) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.rootPath = fixturePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _hasPath(name: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(this.rootPath, name);
|
||||||
|
await stat(filePath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async _readFile(name: string): Promise<Buffer> {
|
||||||
|
const filePath = path.join(this.rootPath, name);
|
||||||
|
return readFile(filePath);
|
||||||
|
}
|
||||||
|
async _isFile(name: string): Promise<boolean> {
|
||||||
|
const filePath = path.join(this.rootPath, name);
|
||||||
|
return (await stat(filePath)).isFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "24.1.0",
|
"version": "24.2.1",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"description": "The command-line interface for Vercel",
|
"description": "The command-line interface for Vercel",
|
||||||
@@ -43,14 +43,15 @@
|
|||||||
"node": ">= 12"
|
"node": ">= 12"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.15.1",
|
"@vercel/build-utils": "2.17.0",
|
||||||
"@vercel/go": "1.3.2",
|
"@vercel/go": "1.4.1",
|
||||||
"@vercel/node": "1.14.1",
|
"@vercel/node": "1.15.1",
|
||||||
"@vercel/python": "2.2.2",
|
"@vercel/python": "2.3.1",
|
||||||
"@vercel/ruby": "1.3.2",
|
"@vercel/ruby": "1.3.4",
|
||||||
"update-notifier": "4.1.0"
|
"update-notifier": "4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@alex_neo/jest-expect-message": "1.0.5",
|
||||||
"@next/env": "11.1.2",
|
"@next/env": "11.1.2",
|
||||||
"@sentry/node": "5.5.0",
|
"@sentry/node": "5.5.0",
|
||||||
"@sindresorhus/slugify": "0.11.0",
|
"@sindresorhus/slugify": "0.11.0",
|
||||||
@@ -68,7 +69,8 @@
|
|||||||
"@types/glob": "7.1.1",
|
"@types/glob": "7.1.1",
|
||||||
"@types/http-proxy": "1.16.2",
|
"@types/http-proxy": "1.16.2",
|
||||||
"@types/inquirer": "7.3.1",
|
"@types/inquirer": "7.3.1",
|
||||||
"@types/jest": "27.0.1",
|
"@types/jest": "27.4.1",
|
||||||
|
"@types/jest-expect-message": "1.0.3",
|
||||||
"@types/load-json-file": "2.0.7",
|
"@types/load-json-file": "2.0.7",
|
||||||
"@types/mime-types": "2.1.0",
|
"@types/mime-types": "2.1.0",
|
||||||
"@types/minimatch": "3.0.3",
|
"@types/minimatch": "3.0.3",
|
||||||
@@ -88,11 +90,9 @@
|
|||||||
"@types/update-notifier": "5.1.0",
|
"@types/update-notifier": "5.1.0",
|
||||||
"@types/which": "1.3.2",
|
"@types/which": "1.3.2",
|
||||||
"@types/write-json-file": "2.2.1",
|
"@types/write-json-file": "2.2.1",
|
||||||
"@vercel/client": "10.4.1",
|
"@vercel/client": "11.0.1",
|
||||||
"@vercel/fetch-retry": "5.0.3",
|
"@vercel/frameworks": "0.9.0",
|
||||||
"@vercel/frameworks": "0.7.1",
|
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"@vercel/nft": "0.17.5",
|
|
||||||
"@zeit/fun": "0.11.2",
|
"@zeit/fun": "0.11.2",
|
||||||
"@zeit/source-map-support": "0.6.2",
|
"@zeit/source-map-support": "0.6.2",
|
||||||
"ajv": "6.12.2",
|
"ajv": "6.12.2",
|
||||||
@@ -177,6 +177,9 @@
|
|||||||
"isolatedModules": true
|
"isolatedModules": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"setupFilesAfterEnv": [
|
||||||
|
"@alex_neo/jest-expect-message"
|
||||||
|
],
|
||||||
"verbose": false,
|
"verbose": false,
|
||||||
"testEnvironment": "node",
|
"testEnvironment": "node",
|
||||||
"testMatch": [
|
"testMatch": [
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default async function set(
|
|||||||
if (args.length === 0) {
|
if (args.length === 0) {
|
||||||
output.error(
|
output.error(
|
||||||
`To ship to production, optionally configure your domains (${link(
|
`To ship to production, optionally configure your domains (${link(
|
||||||
'https://vercel.com/docs/v2/custom-domains'
|
'https://vercel.link/domain-configuration'
|
||||||
)}) and run ${getCommandName(`--prod`)}.`
|
)}) and run ${getCommandName(`--prod`)}.`
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-
|
|||||||
import { Output } from '../../util/output';
|
import { Output } from '../../util/output';
|
||||||
import { help } from './args';
|
import { help } from './args';
|
||||||
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
|
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
|
||||||
|
import parseTarget from '../../util/deploy/parse-target';
|
||||||
|
import getPrebuiltJson from '../../util/deploy/get-prebuilt-json';
|
||||||
|
|
||||||
export default async (client: Client) => {
|
export default async (client: Client) => {
|
||||||
const { output } = client;
|
const { output } = client;
|
||||||
@@ -155,7 +157,7 @@ export default async (client: Client) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { log, debug, error, warn, isTTY } = output;
|
const { log, debug, error, prettyError, isTTY } = output;
|
||||||
|
|
||||||
const quiet = !isTTY;
|
const quiet = !isTTY;
|
||||||
|
|
||||||
@@ -181,6 +183,46 @@ export default async (client: Client) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build `target`
|
||||||
|
const target = parseTarget(output, argv['--target'], argv['--prod']);
|
||||||
|
if (typeof target === 'number') {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build `--prebuilt`
|
||||||
|
if (argv['--prebuilt']) {
|
||||||
|
const prebuiltExists = await fs.pathExists(join(path, '.vercel/output'));
|
||||||
|
if (!prebuiltExists) {
|
||||||
|
error(
|
||||||
|
`The ${param(
|
||||||
|
'--prebuilt'
|
||||||
|
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
|
||||||
|
'build'
|
||||||
|
)} to generate a local build.`
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prebuiltBuild = await getPrebuiltJson(path);
|
||||||
|
const assumedTarget = target || 'preview';
|
||||||
|
if (prebuiltBuild?.target && prebuiltBuild.target !== assumedTarget) {
|
||||||
|
let specifyTarget = '';
|
||||||
|
if (prebuiltBuild.target === 'production') {
|
||||||
|
specifyTarget = ` --prod`;
|
||||||
|
}
|
||||||
|
|
||||||
|
prettyError({
|
||||||
|
message: `The ${param(
|
||||||
|
'--prebuilt'
|
||||||
|
)} option was used with the target environment "${assumedTarget}", but the prebuilt output found in ".vercel/output" was built with target environment "${
|
||||||
|
prebuiltBuild.target
|
||||||
|
}". Please run ${getCommandName(`--prebuilt${specifyTarget}`)}.`,
|
||||||
|
link: 'https://vercel.link/prebuilt-environment-mismatch',
|
||||||
|
});
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// retrieve `project` and `org` from .vercel
|
// retrieve `project` and `org` from .vercel
|
||||||
const link = await getLinkedProject(client, path);
|
const link = await getLinkedProject(client, path);
|
||||||
|
|
||||||
@@ -403,33 +445,6 @@ export default async (client: Client) => {
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
const regions = regionFlag.length > 0 ? regionFlag : localConfig.regions;
|
const regions = regionFlag.length > 0 ? regionFlag : localConfig.regions;
|
||||||
|
|
||||||
// build `target`
|
|
||||||
let target;
|
|
||||||
if (argv['--target']) {
|
|
||||||
const deprecatedTarget = argv['--target'];
|
|
||||||
|
|
||||||
if (!['staging', 'production'].includes(deprecatedTarget)) {
|
|
||||||
error(
|
|
||||||
`The specified ${param('--target')} ${code(
|
|
||||||
deprecatedTarget
|
|
||||||
)} is not valid`
|
|
||||||
);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deprecatedTarget === 'production') {
|
|
||||||
warn(
|
|
||||||
'We recommend using the much shorter `--prod` option instead of `--target production` (deprecated)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
output.debug(`Setting target to ${deprecatedTarget}`);
|
|
||||||
target = deprecatedTarget;
|
|
||||||
} else if (argv['--prod']) {
|
|
||||||
output.debug('Setting target to production');
|
|
||||||
target = 'production';
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentTeam = org?.type === 'team' ? org.id : undefined;
|
const currentTeam = org?.type === 'team' ? org.id : undefined;
|
||||||
const now = new Now({
|
const now = new Now({
|
||||||
client,
|
client,
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { ProjectSettings } from '../../types';
|
|||||||
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
|
||||||
import setupAndLink from '../../util/link/setup-and-link';
|
import setupAndLink from '../../util/link/setup-and-link';
|
||||||
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
import getSystemEnvValues from '../../util/env/get-system-env-values';
|
||||||
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
|
import param from '../../util/output/param';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
'--listen': string;
|
'--listen': string;
|
||||||
@@ -46,6 +48,13 @@ export default async function dev(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (link.status === 'error') {
|
if (link.status === 'error') {
|
||||||
|
if (link.reason === 'HEADLESS') {
|
||||||
|
client.output.error(
|
||||||
|
`Command ${getCommandName(
|
||||||
|
'dev'
|
||||||
|
)} requires confirmation. Use option ${param('--confirm')} to confirm.`
|
||||||
|
);
|
||||||
|
}
|
||||||
return link.exitCode;
|
return link.exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
packages/cli/src/commands/env/index.ts
vendored
9
packages/cli/src/commands/env/index.ts
vendored
@@ -115,9 +115,11 @@ export default async function main(client: Client) {
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { subcommand, args } = getSubcommand(argv._.slice(1), COMMAND_CONFIG);
|
const cwd = argv['--cwd'] || process.cwd();
|
||||||
|
const subArgs = argv._.slice(1);
|
||||||
|
const { subcommand, args } = getSubcommand(subArgs, COMMAND_CONFIG);
|
||||||
const { output, config } = client;
|
const { output, config } = client;
|
||||||
const link = await getLinkedProject(client);
|
const link = await getLinkedProject(client, cwd);
|
||||||
if (link.status === 'error') {
|
if (link.status === 'error') {
|
||||||
return link.exitCode;
|
return link.exitCode;
|
||||||
} else if (link.status === 'not_linked') {
|
} else if (link.status === 'not_linked') {
|
||||||
@@ -144,7 +146,8 @@ export default async function main(client: Client) {
|
|||||||
ProjectEnvTarget.Development,
|
ProjectEnvTarget.Development,
|
||||||
argv,
|
argv,
|
||||||
args,
|
args,
|
||||||
output
|
output,
|
||||||
|
cwd
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
output.error(getInvalidSubcommand(COMMAND_CONFIG));
|
output.error(getInvalidSubcommand(COMMAND_CONFIG));
|
||||||
|
|||||||
14
packages/cli/src/commands/env/pull.ts
vendored
14
packages/cli/src/commands/env/pull.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { closeSync, openSync, promises, readSync } from 'fs';
|
import { outputFile } from 'fs-extra';
|
||||||
|
import { closeSync, openSync, readSync } from 'fs';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import { Project, ProjectEnvTarget } from '../../types';
|
import { Project, ProjectEnvTarget } from '../../types';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
@@ -12,7 +13,6 @@ import { Output } from '../../util/output';
|
|||||||
import param from '../../util/output/param';
|
import param from '../../util/output/param';
|
||||||
import stamp from '../../util/output/stamp';
|
import stamp from '../../util/output/stamp';
|
||||||
import { getCommandName } from '../../util/pkg-name';
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
const { writeFile } = promises;
|
|
||||||
|
|
||||||
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ export default async function pull(
|
|||||||
opts: Partial<Options>,
|
opts: Partial<Options>,
|
||||||
args: string[],
|
args: string[],
|
||||||
output: Output,
|
output: Output,
|
||||||
cwd: string = process.cwd()
|
cwd: string
|
||||||
) {
|
) {
|
||||||
if (args.length > 1) {
|
if (args.length > 1) {
|
||||||
output.error(
|
output.error(
|
||||||
@@ -81,7 +81,7 @@ export default async function pull(
|
|||||||
}
|
}
|
||||||
|
|
||||||
output.print(
|
output.print(
|
||||||
`Downloading Development Environment Variables for Project ${chalk.bold(
|
`Downloading "${environment}" Environment Variables for Project ${chalk.bold(
|
||||||
project.name
|
project.name
|
||||||
)}\n`
|
)}\n`
|
||||||
);
|
);
|
||||||
@@ -99,7 +99,9 @@ export default async function pull(
|
|||||||
const records = exposeSystemEnvs(
|
const records = exposeSystemEnvs(
|
||||||
projectEnvs,
|
projectEnvs,
|
||||||
systemEnvValues,
|
systemEnvValues,
|
||||||
project.autoExposeSystemEnvs
|
project.autoExposeSystemEnvs,
|
||||||
|
undefined,
|
||||||
|
environment
|
||||||
);
|
);
|
||||||
|
|
||||||
const contents =
|
const contents =
|
||||||
@@ -109,7 +111,7 @@ export default async function pull(
|
|||||||
.join('\n') +
|
.join('\n') +
|
||||||
'\n';
|
'\n';
|
||||||
|
|
||||||
await writeFile(fullPath, contents, 'utf8');
|
await outputFile(fullPath, contents, 'utf8');
|
||||||
|
|
||||||
output.print(
|
output.print(
|
||||||
`${prependEmoji(
|
`${prependEmoji(
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import getArgs from '../../util/get-args';
|
|||||||
import logo from '../../util/output/logo';
|
import logo from '../../util/output/logo';
|
||||||
import { getPkgName } from '../../util/pkg-name';
|
import { getPkgName } from '../../util/pkg-name';
|
||||||
import setupAndLink from '../../util/link/setup-and-link';
|
import setupAndLink from '../../util/link/setup-and-link';
|
||||||
|
import { getCommandName } from '../../util/pkg-name';
|
||||||
|
import param from '../../util/output/param';
|
||||||
|
|
||||||
const help = () => {
|
const help = () => {
|
||||||
console.log(`
|
console.log(`
|
||||||
@@ -67,6 +69,13 @@ export default async function main(client: Client) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (link.status === 'error') {
|
if (link.status === 'error') {
|
||||||
|
if (link.reason === 'HEADLESS') {
|
||||||
|
client.output.error(
|
||||||
|
`Command ${getCommandName(
|
||||||
|
'link'
|
||||||
|
)} requires confirmation. Use option ${param('--confirm')} to confirm.`
|
||||||
|
);
|
||||||
|
}
|
||||||
return link.exitCode;
|
return link.exitCode;
|
||||||
} else if (link.status === 'not_linked') {
|
} else if (link.status === 'not_linked') {
|
||||||
// User aborted project linking questions
|
// User aborted project linking questions
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import Client from '../util/client';
|
|||||||
import { ProjectEnvTarget } from '../types';
|
import { ProjectEnvTarget } from '../types';
|
||||||
import { emoji, prependEmoji } from '../util/emoji';
|
import { emoji, prependEmoji } from '../util/emoji';
|
||||||
import getArgs from '../util/get-args';
|
import getArgs from '../util/get-args';
|
||||||
import handleError from '../util/handle-error';
|
|
||||||
import setupAndLink from '../util/link/setup-and-link';
|
import setupAndLink from '../util/link/setup-and-link';
|
||||||
import logo from '../util/output/logo';
|
import logo from '../util/output/logo';
|
||||||
import stamp from '../util/output/stamp';
|
import stamp from '../util/output/stamp';
|
||||||
@@ -16,7 +15,8 @@ import {
|
|||||||
} from '../util/projects/link';
|
} from '../util/projects/link';
|
||||||
import { writeProjectSettings } from '../util/projects/project-settings';
|
import { writeProjectSettings } from '../util/projects/project-settings';
|
||||||
import envPull from './env/pull';
|
import envPull from './env/pull';
|
||||||
|
import { getCommandName } from '../util/pkg-name';
|
||||||
|
import param from '../util/output/param';
|
||||||
import type { Project, Org } from '../types';
|
import type { Project, Org } from '../types';
|
||||||
import {
|
import {
|
||||||
isValidEnvTarget,
|
isValidEnvTarget,
|
||||||
@@ -69,19 +69,14 @@ function processArgs(client: Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseArgs(client: Client) {
|
function parseArgs(client: Client) {
|
||||||
try {
|
const argv = processArgs(client);
|
||||||
const argv = processArgs(client);
|
|
||||||
|
|
||||||
if (argv['--help']) {
|
if (argv['--help']) {
|
||||||
help();
|
help();
|
||||||
return 2;
|
return 2;
|
||||||
}
|
|
||||||
|
|
||||||
return argv;
|
|
||||||
} catch (err) {
|
|
||||||
handleError(err);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkResult = {
|
type LinkResult = {
|
||||||
@@ -108,6 +103,13 @@ async function ensureLink(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (link.status === 'error') {
|
if (link.status === 'error') {
|
||||||
|
if (link.reason === 'HEADLESS') {
|
||||||
|
client.output.error(
|
||||||
|
`Command ${getCommandName(
|
||||||
|
'pull'
|
||||||
|
)} requires confirmation. Use option ${param('--yes')} to confirm.`
|
||||||
|
);
|
||||||
|
}
|
||||||
return link.exitCode;
|
return link.exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,12 @@ let debug: (s: string) => void = () => {};
|
|||||||
let apiUrl = 'https://api.vercel.com';
|
let apiUrl = 'https://api.vercel.com';
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const { isTTY } = process.stdout;
|
let { isTTY } = process.stdout;
|
||||||
|
if (process.env.FORCE_TTY === '1') {
|
||||||
|
isTTY = true;
|
||||||
|
process.stdout.isTTY = true;
|
||||||
|
process.stdin.isTTY = true;
|
||||||
|
}
|
||||||
|
|
||||||
let argv;
|
let argv;
|
||||||
|
|
||||||
@@ -585,73 +590,73 @@ const main = async () => {
|
|||||||
let func: any;
|
let func: any;
|
||||||
switch (targetCommand) {
|
switch (targetCommand) {
|
||||||
case 'alias':
|
case 'alias':
|
||||||
func = await import('./commands/alias');
|
func = require('./commands/alias').default;
|
||||||
break;
|
break;
|
||||||
case 'billing':
|
case 'billing':
|
||||||
func = await import('./commands/billing');
|
func = require('./commands/billing').default;
|
||||||
break;
|
break;
|
||||||
case 'bisect':
|
case 'bisect':
|
||||||
func = await import('./commands/bisect');
|
func = require('./commands/bisect').default;
|
||||||
break;
|
break;
|
||||||
case 'certs':
|
case 'certs':
|
||||||
func = await import('./commands/certs');
|
func = require('./commands/certs').default;
|
||||||
break;
|
break;
|
||||||
case 'deploy':
|
case 'deploy':
|
||||||
func = await import('./commands/deploy');
|
func = require('./commands/deploy').default;
|
||||||
break;
|
break;
|
||||||
case 'dev':
|
case 'dev':
|
||||||
func = await import('./commands/dev');
|
func = require('./commands/dev').default;
|
||||||
break;
|
break;
|
||||||
case 'dns':
|
case 'dns':
|
||||||
func = await import('./commands/dns');
|
func = require('./commands/dns').default;
|
||||||
break;
|
break;
|
||||||
case 'domains':
|
case 'domains':
|
||||||
func = await import('./commands/domains');
|
func = require('./commands/domains').default;
|
||||||
break;
|
break;
|
||||||
case 'env':
|
case 'env':
|
||||||
func = await import('./commands/env');
|
func = require('./commands/env').default;
|
||||||
break;
|
break;
|
||||||
case 'init':
|
case 'init':
|
||||||
func = await import('./commands/init');
|
func = require('./commands/init').default;
|
||||||
break;
|
break;
|
||||||
case 'inspect':
|
case 'inspect':
|
||||||
func = await import('./commands/inspect');
|
func = require('./commands/inspect').default;
|
||||||
break;
|
break;
|
||||||
case 'link':
|
case 'link':
|
||||||
func = await import('./commands/link');
|
func = require('./commands/link').default;
|
||||||
break;
|
break;
|
||||||
case 'list':
|
case 'list':
|
||||||
func = await import('./commands/list');
|
func = require('./commands/list').default;
|
||||||
break;
|
break;
|
||||||
case 'logs':
|
case 'logs':
|
||||||
func = await import('./commands/logs');
|
func = require('./commands/logs').default;
|
||||||
break;
|
break;
|
||||||
case 'login':
|
case 'login':
|
||||||
func = await import('./commands/login');
|
func = require('./commands/login').default;
|
||||||
break;
|
break;
|
||||||
case 'logout':
|
case 'logout':
|
||||||
func = await import('./commands/logout');
|
func = require('./commands/logout').default;
|
||||||
break;
|
break;
|
||||||
case 'projects':
|
case 'projects':
|
||||||
func = await import('./commands/projects');
|
func = require('./commands/projects').default;
|
||||||
break;
|
break;
|
||||||
case 'pull':
|
case 'pull':
|
||||||
func = await import('./commands/pull');
|
func = require('./commands/pull').default;
|
||||||
break;
|
break;
|
||||||
case 'remove':
|
case 'remove':
|
||||||
func = await import('./commands/remove');
|
func = require('./commands/remove').default;
|
||||||
break;
|
break;
|
||||||
case 'secrets':
|
case 'secrets':
|
||||||
func = await import('./commands/secrets');
|
func = require('./commands/secrets').default;
|
||||||
break;
|
break;
|
||||||
case 'teams':
|
case 'teams':
|
||||||
func = await import('./commands/teams');
|
func = require('./commands/teams').default;
|
||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
func = await import('./commands/update');
|
func = require('./commands/update').default;
|
||||||
break;
|
break;
|
||||||
case 'whoami':
|
case 'whoami':
|
||||||
func = await import('./commands/whoami');
|
func = require('./commands/whoami').default;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
func = null;
|
func = null;
|
||||||
|
|||||||
@@ -277,7 +277,17 @@ export interface PaginationOptions {
|
|||||||
export type ProjectLinkResult =
|
export type ProjectLinkResult =
|
||||||
| { status: 'linked'; org: Org; project: Project }
|
| { status: 'linked'; org: Org; project: Project }
|
||||||
| { status: 'not_linked'; org: null; project: null }
|
| { status: 'not_linked'; org: null; project: null }
|
||||||
| { status: 'error'; exitCode: number };
|
| {
|
||||||
|
status: 'error';
|
||||||
|
exitCode: number;
|
||||||
|
reason?:
|
||||||
|
| 'HEADLESS'
|
||||||
|
| 'NOT_AUTHORIZED'
|
||||||
|
| 'TEAM_DELETED'
|
||||||
|
| 'PATH_IS_FILE'
|
||||||
|
| 'INVALID_ROOT_DIRECTORY'
|
||||||
|
| 'MISSING_PROJECT_SETTINGS';
|
||||||
|
};
|
||||||
|
|
||||||
export interface Token {
|
export interface Token {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
12
packages/cli/src/util/deploy/get-prebuilt-json.ts
Normal file
12
packages/cli/src/util/deploy/get-prebuilt-json.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import fs from 'fs-extra';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
export default async function getPrebuiltJson(directory: string) {
|
||||||
|
try {
|
||||||
|
return await fs.readJSON(join(directory, '.vercel/output/builds.json'));
|
||||||
|
} catch (error) {
|
||||||
|
// ignoring error
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
41
packages/cli/src/util/deploy/parse-target.ts
Normal file
41
packages/cli/src/util/deploy/parse-target.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Output } from '../../util/output';
|
||||||
|
import param from '../../util/output/param';
|
||||||
|
import code from '../../util/output/code';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the environment target from the `--target` and `--prod` flags.
|
||||||
|
*/
|
||||||
|
export default function parseTarget(
|
||||||
|
output: Output,
|
||||||
|
targetArg?: string,
|
||||||
|
prodArg?: boolean
|
||||||
|
): string | number | undefined {
|
||||||
|
if (targetArg) {
|
||||||
|
const deprecatedTarget = targetArg;
|
||||||
|
|
||||||
|
if (!['staging', 'production'].includes(deprecatedTarget)) {
|
||||||
|
output.error(
|
||||||
|
`The specified ${param('--target')} ${code(
|
||||||
|
deprecatedTarget
|
||||||
|
)} is not valid`
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedTarget === 'production') {
|
||||||
|
output.warn(
|
||||||
|
'We recommend using the much shorter `--prod` option instead of `--target production` (deprecated)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.debug(`Setting target to ${deprecatedTarget}`);
|
||||||
|
return deprecatedTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prodArg) {
|
||||||
|
output.debug('Setting target to production');
|
||||||
|
return 'production';
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Now from '../../util';
|
import Now from '../../util';
|
||||||
import { VercelConfig } from '../dev/types';
|
|
||||||
import { Org } from '../../types';
|
import { Org } from '../../types';
|
||||||
import ua from '../ua';
|
import ua from '../ua';
|
||||||
import { linkFolderToProject } from '../projects/link';
|
import { linkFolderToProject } from '../projects/link';
|
||||||
@@ -43,7 +42,6 @@ export default async function processDeployment({
|
|||||||
uploadStamp: () => string;
|
uploadStamp: () => string;
|
||||||
deployStamp: () => string;
|
deployStamp: () => string;
|
||||||
quiet: boolean;
|
quiet: boolean;
|
||||||
nowConfig?: VercelConfig;
|
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
withCache?: boolean;
|
withCache?: boolean;
|
||||||
org: Org;
|
org: Org;
|
||||||
@@ -62,7 +60,6 @@ export default async function processDeployment({
|
|||||||
deployStamp,
|
deployStamp,
|
||||||
force,
|
force,
|
||||||
withCache,
|
withCache,
|
||||||
nowConfig,
|
|
||||||
quiet,
|
quiet,
|
||||||
prebuilt,
|
prebuilt,
|
||||||
rootDirectory,
|
rootDirectory,
|
||||||
@@ -104,11 +101,7 @@ export default async function processDeployment({
|
|||||||
const indications = [];
|
const indications = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for await (const event of createDeployment(
|
for await (const event of createDeployment(clientOptions, requestBody)) {
|
||||||
clientOptions,
|
|
||||||
requestBody,
|
|
||||||
nowConfig
|
|
||||||
)) {
|
|
||||||
if (['tip', 'notice', 'warning'].includes(event.type)) {
|
if (['tip', 'notice', 'warning'].includes(event.type)) {
|
||||||
indications.push(event);
|
indications.push(event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,7 +160,6 @@ export default class Now extends EventEmitter {
|
|||||||
uploadStamp,
|
uploadStamp,
|
||||||
deployStamp,
|
deployStamp,
|
||||||
quiet,
|
quiet,
|
||||||
nowConfig,
|
|
||||||
force: forceNew,
|
force: forceNew,
|
||||||
withCache,
|
withCache,
|
||||||
org,
|
org,
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {
|
|||||||
getLinkedProject,
|
getLinkedProject,
|
||||||
linkFolderToProject,
|
linkFolderToProject,
|
||||||
getVercelDirectory,
|
getVercelDirectory,
|
||||||
|
VERCEL_DIR_README,
|
||||||
|
VERCEL_DIR_PROJECT,
|
||||||
} from '../projects/link';
|
} from '../projects/link';
|
||||||
import createProject from '../projects/create-project';
|
import createProject from '../projects/create-project';
|
||||||
import updateProject from '../projects/update-project';
|
import updateProject from '../projects/update-project';
|
||||||
@@ -49,7 +51,7 @@ export default async function setupAndLink(
|
|||||||
const isFile = !isDirectory(path);
|
const isFile = !isDirectory(path);
|
||||||
if (isFile) {
|
if (isFile) {
|
||||||
output.error(`Expected directory but found file: ${path}`);
|
output.error(`Expected directory but found file: ${path}`);
|
||||||
return { status: 'error', exitCode: 1 };
|
return { status: 'error', exitCode: 1, reason: 'PATH_IS_FILE' };
|
||||||
}
|
}
|
||||||
const link = await getLinkedProject(client, path);
|
const link = await getLinkedProject(client, path);
|
||||||
const isTTY = process.stdout.isTTY;
|
const isTTY = process.stdout.isTTY;
|
||||||
@@ -65,7 +67,12 @@ export default async function setupAndLink(
|
|||||||
|
|
||||||
if (forceDelete) {
|
if (forceDelete) {
|
||||||
const vercelDir = getVercelDirectory(path);
|
const vercelDir = getVercelDirectory(path);
|
||||||
remove(vercelDir);
|
remove(join(vercelDir, VERCEL_DIR_README));
|
||||||
|
remove(join(vercelDir, VERCEL_DIR_PROJECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTTY && !autoConfirm) {
|
||||||
|
return { status: 'error', exitCode: 1, reason: 'HEADLESS' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldStartSetup =
|
const shouldStartSetup =
|
||||||
@@ -87,9 +94,14 @@ export default async function setupAndLink(
|
|||||||
autoConfirm
|
autoConfirm
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
|
if (err.code === 'NOT_AUTHORIZED') {
|
||||||
output.prettyError(err);
|
output.prettyError(err);
|
||||||
return { status: 'error', exitCode: 1 };
|
return { status: 'error', exitCode: 1, reason: 'NOT_AUTHORIZED' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err.code === 'TEAM_DELETED') {
|
||||||
|
output.prettyError(err);
|
||||||
|
return { status: 'error', exitCode: 1, reason: 'TEAM_DELETED' };
|
||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
@@ -135,7 +147,7 @@ export default async function setupAndLink(
|
|||||||
rootDirectory &&
|
rootDirectory &&
|
||||||
!(await validateRootDirectory(output, path, sourcePath, ''))
|
!(await validateRootDirectory(output, path, sourcePath, ''))
|
||||||
) {
|
) {
|
||||||
return { status: 'error', exitCode: 1 };
|
return { status: 'error', exitCode: 1, reason: 'INVALID_ROOT_DIRECTORY' };
|
||||||
}
|
}
|
||||||
|
|
||||||
config.currentTeam = org.type === 'team' ? org.id : undefined;
|
config.currentTeam = org.type === 'team' ? org.id : undefined;
|
||||||
@@ -191,7 +203,11 @@ export default async function setupAndLink(
|
|||||||
if (debug) {
|
if (debug) {
|
||||||
console.log(deployment);
|
console.log(deployment);
|
||||||
}
|
}
|
||||||
return { status: 'error', exitCode: 1 };
|
return {
|
||||||
|
status: 'error',
|
||||||
|
exitCode: 1,
|
||||||
|
reason: 'MISSING_PROJECT_SETTINGS',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { projectSettings, framework } = deployment;
|
const { projectSettings, framework } = deployment;
|
||||||
@@ -227,6 +243,7 @@ export default async function setupAndLink(
|
|||||||
return { status: 'linked', org, project };
|
return { status: 'linked', org, project };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
handleError(err);
|
handleError(err);
|
||||||
|
|
||||||
return { status: 'error', exitCode: 1 };
|
return { status: 'error', exitCode: 1 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { writeFile } from 'fs-extra';
|
import { outputJSON } from 'fs-extra';
|
||||||
import { Org, Project, ProjectLink } from '../../types';
|
import { Org, Project, ProjectLink } from '../../types';
|
||||||
import { getLinkFromDir, VERCEL_DIR, VERCEL_DIR_PROJECT } from './link';
|
import { getLinkFromDir, VERCEL_DIR, VERCEL_DIR_PROJECT } from './link';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@@ -22,21 +22,22 @@ export async function writeProjectSettings(
|
|||||||
project: Project,
|
project: Project,
|
||||||
org: Org
|
org: Org
|
||||||
) {
|
) {
|
||||||
return await writeFile(
|
const data = {
|
||||||
join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT),
|
projectId: project.id,
|
||||||
JSON.stringify({
|
orgId: org.id,
|
||||||
projectId: project.id,
|
settings: {
|
||||||
orgId: org.id,
|
buildCommand: project.buildCommand,
|
||||||
settings: {
|
devCommand: project.devCommand,
|
||||||
buildCommand: project.buildCommand,
|
outputDirectory: project.outputDirectory,
|
||||||
devCommand: project.devCommand,
|
directoryListing: project.directoryListing,
|
||||||
outputDirectory: project.outputDirectory,
|
rootDirectory: project.rootDirectory,
|
||||||
directoryListing: project.directoryListing,
|
framework: project.framework,
|
||||||
rootDirectory: project.rootDirectory,
|
},
|
||||||
framework: project.framework,
|
};
|
||||||
},
|
const path = join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT);
|
||||||
})
|
return await outputJSON(path, data, {
|
||||||
);
|
spaces: 2,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readProjectSettings(cwd: string) {
|
export async function readProjectSettings(cwd: string) {
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ import { join } from 'path';
|
|||||||
import { fileNameSymbol } from '@vercel/client';
|
import { fileNameSymbol } from '@vercel/client';
|
||||||
import { client } from '../mocks/client';
|
import { client } from '../mocks/client';
|
||||||
import deploy from '../../src/commands/deploy';
|
import deploy from '../../src/commands/deploy';
|
||||||
|
import { setupFixture } from '../helpers/setup-fixture';
|
||||||
|
import { defaultProject, useProject } from '../mocks/project';
|
||||||
|
import { useTeams } from '../mocks/team';
|
||||||
|
import { useUser } from '../mocks/user';
|
||||||
|
|
||||||
describe('deploy', () => {
|
describe('deploy', () => {
|
||||||
it('should reject deploying a single file', async () => {
|
it('should reject deploying a single file', async () => {
|
||||||
@@ -31,6 +35,59 @@ describe('deploy', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should reject deploying a directory that does not contain ".vercel/output" when `--prebuilt` is used', async () => {
|
||||||
|
client.setArgv('deploy', __dirname, '--prebuilt');
|
||||||
|
const exitCode = await deploy(client);
|
||||||
|
expect(exitCode).toEqual(1);
|
||||||
|
expect(client.outputBuffer).toEqual(
|
||||||
|
'Error! The "--prebuilt" option was used, but no prebuilt output found in ".vercel/output". Run `vercel build` to generate a local build.\n'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject deploying a directory that was built with a different target environment when `--prebuilt --prod` is used on "preview" output', async () => {
|
||||||
|
const cwd = setupFixture('build-output-api-preview');
|
||||||
|
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'build-output-api-preview',
|
||||||
|
name: 'build-output-api-preview',
|
||||||
|
});
|
||||||
|
|
||||||
|
client.setArgv('deploy', cwd, '--prebuilt', '--prod');
|
||||||
|
const exitCode = await deploy(client);
|
||||||
|
expect(exitCode).toEqual(1);
|
||||||
|
expect(client.outputBuffer).toEqual(
|
||||||
|
'Error! The "--prebuilt" option was used with the target environment "production",' +
|
||||||
|
' but the prebuilt output found in ".vercel/output" was built with target environment "preview".' +
|
||||||
|
' Please run `vercel --prebuilt`.\n' +
|
||||||
|
'Learn More: https://vercel.link/prebuilt-environment-mismatch\n'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject deploying a directory that was built with a different target environment when `--prebuilt` is used on "production" output', async () => {
|
||||||
|
const cwd = setupFixture('build-output-api-production');
|
||||||
|
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'build-output-api-preview',
|
||||||
|
name: 'build-output-api-preview',
|
||||||
|
});
|
||||||
|
|
||||||
|
client.setArgv('deploy', cwd, '--prebuilt');
|
||||||
|
const exitCode = await deploy(client);
|
||||||
|
expect(exitCode).toEqual(1);
|
||||||
|
expect(client.outputBuffer).toEqual(
|
||||||
|
'Error! The "--prebuilt" option was used with the target environment "preview",' +
|
||||||
|
' but the prebuilt output found in ".vercel/output" was built with target environment "production".' +
|
||||||
|
' Please run `vercel --prebuilt --prod`.\n' +
|
||||||
|
'Learn More: https://vercel.link/prebuilt-environment-mismatch\n'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should reject deploying "version: 1"', async () => {
|
it('should reject deploying "version: 1"', async () => {
|
||||||
client.setArgv('deploy');
|
client.setArgv('deploy');
|
||||||
client.localConfig = {
|
client.localConfig = {
|
||||||
|
|||||||
75
packages/cli/test/commands/env.test.ts
Normal file
75
packages/cli/test/commands/env.test.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import fs from 'fs-extra';
|
||||||
|
import path from 'path';
|
||||||
|
import env from '../../src/commands/env';
|
||||||
|
import { setupFixture } from '../helpers/setup-fixture';
|
||||||
|
import { client } from '../mocks/client';
|
||||||
|
import { defaultProject, useProject } from '../mocks/project';
|
||||||
|
import { useTeams } from '../mocks/team';
|
||||||
|
import { useUser } from '../mocks/user';
|
||||||
|
|
||||||
|
describe('env', () => {
|
||||||
|
describe('pull', () => {
|
||||||
|
it('should handle pulling', async () => {
|
||||||
|
const cwd = setupFixture('vercel-env-pull');
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'vercel-env-pull',
|
||||||
|
name: 'vercel-env-pull',
|
||||||
|
});
|
||||||
|
client.setArgv('env', 'pull', '--yes', '--cwd', cwd);
|
||||||
|
const exitCode = await env(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||||
|
|
||||||
|
const rawDevEnv = await fs.readFile(path.join(cwd, '.env'));
|
||||||
|
|
||||||
|
// check for development env value
|
||||||
|
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
||||||
|
expect(devFileHasDevEnv).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle alternate filename', async () => {
|
||||||
|
const cwd = setupFixture('vercel-env-pull');
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'vercel-env-pull',
|
||||||
|
name: 'vercel-env-pull',
|
||||||
|
});
|
||||||
|
client.setArgv('env', 'pull', 'other.env', '--yes', '--cwd', cwd);
|
||||||
|
const exitCode = await env(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||||
|
|
||||||
|
const rawDevEnv = await fs.readFile(path.join(cwd, 'other.env'));
|
||||||
|
|
||||||
|
// check for development env value
|
||||||
|
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
||||||
|
expect(devFileHasDevEnv).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should expose production system env variables', async () => {
|
||||||
|
const cwd = setupFixture('vercel-env-pull');
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'vercel-env-pull',
|
||||||
|
name: 'vercel-env-pull',
|
||||||
|
autoExposeSystemEnvs: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
client.setArgv('env', 'pull', 'other.env', '--yes', '--cwd', cwd);
|
||||||
|
const exitCode = await env(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||||
|
|
||||||
|
const rawDevEnv = await fs.readFile(path.join(cwd, 'other.env'));
|
||||||
|
|
||||||
|
const productionFileHasVercelEnv = rawDevEnv
|
||||||
|
.toString()
|
||||||
|
.includes('VERCEL_ENV="development"');
|
||||||
|
expect(productionFileHasVercelEnv).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -11,15 +11,15 @@ describe('pull', () => {
|
|||||||
it('should handle pulling', async () => {
|
it('should handle pulling', async () => {
|
||||||
const cwd = setupFixture('vercel-pull-next');
|
const cwd = setupFixture('vercel-pull-next');
|
||||||
useUser();
|
useUser();
|
||||||
useTeams();
|
useTeams('team_dummy');
|
||||||
useProject({
|
useProject({
|
||||||
...defaultProject,
|
...defaultProject,
|
||||||
id: 'vercel-pull-next',
|
id: 'vercel-pull-next',
|
||||||
name: 'vercel-pull-next',
|
name: 'vercel-pull-next',
|
||||||
});
|
});
|
||||||
client.setArgv('pull', '--yes', cwd);
|
client.setArgv('pull', cwd);
|
||||||
const exitCode = await pull(client);
|
const exitCode = await pull(client);
|
||||||
expect(exitCode).toEqual(0);
|
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||||
|
|
||||||
const rawDevEnv = await fs.readFile(
|
const rawDevEnv = await fs.readFile(
|
||||||
path.join(cwd, '.vercel', '.env.development.local')
|
path.join(cwd, '.vercel', '.env.development.local')
|
||||||
@@ -28,16 +28,86 @@ describe('pull', () => {
|
|||||||
expect(devFileHasDevEnv).toBeTruthy();
|
expect(devFileHasDevEnv).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail with message to pull without a link and without --env', async () => {
|
||||||
|
try {
|
||||||
|
process.stdout.isTTY = undefined;
|
||||||
|
|
||||||
|
const cwd = setupFixture('vercel-pull-unlinked');
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
|
||||||
|
client.setArgv('pull', cwd);
|
||||||
|
const exitCode = await pull(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(1);
|
||||||
|
|
||||||
|
expect(client.outputBuffer).toMatch(
|
||||||
|
/Command `vercel pull` requires confirmation. Use option "--yes" to confirm./gm
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
process.stdout.isTTY = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail without message to pull without a link and with --env', async () => {
|
||||||
|
const cwd = setupFixture('vercel-pull-next');
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
|
||||||
|
client.setArgv('pull', cwd, '--yes');
|
||||||
|
const exitCode = await pull(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(1);
|
||||||
|
|
||||||
|
expect(client.outputBuffer).not.toMatch(
|
||||||
|
/Command `vercel pull` requires confirmation. Use option "--yes" to confirm./gm
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle pulling with env vars (headless mode)', async () => {
|
||||||
|
try {
|
||||||
|
process.env.VERCEL_PROJECT_ID = 'vercel-pull-next';
|
||||||
|
process.env.VERCEL_ORG_ID = 'team_dummy';
|
||||||
|
|
||||||
|
const cwd = setupFixture('vercel-pull-next');
|
||||||
|
|
||||||
|
// Remove the `.vercel` dir to ensure that the `pull`
|
||||||
|
// command creates a new one based on env vars
|
||||||
|
await fs.remove(path.join(cwd, '.vercel'));
|
||||||
|
|
||||||
|
useUser();
|
||||||
|
useTeams('team_dummy');
|
||||||
|
useProject({
|
||||||
|
...defaultProject,
|
||||||
|
id: 'vercel-pull-next',
|
||||||
|
name: 'vercel-pull-next',
|
||||||
|
});
|
||||||
|
client.setArgv('pull', cwd);
|
||||||
|
const exitCode = await pull(client);
|
||||||
|
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||||
|
|
||||||
|
const config = await fs.readJSON(path.join(cwd, '.vercel/project.json'));
|
||||||
|
expect(config).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"orgId": "team_dummy",
|
||||||
|
"projectId": "vercel-pull-next",
|
||||||
|
"settings": Object {},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
} finally {
|
||||||
|
delete process.env.VERCEL_PROJECT_ID;
|
||||||
|
delete process.env.VERCEL_ORG_ID;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle --environment=preview flag', async () => {
|
it('should handle --environment=preview flag', async () => {
|
||||||
const cwd = setupFixture('vercel-pull-next');
|
const cwd = setupFixture('vercel-pull-next');
|
||||||
useUser();
|
useUser();
|
||||||
useTeams();
|
useTeams('team_dummy');
|
||||||
useProject({
|
useProject({
|
||||||
...defaultProject,
|
...defaultProject,
|
||||||
id: 'vercel-pull-next',
|
id: 'vercel-pull-next',
|
||||||
name: 'vercel-pull-next',
|
name: 'vercel-pull-next',
|
||||||
});
|
});
|
||||||
client.setArgv('pull', '--yes', '--environment=preview', cwd);
|
client.setArgv('pull', '--environment=preview', cwd);
|
||||||
const exitCode = await pull(client);
|
const exitCode = await pull(client);
|
||||||
expect(exitCode).toEqual(0);
|
expect(exitCode).toEqual(0);
|
||||||
|
|
||||||
@@ -53,13 +123,13 @@ describe('pull', () => {
|
|||||||
it('should handle --environment=production flag', async () => {
|
it('should handle --environment=production flag', async () => {
|
||||||
const cwd = setupFixture('vercel-pull-next');
|
const cwd = setupFixture('vercel-pull-next');
|
||||||
useUser();
|
useUser();
|
||||||
useTeams();
|
useTeams('team_dummy');
|
||||||
useProject({
|
useProject({
|
||||||
...defaultProject,
|
...defaultProject,
|
||||||
id: 'vercel-pull-next',
|
id: 'vercel-pull-next',
|
||||||
name: 'vercel-pull-next',
|
name: 'vercel-pull-next',
|
||||||
});
|
});
|
||||||
client.setArgv('pull', '--yes', '--environment=production', cwd);
|
client.setArgv('pull', '--environment=production', cwd);
|
||||||
const exitCode = await pull(client);
|
const exitCode = await pull(client);
|
||||||
expect(exitCode).toEqual(0);
|
expect(exitCode).toEqual(0);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ cache:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
# See https://git.io/vdao3 for details.
|
# See https://github.com/ember-cli/ember-cli/blob/master/docs/build-concurrency.md
|
||||||
- JOBS=1
|
- JOBS=1
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
|||||||
3
packages/cli/test/fixtures/unit/build-output-api-preview/.vercel/output/builds.json
vendored
Normal file
3
packages/cli/test/fixtures/unit/build-output-api-preview/.vercel/output/builds.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"target": "preview"
|
||||||
|
}
|
||||||
3
packages/cli/test/fixtures/unit/build-output-api-production/.vercel/output/builds.json
vendored
Normal file
3
packages/cli/test/fixtures/unit/build-output-api-production/.vercel/output/builds.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"target": "production"
|
||||||
|
}
|
||||||
2
packages/cli/test/fixtures/unit/vercel-env-pull/.gitignore
vendored
Normal file
2
packages/cli/test/fixtures/unit/vercel-env-pull/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.next
|
||||||
|
yarn.lock
|
||||||
4
packages/cli/test/fixtures/unit/vercel-env-pull/.vercel/project.json
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-env-pull/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"orgId": "team_dummy",
|
||||||
|
"projectId": "vercel-env-pull"
|
||||||
|
}
|
||||||
12
packages/cli/test/fixtures/unit/vercel-env-pull/package.json
vendored
Normal file
12
packages/cli/test/fixtures/unit/vercel-env-pull/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "next build",
|
||||||
|
"dev": "next",
|
||||||
|
"now-build": "next build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^8.0.0",
|
||||||
|
"react": "^16.7.0",
|
||||||
|
"react-dom": "^16.7.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
packages/cli/test/fixtures/unit/vercel-env-pull/pages/index.js
vendored
Normal file
11
packages/cli/test/fixtures/unit/vercel-env-pull/pages/index.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { withRouter } from 'next/router';
|
||||||
|
|
||||||
|
function Index({ router }) {
|
||||||
|
const data = {
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: router.query,
|
||||||
|
};
|
||||||
|
return <div>{JSON.stringify(data)}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(Index);
|
||||||
10
packages/cli/test/fixtures/unit/vercel-env-pull/vercel.json
vendored
Normal file
10
packages/cli/test/fixtures/unit/vercel-env-pull/vercel.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"name": "vercel-env-pull",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"src": "/(.*)",
|
||||||
|
"dest": "/index?route-param=b"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
.next
|
.next
|
||||||
yarn.lock
|
yarn.lock
|
||||||
.vercel
|
|
||||||
4
packages/cli/test/fixtures/unit/vercel-pull-next/.vercel/project.json
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-pull-next/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"orgId": "team_dummy",
|
||||||
|
"projectId": "vercel-pull-next"
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"name": "vercel-pull-next",
|
"name": "vercel-pull-next",
|
||||||
"builds": [{ "src": "package.json", "use": "@vercel/next@canary" }],
|
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"src": "/(.*)",
|
"src": "/(.*)",
|
||||||
|
|||||||
2
packages/cli/test/fixtures/unit/vercel-pull-unlinked/.gitignore
vendored
Normal file
2
packages/cli/test/fixtures/unit/vercel-pull-unlinked/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.next
|
||||||
|
yarn.lock
|
||||||
12
packages/cli/test/fixtures/unit/vercel-pull-unlinked/package.json
vendored
Normal file
12
packages/cli/test/fixtures/unit/vercel-pull-unlinked/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "next build",
|
||||||
|
"dev": "next",
|
||||||
|
"now-build": "next build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^8.0.0",
|
||||||
|
"react": "^16.7.0",
|
||||||
|
"react-dom": "^16.7.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
packages/cli/test/fixtures/unit/vercel-pull-unlinked/pages/index.js
vendored
Normal file
11
packages/cli/test/fixtures/unit/vercel-pull-unlinked/pages/index.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { withRouter } from 'next/router';
|
||||||
|
|
||||||
|
function Index({ router }) {
|
||||||
|
const data = {
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: router.query,
|
||||||
|
};
|
||||||
|
return <div>{JSON.stringify(data)}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(Index);
|
||||||
1
packages/cli/test/fixtures/unit/vercel-pull-unlinked/static/robots.txt
vendored
Normal file
1
packages/cli/test/fixtures/unit/vercel-pull-unlinked/static/robots.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
User-Agent: *
|
||||||
10
packages/cli/test/fixtures/unit/vercel-pull-unlinked/vercel.json
vendored
Normal file
10
packages/cli/test/fixtures/unit/vercel-pull-unlinked/vercel.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"name": "vercel-pull-next",
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"src": "/(.*)",
|
||||||
|
"dest": "/index?route-param=b"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -179,6 +179,19 @@ module.exports = async function prepare(session, binaryPath) {
|
|||||||
'list/README.md':
|
'list/README.md':
|
||||||
'readme contents for deploy-default-with-conflicting-sub-directory',
|
'readme contents for deploy-default-with-conflicting-sub-directory',
|
||||||
},
|
},
|
||||||
|
'deploy-default-with-prebuilt-preview': {
|
||||||
|
'vercel.json': JSON.stringify({ version: 2 }),
|
||||||
|
'.vercel/output/builds.json': JSON.stringify({ target: 'preview' }),
|
||||||
|
'.vercel/output/config.json': JSON.stringify({ version: 3 }),
|
||||||
|
'.vercel/output/static/README.md':
|
||||||
|
'readme contents for deploy-default-with-prebuilt-preview',
|
||||||
|
},
|
||||||
|
'build-output-api-raw': {
|
||||||
|
'vercel.json': JSON.stringify({ version: 2 }),
|
||||||
|
'.vercel/output/config.json': JSON.stringify({ version: 3 }),
|
||||||
|
'.vercel/output/static/README.md':
|
||||||
|
'readme contents for build-output-api-raw',
|
||||||
|
},
|
||||||
'local-config-v2': {
|
'local-config-v2': {
|
||||||
[`main-${session}.html`]: '<h1>hello main</h1>',
|
[`main-${session}.html`]: '<h1>hello main</h1>',
|
||||||
[`test-${session}.html`]: '<h1>hello test</h1>',
|
[`test-${session}.html`]: '<h1>hello test</h1>',
|
||||||
|
|||||||
231
packages/cli/test/integration.js
vendored
231
packages/cli/test/integration.js
vendored
@@ -7,10 +7,9 @@ import { Readable } from 'stream';
|
|||||||
import { homedir } from 'os';
|
import { homedir } from 'os';
|
||||||
import _execa from 'execa';
|
import _execa from 'execa';
|
||||||
import XDGAppPaths from 'xdg-app-paths';
|
import XDGAppPaths from 'xdg-app-paths';
|
||||||
import nodeFetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import tmp from 'tmp-promise';
|
import tmp from 'tmp-promise';
|
||||||
import retry from 'async-retry';
|
import retry from 'async-retry';
|
||||||
import createFetchRetry from '@vercel/fetch-retry';
|
|
||||||
import fs, {
|
import fs, {
|
||||||
writeFile,
|
writeFile,
|
||||||
readFile,
|
readFile,
|
||||||
@@ -25,8 +24,6 @@ import pkg from '../package';
|
|||||||
import prepareFixtures from './helpers/prepare';
|
import prepareFixtures from './helpers/prepare';
|
||||||
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
|
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
|
||||||
|
|
||||||
const fetch = createFetchRetry(nodeFetch);
|
|
||||||
|
|
||||||
// log command when running `execa`
|
// log command when running `execa`
|
||||||
function execa(file, args, options) {
|
function execa(file, args, options) {
|
||||||
console.log(`$ vercel ${args.join(' ')}`);
|
console.log(`$ vercel ${args.join(' ')}`);
|
||||||
@@ -497,6 +494,56 @@ test('default command should work with --cwd option', async t => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should allow deploying a directory that was built with a target environment of "preview" and `--prebuilt` is used without specifying a target', async t => {
|
||||||
|
const projectDir = fixture('deploy-default-with-prebuilt-preview');
|
||||||
|
|
||||||
|
await vcLink(t, projectDir);
|
||||||
|
|
||||||
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
|
binaryPath,
|
||||||
|
[
|
||||||
|
// omit the default "deploy" command
|
||||||
|
'--prebuilt',
|
||||||
|
...defaultArgs,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cwd: projectDir,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
|
||||||
|
const url = stdout;
|
||||||
|
const deploymentResult = await fetch(`${url}/README.md`);
|
||||||
|
const body = await deploymentResult.text();
|
||||||
|
t.deepEqual(body, 'readme contents for deploy-default-with-prebuilt-preview');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should allow deploying a directory that was prebuilt, but has no builds.json', async t => {
|
||||||
|
const projectDir = fixture('build-output-api-raw');
|
||||||
|
|
||||||
|
await vcLink(t, projectDir);
|
||||||
|
|
||||||
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
|
binaryPath,
|
||||||
|
[
|
||||||
|
// omit the default "deploy" command
|
||||||
|
'--prebuilt',
|
||||||
|
...defaultArgs,
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cwd: projectDir,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
|
|
||||||
|
const url = stdout;
|
||||||
|
const deploymentResult = await fetch(`${url}/README.md`);
|
||||||
|
const body = await deploymentResult.text();
|
||||||
|
t.deepEqual(body, 'readme contents for build-output-api-raw');
|
||||||
|
});
|
||||||
|
|
||||||
test('deploy using only now.json with `redirects` defined', async t => {
|
test('deploy using only now.json with `redirects` defined', async t => {
|
||||||
const target = fixture('redirects-v2');
|
const target = fixture('redirects-v2');
|
||||||
|
|
||||||
@@ -796,13 +843,11 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.regex(stderr, /Created .env file/gm);
|
t.regex(stderr, /Created .env file/gm);
|
||||||
|
|
||||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||||
t.true(contents.startsWith('# Created by Vercel CLI\n'));
|
t.regex(contents, /^# Created by Vercel CLI\n/);
|
||||||
|
t.regex(contents, /MY_NEW_ENV_VAR="my plaintext value"/);
|
||||||
const lines = new Set(contents.split('\n'));
|
t.regex(contents, /MY_STDIN_VAR="{"expect":"quotes"}"/);
|
||||||
t.true(lines.has('MY_NEW_ENV_VAR="my plaintext value"'));
|
t.regex(contents, /MY_DECRYPTABLE_SECRET_ENV="decryptable value"/);
|
||||||
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'));
|
t.notRegex(contents, /MY_PREVIEW/);
|
||||||
t.true(lines.has('MY_DECRYPTABLE_SECRET_ENV="decryptable value"'));
|
|
||||||
t.false(lines.has('MY_PREVIEW'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function vcEnvPullOverwrite() {
|
async function vcEnvPullOverwrite() {
|
||||||
@@ -974,11 +1019,12 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||||
|
|
||||||
const lines = new Set(contents.split('\n'));
|
const lines = new Set(contents.split('\n'));
|
||||||
t.true(lines.has('VERCEL="1"'));
|
|
||||||
t.true(lines.has('VERCEL_URL=""'));
|
t.true(lines.has('VERCEL="1"'), 'VERCEL');
|
||||||
t.true(lines.has('VERCEL_ENV="development"'));
|
t.true(lines.has('VERCEL_URL=""'), 'VERCEL_URL');
|
||||||
t.true(lines.has('VERCEL_GIT_PROVIDER=""'));
|
t.true(lines.has('VERCEL_ENV="development"'), 'VERCEL_ENV');
|
||||||
t.true(lines.has('VERCEL_GIT_REPO_SLUG=""'));
|
t.true(lines.has('VERCEL_GIT_PROVIDER=""'), 'VERCEL_GIT_PROVIDER');
|
||||||
|
t.true(lines.has('VERCEL_GIT_REPO_SLUG=""'), 'VERCEL_GIT_REPO_SLUG');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function vcDevAndFetchSystemVars() {
|
async function vcDevAndFetchSystemVars() {
|
||||||
@@ -1086,29 +1132,48 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
|||||||
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
|
||||||
}
|
}
|
||||||
|
|
||||||
await vcLink();
|
function vcEnvRemoveByName(name) {
|
||||||
await vcEnvLsIsEmpty();
|
return execa(binaryPath, ['env', 'rm', name, '-y', ...defaultArgs], {
|
||||||
await vcEnvAddWithPrompts();
|
reject: false,
|
||||||
await vcEnvAddFromStdin();
|
cwd: target,
|
||||||
await vcEnvAddFromStdinPreview();
|
});
|
||||||
await vcEnvAddFromStdinPreviewWithBranch();
|
}
|
||||||
await vcEnvLsIncludesVar();
|
|
||||||
await createEnvWithDecryptableSecret();
|
async function vcEnvRemoveAll() {
|
||||||
await vcEnvPull();
|
await vcEnvRemoveByName('MY_PREVIEW');
|
||||||
await vcEnvPullOverwrite();
|
await vcEnvRemoveByName('MY_STDIN_VAR');
|
||||||
await vcEnvPullConfirm();
|
await vcEnvRemoveByName('MY_DECRYPTABLE_SECRET_ENV');
|
||||||
await vcDeployWithVar();
|
await vcEnvRemoveByName('MY_NEW_ENV_VAR');
|
||||||
await vcDevWithEnv();
|
}
|
||||||
fs.unlinkSync(path.join(target, '.env'));
|
|
||||||
await vcDevAndFetchCloudVars();
|
try {
|
||||||
await enableAutoExposeSystemEnvs();
|
await vcEnvRemoveAll();
|
||||||
await vcEnvPullFetchSystemVars();
|
await vcLink();
|
||||||
fs.unlinkSync(path.join(target, '.env'));
|
await vcEnvLsIsEmpty();
|
||||||
await vcDevAndFetchSystemVars();
|
await vcEnvAddWithPrompts();
|
||||||
await vcEnvRemove();
|
await vcEnvAddFromStdin();
|
||||||
await vcEnvRemoveWithArgs();
|
await vcEnvAddFromStdinPreview();
|
||||||
await vcEnvRemoveWithNameOnly();
|
await vcEnvAddFromStdinPreviewWithBranch();
|
||||||
await vcEnvLsIsEmpty();
|
await vcEnvLsIncludesVar();
|
||||||
|
await createEnvWithDecryptableSecret();
|
||||||
|
await vcEnvPull();
|
||||||
|
await vcEnvPullOverwrite();
|
||||||
|
await vcEnvPullConfirm();
|
||||||
|
await vcDeployWithVar();
|
||||||
|
await vcDevWithEnv();
|
||||||
|
fs.unlinkSync(path.join(target, '.env'));
|
||||||
|
await vcDevAndFetchCloudVars();
|
||||||
|
await enableAutoExposeSystemEnvs();
|
||||||
|
await vcEnvPullFetchSystemVars();
|
||||||
|
fs.unlinkSync(path.join(target, '.env'));
|
||||||
|
await vcDevAndFetchSystemVars();
|
||||||
|
await vcEnvRemove();
|
||||||
|
await vcEnvRemoveWithArgs();
|
||||||
|
await vcEnvRemoveWithNameOnly();
|
||||||
|
await vcEnvLsIsEmpty();
|
||||||
|
} finally {
|
||||||
|
await vcEnvRemoveAll();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('[vc projects] should create a project successfully', async t => {
|
test('[vc projects] should create a project successfully', async t => {
|
||||||
@@ -1446,6 +1511,9 @@ test('try to purchase a domain', async t => {
|
|||||||
{
|
{
|
||||||
reject: false,
|
reject: false,
|
||||||
input: stream,
|
input: stream,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2144,11 +2212,6 @@ const verifyExampleAngular = (cwd, dir) =>
|
|||||||
fs.existsSync(path.join(cwd, dir, 'tsconfig.json')) &&
|
fs.existsSync(path.join(cwd, dir, 'tsconfig.json')) &&
|
||||||
fs.existsSync(path.join(cwd, dir, 'angular.json'));
|
fs.existsSync(path.join(cwd, dir, 'angular.json'));
|
||||||
|
|
||||||
const verifyExampleAmp = (cwd, dir) =>
|
|
||||||
fs.existsSync(path.join(cwd, dir, 'index.html')) &&
|
|
||||||
fs.existsSync(path.join(cwd, dir, 'logo.png')) &&
|
|
||||||
fs.existsSync(path.join(cwd, dir, 'favicon.png'));
|
|
||||||
|
|
||||||
test('initialize example "angular"', async t => {
|
test('initialize example "angular"', async t => {
|
||||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
||||||
const cwd = tmpDir.name;
|
const cwd = tmpDir.name;
|
||||||
@@ -2183,21 +2246,6 @@ test('initialize example ("angular") to specified directory', async t => {
|
|||||||
t.true(verifyExampleAngular(cwd, 'ang'), formatOutput({ stdout, stderr }));
|
t.true(verifyExampleAngular(cwd, 'ang'), formatOutput({ stdout, stderr }));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('initialize selected example ("amp")', async t => {
|
|
||||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
|
||||||
const cwd = tmpDir.name;
|
|
||||||
const goal = '> Success! Initialized "amp" example in';
|
|
||||||
|
|
||||||
const { stdout, stderr, exitCode } = await execute(['init'], {
|
|
||||||
cwd,
|
|
||||||
input: '\n',
|
|
||||||
});
|
|
||||||
|
|
||||||
t.is(exitCode, 0, formatOutput({ stdout, stderr }));
|
|
||||||
t.true(stderr.includes(goal), formatOutput({ stdout, stderr }));
|
|
||||||
t.true(verifyExampleAmp(cwd, 'amp'), formatOutput({ stdout, stderr }));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('initialize example to existing directory with "-f"', async t => {
|
test('initialize example to existing directory with "-f"', async t => {
|
||||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
||||||
const cwd = tmpDir.name;
|
const cwd = tmpDir.name;
|
||||||
@@ -2274,6 +2322,8 @@ test('try to revert a deployment and assign the automatic aliases', async t => {
|
|||||||
const { name } = JSON.parse(
|
const { name } = JSON.parse(
|
||||||
fs.readFileSync(path.join(firstDeployment, 'now.json'))
|
fs.readFileSync(path.join(firstDeployment, 'now.json'))
|
||||||
);
|
);
|
||||||
|
t.true(!!name, 'name has a value');
|
||||||
|
|
||||||
const url = `https://${name}.user.vercel.app`;
|
const url = `https://${name}.user.vercel.app`;
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2375,6 +2425,9 @@ test('[vercel dev] fails when development commad calls vercel dev recursively',
|
|||||||
const dev = execa(binaryPath, ['dev', ...defaultArgs], {
|
const dev = execa(binaryPath, ['dev', ...defaultArgs], {
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
reject: false,
|
reject: false,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await setupProject(dev, projectName, {
|
await setupProject(dev, projectName, {
|
||||||
@@ -2780,6 +2833,9 @@ test('change user', async t => {
|
|||||||
|
|
||||||
await execute(['login', email, '--api', loginApiUrl, '--debug'], {
|
await execute(['login', email, '--api', loginApiUrl, '--debug'], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const auth = await fs.readJSON(getConfigAuthPath());
|
const auth = await fs.readJSON(getConfigAuthPath());
|
||||||
@@ -2862,7 +2918,7 @@ test('should show prompts to set up project during first deploy', async t => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Send a test request to the deployment
|
// Send a test request to the deployment
|
||||||
const response = await fetch(new URL(output.stdout).href);
|
const response = await fetch(new URL(output.stdout));
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
t.is(text.includes('<h1>custom hello</h1>'), true, text);
|
t.is(text.includes('<h1>custom hello</h1>'), true, text);
|
||||||
|
|
||||||
@@ -2909,7 +2965,11 @@ test('should prefill "project name" prompt with folder name', async t => {
|
|||||||
const directory = path.join(src, '../', projectName);
|
const directory = path.join(src, '../', projectName);
|
||||||
await copy(src, directory);
|
await copy(src, directory);
|
||||||
|
|
||||||
const now = execa(binaryPath, [directory, ...defaultArgs]);
|
const now = execa(binaryPath, [directory, ...defaultArgs], {
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await waitForPrompt(now, chunk => /Set up and deploy [^?]+\?/.test(chunk));
|
await waitForPrompt(now, chunk => /Set up and deploy [^?]+\?/.test(chunk));
|
||||||
now.stdin.write('yes\n');
|
now.stdin.write('yes\n');
|
||||||
@@ -2952,12 +3012,15 @@ test('should prefill "project name" prompt with --name', async t => {
|
|||||||
// remove previously linked project if it exists
|
// remove previously linked project if it exists
|
||||||
await remove(path.join(directory, '.vercel'));
|
await remove(path.join(directory, '.vercel'));
|
||||||
|
|
||||||
const now = execa(binaryPath, [
|
const now = execa(
|
||||||
directory,
|
binaryPath,
|
||||||
'--name',
|
[directory, '--name', projectName, ...defaultArgs],
|
||||||
projectName,
|
{
|
||||||
...defaultArgs,
|
env: {
|
||||||
]);
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let isDeprecated = false;
|
let isDeprecated = false;
|
||||||
|
|
||||||
@@ -3016,7 +3079,11 @@ test('should prefill "project name" prompt with now.json `name`', async t => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const now = execa(binaryPath, [directory, ...defaultArgs]);
|
const now = execa(binaryPath, [directory, ...defaultArgs], {
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
let isDeprecated = false;
|
let isDeprecated = false;
|
||||||
|
|
||||||
@@ -3437,7 +3504,12 @@ test('[vc link] should show prompts to set up project', async t => {
|
|||||||
// remove previously linked project if it exists
|
// remove previously linked project if it exists
|
||||||
await remove(path.join(dir, '.vercel'));
|
await remove(path.join(dir, '.vercel'));
|
||||||
|
|
||||||
const vc = execa(binaryPath, ['link', ...defaultArgs], { cwd: dir });
|
const vc = execa(binaryPath, ['link', ...defaultArgs], {
|
||||||
|
cwd: dir,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await setupProject(vc, projectName, {
|
await setupProject(vc, projectName, {
|
||||||
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
|
||||||
@@ -3510,7 +3582,13 @@ test('[vc link] should not duplicate paths in .gitignore', async t => {
|
|||||||
const { exitCode, stderr, stdout } = await execa(
|
const { exitCode, stderr, stdout } = await execa(
|
||||||
binaryPath,
|
binaryPath,
|
||||||
['link', '--confirm', ...defaultArgs],
|
['link', '--confirm', ...defaultArgs],
|
||||||
{ cwd: dir, reject: false }
|
{
|
||||||
|
cwd: dir,
|
||||||
|
reject: false,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure the exit code is right
|
// Ensure the exit code is right
|
||||||
@@ -3536,6 +3614,9 @@ test('[vc dev] should show prompts to set up project', async t => {
|
|||||||
|
|
||||||
const dev = execa(binaryPath, ['dev', '--listen', port, ...defaultArgs], {
|
const dev = execa(binaryPath, ['dev', '--listen', port, ...defaultArgs], {
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await setupProject(dev, projectName, {
|
await setupProject(dev, projectName, {
|
||||||
@@ -3580,7 +3661,12 @@ test('[vc link] should show project prompts but not framework when `builds` defi
|
|||||||
// remove previously linked project if it exists
|
// remove previously linked project if it exists
|
||||||
await remove(path.join(dir, '.vercel'));
|
await remove(path.join(dir, '.vercel'));
|
||||||
|
|
||||||
const vc = execa(binaryPath, ['link', ...defaultArgs], { cwd: dir });
|
const vc = execa(binaryPath, ['link', ...defaultArgs], {
|
||||||
|
cwd: dir,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await waitForPrompt(vc, chunk => /Set up [^?]+\?/.test(chunk));
|
await waitForPrompt(vc, chunk => /Set up [^?]+\?/.test(chunk));
|
||||||
vc.stdin.write('yes\n');
|
vc.stdin.write('yes\n');
|
||||||
@@ -3639,6 +3725,9 @@ test('[vc dev] should send the platform proxy request headers to frontend dev se
|
|||||||
|
|
||||||
const dev = execa(binaryPath, ['dev', '--listen', port, ...defaultArgs], {
|
const dev = execa(binaryPath, ['dev', '--listen', port, ...defaultArgs], {
|
||||||
cwd: dir,
|
cwd: dir,
|
||||||
|
env: {
|
||||||
|
FORCE_TTY: '1',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await setupProject(dev, projectName, {
|
await setupProject(dev, projectName, {
|
||||||
|
|||||||
@@ -87,7 +87,20 @@ export class MockClient extends Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stopMockServer() {
|
stopMockServer() {
|
||||||
this.mockServer?.close();
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
if (!this.mockServer?.close) {
|
||||||
|
reject(new Error(`mockServer did not exist when closing`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mockServer.close(error => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setArgv(...argv: string[]) {
|
setArgv(...argv: string[]) {
|
||||||
@@ -109,6 +122,6 @@ beforeEach(() => {
|
|||||||
client.reset();
|
client.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(async () => {
|
||||||
client.stopMockServer();
|
await client.stopMockServer();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { client } from './client';
|
import { client } from './client';
|
||||||
|
import { Project } from '../../src/types';
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
{
|
{
|
||||||
@@ -36,6 +37,42 @@ const envs = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const systemEnvs = [
|
||||||
|
{
|
||||||
|
type: 'encrypted',
|
||||||
|
id: 'a235l6frtu25df32',
|
||||||
|
key: 'SYSTEM_ENV_FOR_DEV',
|
||||||
|
value: 'development',
|
||||||
|
target: ['development'],
|
||||||
|
gitBranch: null,
|
||||||
|
configurationId: null,
|
||||||
|
updatedAt: 1557241361445,
|
||||||
|
createdAt: 1557241361445,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'encrypted',
|
||||||
|
id: 'a235l6frtu25df32',
|
||||||
|
key: 'SYSTEM_ENV_FOR_PREV',
|
||||||
|
value: 'preview',
|
||||||
|
target: ['preview'],
|
||||||
|
gitBranch: null,
|
||||||
|
configurationId: null,
|
||||||
|
updatedAt: 1557241361445,
|
||||||
|
createdAt: 1557241361445,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'encrypted',
|
||||||
|
id: 'a235l6frtu25df32',
|
||||||
|
key: 'SYSTEM_ENV_FOR_PROD',
|
||||||
|
value: 'production',
|
||||||
|
target: ['production'],
|
||||||
|
gitBranch: null,
|
||||||
|
configurationId: null,
|
||||||
|
updatedAt: 1557241361445,
|
||||||
|
createdAt: 1557241361445,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const defaultProject = {
|
export const defaultProject = {
|
||||||
id: 'foo',
|
id: 'foo',
|
||||||
name: 'cli',
|
name: 'cli',
|
||||||
@@ -80,25 +117,42 @@ export const defaultProject = {
|
|||||||
requestedAt: 1571239348998,
|
requestedAt: 1571239348998,
|
||||||
target: 'production',
|
target: 'production',
|
||||||
teamId: null,
|
teamId: null,
|
||||||
type: 'LAMBDAS',
|
type: undefined,
|
||||||
url: 'a-project-name-rjtr4pz3f.vercel.app',
|
url: 'a-project-name-rjtr4pz3f.vercel.app',
|
||||||
userId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
userId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useProject(project = defaultProject) {
|
export function useProject(project: Partial<Project> = defaultProject) {
|
||||||
client.scenario.get(`/v8/projects/${project.name}`, (_req, res) => {
|
client.scenario.get(`/v8/projects/${project.name}`, (_req, res) => {
|
||||||
res.json(project);
|
res.json(project);
|
||||||
});
|
});
|
||||||
client.scenario.get(`/v8/projects/${project.id}`, (_req, res) => {
|
client.scenario.get(`/v8/projects/${project.id}`, (_req, res) => {
|
||||||
res.json(project);
|
res.json(project);
|
||||||
});
|
});
|
||||||
|
client.scenario.get(
|
||||||
|
`/v6/projects/${project.id}/system-env-values`,
|
||||||
|
(_req, res) => {
|
||||||
|
const target = _req.query.target || 'development';
|
||||||
|
if (typeof target !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
`/v6/projects/${project.id}/system-env-values was given a query param of "target=${target}", which is not a valid environment.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const targetEnvs = systemEnvs.filter(env => env.target.includes(target));
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
systemEnvValues: targetEnvs,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
client.scenario.get(`/v8/projects/${project.id}/env`, (_req, res) => {
|
client.scenario.get(`/v8/projects/${project.id}/env`, (_req, res) => {
|
||||||
const target = _req.query.target;
|
const target = _req.query.target;
|
||||||
if (typeof target === 'string') {
|
if (typeof target === 'string') {
|
||||||
const targetEnvs = envs.filter(env => env.target.includes(target));
|
const targetEnvs = envs.filter(env => env.target.includes(target));
|
||||||
res.json({ envs: targetEnvs });
|
res.json({ envs: targetEnvs });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({ envs });
|
res.json({ envs });
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import chance from 'chance';
|
import chance from 'chance';
|
||||||
import { client } from './client';
|
import { client } from './client';
|
||||||
|
|
||||||
export function useTeams() {
|
export function useTeams(teamId?: string) {
|
||||||
|
const id = teamId || chance().guid();
|
||||||
const teams = [
|
const teams = [
|
||||||
{
|
{
|
||||||
id: chance().guid(),
|
id,
|
||||||
slug: chance().string({ length: 5, casing: 'lower' }),
|
slug: chance().string({ length: 5, casing: 'lower' }),
|
||||||
name: chance().company(),
|
name: chance().company(),
|
||||||
creatorId: chance().guid(),
|
creatorId: chance().guid(),
|
||||||
@@ -14,7 +15,7 @@ export function useTeams() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (let team of teams) {
|
for (let team of teams) {
|
||||||
client.scenario.get(`/v1/team/${team.id}`, (_req, res) => {
|
client.scenario.get(`/teams/${team.id}`, (_req, res) => {
|
||||||
res.json(team);
|
res.json(team);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
55
packages/cli/test/util/deploy/parse-target.test.ts
Normal file
55
packages/cli/test/util/deploy/parse-target.test.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import parseTarget from '../../../src/util/deploy/parse-target';
|
||||||
|
import { Output } from '../../../src/util/output';
|
||||||
|
|
||||||
|
describe('parseTarget', () => {
|
||||||
|
let output: Output;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
output = new Output();
|
||||||
|
output.warn = jest.fn();
|
||||||
|
output.error = jest.fn();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defaults to `undefined`', () => {
|
||||||
|
let result = parseTarget(output);
|
||||||
|
expect(result).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails when given invalid target', () => {
|
||||||
|
const result = parseTarget(output, 'not-a-real-environment');
|
||||||
|
expect(result).toEqual(1);
|
||||||
|
|
||||||
|
const errorMock = (output.error as jest.Mock<any, any>).mock;
|
||||||
|
expect(errorMock.calls[0][0]).toMatch(
|
||||||
|
/not-a-real-environment.+is not valid/g
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses "production" target', () => {
|
||||||
|
let result = parseTarget(output, 'production');
|
||||||
|
expect(result).toEqual('production');
|
||||||
|
expect(output.warn).toHaveBeenCalledWith(
|
||||||
|
'We recommend using the much shorter `--prod` option instead of `--target production` (deprecated)'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses "staging" target', () => {
|
||||||
|
let result = parseTarget(output, 'staging');
|
||||||
|
expect(result).toEqual('staging');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prefers target over production argument', () => {
|
||||||
|
let result = parseTarget(output, 'staging', true);
|
||||||
|
expect(result).toEqual('staging');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses production argument when `true`', () => {
|
||||||
|
let result = parseTarget(output, undefined, true);
|
||||||
|
expect(result).toEqual('production');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses production argument when `false`', () => {
|
||||||
|
let result = parseTarget(output, undefined, false);
|
||||||
|
expect(result).toEqual(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/client",
|
"name": "@vercel/client",
|
||||||
"version": "10.4.1",
|
"version": "11.0.1",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
"homepage": "https://vercel.com",
|
"homepage": "https://vercel.com",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/async-retry": "1.4.1",
|
"@types/async-retry": "1.4.1",
|
||||||
"@types/fs-extra": "7.0.0",
|
"@types/fs-extra": "7.0.0",
|
||||||
"@types/jest": "27.0.1",
|
"@types/jest": "27.4.1",
|
||||||
"@types/minimatch": "3.0.5",
|
"@types/minimatch": "3.0.5",
|
||||||
"@types/ms": "0.7.30",
|
"@types/ms": "0.7.30",
|
||||||
"@types/node": "12.0.4",
|
"@types/node": "12.0.4",
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "2.15.1",
|
"@vercel/build-utils": "2.17.0",
|
||||||
"@zeit/fetch": "5.2.0",
|
"@zeit/fetch": "5.2.0",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
"async-sema": "3.0.0",
|
"async-sema": "3.0.0",
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { lstatSync } from 'fs-extra';
|
import { lstatSync } from 'fs-extra';
|
||||||
|
import { isAbsolute } from 'path';
|
||||||
import { relative, isAbsolute } from 'path';
|
|
||||||
import { hashes, mapToObject } from './utils/hashes';
|
import { hashes, mapToObject } from './utils/hashes';
|
||||||
import { upload } from './upload';
|
import { upload } from './upload';
|
||||||
import { buildFileTree, createDebug, parseVercelConfig } from './utils';
|
import { buildFileTree, createDebug } from './utils';
|
||||||
import { DeploymentError } from './errors';
|
import { DeploymentError } from './errors';
|
||||||
import {
|
import {
|
||||||
VercelConfig,
|
|
||||||
VercelClientOptions,
|
VercelClientOptions,
|
||||||
DeploymentOptions,
|
DeploymentOptions,
|
||||||
DeploymentEventType,
|
DeploymentEventType,
|
||||||
@@ -15,13 +13,11 @@ import {
|
|||||||
export default function buildCreateDeployment() {
|
export default function buildCreateDeployment() {
|
||||||
return async function* createDeployment(
|
return async function* createDeployment(
|
||||||
clientOptions: VercelClientOptions,
|
clientOptions: VercelClientOptions,
|
||||||
deploymentOptions: DeploymentOptions = {},
|
deploymentOptions: DeploymentOptions = {}
|
||||||
nowConfig: VercelConfig = {}
|
|
||||||
): AsyncIterableIterator<{ type: DeploymentEventType; payload: any }> {
|
): AsyncIterableIterator<{ type: DeploymentEventType; payload: any }> {
|
||||||
const { path } = clientOptions;
|
const { path } = clientOptions;
|
||||||
|
|
||||||
const debug = createDebug(clientOptions.debug);
|
const debug = createDebug(clientOptions.debug);
|
||||||
const cwd = process.cwd();
|
|
||||||
|
|
||||||
debug('Creating deployment...');
|
debug('Creating deployment...');
|
||||||
|
|
||||||
@@ -76,29 +72,6 @@ export default function buildCreateDeployment() {
|
|||||||
|
|
||||||
const { fileList } = await buildFileTree(path, clientOptions, debug);
|
const { fileList } = await buildFileTree(path, clientOptions, debug);
|
||||||
|
|
||||||
let configPath: string | undefined;
|
|
||||||
if (!nowConfig) {
|
|
||||||
// If the user did not provide a config file, use the one in the root directory.
|
|
||||||
const relativePaths = fileList.map(f => relative(cwd, f));
|
|
||||||
const hasVercelConfig = relativePaths.includes('vercel.json');
|
|
||||||
const hasNowConfig = relativePaths.includes('now.json');
|
|
||||||
|
|
||||||
if (hasVercelConfig) {
|
|
||||||
if (hasNowConfig) {
|
|
||||||
throw new DeploymentError({
|
|
||||||
code: 'conflicting_config',
|
|
||||||
message:
|
|
||||||
'Cannot use both a `vercel.json` and `now.json` file. Please delete the `now.json` file.',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
configPath = 'vercel.json';
|
|
||||||
} else if (hasNowConfig) {
|
|
||||||
configPath = 'now.json';
|
|
||||||
}
|
|
||||||
|
|
||||||
nowConfig = await parseVercelConfig(configPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a useful warning because it prevents people
|
// This is a useful warning because it prevents people
|
||||||
// from getting confused about a deployment that renders 404.
|
// from getting confused about a deployment that renders 404.
|
||||||
if (fileList.length === 0) {
|
if (fileList.length === 0) {
|
||||||
|
|||||||
@@ -126,27 +126,6 @@ export async function* deploy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
files.size === 1 &&
|
|
||||||
deploymentOptions.builds === undefined &&
|
|
||||||
deploymentOptions.routes === undefined &&
|
|
||||||
deploymentOptions.cleanUrls === undefined &&
|
|
||||||
deploymentOptions.rewrites === undefined &&
|
|
||||||
deploymentOptions.redirects === undefined &&
|
|
||||||
deploymentOptions.headers === undefined &&
|
|
||||||
deploymentOptions.trailingSlash === undefined
|
|
||||||
) {
|
|
||||||
debug(`Assigning '/' route for single file deployment`);
|
|
||||||
const filePath = Array.from(files.values())[0].names[0];
|
|
||||||
|
|
||||||
deploymentOptions.routes = [
|
|
||||||
{
|
|
||||||
src: '/',
|
|
||||||
dest: `/${filePath.split('/').pop()}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!deploymentOptions.name) {
|
if (!deploymentOptions.name) {
|
||||||
deploymentOptions.name =
|
deploymentOptions.name =
|
||||||
clientOptions.defaultName || getDefaultName(files, clientOptions);
|
clientOptions.defaultName || getDefaultName(files, clientOptions);
|
||||||
|
|||||||
15
packages/frameworks/logos/astro-dark.svg
Normal file
15
packages/frameworks/logos/astro-dark.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg width="1281" height="1280" viewBox="0 0 1281 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.931 94.6439C825.65 106.709 830.606 122.99 840.519 155.553L1057.06 866.901C976.999 825.368 889.964 795.413 798.174 779.252L657.182 302.798C654.875 295.002 647.715 289.654 639.585 289.654C631.434 289.654 624.26 295.03 621.972 302.853L482.688 779.011C390.471 795.1 303.038 825.109 222.634 866.793L440.24 155.388L440.24 155.388C450.183 122.882 455.154 106.629 464.874 94.5853C473.455 83.9531 484.616 75.6958 497.293 70.6002C511.652 64.8284 528.649 64.8284 562.642 64.8284H718.067C752.104 64.8284 769.123 64.8284 783.496 70.6123C796.184 75.7184 807.352 83.9923 815.931 94.6439Z" fill="url(#paint0_linear_709_106)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M841.843 900.754C806.146 931.279 734.895 952.097 652.822 952.097C552.089 952.097 467.659 920.737 445.256 878.561C437.247 902.732 435.45 930.396 435.45 948.068C435.45 948.068 430.173 1034.84 490.528 1095.2C490.528 1063.86 515.934 1038.46 547.273 1038.46C600.989 1038.46 600.929 1085.32 600.88 1123.34C600.878 1124.48 600.877 1125.61 600.877 1126.73C600.877 1184.44 636.147 1233.91 686.308 1254.77C678.816 1239.36 674.613 1222.05 674.613 1203.77C674.613 1148.73 706.926 1128.23 744.48 1104.41L744.481 1104.41C774.361 1085.46 807.56 1064.41 830.44 1022.17C842.379 1000.13 849.158 974.893 849.158 948.068C849.158 931.573 846.594 915.676 841.843 900.754Z" fill="#FF5D01"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M841.843 900.754C806.146 931.279 734.895 952.097 652.822 952.097C552.089 952.097 467.659 920.737 445.256 878.561C437.247 902.732 435.45 930.396 435.45 948.068C435.45 948.068 430.173 1034.84 490.528 1095.2C490.528 1063.86 515.934 1038.46 547.273 1038.46C600.989 1038.46 600.929 1085.32 600.88 1123.34C600.878 1124.48 600.877 1125.61 600.877 1126.73C600.877 1184.44 636.147 1233.91 686.308 1254.77C678.816 1239.36 674.613 1222.05 674.613 1203.77C674.613 1148.73 706.926 1128.23 744.48 1104.41L744.481 1104.41C774.361 1085.46 807.56 1064.41 830.44 1022.17C842.379 1000.13 849.158 974.893 849.158 948.068C849.158 931.573 846.594 915.676 841.843 900.754Z" fill="url(#paint1_linear_709_106)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_709_106" x1="883.889" y1="27.1132" x2="639.848" y2="866.902" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white"/>
|
||||||
|
<stop offset="1" stop-color="#F9FAFB"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_709_106" x1="1002.57" y1="652.45" x2="791.219" y2="1094.91" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#FF1639"/>
|
||||||
|
<stop offset="1" stop-color="#FF1639" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
15
packages/frameworks/logos/astro.svg
Normal file
15
packages/frameworks/logos/astro.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg width="1280" height="1280" viewBox="0 0 1280 1280" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M815.039 94.6439C824.758 106.709 829.714 122.99 839.626 155.553L1056.17 866.901C976.107 825.368 889.072 795.413 797.281 779.252L656.29 302.798C653.983 295.002 646.822 289.654 638.693 289.654C630.542 289.654 623.368 295.03 621.08 302.853L481.795 779.011C389.579 795.1 302.146 825.109 221.741 866.793L439.347 155.388L439.348 155.388C449.291 122.882 454.262 106.629 463.982 94.5853C472.562 83.9531 483.723 75.6958 496.4 70.6002C510.76 64.8284 527.756 64.8284 561.749 64.8284H717.174C751.212 64.8284 768.23 64.8284 782.603 70.6123C795.292 75.7184 806.459 83.9923 815.039 94.6439Z" fill="url(#paint0_linear_709_110)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="#FF5D01"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M840.951 900.754C805.253 931.279 734.002 952.097 651.929 952.097C551.197 952.097 466.767 920.737 444.363 878.561C436.354 902.732 434.558 930.396 434.558 948.068C434.558 948.068 429.281 1034.84 489.636 1095.2C489.636 1063.86 515.042 1038.46 546.381 1038.46C600.097 1038.46 600.036 1085.32 599.987 1123.34C599.986 1124.48 599.984 1125.61 599.984 1126.73C599.984 1184.44 635.255 1233.91 685.416 1254.77C677.924 1239.36 673.721 1222.05 673.721 1203.77C673.721 1148.73 706.034 1128.23 743.588 1104.41L743.588 1104.41C773.469 1085.46 806.668 1064.41 829.548 1022.17C841.486 1000.13 848.265 974.893 848.265 948.068C848.265 931.573 845.702 915.676 840.951 900.754Z" fill="url(#paint1_linear_709_110)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_709_110" x1="882.997" y1="27.1132" x2="638.955" y2="866.902" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#000014"/>
|
||||||
|
<stop offset="1" stop-color="#150426"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_709_110" x1="1001.68" y1="652.45" x2="790.326" y2="1094.91" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#FF1639"/>
|
||||||
|
<stop offset="1" stop-color="#FF1639" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user