Compare commits

...

12 Commits

Author SHA1 Message Date
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
61 changed files with 9085 additions and 169 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.16.0",
"version": "2.16.1-canary.2",
"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.8.1-canary.0",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",

View File

@@ -285,15 +285,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 +442,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

@@ -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-canary.2",
"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.16.1-canary.2",
"@vercel/go": "1.4.1-canary.2",
"@vercel/node": "1.15.1-canary.2",
"@vercel/python": "2.3.1-canary.2",
"@vercel/ruby": "1.3.4-canary.2",
"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-canary.2",
"@vercel/frameworks": "0.8.1-canary.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-canary.2",
"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.16.1-canary.2",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

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

View File

@@ -204,9 +204,7 @@ export const frameworks = [
detectors: {
every: [
{
path: 'package.json',
matchContent:
'"(dev)?(d|D)ependencies":\\s*{[^}]*"remix":\\s*".+?"[^}]*}',
path: 'remix.config.js',
},
],
},

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "1.4.0",
"version": "1.4.1-canary.2",
"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.16.1-canary.2",
"@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-canary.2",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -12,13 +12,24 @@
"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/jest": "27.4.1",
"@types/node": "*",
"@vercel/node-bridge": "2.2.1",
"ts-node": "8.9.1",
@@ -33,7 +44,7 @@
"@types/cookie": "0.3.3",
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@vercel/build-utils": "2.16.0",
"@vercel/build-utils": "2.16.1-canary.2",
"@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-canary.2",
"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.16.1-canary.2",
"@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-canary.2",
"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.16.1-canary.2"
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.3.3",
"version": "1.3.4-canary.2",
"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.16.1-canary.2",
"@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-canary.2",
"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.16.1-canary.2",
"@vercel/frameworks": "0.8.1-canary.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"