Compare commits

...

19 Commits

Author SHA1 Message Date
Steven
15c7ad241a Publish Stable
- @vercel/build-utils@2.17.0
 - vercel@24.2.1
 - @vercel/client@11.0.1
 - @vercel/frameworks@0.9.0
 - @vercel/go@1.4.1
 - @vercel/node@1.15.1
 - @vercel/python@2.3.1
 - @vercel/redwood@0.8.1
 - @vercel/ruby@1.3.4
 - @vercel/static-build@0.24.1
2022-05-09 10:41:56 -04:00
Steven
ec57654b5b Publish Canary
- @vercel/build-utils@2.16.1-canary.4
 - vercel@24.2.1-canary.4
 - @vercel/client@11.0.1-canary.4
 - @vercel/go@1.4.1-canary.4
 - @vercel/node@1.15.1-canary.4
 - @vercel/python@2.3.1-canary.4
 - @vercel/redwood@0.8.1-canary.4
 - @vercel/ruby@1.3.4-canary.4
 - @vercel/static-build@0.24.1-canary.4
2022-05-09 10:13:58 -04:00
Steven
3b9a9878bc [build-utils] Add Node.js 16.x (#7772)
Add support for Node.js 16

- Related to https://github.com/aws/aws-lambda-base-images/issues/14#issuecomment-1120864028
2022-05-09 10:13:11 -04:00
Nathan Rajlich
70b7db1a15 [node] Move @types/jest to "devDependencies" (#7768)
This should be a dev dep.
2022-05-09 09:23:10 -04:00
Nathan Rajlich
41d6666139 Publish Canary
- @vercel/build-utils@2.16.1-canary.3
 - vercel@24.2.1-canary.3
 - @vercel/client@11.0.1-canary.3
 - @vercel/frameworks@0.8.1-canary.1
 - @vercel/go@1.4.1-canary.3
 - @vercel/node@1.15.1-canary.3
 - @vercel/python@2.3.1-canary.3
 - @vercel/redwood@0.8.1-canary.3
 - @vercel/ruby@1.3.4-canary.3
 - @vercel/static-build@0.24.1-canary.3
2022-05-07 16:08:08 -07:00
Nathan Rajlich
2857219f89 Fix "astro" slug 2022-05-07 11:57:14 -07:00
Tony Sullivan
246c2a0f5d [frameworks] Add Astro (#7747) 2022-05-06 16:51:42 -07:00
Ethan Arrowood
d91bca7d6b Publish Canary
- @vercel/build-utils@2.16.1-canary.2
 - vercel@24.2.1-canary.2
 - @vercel/client@11.0.1-canary.2
 - @vercel/frameworks@0.8.1-canary.0
 - @vercel/go@1.4.1-canary.2
 - @vercel/node@1.15.1-canary.2
 - @vercel/python@2.3.1-canary.2
 - @vercel/redwood@0.8.1-canary.2
 - @vercel/ruby@1.3.4-canary.2
 - @vercel/static-build@0.24.1-canary.2
2022-05-06 14:16:00 -06:00
Ethan Arrowood
be54fce67b [build-utils] add pnpm7 to path when lockfile v5.4 is detected (#7758)
### Related Issues

Adds support for `pnpm@7` using a similar lock file detection and path setting method that `npm@7` uses

### 📋 Checklist

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

#### Tests

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

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-06 19:47:41 +00:00
Sean Massa
7753bb8d89 [cli] check prebuilt target env against deploy target env (#7748)
This check prevents a user from creating a build output targeting one environment (like `preview`) and deploying targeting another environment (like `production`). It checks `.vercel/output/builds.json` for the `target` property to decide this. If that file is missing, the check is not run.
2022-05-06 07:06:07 +00:00
Logan McAnsh
ce17ac5c35 [frameworks] Update Remix detection to check for "remix.config.js" (#7761)
The "remix" magic package is no longer preferred by Remix,
so anyone who is using a modern template won't have it installed.

Checking for `remix.config.js` is safer detection logic.
2022-05-05 19:13:44 -07:00
Sean Massa
8006fc32b8 [cli] require non-TTY uses of pull to also pass --yes (#7700)
Checks for `TTY` input to decide to handle the command or not. If the input is not TTY and the user did not pass the `--yes` option, the CLi will exit with the message:

> Command `vercel pull` requires confirmation. Use option "--yes" to confirm.
2022-05-05 22:40:26 +00:00
Nathan Rajlich
8038a90db1 [node] Use TypeScript for unit tests (#7756)
Random change I had in my working directory.
2022-05-05 19:13:01 +00:00
agadzik
f88c862e9d Publish Canary
- @vercel/build-utils@2.16.1-canary.1
 - vercel@24.2.1-canary.1
 - @vercel/client@11.0.1-canary.1
 - @vercel/go@1.4.1-canary.1
 - @vercel/node@1.15.1-canary.1
 - @vercel/python@2.3.1-canary.1
 - @vercel/redwood@0.8.1-canary.1
 - @vercel/ruby@1.3.4-canary.1
 - @vercel/static-build@0.24.1-canary.1
2022-05-05 14:11:13 -04:00
Nathan Rajlich
9170820371 [build-utils] Add ShouldServe type (#7755)
Version 3 Builders can define a `shouldServe()` function that is used in `vercel dev`, so add the proper type for that.
2022-05-05 17:06:20 +00:00
Andrew Gadzik
c881546e0e [build-utils] Add supported list of workspace managers (#7737)
In order to support monorepo detection, we need to build out the list of supported workspace managers so that our helper functions and API endpoints can utilize the same `detectFramework` function / logic to detect a workspace manager for a given git repository.

### Related Issues

- Closes https://github.com/vercel/vercel/issues/7731

### 📋 Checklist

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

#### Tests

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

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-05-05 14:44:34 +00:00
Nathan Rajlich
fa21db98e4 [cli] Revert "Use @vercel/fetch-retry in CLI integration tests" (#7738)
This reverts commit 03a8fbd3a7 (#7360).
2022-05-04 17:15:54 +00:00
Ethan Arrowood
8eabbfc666 Publish Canary
- @vercel/build-utils@2.16.1-canary.0
 - vercel@24.2.1-canary.0
 - @vercel/client@11.0.1-canary.0
 - @vercel/go@1.4.1-canary.0
 - @vercel/node@1.15.1-canary.0
 - @vercel/python@2.3.1-canary.0
 - @vercel/redwood@0.8.1-canary.0
 - @vercel/ruby@1.3.4-canary.0
 - @vercel/static-build@0.24.1-canary.0
2022-05-02 11:33:22 -06:00
Ethan Arrowood
6783f7afc9 [build-utils] Fix package manager auto detection precedence (#7733)
### Related Issues

improves package manager auto detection so that when multiple lock files are found, the highest priority one is selected rather than defaulting to yarn. 

### 📋 Checklist

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

#### Tests

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

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-02 17:22:01 +00:00
76 changed files with 12990 additions and 195 deletions

20
examples/astro/.gitignore vendored Normal file
View 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
View File

@@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true

View File

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

42
examples/astro/README.md Normal file
View File

@@ -0,0 +1,42 @@
# Welcome to [Astro](https://astro.build)
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](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).

View File

@@ -0,0 +1,4 @@
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({});

View 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View 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>

View 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>&rarr;</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>&rarr;</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>&rarr;</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>&rarr;</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>

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.16.0",
"version": "2.17.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -30,7 +30,7 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "2.4.2",
"@vercel/frameworks": "0.8.0",
"@vercel/frameworks": "0.9.0",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",

View File

@@ -4,6 +4,7 @@ import { NowBuildError } from '../errors';
import debug from '../debug';
const allOptions = [
{ major: 16, range: '16.x', runtime: 'nodejs16.x' },
{ major: 14, range: '14.x', runtime: 'nodejs14.x' },
{ major: 12, range: '12.x', runtime: 'nodejs12.x' },
{

View File

@@ -222,12 +222,6 @@ export async function getNodeVersion(
const latest = getLatestNodeVersion();
return { ...latest, runtime: 'nodejs' };
}
if (process.env.ENABLE_EXPERIMENTAL_NODE16 === '1') {
console.warn(
'Warning: Using experimental Node.js 16.x due to ENABLE_EXPERIMENTAL_NODE16=1'
);
return { major: 16, range: '16.x', runtime: 'nodejs16.x' };
}
const { packageJson } = await scanParentDirs(destPath, true);
let { nodeVersion } = config;
let isAuto = true;
@@ -285,15 +279,17 @@ export async function scanParentDirs(
),
]);
if (packageLockJson && !hasYarnLock && !pnpmLockYaml) {
cliType = 'npm';
lockfileVersion = packageLockJson.lockfileVersion;
}
if (!packageLockJson && !hasYarnLock && pnpmLockYaml) {
// Priority order is Yarn > pnpm > npm
// - find highest priority lock file and use that
if (hasYarnLock) {
cliType = 'yarn';
} else if (pnpmLockYaml) {
cliType = 'pnpm';
// just ensure that it is read as a number and not a string
lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
} else if (packageLockJson) {
cliType = 'npm';
lockfileVersion = packageLockJson.lockfileVersion;
}
// Only stop iterating if a lockfile was found, because it's possible
@@ -440,6 +436,16 @@ export function getEnvForPackageManager({
newEnv.PATH = `/node16/bin-npm7:${env.PATH}`;
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 {
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
if (!env.YARN_NODE_LINKER) {

View File

@@ -33,7 +33,6 @@ import {
getDiscontinuedNodeVersions,
} from './fs/node-version';
import streamToBuffer from './fs/stream-to-buffer';
import shouldServe from './should-serve';
import debug from './debug';
import getIgnoreFilter from './get-ignore-filter';
import { getPlatformEnv } from './get-platform-env';
@@ -73,7 +72,6 @@ export {
getSpawnOptions,
getPlatformEnv,
streamToBuffer,
shouldServe,
debug,
isSymbolicLink,
getLambdaOptionsFromFunction,
@@ -94,6 +92,7 @@ export { DetectorFilesystem } from './detectors/filesystem';
export { readConfigFile } from './fs/read-config-file';
export { normalizePath } from './fs/normalize-path';
export * from './should-serve';
export * from './schemas';
export * from './types';
export * from './errors';
@@ -116,3 +115,5 @@ export const isOfficialRuntime = (desired: string, name?: string): boolean => {
export const isStaticRuntime = (name?: string): boolean => {
return isOfficialRuntime('static', name);
};
export { workspaceManagers } from './workspaces/workspace-managers';

View File

@@ -1,12 +1,12 @@
import { parse } from 'path';
import { ShouldServeOptions } from './types';
import FileFsRef from './file-fs-ref';
import type FileFsRef from './file-fs-ref';
import type { ShouldServe } from './types';
export default function shouldServe({
export const shouldServe: ShouldServe = ({
entrypoint,
files,
requestPath,
}: ShouldServeOptions): boolean {
}) => {
requestPath = requestPath.replace(/\/$/, ''); // sanitize trailing '/'
entrypoint = entrypoint.replace(/\\/, '/'); // windows compatibility
@@ -20,7 +20,7 @@ export default function shouldServe({
}
return false;
}
};
function hasProp(obj: { [path: string]: FileFsRef }, key: string): boolean {
return Object.hasOwnProperty.call(obj, key);

View File

@@ -345,6 +345,7 @@ export interface BuilderV3 {
version: 3;
build: BuildV3;
prepareCache?: PrepareCache;
shouldServe?: ShouldServe;
startDevServer?: StartDevServer;
}
@@ -401,6 +402,9 @@ export interface BuildResultV3 {
export type BuildV2 = (options: BuildOptions) => Promise<BuildResultV2>;
export type BuildV3 = (options: BuildOptions) => Promise<BuildResultV3>;
export type PrepareCache = (options: PrepareCacheOptions) => Promise<Files>;
export type ShouldServe = (
options: ShouldServeOptions
) => boolean | Promise<boolean>;
export type StartDevServer = (
options: StartDevServerOptions
) => Promise<StartDevServerResult>;

View 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;

File diff suppressed because it is too large Load Diff

View 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"
}
}

View 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

View 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"
}
]
}

View 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=

View 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="
}
}
}

View 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"
}
}

View 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

View File

@@ -0,0 +1,3 @@
packages:
- 'a'
- 'b'

View 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"
}
]
}

View 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"
}
}

View 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"
}
}

View File

@@ -0,0 +1,9 @@
{
"name": "21-npm-workspaces",
"version": "1.0.0",
"private": true,
"workspaces": [
"a",
"b"
]
}

View 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"

View 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"
}
}

View 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

View 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"
}
]
}

