mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
30 Commits
@vercel/no
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
698b89a2ba | ||
|
|
bae2a2e4df | ||
|
|
57916bb712 | ||
|
|
12bbd4e8eb | ||
|
|
4e4c7023dc | ||
|
|
41805790e7 | ||
|
|
6ad77ae8e1 | ||
|
|
e8daf36cd7 | ||
|
|
c319a2c499 | ||
|
|
a410baa797 | ||
|
|
625568e659 | ||
|
|
41868c1fe0 | ||
|
|
1b644f1218 | ||
|
|
29ea0fb06b | ||
|
|
b61f049f11 | ||
|
|
16e28f326b | ||
|
|
276397c940 | ||
|
|
85d7311199 | ||
|
|
b8114b8b39 | ||
|
|
d63e8d3187 | ||
|
|
11d3dd04aa | ||
|
|
46bf95ee36 | ||
|
|
92252468c2 | ||
|
|
71b83d5587 | ||
|
|
d9e5fdc5e4 | ||
|
|
58f479c603 | ||
|
|
d62461d952 | ||
|
|
e7f524defb | ||
|
|
bdefd0d05d | ||
|
|
ca522fc9f1 |
@@ -6,6 +6,7 @@
|
||||
!.yarnrc
|
||||
!yarn.lock
|
||||
!package.json
|
||||
!turbo.json
|
||||
|
||||
# api
|
||||
!api/
|
||||
@@ -14,4 +15,4 @@
|
||||
# packages
|
||||
!packages/
|
||||
!packages/frameworks
|
||||
!packages/frameworks/**
|
||||
!packages/frameworks/**
|
||||
@@ -307,15 +307,15 @@ This is a [class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere
|
||||
|
||||
This is an abstract enumeration type that is implemented by one of the following possible `String` values:
|
||||
|
||||
- `nodejs14.x`
|
||||
- `nodejs12.x`
|
||||
- `nodejs10.x`
|
||||
- `go1.x`
|
||||
- `java11`
|
||||
- `python3.9`
|
||||
- `python3.6`
|
||||
- `dotnetcore2.1`
|
||||
- `ruby2.5`
|
||||
- `provided`
|
||||
- `dotnet6`
|
||||
- `dotnetcore3.1`
|
||||
- `ruby2.7`
|
||||
- `provided.al2`
|
||||
|
||||
## `@vercel/build-utils` Helper Functions
|
||||
|
||||
|
||||
@@ -16,4 +16,4 @@ If you would not like to verify your domain, you can remove it from your account
|
||||
|
||||
#### Resources
|
||||
|
||||
- [Vercel Custom Domains Documentation](https://vercel.com/docs/v2/custom-domains)
|
||||
- [Vercel Custom Domains Documentation](https://vercel.com/docs/concepts/projects/custom-domains)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#### Why This Error Occurred
|
||||
|
||||
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/v2/build-step#environment-variables).
|
||||
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||
|
||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
|
||||
|
||||
@@ -24,4 +24,4 @@ TEST=value
|
||||
|
||||
In the above example, `TEST` represents the name of the environment variable and `value` its value.
|
||||
|
||||
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/v2/build-step#environment-variables).
|
||||
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||
|
||||
1
examples/amp/.gitignore
vendored
1
examples/amp/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
.env
|
||||
@@ -1,19 +0,0 @@
|
||||
# AMP Example
|
||||
|
||||
This directory is a brief example of an [AMP](https://amp.dev/) site that can be deployed to Vercel with zero configuration.
|
||||
|
||||
## Deploy Your Own
|
||||
|
||||
Deploy your own AMP project with Vercel.
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/amp)
|
||||
|
||||
_Live Example: https://amp-template.vercel.app_
|
||||
|
||||
### How We Created This Example
|
||||
|
||||
To get started deploying AMP with Vercel, you can use the [Vercel CLI](https://vercel.com/download) to initialize the project:
|
||||
|
||||
```shell
|
||||
$ vercel init amp
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,72 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html ⚡>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,minimum-scale=1" />
|
||||
<link rel="shortcut icon" href="favicon.png">
|
||||
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
|
||||
<link rel="canonical" href="index.html" />
|
||||
<title>AMP Website</title>
|
||||
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
||||
<style amp-custom>
|
||||
body > * {
|
||||
margin: 3rem 1rem;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
color: #525252;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.2rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.links a {
|
||||
margin: 0 10px;
|
||||
font-size: 1rem;
|
||||
color: #005af0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<amp-img width=150 height=150 layout="fixed" class="logo" src="logo.png"></amp-img>
|
||||
<h3>Welcome to your AMP page</h3>
|
||||
<p>AMP is a web component framework to <br> easily create user-first websites, stories, ads and emails.</p>
|
||||
|
||||
<h4>Links</h4>
|
||||
<div class="links">
|
||||
<a href="https://amp.dev/">Homepage</a>
|
||||
<a href="https://amp.dev/documentation/guides-and-tutorials/?format=websites">Tutorials</a>
|
||||
<a href="https://amp.dev/documentation/examples/">Examples</a>
|
||||
<a href="https://blog.amp.dev">Blog</a>
|
||||
</div>
|
||||
|
||||
<h4>Ready to get started?</h4>
|
||||
<div class="links">
|
||||
<a href="https://amp.dev/documentation/guides-and-tutorials/start/create/?format=websites">Create your first AMP page</a>
|
||||
</div>
|
||||
|
||||
<h4>Get involved</h4>
|
||||
<div class="links">
|
||||
<a href="https://twitter.com/amphtml">Twitter</a>
|
||||
<a href="https://amphtml.slack.com">Slack</a>
|
||||
<a href="https://amp.dev/events/amp-conf-2019">AMP Conf</a>
|
||||
<a href="https://amp.dev/events/amp-roadshow">AMP Roadshow</a>
|
||||
</div>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
@@ -6,7 +6,7 @@ This directory is a brief example of a [Dojo](https://dojo.io) site that can be
|
||||
|
||||
Deploy your own Dojo project with Vercel.
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/dojo&template=dojo)
|
||||
[](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/dojo&template=dojo)
|
||||
|
||||
### How We Created This Example
|
||||
|
||||
|
||||
15
package.json
15
package.json
@@ -14,19 +14,6 @@
|
||||
"dependencies": {
|
||||
"lerna": "3.16.4"
|
||||
},
|
||||
"turbo": {
|
||||
"baseBranch": "origin/main",
|
||||
"pipeline": {
|
||||
"build": {
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
],
|
||||
"outputs": [
|
||||
"dist/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "4.28.0",
|
||||
"@typescript-eslint/parser": "4.28.0",
|
||||
@@ -44,7 +31,7 @@
|
||||
"prettier": "2.3.1",
|
||||
"ts-eager": "2.0.2",
|
||||
"ts-jest": "27.0.4",
|
||||
"turbo": "1.1.9"
|
||||
"turbo": "1.2.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lerna": "lerna",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "2.15.1",
|
||||
"version": "2.15.2-canary.3",
|
||||
"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.1",
|
||||
"@vercel/frameworks": "0.7.1",
|
||||
"@vercel/frameworks": "0.7.2-canary.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"aggregate-error": "3.0.1",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -538,7 +538,7 @@ function getMissingBuildScriptError() {
|
||||
code: 'missing_build_script',
|
||||
message:
|
||||
'Your `package.json` file is missing a `build` property inside the `scripts` property.' +
|
||||
'\nLearn More: https://vercel.com/docs/v2/platform/frequently-asked-questions#missing-build-script',
|
||||
'\nLearn More: https://vercel.link/missing-build-script',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ export async function getSupportedNodeVersion(
|
||||
): Promise<NodeVersion> {
|
||||
let selection: NodeVersion = getLatestNodeVersion();
|
||||
|
||||
if (process.env.ENABLE_EXPERIMENTAL_NODE16 === '1') {
|
||||
return { major: 16, range: '16.x', runtime: 'nodejs16.x' };
|
||||
}
|
||||
|
||||
if (engineRange) {
|
||||
const found =
|
||||
validRange(engineRange) &&
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import assert from 'assert';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import debug from '../debug';
|
||||
import Sema from 'async-sema';
|
||||
import spawn from 'cross-spawn';
|
||||
import { SpawnOptions } from 'child_process';
|
||||
import { deprecate } from 'util';
|
||||
import debug from '../debug';
|
||||
import { NowBuildError } from '../errors';
|
||||
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
||||
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
||||
import { readConfigFile } from './read-config-file';
|
||||
|
||||
// Only allow one `runNpmInstall()` invocation to run concurrently
|
||||
const runNpmInstallSema = new Sema(1);
|
||||
|
||||
export type CliType = 'yarn' | 'npm' | 'pnpm';
|
||||
|
||||
export interface ScanParentDirsResult {
|
||||
@@ -17,6 +21,11 @@ export interface ScanParentDirsResult {
|
||||
* "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
|
||||
*/
|
||||
cliType: CliType;
|
||||
/**
|
||||
* The file path of found `package.json` file, or `undefined` if none was
|
||||
* found.
|
||||
*/
|
||||
packageJsonPath?: string;
|
||||
/**
|
||||
* The contents of found `package.json` file, when the `readPackageJson`
|
||||
* option is enabled.
|
||||
@@ -237,12 +246,13 @@ export async function scanParentDirs(
|
||||
|
||||
let cliType: CliType = 'yarn';
|
||||
let packageJson: PackageJson | undefined;
|
||||
let packageJsonPath: string | undefined;
|
||||
let currentDestPath = destPath;
|
||||
let lockfileVersion: number | undefined;
|
||||
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const packageJsonPath = path.join(currentDestPath, 'package.json');
|
||||
packageJsonPath = path.join(currentDestPath, 'package.json');
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
if (await fs.pathExists(packageJsonPath)) {
|
||||
// Only read the contents of the *first* `package.json` file found,
|
||||
@@ -293,7 +303,7 @@ export async function scanParentDirs(
|
||||
currentDestPath = newDestPath;
|
||||
}
|
||||
|
||||
return { cliType, packageJson, lockfileVersion };
|
||||
return { cliType, packageJson, lockfileVersion, packageJsonPath };
|
||||
}
|
||||
|
||||
export async function walkParentDirs({
|
||||
@@ -319,55 +329,87 @@ export async function walkParentDirs({
|
||||
return null;
|
||||
}
|
||||
|
||||
function isSet<T>(v: any): v is Set<T> {
|
||||
return v?.constructor?.name === 'Set';
|
||||
}
|
||||
|
||||
export async function runNpmInstall(
|
||||
destPath: string,
|
||||
args: string[] = [],
|
||||
spawnOpts?: SpawnOptions,
|
||||
meta?: Meta,
|
||||
nodeVersion?: NodeVersion
|
||||
) {
|
||||
): Promise<boolean> {
|
||||
if (meta?.isDev) {
|
||||
debug('Skipping dependency installation because dev mode is enabled');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(path.isAbsolute(destPath));
|
||||
debug(`Installing to ${destPath}`);
|
||||
|
||||
const { cliType, lockfileVersion } = await scanParentDirs(destPath);
|
||||
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
||||
const env = opts.env ? { ...opts.env } : { ...process.env };
|
||||
delete env.NODE_ENV;
|
||||
opts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
nodeVersion,
|
||||
env,
|
||||
});
|
||||
let commandArgs: string[];
|
||||
try {
|
||||
await runNpmInstallSema.acquire();
|
||||
const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(
|
||||
destPath
|
||||
);
|
||||
|
||||
if (cliType === 'npm') {
|
||||
opts.prettyCommand = 'npm install';
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
||||
} else if (cliType === 'pnpm') {
|
||||
// PNPM's install command is similar to NPM's but without the audit nonsense
|
||||
// @see options https://pnpm.io/cli/install
|
||||
opts.prettyCommand = 'pnpm install';
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--unsafe-perm']);
|
||||
} else {
|
||||
opts.prettyCommand = 'yarn install';
|
||||
commandArgs = ['install', ...args];
|
||||
// Only allow `runNpmInstall()` to run once per `package.json`
|
||||
// when doing a default install (no additional args)
|
||||
if (meta && packageJsonPath && args.length === 0) {
|
||||
if (!isSet<string>(meta.runNpmInstallSet)) {
|
||||
meta.runNpmInstallSet = new Set<string>();
|
||||
}
|
||||
if (isSet<string>(meta.runNpmInstallSet)) {
|
||||
if (meta.runNpmInstallSet.has(packageJsonPath)) {
|
||||
return false;
|
||||
} else {
|
||||
meta.runNpmInstallSet.add(packageJsonPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const installTime = Date.now();
|
||||
console.log('Installing dependencies...');
|
||||
debug(`Installing to ${destPath}`);
|
||||
|
||||
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
||||
const env = opts.env ? { ...opts.env } : { ...process.env };
|
||||
delete env.NODE_ENV;
|
||||
opts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
nodeVersion,
|
||||
env,
|
||||
});
|
||||
let commandArgs: string[];
|
||||
|
||||
if (cliType === 'npm') {
|
||||
opts.prettyCommand = 'npm install';
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
||||
} else if (cliType === 'pnpm') {
|
||||
// PNPM's install command is similar to NPM's but without the audit nonsense
|
||||
// @see options https://pnpm.io/cli/install
|
||||
opts.prettyCommand = 'pnpm install';
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--unsafe-perm']);
|
||||
} else {
|
||||
opts.prettyCommand = 'yarn install';
|
||||
commandArgs = ['install', ...args];
|
||||
}
|
||||
|
||||
if (process.env.NPM_ONLY_PRODUCTION) {
|
||||
commandArgs.push('--production');
|
||||
}
|
||||
|
||||
await spawnAsync(cliType, commandArgs, opts);
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
return true;
|
||||
} finally {
|
||||
runNpmInstallSema.release();
|
||||
}
|
||||
|
||||
if (process.env.NPM_ONLY_PRODUCTION) {
|
||||
commandArgs.push('--production');
|
||||
}
|
||||
|
||||
return spawnAsync(cliType, commandArgs, opts);
|
||||
}
|
||||
|
||||
export function getEnvForPackageManager({
|
||||
|
||||
@@ -332,6 +332,7 @@ export interface ProjectSettings {
|
||||
sourceFilesOutsideRootDirectory?: boolean;
|
||||
directoryListing?: boolean;
|
||||
gitForkProtection?: boolean;
|
||||
commandForIgnoringBuildStep?: string | null;
|
||||
}
|
||||
|
||||
export interface BuilderV2 {
|
||||
@@ -356,7 +357,29 @@ export interface Images {
|
||||
formats?: ImageFormat[];
|
||||
}
|
||||
|
||||
export interface BuildResultV2 {
|
||||
/**
|
||||
* If a Builder ends up creating filesystem outputs conforming to
|
||||
* the Build Output API, then the Builder should return this type.
|
||||
*/
|
||||
export interface BuildResultBuildOutput {
|
||||
/**
|
||||
* Version number of the Build Output API that was created.
|
||||
* Currently only `3` is a valid value.
|
||||
* @example 3
|
||||
*/
|
||||
buildOutputVersion: 3;
|
||||
/**
|
||||
* Filesystem path to the Build Output directory.
|
||||
* @example "/path/to/.vercel/output"
|
||||
*/
|
||||
buildOutputPath: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a Builder implements `version: 2`, the `build()` function is expected
|
||||
* to return this type.
|
||||
*/
|
||||
export interface BuildResultV2Typical {
|
||||
// TODO: use proper `Route` type from `routing-utils` (perhaps move types to a common package)
|
||||
routes?: any[];
|
||||
images?: Images;
|
||||
@@ -369,6 +392,8 @@ export interface BuildResultV2 {
|
||||
}>;
|
||||
}
|
||||
|
||||
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
|
||||
|
||||
export interface BuildResultV3 {
|
||||
output: Lambda;
|
||||
}
|
||||
|
||||
4
packages/build-utils/test/fixtures/02-zero-config-api/yarn.lock
vendored
Normal file
4
packages/build-utils/test/fixtures/02-zero-config-api/yarn.lock
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
45
packages/build-utils/test/unit.test.ts
vendored
45
packages/build-utils/test/unit.test.ts
vendored
@@ -15,6 +15,7 @@ import {
|
||||
runPackageJsonScript,
|
||||
scanParentDirs,
|
||||
FileBlob,
|
||||
Meta,
|
||||
} from '../src';
|
||||
|
||||
async function expectBuilderError(promise: Promise<any>, pattern: string) {
|
||||
@@ -276,6 +277,14 @@ 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([]);
|
||||
});
|
||||
|
||||
it('should get latest node version', async () => {
|
||||
expect(getLatestNodeVersion()).toHaveProperty('major', 14);
|
||||
});
|
||||
@@ -413,3 +422,39 @@ it('should detect pnpm Workspaces', async () => {
|
||||
expect(result.cliType).toEqual('pnpm');
|
||||
expect(result.lockfileVersion).toEqual(5.3);
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
const run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run1).toEqual(true);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
const run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run2).toEqual(false);
|
||||
const run3 = await runNpmInstall(fixture, [], undefined, meta);
|
||||
expect(run3).toEqual(false);
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
const [run1, run2, run3] = await Promise.all([
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(fixture, [], undefined, meta),
|
||||
]);
|
||||
expect(run1).toEqual(true);
|
||||
expect(run2).toEqual(false);
|
||||
expect(run3).toEqual(false);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "24.1.0",
|
||||
"version": "24.1.1-canary.5",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -43,14 +43,15 @@
|
||||
"node": ">= 12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.15.1",
|
||||
"@vercel/go": "1.3.2",
|
||||
"@vercel/node": "1.14.1",
|
||||
"@vercel/python": "2.2.2",
|
||||
"@vercel/ruby": "1.3.2",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/go": "1.3.3-canary.3",
|
||||
"@vercel/node": "1.14.2-canary.4",
|
||||
"@vercel/python": "2.2.3-canary.3",
|
||||
"@vercel/ruby": "1.3.3-canary.3",
|
||||
"update-notifier": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alex_neo/jest-expect-message": "1.0.5",
|
||||
"@next/env": "11.1.2",
|
||||
"@sentry/node": "5.5.0",
|
||||
"@sindresorhus/slugify": "0.11.0",
|
||||
@@ -69,6 +70,7 @@
|
||||
"@types/http-proxy": "1.16.2",
|
||||
"@types/inquirer": "7.3.1",
|
||||
"@types/jest": "27.0.1",
|
||||
"@types/jest-expect-message": "1.0.3",
|
||||
"@types/load-json-file": "2.0.7",
|
||||
"@types/mime-types": "2.1.0",
|
||||
"@types/minimatch": "3.0.3",
|
||||
@@ -88,11 +90,10 @@
|
||||
"@types/update-notifier": "5.1.0",
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@vercel/client": "10.4.1",
|
||||
"@vercel/client": "10.4.2-canary.4",
|
||||
"@vercel/fetch-retry": "5.0.3",
|
||||
"@vercel/frameworks": "0.7.1",
|
||||
"@vercel/frameworks": "0.7.2-canary.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/nft": "0.17.5",
|
||||
"@zeit/fun": "0.11.2",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
"ajv": "6.12.2",
|
||||
@@ -177,6 +178,9 @@
|
||||
"isolatedModules": true
|
||||
}
|
||||
},
|
||||
"setupFilesAfterEnv": [
|
||||
"@alex_neo/jest-expect-message"
|
||||
],
|
||||
"verbose": false,
|
||||
"testEnvironment": "node",
|
||||
"testMatch": [
|
||||
|
||||
@@ -73,7 +73,7 @@ export default async function set(
|
||||
if (args.length === 0) {
|
||||
output.error(
|
||||
`To ship to production, optionally configure your domains (${link(
|
||||
'https://vercel.com/docs/v2/custom-domains'
|
||||
'https://vercel.link/domain-configuration'
|
||||
)}) and run ${getCommandName(`--prod`)}.`
|
||||
);
|
||||
return 1;
|
||||
|
||||
@@ -181,6 +181,21 @@ export default async (client: Client) => {
|
||||
);
|
||||
}
|
||||
|
||||
// build `--prebuilt`
|
||||
if (argv['--prebuilt']) {
|
||||
const prebuiltExists = await fs.pathExists(join(path, '.vercel/output'));
|
||||
if (!prebuiltExists) {
|
||||
error(
|
||||
`The ${param(
|
||||
'--prebuilt'
|
||||
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
|
||||
'build'
|
||||
)} to generate a local build.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// retrieve `project` and `org` from .vercel
|
||||
const link = await getLinkedProject(client, path);
|
||||
|
||||
|
||||
9
packages/cli/src/commands/env/index.ts
vendored
9
packages/cli/src/commands/env/index.ts
vendored
@@ -115,9 +115,11 @@ export default async function main(client: Client) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const { subcommand, args } = getSubcommand(argv._.slice(1), COMMAND_CONFIG);
|
||||
const cwd = argv['--cwd'] || process.cwd();
|
||||
const subArgs = argv._.slice(1);
|
||||
const { subcommand, args } = getSubcommand(subArgs, COMMAND_CONFIG);
|
||||
const { output, config } = client;
|
||||
const link = await getLinkedProject(client);
|
||||
const link = await getLinkedProject(client, cwd);
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
} else if (link.status === 'not_linked') {
|
||||
@@ -144,7 +146,8 @@ export default async function main(client: Client) {
|
||||
ProjectEnvTarget.Development,
|
||||
argv,
|
||||
args,
|
||||
output
|
||||
output,
|
||||
cwd
|
||||
);
|
||||
default:
|
||||
output.error(getInvalidSubcommand(COMMAND_CONFIG));
|
||||
|
||||
14
packages/cli/src/commands/env/pull.ts
vendored
14
packages/cli/src/commands/env/pull.ts
vendored
@@ -1,5 +1,6 @@
|
||||
import chalk from 'chalk';
|
||||
import { closeSync, openSync, promises, readSync } from 'fs';
|
||||
import { outputFile } from 'fs-extra';
|
||||
import { closeSync, openSync, readSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { Project, ProjectEnvTarget } from '../../types';
|
||||
import Client from '../../util/client';
|
||||
@@ -12,7 +13,6 @@ import { Output } from '../../util/output';
|
||||
import param from '../../util/output/param';
|
||||
import stamp from '../../util/output/stamp';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
const { writeFile } = promises;
|
||||
|
||||
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
|
||||
|
||||
@@ -49,7 +49,7 @@ export default async function pull(
|
||||
opts: Partial<Options>,
|
||||
args: string[],
|
||||
output: Output,
|
||||
cwd: string = process.cwd()
|
||||
cwd: string
|
||||
) {
|
||||
if (args.length > 1) {
|
||||
output.error(
|
||||
@@ -81,7 +81,7 @@ export default async function pull(
|
||||
}
|
||||
|
||||
output.print(
|
||||
`Downloading Development Environment Variables for Project ${chalk.bold(
|
||||
`Downloading "${environment}" Environment Variables for Project ${chalk.bold(
|
||||
project.name
|
||||
)}\n`
|
||||
);
|
||||
@@ -99,7 +99,9 @@ export default async function pull(
|
||||
const records = exposeSystemEnvs(
|
||||
projectEnvs,
|
||||
systemEnvValues,
|
||||
project.autoExposeSystemEnvs
|
||||
project.autoExposeSystemEnvs,
|
||||
undefined,
|
||||
environment
|
||||
);
|
||||
|
||||
const contents =
|
||||
@@ -109,7 +111,7 @@ export default async function pull(
|
||||
.join('\n') +
|
||||
'\n';
|
||||
|
||||
await writeFile(fullPath, contents, 'utf8');
|
||||
await outputFile(fullPath, contents, 'utf8');
|
||||
|
||||
output.print(
|
||||
`${prependEmoji(
|
||||
|
||||
@@ -4,7 +4,6 @@ import Client from '../util/client';
|
||||
import { ProjectEnvTarget } from '../types';
|
||||
import { emoji, prependEmoji } from '../util/emoji';
|
||||
import getArgs from '../util/get-args';
|
||||
import handleError from '../util/handle-error';
|
||||
import setupAndLink from '../util/link/setup-and-link';
|
||||
import logo from '../util/output/logo';
|
||||
import stamp from '../util/output/stamp';
|
||||
@@ -69,19 +68,14 @@ function processArgs(client: Client) {
|
||||
}
|
||||
|
||||
function parseArgs(client: Client) {
|
||||
try {
|
||||
const argv = processArgs(client);
|
||||
const argv = processArgs(client);
|
||||
|
||||
if (argv['--help']) {
|
||||
help();
|
||||
return 2;
|
||||
}
|
||||
|
||||
return argv;
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
return 1;
|
||||
if (argv['--help']) {
|
||||
help();
|
||||
return 2;
|
||||
}
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
type LinkResult = {
|
||||
|
||||
@@ -585,73 +585,73 @@ const main = async () => {
|
||||
let func: any;
|
||||
switch (targetCommand) {
|
||||
case 'alias':
|
||||
func = await import('./commands/alias');
|
||||
func = require('./commands/alias').default;
|
||||
break;
|
||||
case 'billing':
|
||||
func = await import('./commands/billing');
|
||||
func = require('./commands/billing').default;
|
||||
break;
|
||||
case 'bisect':
|
||||
func = await import('./commands/bisect');
|
||||
func = require('./commands/bisect').default;
|
||||
break;
|
||||
case 'certs':
|
||||
func = await import('./commands/certs');
|
||||
func = require('./commands/certs').default;
|
||||
break;
|
||||
case 'deploy':
|
||||
func = await import('./commands/deploy');
|
||||
func = require('./commands/deploy').default;
|
||||
break;
|
||||
case 'dev':
|
||||
func = await import('./commands/dev');
|
||||
func = require('./commands/dev').default;
|
||||
break;
|
||||
case 'dns':
|
||||
func = await import('./commands/dns');
|
||||
func = require('./commands/dns').default;
|
||||
break;
|
||||
case 'domains':
|
||||
func = await import('./commands/domains');
|
||||
func = require('./commands/domains').default;
|
||||
break;
|
||||
case 'env':
|
||||
func = await import('./commands/env');
|
||||
func = require('./commands/env').default;
|
||||
break;
|
||||
case 'init':
|
||||
func = await import('./commands/init');
|
||||
func = require('./commands/init').default;
|
||||
break;
|
||||
case 'inspect':
|
||||
func = await import('./commands/inspect');
|
||||
func = require('./commands/inspect').default;
|
||||
break;
|
||||
case 'link':
|
||||
func = await import('./commands/link');
|
||||
func = require('./commands/link').default;
|
||||
break;
|
||||
case 'list':
|
||||
func = await import('./commands/list');
|
||||
func = require('./commands/list').default;
|
||||
break;
|
||||
case 'logs':
|
||||
func = await import('./commands/logs');
|
||||
func = require('./commands/logs').default;
|
||||
break;
|
||||
case 'login':
|
||||
func = await import('./commands/login');
|
||||
func = require('./commands/login').default;
|
||||
break;
|
||||
case 'logout':
|
||||
func = await import('./commands/logout');
|
||||
func = require('./commands/logout').default;
|
||||
break;
|
||||
case 'projects':
|
||||
func = await import('./commands/projects');
|
||||
func = require('./commands/projects').default;
|
||||
break;
|
||||
case 'pull':
|
||||
func = await import('./commands/pull');
|
||||
func = require('./commands/pull').default;
|
||||
break;
|
||||
case 'remove':
|
||||
func = await import('./commands/remove');
|
||||
func = require('./commands/remove').default;
|
||||
break;
|
||||
case 'secrets':
|
||||
func = await import('./commands/secrets');
|
||||
func = require('./commands/secrets').default;
|
||||
break;
|
||||
case 'teams':
|
||||
func = await import('./commands/teams');
|
||||
func = require('./commands/teams').default;
|
||||
break;
|
||||
case 'update':
|
||||
func = await import('./commands/update');
|
||||
func = require('./commands/update').default;
|
||||
break;
|
||||
case 'whoami':
|
||||
func = await import('./commands/whoami');
|
||||
func = require('./commands/whoami').default;
|
||||
break;
|
||||
default:
|
||||
func = null;
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import { Output } from '../output';
|
||||
// @ts-ignore
|
||||
import Now from '../../util';
|
||||
import { VercelConfig } from '../dev/types';
|
||||
import { Org } from '../../types';
|
||||
import ua from '../ua';
|
||||
import { linkFolderToProject } from '../projects/link';
|
||||
@@ -43,7 +42,6 @@ export default async function processDeployment({
|
||||
uploadStamp: () => string;
|
||||
deployStamp: () => string;
|
||||
quiet: boolean;
|
||||
nowConfig?: VercelConfig;
|
||||
force?: boolean;
|
||||
withCache?: boolean;
|
||||
org: Org;
|
||||
@@ -62,7 +60,6 @@ export default async function processDeployment({
|
||||
deployStamp,
|
||||
force,
|
||||
withCache,
|
||||
nowConfig,
|
||||
quiet,
|
||||
prebuilt,
|
||||
rootDirectory,
|
||||
@@ -104,11 +101,7 @@ export default async function processDeployment({
|
||||
const indications = [];
|
||||
|
||||
try {
|
||||
for await (const event of createDeployment(
|
||||
clientOptions,
|
||||
requestBody,
|
||||
nowConfig
|
||||
)) {
|
||||
for await (const event of createDeployment(clientOptions, requestBody)) {
|
||||
if (['tip', 'notice', 'warning'].includes(event.type)) {
|
||||
indications.push(event);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,6 @@ export default class Now extends EventEmitter {
|
||||
uploadStamp,
|
||||
deployStamp,
|
||||
quiet,
|
||||
nowConfig,
|
||||
force: forceNew,
|
||||
withCache,
|
||||
org,
|
||||
|
||||
@@ -227,6 +227,7 @@ export default async function setupAndLink(
|
||||
return { status: 'linked', org, project };
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
|
||||
return { status: 'error', exitCode: 1 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { writeFile } from 'fs-extra';
|
||||
import { outputJSON } from 'fs-extra';
|
||||
import { Org, Project, ProjectLink } from '../../types';
|
||||
import { getLinkFromDir, VERCEL_DIR, VERCEL_DIR_PROJECT } from './link';
|
||||
import { join } from 'path';
|
||||
@@ -22,21 +22,22 @@ export async function writeProjectSettings(
|
||||
project: Project,
|
||||
org: Org
|
||||
) {
|
||||
return await writeFile(
|
||||
join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT),
|
||||
JSON.stringify({
|
||||
projectId: project.id,
|
||||
orgId: org.id,
|
||||
settings: {
|
||||
buildCommand: project.buildCommand,
|
||||
devCommand: project.devCommand,
|
||||
outputDirectory: project.outputDirectory,
|
||||
directoryListing: project.directoryListing,
|
||||
rootDirectory: project.rootDirectory,
|
||||
framework: project.framework,
|
||||
},
|
||||
})
|
||||
);
|
||||
const data = {
|
||||
projectId: project.id,
|
||||
orgId: org.id,
|
||||
settings: {
|
||||
buildCommand: project.buildCommand,
|
||||
devCommand: project.devCommand,
|
||||
outputDirectory: project.outputDirectory,
|
||||
directoryListing: project.directoryListing,
|
||||
rootDirectory: project.rootDirectory,
|
||||
framework: project.framework,
|
||||
},
|
||||
};
|
||||
const path = join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT);
|
||||
return await outputJSON(path, data, {
|
||||
spaces: 2,
|
||||
});
|
||||
}
|
||||
|
||||
export async function readProjectSettings(cwd: string) {
|
||||
|
||||
@@ -31,6 +31,15 @@ describe('deploy', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject deploying a directory that does not contain ".vercel/output" when `--prebuilt` is used', async () => {
|
||||
client.setArgv('deploy', __dirname, '--prebuilt');
|
||||
const exitCode = await deploy(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
expect(client.outputBuffer).toEqual(
|
||||
'Error! The "--prebuilt" option was used, but no prebuilt output found in ".vercel/output". Run `vercel build` to generate a local build.\n'
|
||||
);
|
||||
});
|
||||
|
||||
it('should reject deploying "version: 1"', async () => {
|
||||
client.setArgv('deploy');
|
||||
client.localConfig = {
|
||||
|
||||
75
packages/cli/test/commands/env.test.ts
Normal file
75
packages/cli/test/commands/env.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import env from '../../src/commands/env';
|
||||
import { setupFixture } from '../helpers/setup-fixture';
|
||||
import { client } from '../mocks/client';
|
||||
import { defaultProject, useProject } from '../mocks/project';
|
||||
import { useTeams } from '../mocks/team';
|
||||
import { useUser } from '../mocks/user';
|
||||
|
||||
describe('env', () => {
|
||||
describe('pull', () => {
|
||||
it('should handle pulling', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
});
|
||||
client.setArgv('env', 'pull', '--yes', '--cwd', cwd);
|
||||
const exitCode = await env(client);
|
||||
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env'));
|
||||
|
||||
// check for development env value
|
||||
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
||||
expect(devFileHasDevEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle alternate filename', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
});
|
||||
client.setArgv('env', 'pull', 'other.env', '--yes', '--cwd', cwd);
|
||||
const exitCode = await env(client);
|
||||
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, 'other.env'));
|
||||
|
||||
// check for development env value
|
||||
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
||||
expect(devFileHasDevEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should expose production system env variables', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
autoExposeSystemEnvs: true,
|
||||
});
|
||||
|
||||
client.setArgv('env', 'pull', 'other.env', '--yes', '--cwd', cwd);
|
||||
const exitCode = await env(client);
|
||||
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, 'other.env'));
|
||||
|
||||
const productionFileHasVercelEnv = rawDevEnv
|
||||
.toString()
|
||||
.includes('VERCEL_ENV="development"');
|
||||
expect(productionFileHasVercelEnv).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,7 @@ describe('pull', () => {
|
||||
it('should handle pulling', async () => {
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
useUser();
|
||||
useTeams();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
@@ -19,7 +19,7 @@ describe('pull', () => {
|
||||
});
|
||||
client.setArgv('pull', '--yes', cwd);
|
||||
const exitCode = await pull(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(
|
||||
path.join(cwd, '.vercel', '.env.development.local')
|
||||
@@ -28,10 +28,46 @@ describe('pull', () => {
|
||||
expect(devFileHasDevEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should handle pulling with env vars (headless mode)', async () => {
|
||||
try {
|
||||
process.env.VERCEL_PROJECT_ID = 'vercel-pull-next';
|
||||
process.env.VERCEL_ORG_ID = 'team_dummy';
|
||||
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
|
||||
// Remove the `.vercel` dir to ensure that the `pull`
|
||||
// command creates a new one based on env vars
|
||||
await fs.remove(path.join(cwd, '.vercel'));
|
||||
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
name: 'vercel-pull-next',
|
||||
});
|
||||
client.setArgv('pull', cwd);
|
||||
const exitCode = await pull(client);
|
||||
expect(exitCode, client.outputBuffer).toEqual(0);
|
||||
|
||||
const config = await fs.readJSON(path.join(cwd, '.vercel/project.json'));
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"orgId": "team_dummy",
|
||||
"projectId": "vercel-pull-next",
|
||||
"settings": Object {},
|
||||
}
|
||||
`);
|
||||
} finally {
|
||||
delete process.env.VERCEL_PROJECT_ID;
|
||||
delete process.env.VERCEL_ORG_ID;
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle --environment=preview flag', async () => {
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
useUser();
|
||||
useTeams();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
@@ -53,7 +89,7 @@ describe('pull', () => {
|
||||
it('should handle --environment=production flag', async () => {
|
||||
const cwd = setupFixture('vercel-pull-next');
|
||||
useUser();
|
||||
useTeams();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-pull-next',
|
||||
|
||||
2
packages/cli/test/fixtures/unit/vercel-env-pull/.gitignore
vendored
Normal file
2
packages/cli/test/fixtures/unit/vercel-env-pull/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.next
|
||||
yarn.lock
|
||||
4
packages/cli/test/fixtures/unit/vercel-env-pull/.vercel/project.json
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-env-pull/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"orgId": "team_dummy",
|
||||
"projectId": "vercel-env-pull"
|
||||
}
|
||||
12
packages/cli/test/fixtures/unit/vercel-env-pull/package.json
vendored
Normal file
12
packages/cli/test/fixtures/unit/vercel-env-pull/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next",
|
||||
"now-build": "next build"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^8.0.0",
|
||||
"react": "^16.7.0",
|
||||
"react-dom": "^16.7.0"
|
||||
}
|
||||
}
|
||||
11
packages/cli/test/fixtures/unit/vercel-env-pull/pages/index.js
vendored
Normal file
11
packages/cli/test/fixtures/unit/vercel-env-pull/pages/index.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { withRouter } from 'next/router';
|
||||
|
||||
function Index({ router }) {
|
||||
const data = {
|
||||
pathname: router.pathname,
|
||||
query: router.query,
|
||||
};
|
||||
return <div>{JSON.stringify(data)}</div>;
|
||||
}
|
||||
|
||||
export default withRouter(Index);
|
||||
10
packages/cli/test/fixtures/unit/vercel-env-pull/vercel.json
vendored
Normal file
10
packages/cli/test/fixtures/unit/vercel-env-pull/vercel.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "vercel-env-pull",
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "/index?route-param=b"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
.next
|
||||
yarn.lock
|
||||
.vercel
|
||||
4
packages/cli/test/fixtures/unit/vercel-pull-next/.vercel/project.json
vendored
Normal file
4
packages/cli/test/fixtures/unit/vercel-pull-next/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"orgId": "team_dummy",
|
||||
"projectId": "vercel-pull-next"
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"version": 2,
|
||||
"name": "vercel-pull-next",
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next@canary" }],
|
||||
"routes": [
|
||||
{
|
||||
"src": "/(.*)",
|
||||
|
||||
48
packages/cli/test/integration.js
vendored
48
packages/cli/test/integration.js
vendored
@@ -796,13 +796,16 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
t.regex(stderr, /Created .env file/gm);
|
||||
|
||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||
t.true(contents.startsWith('# Created by Vercel CLI\n'));
|
||||
t.regex(contents, /^# Created by Vercel CLI\n/);
|
||||
|
||||
const lines = new Set(contents.split('\n'));
|
||||
t.true(lines.has('MY_NEW_ENV_VAR="my plaintext value"'));
|
||||
t.true(lines.has('MY_STDIN_VAR="{"expect":"quotes"}"'));
|
||||
t.true(lines.has('MY_DECRYPTABLE_SECRET_ENV="decryptable value"'));
|
||||
t.false(lines.has('MY_PREVIEW'));
|
||||
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');
|
||||
}
|
||||
|
||||
async function vcEnvPullOverwrite() {
|
||||
@@ -974,11 +977,12 @@ test('Deploy `api-env` fixture and test `vercel env` command', async t => {
|
||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||
|
||||
const lines = new Set(contents.split('\n'));
|
||||
t.true(lines.has('VERCEL="1"'));
|
||||
t.true(lines.has('VERCEL_URL=""'));
|
||||
t.true(lines.has('VERCEL_ENV="development"'));
|
||||
t.true(lines.has('VERCEL_GIT_PROVIDER=""'));
|
||||
t.true(lines.has('VERCEL_GIT_REPO_SLUG=""'));
|
||||
|
||||
t.true(lines.has('VERCEL="1"'), 'VERCEL');
|
||||
t.true(lines.has('VERCEL_URL=""'), 'VERCEL_URL');
|
||||
t.true(lines.has('VERCEL_ENV="development"'), 'VERCEL_ENV');
|
||||
t.true(lines.has('VERCEL_GIT_PROVIDER=""'), 'VERCEL_GIT_PROVIDER');
|
||||
t.true(lines.has('VERCEL_GIT_REPO_SLUG=""'), 'VERCEL_GIT_REPO_SLUG');
|
||||
}
|
||||
|
||||
async function vcDevAndFetchSystemVars() {
|
||||
@@ -2144,11 +2148,6 @@ const verifyExampleAngular = (cwd, dir) =>
|
||||
fs.existsSync(path.join(cwd, dir, 'tsconfig.json')) &&
|
||||
fs.existsSync(path.join(cwd, dir, 'angular.json'));
|
||||
|
||||
const verifyExampleAmp = (cwd, dir) =>
|
||||
fs.existsSync(path.join(cwd, dir, 'index.html')) &&
|
||||
fs.existsSync(path.join(cwd, dir, 'logo.png')) &&
|
||||
fs.existsSync(path.join(cwd, dir, 'favicon.png'));
|
||||
|
||||
test('initialize example "angular"', async t => {
|
||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
||||
const cwd = tmpDir.name;
|
||||
@@ -2183,21 +2182,6 @@ test('initialize example ("angular") to specified directory', async t => {
|
||||
t.true(verifyExampleAngular(cwd, 'ang'), formatOutput({ stdout, stderr }));
|
||||
});
|
||||
|
||||
test('initialize selected example ("amp")', async t => {
|
||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
||||
const cwd = tmpDir.name;
|
||||
const goal = '> Success! Initialized "amp" example in';
|
||||
|
||||
const { stdout, stderr, exitCode } = await execute(['init'], {
|
||||
cwd,
|
||||
input: '\n',
|
||||
});
|
||||
|
||||
t.is(exitCode, 0, formatOutput({ stdout, stderr }));
|
||||
t.true(stderr.includes(goal), formatOutput({ stdout, stderr }));
|
||||
t.true(verifyExampleAmp(cwd, 'amp'), formatOutput({ stdout, stderr }));
|
||||
});
|
||||
|
||||
test('initialize example to existing directory with "-f"', async t => {
|
||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
||||
const cwd = tmpDir.name;
|
||||
@@ -2274,6 +2258,8 @@ test('try to revert a deployment and assign the automatic aliases', async t => {
|
||||
const { name } = JSON.parse(
|
||||
fs.readFileSync(path.join(firstDeployment, 'now.json'))
|
||||
);
|
||||
t.true(!!name, 'name has a value');
|
||||
|
||||
const url = `https://${name}.user.vercel.app`;
|
||||
|
||||
{
|
||||
@@ -2862,7 +2848,7 @@ test('should show prompts to set up project during first deploy', async t => {
|
||||
);
|
||||
|
||||
// Send a test request to the deployment
|
||||
const response = await fetch(new URL(output.stdout).href);
|
||||
const response = await fetch(new URL(output.stdout));
|
||||
const text = await response.text();
|
||||
t.is(text.includes('<h1>custom hello</h1>'), true, text);
|
||||
|
||||
|
||||
@@ -87,7 +87,20 @@ export class MockClient extends Client {
|
||||
}
|
||||
|
||||
stopMockServer() {
|
||||
this.mockServer?.close();
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (!this.mockServer?.close) {
|
||||
reject(new Error(`mockServer did not exist when closing`));
|
||||
return;
|
||||
}
|
||||
|
||||
this.mockServer.close(error => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setArgv(...argv: string[]) {
|
||||
@@ -109,6 +122,6 @@ beforeEach(() => {
|
||||
client.reset();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
client.stopMockServer();
|
||||
afterAll(async () => {
|
||||
await client.stopMockServer();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { client } from './client';
|
||||
import { Project } from '../../src/types';
|
||||
|
||||
const envs = [
|
||||
{
|
||||
@@ -36,6 +37,42 @@ const envs = [
|
||||
},
|
||||
];
|
||||
|
||||
const systemEnvs = [
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: 'a235l6frtu25df32',
|
||||
key: 'SYSTEM_ENV_FOR_DEV',
|
||||
value: 'development',
|
||||
target: ['development'],
|
||||
gitBranch: null,
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361445,
|
||||
createdAt: 1557241361445,
|
||||
},
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: 'a235l6frtu25df32',
|
||||
key: 'SYSTEM_ENV_FOR_PREV',
|
||||
value: 'preview',
|
||||
target: ['preview'],
|
||||
gitBranch: null,
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361445,
|
||||
createdAt: 1557241361445,
|
||||
},
|
||||
{
|
||||
type: 'encrypted',
|
||||
id: 'a235l6frtu25df32',
|
||||
key: 'SYSTEM_ENV_FOR_PROD',
|
||||
value: 'production',
|
||||
target: ['production'],
|
||||
gitBranch: null,
|
||||
configurationId: null,
|
||||
updatedAt: 1557241361445,
|
||||
createdAt: 1557241361445,
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultProject = {
|
||||
id: 'foo',
|
||||
name: 'cli',
|
||||
@@ -80,25 +117,42 @@ export const defaultProject = {
|
||||
requestedAt: 1571239348998,
|
||||
target: 'production',
|
||||
teamId: null,
|
||||
type: 'LAMBDAS',
|
||||
type: undefined,
|
||||
url: 'a-project-name-rjtr4pz3f.vercel.app',
|
||||
userId: 'K4amb7K9dAt5R2vBJWF32bmY',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export function useProject(project = defaultProject) {
|
||||
export function useProject(project: Partial<Project> = defaultProject) {
|
||||
client.scenario.get(`/v8/projects/${project.name}`, (_req, res) => {
|
||||
res.json(project);
|
||||
});
|
||||
client.scenario.get(`/v8/projects/${project.id}`, (_req, res) => {
|
||||
res.json(project);
|
||||
});
|
||||
client.scenario.get(
|
||||
`/v6/projects/${project.id}/system-env-values`,
|
||||
(_req, res) => {
|
||||
const target = _req.query.target || 'development';
|
||||
if (typeof target !== 'string') {
|
||||
throw new Error(
|
||||
`/v6/projects/${project.id}/system-env-values was given a query param of "target=${target}", which is not a valid environment.`
|
||||
);
|
||||
}
|
||||
const targetEnvs = systemEnvs.filter(env => env.target.includes(target));
|
||||
|
||||
res.json({
|
||||
systemEnvValues: targetEnvs,
|
||||
});
|
||||
}
|
||||
);
|
||||
client.scenario.get(`/v8/projects/${project.id}/env`, (_req, res) => {
|
||||
const target = _req.query.target;
|
||||
if (typeof target === 'string') {
|
||||
const targetEnvs = envs.filter(env => env.target.includes(target));
|
||||
res.json({ envs: targetEnvs });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ envs });
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import chance from 'chance';
|
||||
import { client } from './client';
|
||||
|
||||
export function useTeams() {
|
||||
export function useTeams(teamId?: string) {
|
||||
const id = teamId || chance().guid();
|
||||
const teams = [
|
||||
{
|
||||
id: chance().guid(),
|
||||
id,
|
||||
slug: chance().string({ length: 5, casing: 'lower' }),
|
||||
name: chance().company(),
|
||||
creatorId: chance().guid(),
|
||||
@@ -14,7 +15,7 @@ export function useTeams() {
|
||||
];
|
||||
|
||||
for (let team of teams) {
|
||||
client.scenario.get(`/v1/team/${team.id}`, (_req, res) => {
|
||||
client.scenario.get(`/teams/${team.id}`, (_req, res) => {
|
||||
res.json(team);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "10.4.1",
|
||||
"version": "10.4.2-canary.4",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -41,7 +41,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "2.15.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { lstatSync } from 'fs-extra';
|
||||
|
||||
import { relative, isAbsolute } from 'path';
|
||||
import { isAbsolute } from 'path';
|
||||
import { hashes, mapToObject } from './utils/hashes';
|
||||
import { upload } from './upload';
|
||||
import { buildFileTree, createDebug, parseVercelConfig } from './utils';
|
||||
import { buildFileTree, createDebug } from './utils';
|
||||
import { DeploymentError } from './errors';
|
||||
import {
|
||||
VercelConfig,
|
||||
VercelClientOptions,
|
||||
DeploymentOptions,
|
||||
DeploymentEventType,
|
||||
@@ -15,13 +13,11 @@ import {
|
||||
export default function buildCreateDeployment() {
|
||||
return async function* createDeployment(
|
||||
clientOptions: VercelClientOptions,
|
||||
deploymentOptions: DeploymentOptions = {},
|
||||
nowConfig: VercelConfig = {}
|
||||
deploymentOptions: DeploymentOptions = {}
|
||||
): AsyncIterableIterator<{ type: DeploymentEventType; payload: any }> {
|
||||
const { path } = clientOptions;
|
||||
|
||||
const debug = createDebug(clientOptions.debug);
|
||||
const cwd = process.cwd();
|
||||
|
||||
debug('Creating deployment...');
|
||||
|
||||
@@ -76,29 +72,6 @@ export default function buildCreateDeployment() {
|
||||
|
||||
const { fileList } = await buildFileTree(path, clientOptions, debug);
|
||||
|
||||
let configPath: string | undefined;
|
||||
if (!nowConfig) {
|
||||
// If the user did not provide a config file, use the one in the root directory.
|
||||
const relativePaths = fileList.map(f => relative(cwd, f));
|
||||
const hasVercelConfig = relativePaths.includes('vercel.json');
|
||||
const hasNowConfig = relativePaths.includes('now.json');
|
||||
|
||||
if (hasVercelConfig) {
|
||||
if (hasNowConfig) {
|
||||
throw new DeploymentError({
|
||||
code: 'conflicting_config',
|
||||
message:
|
||||
'Cannot use both a `vercel.json` and `now.json` file. Please delete the `now.json` file.',
|
||||
});
|
||||
}
|
||||
configPath = 'vercel.json';
|
||||
} else if (hasNowConfig) {
|
||||
configPath = 'now.json';
|
||||
}
|
||||
|
||||
nowConfig = await parseVercelConfig(configPath);
|
||||
}
|
||||
|
||||
// This is a useful warning because it prevents people
|
||||
// from getting confused about a deployment that renders 404.
|
||||
if (fileList.length === 0) {
|
||||
|
||||
@@ -126,27 +126,6 @@ export async function* deploy(
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
files.size === 1 &&
|
||||
deploymentOptions.builds === undefined &&
|
||||
deploymentOptions.routes === undefined &&
|
||||
deploymentOptions.cleanUrls === undefined &&
|
||||
deploymentOptions.rewrites === undefined &&
|
||||
deploymentOptions.redirects === undefined &&
|
||||
deploymentOptions.headers === undefined &&
|
||||
deploymentOptions.trailingSlash === undefined
|
||||
) {
|
||||
debug(`Assigning '/' route for single file deployment`);
|
||||
const filePath = Array.from(files.values())[0].names[0];
|
||||
|
||||
deploymentOptions.routes = [
|
||||
{
|
||||
src: '/',
|
||||
dest: `/${filePath.split('/').pop()}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (!deploymentOptions.name) {
|
||||
deploymentOptions.name =
|
||||
clientOptions.defaultName || getDefaultName(files, clientOptions);
|
||||
|
||||
1
packages/frameworks/logos/next-dark.svg
Normal file
1
packages/frameworks/logos/next-dark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "0.7.1",
|
||||
"version": "0.7.2-canary.0",
|
||||
"main": "./dist/frameworks.js",
|
||||
"types": "./dist/frameworks.d.ts",
|
||||
"files": [
|
||||
|
||||
@@ -60,6 +60,7 @@ 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',
|
||||
screenshot:
|
||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
|
||||
tagline:
|
||||
|
||||
@@ -60,6 +60,11 @@ export interface Framework {
|
||||
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg"
|
||||
*/
|
||||
logo: string;
|
||||
/**
|
||||
* An additional URL to the logo of the framework optimized for dark mode
|
||||
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg"
|
||||
*/
|
||||
darkModeLogo?: string;
|
||||
/**
|
||||
* A URL to a screenshot of the demo
|
||||
* @example "https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png"
|
||||
|
||||
@@ -6,6 +6,7 @@ import { join } from 'path';
|
||||
import stringArgv from 'string-argv';
|
||||
import { debug } from '@vercel/build-utils';
|
||||
const versionMap = new Map([
|
||||
['1.18', '1.18.1'],
|
||||
['1.17', '1.17.3'],
|
||||
['1.16', '1.16.10'],
|
||||
['1.15', '1.15.8'],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3-canary.3",
|
||||
"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.15.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.1",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
{ "src": "subdirectory/index.go", "use": "@vercel/go" }
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "cow:go1.17.3:RANDOMNESS_PLACEHOLDER" },
|
||||
{ "path": "/", "mustContain": "cow:go1.18.1:RANDOMNESS_PLACEHOLDER" },
|
||||
{
|
||||
"path": "/subdirectory",
|
||||
"mustContain": "subcow:go1.17.3:RANDOMNESS_PLACEHOLDER"
|
||||
"mustContain": "subcow:go1.18.1:RANDOMNESS_PLACEHOLDER"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -186,9 +186,6 @@ class Bridge {
|
||||
'payloads' in normalizedEvent &&
|
||||
Array.isArray(normalizedEvent.payloads)
|
||||
) {
|
||||
// statusCode and headers are required to match when using
|
||||
// multiple payloads in a single invocation so we can use
|
||||
// the first
|
||||
let statusCode = 200;
|
||||
/**
|
||||
* @type {import('http').IncomingHttpHeaders}
|
||||
@@ -200,6 +197,14 @@ class Bridge {
|
||||
let combinedBody = '';
|
||||
const multipartBoundary = 'payload-separator';
|
||||
const CLRF = '\r\n';
|
||||
/**
|
||||
* @type {Record<string, any>[]}
|
||||
*/
|
||||
const separateHeaders = [];
|
||||
/**
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
const allHeaderKeys = new Set();
|
||||
|
||||
// we execute the payloads one at a time to ensure
|
||||
// lambda semantics
|
||||
@@ -209,20 +214,49 @@ class Bridge {
|
||||
// build a combined body using multipart
|
||||
// https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
|
||||
combinedBody += `--${multipartBoundary}${CLRF}`;
|
||||
if (response.headers['content-type']) {
|
||||
combinedBody += `content-type: ${response.headers['content-type']}${CLRF}${CLRF}`;
|
||||
}
|
||||
combinedBody += response.body;
|
||||
combinedBody += `content-type: ${
|
||||
response.headers['content-type'] || 'text/plain'
|
||||
}${CLRF}${CLRF}`;
|
||||
combinedBody += response.body || '';
|
||||
combinedBody += CLRF;
|
||||
|
||||
if (i === normalizedEvent.payloads.length - 1) {
|
||||
combinedBody += `--${multipartBoundary}--${CLRF}`;
|
||||
}
|
||||
|
||||
statusCode = response.statusCode;
|
||||
headers = response.headers;
|
||||
// pass non-200 status code in header so it can be handled
|
||||
// separately from other payloads e.g. HTML payload redirects
|
||||
// (307) but data payload does not (200)
|
||||
if (response.statusCode !== 200) {
|
||||
headers[`x-vercel-payload-${i + 1}-status`] =
|
||||
response.statusCode + '';
|
||||
}
|
||||
separateHeaders.push(response.headers);
|
||||
Object.keys(response.headers).forEach(key => allHeaderKeys.add(key));
|
||||
}
|
||||
|
||||
allHeaderKeys.forEach(curKey => {
|
||||
/**
|
||||
* @type string | string[] | undefined
|
||||
*/
|
||||
const curValue = separateHeaders[0] && separateHeaders[0][curKey];
|
||||
const canDedupe = separateHeaders.every(
|
||||
headers => headers[curKey] === curValue
|
||||
);
|
||||
|
||||
if (canDedupe) {
|
||||
headers[curKey] = curValue;
|
||||
} else {
|
||||
// if a header is unique per payload ensure it is prefixed
|
||||
// so it can be parsed and provided separately
|
||||
separateHeaders.forEach((curHeaders, idx) => {
|
||||
if (curHeaders[curKey]) {
|
||||
headers[`x-vercel-payload-${idx + 1}-${curKey}`] =
|
||||
curHeaders[curKey];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
headers[
|
||||
'content-type'
|
||||
] = `multipart/mixed; boundary="${multipartBoundary}"`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node-bridge",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.1-canary.0",
|
||||
"license": "MIT",
|
||||
"main": "./index.js",
|
||||
"repository": {
|
||||
|
||||
37
packages/node-bridge/test/bridge.test.js
vendored
37
packages/node-bridge/test/bridge.test.js
vendored
@@ -86,6 +86,12 @@ test('`NowProxyEvent` normalizing', async () => {
|
||||
|
||||
test('multi-payload handling', async () => {
|
||||
const server = new Server((req, res) => {
|
||||
if (req.url === '/redirect') {
|
||||
res.setHeader('Location', '/somewhere');
|
||||
res.statusCode = 307;
|
||||
res.end('/somewhere');
|
||||
return;
|
||||
}
|
||||
res.setHeader(
|
||||
'content-type',
|
||||
req.url.includes('_next/data') ? 'application/json' : 'text/html'
|
||||
@@ -117,6 +123,11 @@ test('multi-payload handling', async () => {
|
||||
headers: { foo: 'baz' },
|
||||
path: '/_next/data/build-id/nowproxy.json',
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
headers: { foo: 'baz' },
|
||||
path: '/redirect',
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
@@ -137,20 +148,36 @@ test('multi-payload handling', async () => {
|
||||
!item.startsWith('content-type:') &&
|
||||
!item.startsWith('--payload')
|
||||
) {
|
||||
bodies.push(
|
||||
JSON.parse(
|
||||
Buffer.from(item.split('--payload-separator')[0], 'base64').toString()
|
||||
)
|
||||
);
|
||||
const content = Buffer.from(
|
||||
item.split('--payload-separator')[0],
|
||||
'base64'
|
||||
).toString();
|
||||
bodies.push(content.startsWith('{') ? JSON.parse(content) : content);
|
||||
}
|
||||
});
|
||||
|
||||
// ensure content-type is always specified as is required for
|
||||
// proper parsing of the multipart body
|
||||
assert(payloadParts.some(part => part.includes('content-type: text/plain')));
|
||||
|
||||
assert.equal(bodies[0].method, 'GET');
|
||||
assert.equal(bodies[0].path, '/nowproxy');
|
||||
assert.equal(bodies[0].headers.foo, 'baz');
|
||||
assert.equal(bodies[1].method, 'GET');
|
||||
assert.equal(bodies[1].path, '/_next/data/build-id/nowproxy.json');
|
||||
assert.equal(bodies[1].headers.foo, 'baz');
|
||||
assert.equal(bodies[2], '/somewhere');
|
||||
assert.equal(result.headers['x-vercel-payload-3-status'], '307');
|
||||
assert.equal(result.headers['x-vercel-payload-2-status'], undefined);
|
||||
assert.equal(result.headers['x-vercel-payload-1-status'], undefined);
|
||||
assert.equal(result.headers['x-vercel-payload-1-content-type'], 'text/html');
|
||||
assert.equal(
|
||||
result.headers['x-vercel-payload-2-content-type'],
|
||||
'application/json'
|
||||
);
|
||||
assert.equal(result.headers['x-vercel-payload-3-content-type'], undefined);
|
||||
assert.equal(result.headers['x-vercel-payload-3-location'], '/somewhere');
|
||||
assert.equal(result.headers['x-vercel-payload-2-location'], undefined);
|
||||
assert.equal(context.callbackWaitsForEmptyEventLoop, false);
|
||||
|
||||
server.close();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "1.14.1",
|
||||
"version": "1.14.2-canary.4",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
|
||||
@@ -19,7 +19,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@vercel/node-bridge": "2.2.0",
|
||||
"@vercel/node-bridge": "2.2.1-canary.0",
|
||||
"ts-node": "8.9.1",
|
||||
"typescript": "4.3.4"
|
||||
},
|
||||
@@ -32,9 +32,9 @@
|
||||
"@types/cookie": "0.3.3",
|
||||
"@types/etag": "1.8.0",
|
||||
"@types/test-listen": "1.1.0",
|
||||
"@vercel/build-utils": "2.15.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/nft": "0.17.5",
|
||||
"@vercel/nft": "0.18.1",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"etag": "1.8.1",
|
||||
|
||||
@@ -86,7 +86,6 @@ async function downloadInstallAndBundle({
|
||||
meta,
|
||||
}: DownloadOptions) {
|
||||
const downloadedFiles = await download(files, workPath, meta);
|
||||
|
||||
const entrypointFsDirname = join(workPath, dirname(entrypoint));
|
||||
const nodeVersion = await getNodeVersion(
|
||||
entrypointFsDirname,
|
||||
@@ -95,16 +94,7 @@ async function downloadInstallAndBundle({
|
||||
meta
|
||||
);
|
||||
const spawnOpts = getSpawnOptions(meta, nodeVersion);
|
||||
|
||||
if (meta.isDev) {
|
||||
debug('Skipping dependency installation because dev mode is enabled');
|
||||
} else {
|
||||
const installTime = Date.now();
|
||||
console.log('Installing dependencies...');
|
||||
await runNpmInstall(entrypointFsDirname, [], spawnOpts, meta, nodeVersion);
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
}
|
||||
|
||||
await runNpmInstall(entrypointFsDirname, [], spawnOpts, meta, nodeVersion);
|
||||
const entrypointPath = downloadedFiles[entrypoint].fsPath;
|
||||
return { entrypointPath, entrypointFsDirname, nodeVersion, spawnOpts };
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/python",
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.3-canary.3",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/execa": "^0.9.0",
|
||||
"@vercel/build-utils": "2.15.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "^1.0.0",
|
||||
"typescript": "4.3.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from sanic import Sanic
|
||||
from sanic.response import json
|
||||
app = Sanic()
|
||||
app = Sanic(name='test')
|
||||
|
||||
@app.route('/')
|
||||
@app.route('/<path:path>')
|
||||
|
||||
@@ -1,2 +1,23 @@
|
||||
sanic==19.6.0
|
||||
flask==1.0.2
|
||||
sanic==20.12.6
|
||||
flask==2.1.1
|
||||
# below is meant to lock the version of transitive deps
|
||||
aiofiles==0.8.0; python_version >= "3.6" and python_version < "4.0"
|
||||
certifi==2021.10.8
|
||||
click==8.1.2; python_version >= "3.7"
|
||||
h11==0.9.0
|
||||
httpcore==0.11.1; python_version >= "3.6"
|
||||
httptools==0.4.0; python_version >= "3.5"
|
||||
httpx==0.15.4; python_version >= "3.6"
|
||||
idna==3.3
|
||||
importlib-metadata==4.11.3; python_version < "3.10"
|
||||
itsdangerous==2.1.2; python_version >= "3.7"
|
||||
jinja2==3.1.1; python_version >= "3.7"
|
||||
markupsafe==2.1.1; python_version >= "3.7"
|
||||
multidict==5.2.0; python_version >= "3.6"
|
||||
rfc3986[idna2008]==1.5.0
|
||||
sniffio==1.2.0; python_version >= "3.5"
|
||||
ujson==5.2.0; sys_platform != "win32" and implementation_name == "cpython"
|
||||
uvloop==0.16.0; sys_platform != "win32" and implementation_name == "cpython"
|
||||
websockets==9.1; python_full_version >= "3.6.1"
|
||||
werkzeug==2.1.1; python_version >= "3.7"
|
||||
zipp==3.8.0; python_version >= "3.7"
|
||||
|
||||
12
packages/python/test/fixtures/09-url-params/Pipfile
vendored
Normal file
12
packages/python/test/fixtures/09-url-params/Pipfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
flask = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
123
packages/python/test/fixtures/09-url-params/Pipfile.lock
generated
vendored
Normal file
123
packages/python/test/fixtures/09-url-params/Pipfile.lock
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "f7f1cea682a03d85328caf2f88382c4380283d3892a9ba31b374784fb29536c4"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
|
||||
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.2"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264",
|
||||
"sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6",
|
||||
"sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"
|
||||
],
|
||||
"markers": "python_version < '3.10'",
|
||||
"version": "==4.11.3"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
|
||||
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119",
|
||||
"sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
|
||||
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
|
||||
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
|
||||
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
|
||||
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
|
||||
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
|
||||
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
|
||||
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
|
||||
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
|
||||
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
|
||||
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
|
||||
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
|
||||
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
|
||||
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
|
||||
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
|
||||
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
|
||||
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
|
||||
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
|
||||
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
|
||||
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
|
||||
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
|
||||
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
|
||||
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
|
||||
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
|
||||
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
|
||||
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
|
||||
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
|
||||
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
|
||||
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
|
||||
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
|
||||
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
|
||||
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
|
||||
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
|
||||
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
|
||||
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
|
||||
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
|
||||
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
|
||||
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
|
||||
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
|
||||
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:3c5493ece8268fecdcdc9c0b112211acd006354723b280d643ec732b6d4063d6",
|
||||
"sha256:f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
|
||||
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.8.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Flask==1.0.2
|
||||
12
packages/python/test/fixtures/20-multivalue-header/Pipfile
vendored
Normal file
12
packages/python/test/fixtures/20-multivalue-header/Pipfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
flask = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
123
packages/python/test/fixtures/20-multivalue-header/Pipfile.lock
generated
vendored
Normal file
123
packages/python/test/fixtures/20-multivalue-header/Pipfile.lock
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "f7f1cea682a03d85328caf2f88382c4380283d3892a9ba31b374784fb29536c4"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e",
|
||||
"sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.2"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264",
|
||||
"sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6",
|
||||
"sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"
|
||||
],
|
||||
"markers": "python_version < '3.10'",
|
||||
"version": "==4.11.3"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
|
||||
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119",
|
||||
"sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
|
||||
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
|
||||
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
|
||||
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
|
||||
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
|
||||
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
|
||||
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
|
||||
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
|
||||
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
|
||||
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
|
||||
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
|
||||
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
|
||||
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
|
||||
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
|
||||
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
|
||||
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
|
||||
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
|
||||
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
|
||||
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
|
||||
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
|
||||
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
|
||||
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
|
||||
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
|
||||
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
|
||||
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
|
||||
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
|
||||
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
|
||||
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
|
||||
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
|
||||
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
|
||||
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
|
||||
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
|
||||
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
|
||||
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
|
||||
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
|
||||
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
|
||||
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
|
||||
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
|
||||
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
|
||||
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:3c5493ece8268fecdcdc9c0b112211acd006354723b280d643ec732b6d4063d6",
|
||||
"sha256:f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad",
|
||||
"sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.8.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Flask==1.0.2
|
||||
@@ -16,7 +16,7 @@ __vc_variables = dir(__vc_module)
|
||||
def format_headers(headers, decode=False):
|
||||
keyToList = {}
|
||||
for key, value in headers.items():
|
||||
if decode:
|
||||
if decode and 'decode' in dir(key) and 'decode' in dir(value):
|
||||
key = key.decode()
|
||||
value = value.decode()
|
||||
if key not in keyToList:
|
||||
@@ -102,7 +102,7 @@ elif 'app' in __vc_variables:
|
||||
if isinstance(s, str):
|
||||
s = s.encode(charset)
|
||||
return s.decode("latin1", errors)
|
||||
|
||||
|
||||
def vc_handler(event, context):
|
||||
payload = json.loads(event['body'])
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/redwood",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1-canary.3",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -18,7 +18,7 @@
|
||||
"prepublishOnly": "node build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.17.5",
|
||||
"@vercel/nft": "0.18.1",
|
||||
"@vercel/routing-utils": "1.13.1",
|
||||
"semver": "6.1.1"
|
||||
},
|
||||
@@ -26,6 +26,6 @@
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/node": "*",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "2.15.1"
|
||||
"@vercel/build-utils": "2.15.2-canary.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,10 +105,7 @@ export const build: BuildV2 = async ({
|
||||
console.log(`Skipping "install" command...`);
|
||||
}
|
||||
} else {
|
||||
console.log('Installing dependencies...');
|
||||
const installTime = Date.now();
|
||||
await runNpmInstall(entrypointFsDirname, [], spawnOpts, meta, nodeVersion);
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
}
|
||||
|
||||
if (meta.isDev) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@vercel/ruby",
|
||||
"author": "Nathan Cahill <nathan@nathancahill.com>",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.3-canary.3",
|
||||
"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.15.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "2.0.4",
|
||||
"fs-extra": "^7.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "0.23.1",
|
||||
"version": "0.23.2-canary.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/build-step",
|
||||
@@ -14,18 +14,29 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build",
|
||||
"test-unit": "jest --env node --verbose --runInBand --bail test/unit.test.js",
|
||||
"test-unit": "jest --env node --verbose --bail test/build.test.ts test/prepare-cache.test.ts",
|
||||
"test-integration-once": "jest --env node --verbose --runInBand --bail test/integration.test.js",
|
||||
"prepublishOnly": "node build"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest/presets/default",
|
||||
"testEnvironment": "node",
|
||||
"globals": {
|
||||
"ts-jest": {
|
||||
"diagnostics": true,
|
||||
"isolatedModules": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.64",
|
||||
"@types/cross-spawn": "6.0.0",
|
||||
"@types/jest": "27.4.1",
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node-fetch": "2.5.4",
|
||||
"@types/promise-timeout": "1.3.0",
|
||||
"@vercel/build-utils": "2.15.1",
|
||||
"@vercel/frameworks": "0.7.1",
|
||||
"@vercel/build-utils": "2.15.2-canary.3",
|
||||
"@vercel/frameworks": "0.7.2-canary.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/routing-utils": "1.13.1",
|
||||
"get-port": "5.0.0",
|
||||
|
||||
@@ -4,7 +4,7 @@ import fetch from 'node-fetch';
|
||||
import getPort from 'get-port';
|
||||
import isPortReachable from 'is-port-reachable';
|
||||
import frameworks, { Framework } from '@vercel/frameworks';
|
||||
import { ChildProcess, SpawnOptions } from 'child_process';
|
||||
import type { ChildProcess, SpawnOptions } from 'child_process';
|
||||
import { existsSync, readFileSync, statSync, readdirSync } from 'fs';
|
||||
import { cpus } from 'os';
|
||||
import {
|
||||
@@ -30,14 +30,12 @@ import {
|
||||
NowBuildError,
|
||||
scanParentDirs,
|
||||
} from '@vercel/build-utils';
|
||||
import { Route, Source } from '@vercel/routing-utils';
|
||||
import {
|
||||
readBuildOutputDirectory,
|
||||
readBuildOutputConfig,
|
||||
} from './utils/read-build-output';
|
||||
import type { Route, Source } from '@vercel/routing-utils';
|
||||
import * as BuildOutputV1 from './utils/build-output-v1';
|
||||
import * as BuildOutputV3 from './utils/build-output-v3';
|
||||
import * as GatsbyUtils from './utils/gatsby';
|
||||
import * as NuxtUtils from './utils/nuxt';
|
||||
import { ImagesConfig, BuildConfig } from './utils/_shared';
|
||||
import type { ImagesConfig, BuildConfig } from './utils/_shared';
|
||||
|
||||
const sleep = (n: number) => new Promise(resolve => setTimeout(resolve, n));
|
||||
|
||||
@@ -212,7 +210,7 @@ function getPkg(entrypoint: string, workPath: string) {
|
||||
|
||||
try {
|
||||
const pkgPath = path.join(workPath, entrypoint);
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as PackageJson;
|
||||
const pkg: PackageJson = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
||||
return pkg;
|
||||
} catch (err: any) {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
@@ -255,7 +253,7 @@ async function fetchBinary(url: string, framework: string, version: string) {
|
||||
throw new NowBuildError({
|
||||
code: 'STATIC_BUILD_BINARY_NOT_FOUND',
|
||||
message: `Version ${version} of ${framework} does not exist. Please specify a different one.`,
|
||||
link: 'https://vercel.com/docs/v2/build-step#framework-versioning',
|
||||
link: 'https://vercel.link/framework-versioning',
|
||||
});
|
||||
}
|
||||
await spawnAsync(`curl -sSL ${url} | tar -zx -C /usr/local/bin`, [], {
|
||||
@@ -278,17 +276,12 @@ export const build: BuildV2 = async ({
|
||||
let distPath = path.join(
|
||||
workPath,
|
||||
path.dirname(entrypoint),
|
||||
(config && (config.distDir as string)) ||
|
||||
(config.outputDirectory as string) ||
|
||||
'dist'
|
||||
(config.distDir as string) || config.outputDirectory || 'dist'
|
||||
);
|
||||
|
||||
const pkg = getPkg(entrypoint, workPath);
|
||||
|
||||
const devScript = pkg ? getScriptName(pkg, 'dev', config) : null;
|
||||
|
||||
const framework = getFramework(config, pkg);
|
||||
|
||||
const devCommand = getCommand('dev', pkg, config, framework);
|
||||
const buildCommand = getCommand('build', pkg, config, framework);
|
||||
const installCommand = getCommand('install', pkg, config, framework);
|
||||
@@ -331,7 +324,7 @@ export const build: BuildV2 = async ({
|
||||
distPath = path.join(
|
||||
workPath,
|
||||
path.dirname(entrypoint),
|
||||
(config.outputDirectory as string) || 'public'
|
||||
config.outputDirectory || 'public'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -387,12 +380,12 @@ export const build: BuildV2 = async ({
|
||||
Node.js will load 'false' as a string, not a boolean, so it's truthy still.
|
||||
This is to ensure we don't accidentally break other packages that check
|
||||
if process.env.CI is true somewhere.
|
||||
|
||||
|
||||
https://github.com/facebook/create-react-app/issues/2453
|
||||
https://github.com/facebook/create-react-app/pull/2501
|
||||
https://github.com/vercel/community/discussions/30
|
||||
*/
|
||||
if (framework && framework.slug === 'create-react-app') {
|
||||
if (framework?.slug === 'create-react-app') {
|
||||
if (!spawnOpts.env) {
|
||||
spawnOpts.env = {};
|
||||
}
|
||||
@@ -412,10 +405,7 @@ export const build: BuildV2 = async ({
|
||||
|
||||
if (!config.zeroConfig) {
|
||||
debug('Detected "builds" - not zero config');
|
||||
printInstall();
|
||||
const installTime = Date.now();
|
||||
await runNpmInstall(entrypointDir, [], spawnOpts, meta, nodeVersion);
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
isNpmInstall = true;
|
||||
} else if (typeof installCommand === 'string') {
|
||||
if (installCommand.trim()) {
|
||||
@@ -487,11 +477,7 @@ export const build: BuildV2 = async ({
|
||||
isPipInstall = true;
|
||||
}
|
||||
if (pkg) {
|
||||
console.log('Detected package.json');
|
||||
printInstall();
|
||||
const installTime = Date.now();
|
||||
await runNpmInstall(entrypointDir, [], spawnOpts, meta, nodeVersion);
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
isNpmInstall = true;
|
||||
}
|
||||
}
|
||||
@@ -637,6 +623,30 @@ export const build: BuildV2 = async ({
|
||||
|
||||
const outputDirPrefix = path.join(workPath, path.dirname(entrypoint));
|
||||
|
||||
// If the Build Command or Framework output files according to the
|
||||
// Build Output v3 API, then stop processing here in `static-build`
|
||||
// since the output is already in its final form.
|
||||
const buildOutputPath = await BuildOutputV3.getBuildOutputDirectory(
|
||||
outputDirPrefix
|
||||
);
|
||||
|
||||
if (buildOutputPath) {
|
||||
// Ensure that `vercel build` is being used for this Deployment
|
||||
if (!meta.cliVersion) {
|
||||
let buildCommandName: string;
|
||||
if (buildCommand) buildCommandName = `"${buildCommand}"`;
|
||||
else if (framework) buildCommandName = framework.name;
|
||||
else buildCommandName = 'the "build" script';
|
||||
throw new Error(
|
||||
`Detected Build Output v3 from ${buildCommandName}, but this Deployment is not using \`vercel build\`.\nPlease set the \`ENABLE_VC_BUILD=1\` environment variable.`
|
||||
);
|
||||
}
|
||||
return {
|
||||
buildOutputVersion: 3,
|
||||
buildOutputPath,
|
||||
};
|
||||
}
|
||||
|
||||
if (framework) {
|
||||
const outputDirName = config.outputDirectory
|
||||
? config.outputDirectory
|
||||
@@ -656,7 +666,7 @@ export const build: BuildV2 = async ({
|
||||
}
|
||||
}
|
||||
|
||||
const extraOutputs = await readBuildOutputDirectory({
|
||||
const extraOutputs = await BuildOutputV1.readBuildOutputDirectory({
|
||||
workPath,
|
||||
nodeVersion,
|
||||
});
|
||||
@@ -749,13 +759,22 @@ export const prepareCache: PrepareCache = async ({
|
||||
}) => {
|
||||
const cacheFiles: Files = {};
|
||||
|
||||
// Build Output API v3 cache files
|
||||
const configV3 = await BuildOutputV3.readConfig(workPath);
|
||||
if (configV3?.cache && Array.isArray(configV3.cache)) {
|
||||
for (const cacheGlob of configV3.cache) {
|
||||
Object.assign(cacheFiles, await glob(cacheGlob, workPath));
|
||||
}
|
||||
return cacheFiles;
|
||||
}
|
||||
|
||||
// File System API v1 cache files
|
||||
const buildConfig = await readBuildOutputConfig<BuildConfig>({
|
||||
const buildConfigV1 = await BuildOutputV1.readBuildOutputConfig<BuildConfig>({
|
||||
workPath,
|
||||
configFileName: 'build.json',
|
||||
});
|
||||
if (buildConfig?.cache && Array.isArray(buildConfig.cache)) {
|
||||
for (const cacheGlob of buildConfig.cache) {
|
||||
if (buildConfigV1?.cache && Array.isArray(buildConfigV1.cache)) {
|
||||
for (const cacheGlob of buildConfigV1.cache) {
|
||||
Object.assign(cacheFiles, await glob(cacheGlob, workPath));
|
||||
}
|
||||
return cacheFiles;
|
||||
|
||||
36
packages/static-build/src/utils/build-output-v3.ts
Normal file
36
packages/static-build/src/utils/build-output-v3.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { join } from 'path';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
const BUILD_OUTPUT_DIR = '.vercel/output';
|
||||
|
||||
/**
|
||||
* Returns the path to the Build Output v3 directory when the
|
||||
* `config.json` file was created by the framework / build script,
|
||||
* or `undefined` if the framework did not create the v3 output.
|
||||
*/
|
||||
export async function getBuildOutputDirectory(
|
||||
path: string
|
||||
): Promise<string | undefined> {
|
||||
try {
|
||||
const outputDir = join(path, BUILD_OUTPUT_DIR);
|
||||
const configPath = join(outputDir, 'config.json');
|
||||
await fs.stat(configPath);
|
||||
return outputDir;
|
||||
} catch (err: any) {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function readConfig(
|
||||
path: string
|
||||
): Promise<{ cache?: string[] } | undefined> {
|
||||
try {
|
||||
const outputDir = join(path, BUILD_OUTPUT_DIR);
|
||||
const configPath = join(outputDir, 'config.json');
|
||||
return JSON.parse(await fs.readFile(configPath, 'utf8'));
|
||||
} catch (err: any) {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -30,9 +30,7 @@ export async function injectVercelAnalyticsPlugin(dir: string) {
|
||||
`Injecting Gatsby.js analytics plugin "${gatsbyPluginPackageName}" to \`${gatsbyConfigPath}\``
|
||||
);
|
||||
|
||||
const pkgJson: DeepWriteable<PackageJson> = (await readPackageJson(
|
||||
dir
|
||||
)) as DeepWriteable<PackageJson>;
|
||||
const pkgJson = (await readPackageJson(dir)) as DeepWriteable<PackageJson>;
|
||||
if (!pkgJson.dependencies) {
|
||||
pkgJson.dependencies = {};
|
||||
}
|
||||
|
||||
7
packages/static-build/test/build-fixtures/09-build-output-v3/build.js
Executable file
7
packages/static-build/test/build-fixtures/09-build-output-v3/build.js
Executable file
@@ -0,0 +1,7 @@
|
||||
const fs = require('fs');
|
||||
fs.mkdirSync('.vercel/output/static', { recursive: true });
|
||||
fs.writeFileSync('.vercel/output/config.json', '{}');
|
||||
fs.writeFileSync(
|
||||
'.vercel/output/static/index.html',
|
||||
'<h1>Build Output API</h1>'
|
||||
);
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "09-build-output-v3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node build.js"
|
||||
}
|
||||
}
|
||||
54
packages/static-build/test/build.test.ts
vendored
Normal file
54
packages/static-build/test/build.test.ts
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import path from 'path';
|
||||
import { build } from '../src';
|
||||
|
||||
describe('build()', () => {
|
||||
it('should detect Builder Output v3', async () => {
|
||||
const workPath = path.join(
|
||||
__dirname,
|
||||
'build-fixtures',
|
||||
'09-build-output-v3'
|
||||
);
|
||||
const buildResult = await build({
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
workPath,
|
||||
config: {},
|
||||
meta: {
|
||||
skipDownload: true,
|
||||
cliVersion: '0.0.0',
|
||||
},
|
||||
});
|
||||
if ('output' in buildResult) {
|
||||
throw new Error('Unexpected `output` in build result');
|
||||
}
|
||||
expect(buildResult.buildOutputVersion).toEqual(3);
|
||||
expect(buildResult.buildOutputPath).toEqual(
|
||||
path.join(workPath, '.vercel/output')
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an Error with Builder Output v3 without `vercel build`', async () => {
|
||||
let err;
|
||||
const workPath = path.join(
|
||||
__dirname,
|
||||
'build-fixtures',
|
||||
'09-build-output-v3'
|
||||
);
|
||||
try {
|
||||
await build({
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
workPath,
|
||||
config: {},
|
||||
meta: {
|
||||
skipDownload: true,
|
||||
},
|
||||
});
|
||||
} catch (_err: any) {
|
||||
err = _err;
|
||||
}
|
||||
expect(err.message).toEqual(
|
||||
`Detected Build Output v3 from the "build" script, but this Deployment is not using \`vercel build\`.\nPlease set the \`ENABLE_VC_BUILD=1\` environment variable.`
|
||||
);
|
||||
});
|
||||
});
|
||||
1
packages/static-build/test/cache-fixtures/build-output-api-v3/.gitignore
vendored
Normal file
1
packages/static-build/test/cache-fixtures/build-output-api-v3/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!.vercel
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cache": ["some-dir/**", "another.txt"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
another
|
||||
@@ -0,0 +1 @@
|
||||
File that shouldn't be cached
|
||||
@@ -0,0 +1 @@
|
||||
one
|
||||
@@ -0,0 +1 @@
|
||||
two
|
||||
@@ -1,12 +1,13 @@
|
||||
const { prepareCache } = require('../dist');
|
||||
const path = require('path');
|
||||
import path from 'path';
|
||||
import { prepareCache } from '../src';
|
||||
|
||||
describe('prepareCache', () => {
|
||||
describe('prepareCache()', () => {
|
||||
test('should cache node_modules and .shadow-cljs', async () => {
|
||||
const files = await prepareCache({
|
||||
config: { zeroConfig: true },
|
||||
workPath: path.resolve(__dirname, './cache-fixtures/default'),
|
||||
entrypoint: 'index.js',
|
||||
files: {},
|
||||
});
|
||||
|
||||
expect(files['node_modules/file']).toBeDefined();
|
||||
@@ -19,6 +20,7 @@ describe('prepareCache', () => {
|
||||
config: { zeroConfig: true },
|
||||
workPath: path.resolve(__dirname, './cache-fixtures/withCacheConfig'),
|
||||
entrypoint: 'index.js',
|
||||
files: {},
|
||||
});
|
||||
|
||||
expect(files['node_modules/file']).toBeUndefined();
|
||||
@@ -32,6 +34,7 @@ describe('prepareCache', () => {
|
||||
config: { zeroConfig: true },
|
||||
workPath: path.resolve(__dirname, './cache-fixtures/gatsby'),
|
||||
entrypoint: 'package.json',
|
||||
files: {},
|
||||
});
|
||||
|
||||
expect(files['node_modules/file2']).toBeDefined();
|
||||
@@ -45,6 +48,7 @@ describe('prepareCache', () => {
|
||||
config: { zeroConfig: true, framework: 'jekyll' },
|
||||
workPath: path.resolve(__dirname, './cache-fixtures/jekyll'),
|
||||
entrypoint: 'Gemfile',
|
||||
files: {},
|
||||
});
|
||||
|
||||
expect(files['vendor/bundle/b1']).toBeDefined();
|
||||
@@ -55,4 +59,18 @@ describe('prepareCache', () => {
|
||||
expect(files['_config.yml']).toBeUndefined();
|
||||
expect(files['_posts/hello.markdown']).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should cache Build Output API v3 "cache" assets from `config.json` file', async () => {
|
||||
const files = await prepareCache({
|
||||
config: {},
|
||||
workPath: path.resolve(__dirname, './cache-fixtures/build-output-api-v3'),
|
||||
entrypoint: 'package.json',
|
||||
files: {},
|
||||
});
|
||||
expect(Object.keys(files).sort()).toStrictEqual([
|
||||
'another.txt',
|
||||
'some-dir/one.txt',
|
||||
'some-dir/two.txt',
|
||||
]);
|
||||
});
|
||||
});
|
||||
4
packages/static-build/test/tsconfig.json
vendored
Normal file
4
packages/static-build/test/tsconfig.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"include": ["*.test.ts"]
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"outDir": "dist",
|
||||
"types": ["node"],
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "es2018"
|
||||
},
|
||||
|
||||
9
turbo.json
Normal file
9
turbo.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"baseBranch": "origin/main",
|
||||
"pipeline": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
203
yarn.lock
203
yarn.lock
@@ -2,6 +2,11 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@alex_neo/jest-expect-message@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz#bdc96f5764cb42ab677941c1ac86b2e4bea96fa7"
|
||||
integrity sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==
|
||||
|
||||
"@ava/babel-plugin-throws-helper@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-3.0.0.tgz#2c933ec22da0c4ce1fc5369f2b95452c70420586"
|
||||
@@ -2164,6 +2169,21 @@
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest-expect-message@1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest-expect-message/-/jest-expect-message-1.0.3.tgz#433ad89565c871acefafedeb957d0a8ec2a977a0"
|
||||
integrity sha512-sp70Lc8POkOcXHEcLERpX/7B/BtQiqIYz3AvC9ZMNKSaiDttr8hKvz9DljIn7N6WJi3ioVoTtB1utDAX46oPlg==
|
||||
dependencies:
|
||||
"@types/jest" "*"
|
||||
|
||||
"@types/jest@*":
|
||||
version "27.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||
dependencies:
|
||||
jest-matcher-utils "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/jest@27.0.1":
|
||||
version "27.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca"
|
||||
@@ -2180,6 +2200,14 @@
|
||||
jest-diff "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/jest@27.4.1":
|
||||
version "27.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||
dependencies:
|
||||
jest-matcher-utils "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/js-yaml@3.12.1":
|
||||
version "3.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
|
||||
@@ -2560,10 +2588,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
|
||||
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
|
||||
|
||||
"@vercel/nft@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.17.5.tgz#eab288a3786b8bd6fc08c0ef0b70d162984d1643"
|
||||
integrity sha512-6n4uXmfkcHAmkI4rJlwFJb8yvWuH6uDOi5qme0yGC1B/KmWJ66dERupdAj9uj7eEmgM7N3bKNY5zOYE7cKZE1g==
|
||||
"@vercel/nft@0.18.1":
|
||||
version "0.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.18.1.tgz#d1681f7fd538168553d8df19fc3761ca643ebb73"
|
||||
integrity sha512-i2zmXs8ueqCe/dmQ0fzQk9MmXoqdqxR1ZsxPN8poHZfc3NQES1WTEsXkEoaL+RV5BKZi04lNpkoGwtqcxERAOQ==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.5"
|
||||
acorn "^8.6.0"
|
||||
@@ -4677,6 +4705,11 @@ diff-sequences@^27.0.6:
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723"
|
||||
integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==
|
||||
|
||||
diff-sequences@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
|
||||
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
@@ -7160,6 +7193,16 @@ jest-diff@^27.3.1:
|
||||
jest-get-type "^27.3.1"
|
||||
pretty-format "^27.3.1"
|
||||
|
||||
jest-diff@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
|
||||
integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
diff-sequences "^27.5.1"
|
||||
jest-get-type "^27.5.1"
|
||||
pretty-format "^27.5.1"
|
||||
|
||||
jest-docblock@^27.0.6:
|
||||
version "27.0.6"
|
||||
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3"
|
||||
@@ -7213,6 +7256,11 @@ jest-get-type@^27.3.1:
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.3.1.tgz#a8a2b0a12b50169773099eee60a0e6dd11423eff"
|
||||
integrity sha512-+Ilqi8hgHSAdhlQ3s12CAVNd8H96ZkQBfYoXmArzZnOfAtVAJEiPDBirjByEblvG/4LPJmkL+nBqPO3A1YJAEg==
|
||||
|
||||
jest-get-type@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
|
||||
integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
|
||||
|
||||
jest-haste-map@^27.3.1:
|
||||
version "27.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.3.1.tgz#7656fbd64bf48bda904e759fc9d93e2c807353ee"
|
||||
@@ -7265,6 +7313,16 @@ jest-leak-detector@^27.3.1:
|
||||
jest-get-type "^27.3.1"
|
||||
pretty-format "^27.3.1"
|
||||
|
||||
jest-matcher-utils@^27.0.0:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
|
||||
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
jest-diff "^27.5.1"
|
||||
jest-get-type "^27.5.1"
|
||||
pretty-format "^27.5.1"
|
||||
|
||||
jest-matcher-utils@^27.3.1:
|
||||
version "27.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.3.1.tgz#257ad61e54a6d4044e080d85dbdc4a08811e9c1c"
|
||||
@@ -9540,6 +9598,15 @@ pretty-format@^27.3.1:
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
pretty-format@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
|
||||
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
pretty-ms@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-5.1.0.tgz#b906bdd1ec9e9799995c372e2b1c34f073f95384"
|
||||
@@ -11419,83 +11486,83 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
turbo-darwin-64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.1.9.tgz#5c642fec610d26d7acb7bbe51020804e1ff9bc73"
|
||||
integrity sha512-DAeQkBXvIVMwdlT/OvJYKNbhijUJQr4ug/sLJpNMEMPVW2Fs1aVZpr+ea4W+Xo90nOk+Ac0oCbv4nx3v8UZ1iQ==
|
||||
turbo-darwin-64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.2.2.tgz#001151b708207141fe17371004b0871ca048dedb"
|
||||
integrity sha512-2hidknFGrm2OzTcE0FBcvPIb2oewrnq4WbOOuVj+9e19rBVIs5BdN4LLvxihIxQelQdZXiPvSTVGLvvg8+mSpg==
|
||||
|
||||
turbo-darwin-arm64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.1.9.tgz#c3a7ad58d39af375fab6b944558da29cd2ac0e01"
|
||||
integrity sha512-15WTOOngcUALX1Pso6tG/vot8ksi1l5/Sljv4sXjfpFup9Xkc2m6AE6QlKllextL10SD4x52K2z01ClV7YIKEQ==
|
||||
turbo-darwin-arm64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.2.2.tgz#b392a013338e946b6973240fe7e6e66751bd86fa"
|
||||
integrity sha512-R+7TAOdTSTDHZJoFVtL24GKUuWD4v+0qUcq8KzkLyAd7AeaPssTpwN+Tc0Nj/46RStf1PryBflu0J8ovi7SWbQ==
|
||||
|
||||
turbo-freebsd-64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.1.9.tgz#88bf9eff412f6277e75cec6aadbb554c78a469f0"
|
||||
integrity sha512-DqDt4o79guYef7MlYQChHMOMxJNbvE+SVuBP0+CxG4WreSUnsT+D4+/+KBs9e/o2p1xHRoDOtuKbDai8tWgKaQ==
|
||||
turbo-freebsd-64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.2.2.tgz#ef2e1da981f6b5f0485cc6c07fbd5385a621cf47"
|
||||
integrity sha512-EviJUMNfw9qah3Ko8Aow0qrglJ/qGadsv8LHfTuRL8SNix4cx3s2eEAkQ82kQey1eWjtfB6XSf4JTr5EzHko8w==
|
||||
|
||||
turbo-freebsd-arm64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.1.9.tgz#a2bf29386b0bcf5ee43ce5a1cbf39e3d0550d7a0"
|
||||
integrity sha512-tiudLNRsOmmWD9guqWEoW63x3F0YKtkQis0DRrFqJBVcnMDfKYtMWIr6kP7DhK9PxKwnJY4Y1WIawXPIWl66EQ==
|
||||
turbo-freebsd-arm64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.2.2.tgz#52f0d30a9ce43ef0200c848c32b52c1e53abb39e"
|
||||
integrity sha512-enz9o3qJq7SwD8pNU1EIcRIZaymNWih/SYQyrTnkD88kLcTS3LKsoenv8Jy2G0w4rCgoBsBLHLpepzRttGaxwQ==
|
||||
|
||||
turbo-linux-32@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.1.9.tgz#6fae00fffc171ebf990b28f9e1635da8800bc3ef"
|
||||
integrity sha512-u0VI41gqxRqGR41+nVmWvNZ6d2AS/KYfrfDeFbw8mRVsuAR2OP6emsbt7cUN++0ZzH9qsRgGcBR/k2Ge/EEx5g==
|
||||
turbo-linux-32@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.2.2.tgz#cabbd7991df856441cc15b34ae646446c435d480"
|
||||
integrity sha512-JyuJnFVT2u2wrvd3a5VpHigoKPJnGuNwGDnYYh6hJLpQLDk0mCRcdtViKInryPIQjbiq1oZYefYJfpPnU4MgtA==
|
||||
|
||||
turbo-linux-64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.1.9.tgz#3d608908c2e5dfab18316a07427dd5f4369b8eab"
|
||||
integrity sha512-BU3ulyNivyrDwGVA2NnMcqUH9o4njk59DgantoF7rRSWNeyt5abneOG7CVAdaAy03JIc1gzErjVV+QSQ25H9ug==
|
||||
turbo-linux-64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.2.2.tgz#11a1c9d765502ca84419ab073eec95d846a5205c"
|
||||
integrity sha512-UT7SiMcN+4fyVcM7Y/p11qdypNmCUkY6zqyEGpC6G3HLZHeNt3z+nq0FZDDPiMskEP0WUbLAv1sICUKvHC4wPA==
|
||||
|
||||
turbo-linux-arm64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.1.9.tgz#7b7350c155c1ec3cea6be00840837ca020a8bcca"
|
||||
integrity sha512-bVD+8n8qDDlZxG6Z8rn58m50BjczIV4zCgjDQDIN2E6H9FjWuLOpKXk3mdTgM31w1Om8HYZgkbvla/jQSwWHrQ==
|
||||
turbo-linux-arm64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.2.2.tgz#cc283cf69715366a6aeb4ab3e51df81af1eaa479"
|
||||
integrity sha512-RG/cXgrjLKowLYuYd5I7W0KS+RKoCpu6UI2YiIXShG8UGVHpGhKb1duJ2GC5gptYVWIJC3q1jqNgr5a93W+Rfw==
|
||||
|
||||
turbo-linux-arm@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.1.9.tgz#6f71462f3e3becf73cd1e2ded0936260b531075e"
|
||||
integrity sha512-sAI2BqkipyvH6fQhhnOGhY9C9z9AMUdTizOm0Luj6gmEMZhUmjfk5K8BsX3uKzY6cWx5+twaTPXFd1EGV/o7Pg==
|
||||
turbo-linux-arm@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.2.2.tgz#7b3ef11685f80185490702dfc1cbd0d0c3dad998"
|
||||
integrity sha512-HZPZG2eU1D+iHu7OvIIsMu2retLvERKgqAPb4mJ4R/xynXO0FUd07uUEJWU881ZH11mKPFWDwVfI4gjW95UuRg==
|
||||
|
||||
turbo-linux-mips64le@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.1.9.tgz#a3e08850bdf022720bef5b9d5d8a3111ba65851d"
|
||||
integrity sha512-/34pGwWKRes3FYAUpZn+s8rKIbi76ZHuGxvXWx7clIfmLwNw1dN04c7cXU/t2PwDv4CzsGkqPgVNMGitnLxeUQ==
|
||||
turbo-linux-mips64le@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.2.2.tgz#0c4081206c0ca559c0c46f4c6959c7144202ccd2"
|
||||
integrity sha512-r7M0e7AFBa8xBkifqsFfW3F+FLQanJkK4NiaSi2Y9IUgI1v4JEw6o6HKRGtUZ8wRRxGKY/4t8NyzzUH8a+PBXA==
|
||||
|
||||
turbo-linux-ppc64le@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.1.9.tgz#fd8740b87bbabcd363268040bdae6a9643d77b2a"
|
||||
integrity sha512-5yR59wLf+HTV2Zb7ycPHXloTgYql22F4lhL6H7cWBVmbDFzrWR3N1d/sPaNLHtaDEE4l6UtTOFd/WQCfPDq/Hw==
|
||||
turbo-linux-ppc64le@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.2.2.tgz#e3b94a009eb8189c26b72f146920d2c146966363"
|
||||
integrity sha512-NY96rIJxKHqQgUkvLYQCwSsXeUkkcUFmKyRqrBlsVP0BZO3CbNvLgt+EPKy1+/RLAI7wwdes9B57GoezLyZezQ==
|
||||
|
||||
turbo-windows-32@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.1.9.tgz#ddfd8c83cbd6693e89df6fe099ae3ba2b34c4b8f"
|
||||
integrity sha512-dVwjFWg/SsW+pVk1iOnfovXSzsMsIgiEQvkAEnN3+XNEkjtYhLQ73bntZhP/mO4IKpDEkPoBcOlV/092uwadOg==
|
||||
turbo-windows-32@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.2.2.tgz#0c889f0fb85a192e1a29922313e0b141da24f5da"
|
||||
integrity sha512-IQYdaKqP7BxSGyU3iFNO/wKuJ17NwHPExACJiYZmua1pxM4wkeNcUCmb1u5zuJ2QbPB/+m4iGnDgitAdxUmdLw==
|
||||
|
||||
turbo-windows-64@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.1.9.tgz#2ed9fbad8ab5384ce14bd0e87f4fa2fd2117f3e0"
|
||||
integrity sha512-fzjO2D9lzhrBNjnuqaFTBpRU9DjYMhhgFgvD3ynwNWiBgm4wcer58DpRMDEzjq51Q+0HwFIrsKzEMyVK4Ubu/Q==
|
||||
turbo-windows-64@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.2.2.tgz#446d96ce8c015d380dfa4d805296cc4e3ce6c00d"
|
||||
integrity sha512-o7jF8cCzfhTZXvGySudi/Tx72Dqv6mce8Qq58jXWXEpbMV8KJwYuX2BMhIZilNZWyCk0IUqofVPMmampga6nfQ==
|
||||
|
||||
turbo@1.1.9:
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.1.9.tgz#cbff85b927558e4f7b731ee17b3739471dca0fae"
|
||||
integrity sha512-xFtKZ9EFEkENhRxn89RQWmgMKCnUvKWPwiOXz60ztp4HEKXAdOBgEmgCOhyn5osfgQYOiaOI6gBIjSf/UMorQQ==
|
||||
turbo@1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.2.2.tgz#27e9530cfa8457d2dae50c538073f6d8fcc2e78c"
|
||||
integrity sha512-gt+QuvZVAQVcrKhgSCDJObIdh12bpt4zWOPe0yiWD/zyRJjNzkiXxR6WKSuAEUl0uQIB4XrRn2OGTmrR7KROJw==
|
||||
optionalDependencies:
|
||||
turbo-darwin-64 "1.1.9"
|
||||
turbo-darwin-arm64 "1.1.9"
|
||||
turbo-freebsd-64 "1.1.9"
|
||||
turbo-freebsd-arm64 "1.1.9"
|
||||
turbo-linux-32 "1.1.9"
|
||||
turbo-linux-64 "1.1.9"
|
||||
turbo-linux-arm "1.1.9"
|
||||
turbo-linux-arm64 "1.1.9"
|
||||
turbo-linux-mips64le "1.1.9"
|
||||
turbo-linux-ppc64le "1.1.9"
|
||||
turbo-windows-32 "1.1.9"
|
||||
turbo-windows-64 "1.1.9"
|
||||
turbo-darwin-64 "1.2.2"
|
||||
turbo-darwin-arm64 "1.2.2"
|
||||
turbo-freebsd-64 "1.2.2"
|
||||
turbo-freebsd-arm64 "1.2.2"
|
||||
turbo-linux-32 "1.2.2"
|
||||
turbo-linux-64 "1.2.2"
|
||||
turbo-linux-arm "1.2.2"
|
||||
turbo-linux-arm64 "1.2.2"
|
||||
turbo-linux-mips64le "1.2.2"
|
||||
turbo-linux-ppc64le "1.2.2"
|
||||
turbo-windows-32 "1.2.2"
|
||||
turbo-windows-64 "1.2.2"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
|
||||
Reference in New Issue
Block a user