View File

@@ -32,6 +32,7 @@ const skipFixtures: string[] = [
'08-zero-config-middleman',
'21-npm-workspaces',
'23-pnpm-workspaces',
'27-yarn-workspaces',
];
// eslint-disable-next-line no-restricted-syntax

View 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);
});
});
});

View File

@@ -1,16 +1,17 @@
import assert from 'assert';
import { getEnvForPackageManager, NodeVersion } from '../src';
import { CliType } from '../src/fs/run-user-scripts';
import { getEnvForPackageManager } from '../src';
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',
args: {
cliType: 'npm' as CliType,
nodeVersion: {
major: 14,
} as NodeVersion,
cliType: 'npm',
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
lockfileVersion: 1,
env: {
FOO: 'bar',
@@ -23,10 +24,8 @@ describe('Test `getEnvForPackageManager()`', () => {
{
name: 'should set path if npm 7+ is detected and node < 16',
args: {
cliType: 'npm' as CliType,
nodeVersion: {
major: 14,
} as NodeVersion,
cliType: 'npm',
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -41,10 +40,8 @@ describe('Test `getEnvForPackageManager()`', () => {
{
name: 'should not set path if node is 16 and npm 7+ is detected',
args: {
cliType: 'npm' as CliType,
nodeVersion: {
major: 16,
} as NodeVersion,
cliType: 'npm',
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -59,10 +56,8 @@ describe('Test `getEnvForPackageManager()`', () => {
{
name: 'should set YARN_NODE_LINKER w/yarn if it is not already defined',
args: {
cliType: 'yarn' as CliType,
nodeVersion: {
major: 16,
} as NodeVersion,
cliType: 'yarn',
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -76,10 +71,8 @@ describe('Test `getEnvForPackageManager()`', () => {
{
name: 'should not set YARN_NODE_LINKER if it already exists',
args: {
cliType: 'yarn' as CliType,
nodeVersion: {
major: 16,
} as NodeVersion,
cliType: 'yarn',
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
lockfileVersion: 2,
env: {
FOO: 'bar',
@@ -91,6 +84,50 @@ describe('Test `getEnvForPackageManager()`', () => {
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) {

View File

@@ -176,9 +176,13 @@ it('should only match supported node versions, otherwise throw an error', async
'major',
14
);
expect(await getSupportedNodeVersion('16.x', false)).toHaveProperty(
'major',
16
);
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(
getSupportedNodeVersion('8.11.x', true),
autoMessage
@@ -196,9 +200,13 @@ it('should only match supported node versions, otherwise throw an error', async
'major',
14
);
expect(await getSupportedNodeVersion('16.x', true)).toHaveProperty(
'major',
16
);
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(
getSupportedNodeVersion('8.11.x', false),
foundMessage
@@ -219,8 +227,8 @@ it('should match all semver ranges', async () => {
// See https://docs.npmjs.com/files/package.json#engines
expect(await getSupportedNodeVersion('12.0.0')).toHaveProperty('major', 12);
expect(await getSupportedNodeVersion('12.x')).toHaveProperty('major', 12);
expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 14);
expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 14);
expect(await getSupportedNodeVersion('>=10')).toHaveProperty('major', 16);
expect(await getSupportedNodeVersion('>=10.3.0')).toHaveProperty('major', 16);
expect(await getSupportedNodeVersion('11.5.0 - 12.5.0')).toHaveProperty(
'major',
12
@@ -231,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 - 14.5.0')).toHaveProperty(
'major',
14
);
});
it('should ignore node version in vercel dev getNodeVersion()', async () => {
@@ -246,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 () => {
expect(
await getNodeVersion('/tmp', undefined, { nodeVersion: '14.x' }, {})
).toHaveProperty('range', '14.x');
await getNodeVersion('/tmp', undefined, { nodeVersion: '16.x' }, {})
).toHaveProperty('range', '16.x');
expect(warningMessages).toStrictEqual([]);
});
@@ -277,18 +289,8 @@ it('should not warn when package.json engines matches project setting from confi
expect(warningMessages).toStrictEqual([]);
});
it('should select nodejs16.x with ENABLE_EXPERIMENTAL_NODE16', async () => {
process.env.ENABLE_EXPERIMENTAL_NODE16 = '1';
const result = await getNodeVersion('/tmp', undefined, {}, {});
delete process.env.ENABLE_EXPERIMENTAL_NODE16;
expect(result).toEqual({ major: 16, range: '16.x', runtime: 'nodejs16.x' });
expect(warningMessages).toStrictEqual([
'Warning: Using experimental Node.js 16.x due to ENABLE_EXPERIMENTAL_NODE16=1',
]);
});
it('should get latest node version', async () => {
expect(getLatestNodeVersion()).toHaveProperty('major', 14);
expect(getLatestNodeVersion()).toHaveProperty('major', 16);
});
it('should throw for discontinued versions', async () => {
@@ -323,8 +325,8 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
10
);
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 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 "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 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;

View 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();
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "24.2.0",
"version": "24.2.1",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -43,11 +43,11 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.16.0",
"@vercel/go": "1.4.0",
"@vercel/node": "1.15.0",
"@vercel/python": "2.3.0",
"@vercel/ruby": "1.3.3",
"@vercel/build-utils": "2.17.0",
"@vercel/go": "1.4.1",
"@vercel/node": "1.15.1",
"@vercel/python": "2.3.1",
"@vercel/ruby": "1.3.4",
"update-notifier": "4.1.0"
},
"devDependencies": {
@@ -90,9 +90,8 @@
"@types/update-notifier": "5.1.0",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/client": "11.0.0",
"@vercel/fetch-retry": "5.0.3",
"@vercel/frameworks": "0.8.0",
"@vercel/client": "11.0.1",
"@vercel/frameworks": "0.9.0",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",

View File

@@ -61,6 +61,8 @@ import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-
import { Output } from '../../util/output';
import { help } from './args';
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) => {
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;
@@ -181,6 +183,12 @@ 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'));
@@ -194,6 +202,25 @@ export default async (client: Client) => {
);
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
@@ -418,33 +445,6 @@ export default async (client: Client) => {
.filter(Boolean);
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 now = new Now({
client,

View File

@@ -10,6 +10,8 @@ import { ProjectSettings } from '../../types';
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
import setupAndLink from '../../util/link/setup-and-link';
import getSystemEnvValues from '../../util/env/get-system-env-values';
import { getCommandName } from '../../util/pkg-name';
import param from '../../util/output/param';
type Options = {
'--listen': string;
@@ -46,6 +48,13 @@ export default async function dev(
}
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;
}

View File

@@ -4,6 +4,8 @@ import getArgs from '../../util/get-args';
import logo from '../../util/output/logo';
import { getPkgName } from '../../util/pkg-name';
import setupAndLink from '../../util/link/setup-and-link';
import { getCommandName } from '../../util/pkg-name';
import param from '../../util/output/param';
const help = () => {
console.log(`
@@ -67,6 +69,13 @@ export default async function main(client: Client) {
});
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;
} else if (link.status === 'not_linked') {
// User aborted project linking questions

View File

@@ -15,7 +15,8 @@ import {
} from '../util/projects/link';
import { writeProjectSettings } from '../util/projects/project-settings';
import envPull from './env/pull';
import { getCommandName } from '../util/pkg-name';
import param from '../util/output/param';
import type { Project, Org } from '../types';
import {
isValidEnvTarget,
@@ -102,6 +103,13 @@ async function ensureLink(
}
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;
}

View File

@@ -82,7 +82,12 @@ let debug: (s: string) => void = () => {};
let apiUrl = 'https://api.vercel.com';
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;

View File

@@ -277,7 +277,17 @@ export interface PaginationOptions {
export type ProjectLinkResult =
| { status: 'linked'; org: Org; project: Project }
| { 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 {
id: string;

View 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;
}

View 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;
}

View File

@@ -6,6 +6,8 @@ import {
getLinkedProject,
linkFolderToProject,
getVercelDirectory,
VERCEL_DIR_README,
VERCEL_DIR_PROJECT,
} from '../projects/link';
import createProject from '../projects/create-project';
import updateProject from '../projects/update-project';
@@ -49,7 +51,7 @@ export default async function setupAndLink(
const isFile = !isDirectory(path);
if (isFile) {
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 isTTY = process.stdout.isTTY;
@@ -65,7 +67,12 @@ export default async function setupAndLink(
if (forceDelete) {
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 =
@@ -87,9 +94,14 @@ export default async function setupAndLink(
autoConfirm
);
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
if (err.code === 'NOT_AUTHORIZED') {
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;
@@ -135,7 +147,7 @@ export default async function setupAndLink(
rootDirectory &&
!(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;
@@ -191,7 +203,11 @@ export default async function setupAndLink(
if (debug) {
console.log(deployment);
}
return { status: 'error', exitCode: 1 };
return {
status: 'error',
exitCode: 1,
reason: 'MISSING_PROJECT_SETTINGS',
};
}
const { projectSettings, framework } = deployment;

View File

@@ -2,6 +2,10 @@ import { join } from 'path';
import { fileNameSymbol } from '@vercel/client';
import { client } from '../mocks/client';
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', () => {
it('should reject deploying a single file', async () => {
@@ -40,6 +44,50 @@ describe('deploy', () => {
);
});
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 () => {
client.setArgv('deploy');
client.localConfig = {

View File

@@ -17,7 +17,7 @@ describe('pull', () => {
id: 'vercel-pull-next',
name: 'vercel-pull-next',
});
client.setArgv('pull', '--yes', cwd);
client.setArgv('pull', cwd);
const exitCode = await pull(client);
expect(exitCode, client.outputBuffer).toEqual(0);
@@ -28,6 +28,40 @@ describe('pull', () => {
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';
@@ -73,7 +107,7 @@ describe('pull', () => {
id: '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);
expect(exitCode).toEqual(0);
@@ -95,7 +129,7 @@ describe('pull', () => {
id: '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);
expect(exitCode).toEqual(0);

View File

@@ -0,0 +1,3 @@
{
"target": "preview"
}

View File

@@ -0,0 +1,3 @@
{
"target": "production"
}

View File

@@ -0,0 +1,2 @@
.next
yarn.lock

View 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"
}
}

View 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);

View File

@@ -0,0 +1 @@
User-Agent: *

View File

@@ -0,0 +1,10 @@
{
"version": 2,
"name": "vercel-pull-next",
"routes": [
{
"src": "/(.*)",
"dest": "/index?route-param=b"
}
]
}

View File

@@ -179,6 +179,19 @@ module.exports = async function prepare(session, binaryPath) {
'list/README.md':
'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': {
[`main-${session}.html`]: '<h1>hello main</h1>',
[`test-${session}.html`]: '<h1>hello test</h1>',

View File

@@ -7,10 +7,9 @@ import { Readable } from 'stream';
import { homedir } from 'os';
import _execa from 'execa';
import XDGAppPaths from 'xdg-app-paths';
import nodeFetch from 'node-fetch';
import fetch from 'node-fetch';
import tmp from 'tmp-promise';
import retry from 'async-retry';
import createFetchRetry from '@vercel/fetch-retry';
import fs, {
writeFile,
readFile,
@@ -25,8 +24,6 @@ import pkg from '../package';
import prepareFixtures from './helpers/prepare';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
const fetch = createFetchRetry(nodeFetch);
// log command when running `execa`
function execa(file, args, options) {
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 => {
const target = fixture('redirects-v2');
@@ -797,15 +844,10 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
t.regex(contents, /^# Created by Vercel CLI\n/);
const lines = new Set(contents.split('\n'));
t.true(lines.has('MY_NEW_ENV_VAR="my plaintext value"'), 'MY_NEW_ENV_VAR');
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'), 'MY_STDIN_VAR');
t.true(
lines.has('MY_DECRYPTABLE_SECRET_ENV="decryptable value"'),
'MY_DECRYPTABLE_SECRET_ENV'
);
t.false(lines.has('MY_PREVIEW'), 'MY_PREVIEW');
t.regex(contents, /MY_NEW_ENV_VAR="my plaintext value"/);
t.regex(contents, /MY_STDIN_VAR="{"expect":"quotes"}"/);
t.regex(contents, /MY_DECRYPTABLE_SECRET_ENV="decryptable value"/);
t.notRegex(contents, /MY_PREVIEW/);
}
async function vcEnvPullOverwrite() {
@@ -1090,29 +1132,48 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
t.is(exitCode, 0, formatOutput({ stderr, stdout }));
}
await vcLink();
await vcEnvLsIsEmpty();
await vcEnvAddWithPrompts();
await vcEnvAddFromStdin();
await vcEnvAddFromStdinPreview();
await vcEnvAddFromStdinPreviewWithBranch();
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();
function vcEnvRemoveByName(name) {
return execa(binaryPath, ['env', 'rm', name, '-y', ...defaultArgs], {
reject: false,
cwd: target,
});
}
async function vcEnvRemoveAll() {
await vcEnvRemoveByName('MY_PREVIEW');
await vcEnvRemoveByName('MY_STDIN_VAR');
await vcEnvRemoveByName('MY_DECRYPTABLE_SECRET_ENV');
await vcEnvRemoveByName('MY_NEW_ENV_VAR');
}
try {
await vcEnvRemoveAll();
await vcLink();
await vcEnvLsIsEmpty();
await vcEnvAddWithPrompts();
await vcEnvAddFromStdin();
await vcEnvAddFromStdinPreview();
await vcEnvAddFromStdinPreviewWithBranch();
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 => {
@@ -1450,6 +1511,9 @@ test('try to purchase a domain', async t => {
{
reject: false,
input: stream,
env: {
FORCE_TTY: '1',
},
}
);
@@ -2361,6 +2425,9 @@ test('[vercel dev] fails when development commad calls vercel dev recursively',
const dev = execa(binaryPath, ['dev', ...defaultArgs], {
cwd: dir,
reject: false,
env: {
FORCE_TTY: '1',
},
});
await setupProject(dev, projectName, {
@@ -2766,6 +2833,9 @@ test('change user', async t => {
await execute(['login', email, '--api', loginApiUrl, '--debug'], {
stdio: 'inherit',
env: {
FORCE_TTY: '1',
},
});
const auth = await fs.readJSON(getConfigAuthPath());
@@ -2895,7 +2965,11 @@ test('should prefill "project name" prompt with folder name', async t => {
const directory = path.join(src, '../', projectName);
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));
now.stdin.write('yes\n');
@@ -2938,12 +3012,15 @@ test('should prefill "project name" prompt with --name', async t => {
// remove previously linked project if it exists
await remove(path.join(directory, '.vercel'));
const now = execa(binaryPath, [
directory,
'--name',
projectName,
...defaultArgs,
]);
const now = execa(
binaryPath,
[directory, '--name', projectName, ...defaultArgs],
{
env: {
FORCE_TTY: '1',
},
}
);
let isDeprecated = false;
@@ -3002,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;
@@ -3423,7 +3504,12 @@ test('[vc link] should show prompts to set up project', async t => {
// remove previously linked project if it exists
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, {
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
@@ -3496,7 +3582,13 @@ test('[vc link] should not duplicate paths in .gitignore', async t => {
const { exitCode, stderr, stdout } = await execa(
binaryPath,
['link', '--confirm', ...defaultArgs],
{ cwd: dir, reject: false }
{
cwd: dir,
reject: false,
env: {
FORCE_TTY: '1',
},
}
);
// Ensure the exit code is right
@@ -3522,6 +3614,9 @@ test('[vc dev] should show prompts to set up project', async t => {
const dev = execa(binaryPath, ['dev', '--listen', port, ...defaultArgs], {
cwd: dir,
env: {
FORCE_TTY: '1',
},
});
await setupProject(dev, projectName, {
@@ -3566,7 +3661,12 @@ test('[vc link] should show project prompts but not framework when `builds` defi
// remove previously linked project if it exists
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));
vc.stdin.write('yes\n');
@@ -3625,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], {
cwd: dir,
env: {
FORCE_TTY: '1',
},
});
await setupProject(dev, projectName, {

View 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);
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "11.0.0",
"version": "11.0.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -41,7 +41,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.17.0",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View 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

View 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

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.8.0",
"version": "0.9.0",
"main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts",
"files": [

View File

@@ -60,7 +60,8 @@ export const frameworks = [
slug: 'nextjs',
demo: 'https://nextjs-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg',
darkModeLogo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg',
darkModeLogo:
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg',
screenshot:
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
tagline:
@@ -204,9 +205,7 @@ export const frameworks = [
detectors: {
every: [
{
path: 'package.json',
matchContent:
'"(dev)?(d|D)ependencies":\\s*{[^}]*"remix":\\s*".+?"[^}]*}',
path: 'remix.config.js',
},
],
},
@@ -262,6 +261,73 @@ export const frameworks = [
},
],
},
{
name: 'Astro',
slug: 'astro',
demo: 'https://astro-template.vercel.app',
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro.svg',
darkModeLogo:
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro-dark.svg',
tagline:
'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.',
description: 'An Astro site, using the basics starter kit.',
website: 'https://astro.build',
envPrefix: 'PUBLIC_',
detectors: {
every: [
{
path: 'package.json',
matchContent:
'"(dev)?(d|D)ependencies":\\s*{[^}]*"astro":\\s*".+?"[^}]*}',
},
],
},
settings: {
installCommand: {
placeholder: '`yarn install` or `npm install`',
},
buildCommand: {
value: 'astro build',
placeholder: '`npm run build` or `astro build`',
},
devCommand: {
value: 'astro dev --port $PORT',
placeholder: 'astro dev',
},
outputDirectory: {
value: 'dist',
},
},
dependency: 'astro',
getFsOutputDir: async () => 'dist',
getOutputDirName: async () => 'dist',
defaultRoutes: [
{
src: '^/dist/(.*)$',
headers: { 'cache-control': 'public, max-age=31536000, immutable' },
continue: true,
},
{
handle: 'filesystem',
},
{
src: '/(.*)',
dest: '/index.html',
},
],
defaultHeaders: [
{
source: '^/dist/(.*)$',
regex: '^/dist/(.*)$',
headers: [
{
key: 'cache-control',
value: 'public, max-age=31536000, immutable',
},
],
},
],
},
{
name: 'Hexo',
slug: 'hexo',

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "1.4.0",
"version": "1.4.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -24,7 +24,7 @@
"@types/fs-extra": "^5.0.5",
"@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0",
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.17.0",
"@vercel/ncc": "0.24.0",
"async-retry": "1.3.1",
"execa": "^1.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.15.0",
"version": "1.15.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -12,12 +12,22 @@
"scripts": {
"build": "node build",
"test-integration-once": "jest --env node --verbose --runInBand --bail test/integration.test.js",
"test-unit": "jest --env node --verbose --bail test/prepare-cache.test.js",
"test-unit": "jest --env node --verbose --bail test/prepare-cache.test.ts",
"prepublishOnly": "node build"
},
"files": [
"dist"
],
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"globals": {
"ts-jest": {
"diagnostics": true,
"isolatedModules": true
}
}
},
"dependencies": {
"@types/node": "*",
"@vercel/node-bridge": "2.2.1",
@@ -32,8 +42,9 @@
"@types/content-type": "1.1.3",
"@types/cookie": "0.3.3",
"@types/etag": "1.8.0",
"@types/jest": "27.4.1",
"@types/test-listen": "1.1.0",
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.17.0",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.18.1",
"content-type": "1.0.4",

View File

@@ -1,9 +1,14 @@
const path = require('path');
const { prepareCache } = require('../dist');
import path from 'path';
import assert from 'assert';
import { prepareCache } from '../src';
describe('prepareCache()', () => {
test('should cache **/node_modules/**', async () => {
test('should cache `**/node_modules/**`', async () => {
const files = await prepareCache({
files: {},
entrypoint: '.',
config: {},
workPath: path.resolve(__dirname, './cache-fixtures/'),
repoRootPath: path.resolve(__dirname, './cache-fixtures/'),
});
@@ -14,14 +19,17 @@ describe('prepareCache()', () => {
test('should ignore root modules', async () => {
const files = await prepareCache({
files: {},
entrypoint: '.',
config: {},
workPath: path.resolve(__dirname, './cache-fixtures/foo/'),
});
expect(files['node_modules/file']).toBeDefined();
const file = files['node_modules/file'];
expect(file).toBeDefined();
assert(file.type === 'FileFsRef');
expect(
files['node_modules/file'].fsPath.includes(
'cache-fixtures/foo/node_modules/file'
)
file.fsPath.includes('cache-fixtures/foo/node_modules/file')
).toBeTruthy();
expect(files['index.js']).toBeUndefined();
});

4
packages/node/test/tsconfig.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"extends": "../tsconfig.json",
"include": ["*.test.ts"]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "2.3.0",
"version": "2.3.1",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/execa": "^0.9.0",
"@types/jest": "27.4.1",
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.17.0",
"@vercel/ncc": "0.24.0",
"execa": "^1.0.0",
"typescript": "4.3.4"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/redwood",
"version": "0.8.0",
"version": "0.8.1",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs",
@@ -27,6 +27,6 @@
"@types/aws-lambda": "8.10.19",
"@types/node": "*",
"@types/semver": "6.0.0",
"@vercel/build-utils": "2.16.0"
"@vercel/build-utils": "2.17.0"
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.3.3",
"version": "1.3.4",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/fs-extra": "8.0.0",
"@types/semver": "6.0.0",
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.17.0",
"@vercel/ncc": "0.24.0",
"execa": "2.0.4",
"fs-extra": "^7.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "0.24.0",
"version": "0.24.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/build-step",
@@ -35,8 +35,8 @@
"@types/ms": "0.7.31",
"@types/node-fetch": "2.5.4",
"@types/promise-timeout": "1.3.0",
"@vercel/build-utils": "2.16.0",
"@vercel/frameworks": "0.8.0",
"@vercel/build-utils": "2.17.0",
"@vercel/frameworks": "0.9.0",
"@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "1.13.2",
"get-port": "5.0.0",

View File

@@ -2715,14 +2715,6 @@
"@typescript-eslint/types" "5.21.0"
eslint-visitor-keys "^3.0.0"
"@vercel/fetch-retry@5.0.3":
version "5.0.3"
resolved "https://registry.yarnpkg.com/@vercel/fetch-retry/-/fetch-retry-5.0.3.tgz#cce5d23f6e64f6f525c24e2ac7c78f65d6c5b1f4"
integrity sha512-DIIoBY92r+sQ6iHSf5WjKiYvkdsDIMPWKYATlE0KcUAj2RV6SZK9UWpUzBRKsofXqedOqpVjrI0IE6AWL7JRtg==
dependencies:
async-retry "^1.3.1"
debug "^3.1.0"
"@vercel/ncc@0.24.0":
version "0.24.0"
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"