mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
14 Commits
@vercel/py
...
@vercel/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de0d2fba0b | ||
|
|
e0900128d6 | ||
|
|
8d15f30579 | ||
|
|
960c66584c | ||
|
|
1c8f91031a | ||
|
|
68cb23c3cc | ||
|
|
94f6ae2595 | ||
|
|
b92aeac84d | ||
|
|
00420b7a01 | ||
|
|
a5128790d0 | ||
|
|
ae9aa91f4f | ||
|
|
d4cef69cc9 | ||
|
|
323f67c31a | ||
|
|
63c499a826 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"target": "ES2020",
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
@@ -22,8 +22,5 @@
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"typescript": "^4.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "14.x"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"env": {
|
||||
"ENABLE_FILE_SYSTEM_API": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "3.1.1",
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"@types/node-fetch": "^2.1.6",
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/yazl": "2.4.2",
|
||||
"@vercel/frameworks": "1.0.0",
|
||||
"@vercel/frameworks": "1.0.1",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"aggregate-error": "3.0.1",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import Sema from 'async-sema';
|
||||
import spawn from 'cross-spawn';
|
||||
import { coerce, intersects, validRange } from 'semver';
|
||||
import { SpawnOptions } from 'child_process';
|
||||
import { deprecate } from 'util';
|
||||
import debug from '../debug';
|
||||
@@ -219,9 +220,9 @@ export async function getNodeVersion(
|
||||
config: Config = {},
|
||||
meta: Meta = {}
|
||||
): Promise<NodeVersion> {
|
||||
const latest = getLatestNodeVersion();
|
||||
if (meta && meta.isDev) {
|
||||
// Use the system-installed version of `node` in PATH for `vercel dev`
|
||||
const latest = getLatestNodeVersion();
|
||||
return { ...latest, runtime: 'nodejs' };
|
||||
}
|
||||
const { packageJson } = await scanParentDirs(destPath, true);
|
||||
@@ -229,10 +230,27 @@ export async function getNodeVersion(
|
||||
let isAuto = true;
|
||||
if (packageJson && packageJson.engines && packageJson.engines.node) {
|
||||
const { node } = packageJson.engines;
|
||||
if (nodeVersion && nodeVersion !== node && !meta.isDev) {
|
||||
if (
|
||||
nodeVersion &&
|
||||
validRange(node) &&
|
||||
!intersects(nodeVersion, node) &&
|
||||
!meta.isDev
|
||||
) {
|
||||
console.warn(
|
||||
`Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${nodeVersion}") will not apply. Learn More: http://vercel.link/node-version`
|
||||
);
|
||||
} else if (coerce(node)?.raw === node && !meta.isDev) {
|
||||
console.warn(
|
||||
`Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version`
|
||||
);
|
||||
} else if (
|
||||
validRange(node) &&
|
||||
intersects(`${latest.major + 1}.x`, node) &&
|
||||
!meta.isDev
|
||||
) {
|
||||
console.warn(
|
||||
`Warning: Detected "engines": { "node": "${node}" } in your \`package.json\` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version`
|
||||
);
|
||||
}
|
||||
nodeVersion = node;
|
||||
isAuto = false;
|
||||
|
||||
@@ -82,7 +82,7 @@ export interface BuildOptions {
|
||||
* is the Git Repository Root. This is only relevant for Monorepos.
|
||||
* See https://vercel.com/blog/monorepos
|
||||
*/
|
||||
repoRootPath?: string;
|
||||
repoRootPath: string;
|
||||
|
||||
/**
|
||||
* An arbitrary object passed by the user in the build definition defined
|
||||
@@ -123,7 +123,7 @@ export interface PrepareCacheOptions {
|
||||
* is the Git Repository Root. This is only relevant for Monorepos.
|
||||
* See https://vercel.com/blog/monorepos
|
||||
*/
|
||||
repoRootPath?: string;
|
||||
repoRootPath: string;
|
||||
|
||||
/**
|
||||
* An arbitrary object passed by the user in the build definition defined
|
||||
@@ -295,6 +295,7 @@ export interface PackageJson {
|
||||
readonly preferGlobal?: boolean;
|
||||
readonly private?: boolean;
|
||||
readonly publishConfig?: PackageJson.PublishConfig;
|
||||
readonly packageManager?: string;
|
||||
}
|
||||
|
||||
export interface NodeVersion {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.14.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
}
|
||||
48
packages/build-utils/test/unit.test.ts
vendored
48
packages/build-utils/test/unit.test.ts
vendored
@@ -277,7 +277,45 @@ it('should prefer package.json engines over project setting from config and warn
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when package.json engines is exact version', async () => {
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node-exact'),
|
||||
undefined,
|
||||
{},
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '16.x');
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Detected "engines": { "node": "16.14.0" } in your `package.json` with major.minor.patch, but only major Node.js Version can be selected. Learn More: http://vercel.link/node-version',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when package.json engines is greater than', async () => {
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node-greaterthan'),
|
||||
undefined,
|
||||
{},
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '16.x');
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Detected "engines": { "node": ">=16" } in your `package.json` that will automatically upgrade when a new major Node.js Version is released. Learn More: http://vercel.link/node-version',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not warn when package.json engines matches project setting from config', async () => {
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
undefined,
|
||||
{ nodeVersion: '14' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
@@ -287,6 +325,16 @@ it('should not warn when package.json engines matches project setting from confi
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node'),
|
||||
undefined,
|
||||
{ nodeVersion: '<15' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '14.x');
|
||||
expect(warningMessages).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('should get latest node version', async () => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,7 +13,7 @@
|
||||
"outDir": "./dist",
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "es2019"
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "24.2.5",
|
||||
"version": "25.0.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -30,7 +30,6 @@
|
||||
"scripts/preinstall.js"
|
||||
],
|
||||
"ava": {
|
||||
"compileEnhancements": false,
|
||||
"extensions": [
|
||||
"ts"
|
||||
],
|
||||
@@ -40,19 +39,19 @@
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
"node": ">= 14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/go": "1.4.4",
|
||||
"@vercel/next": "2.9.0",
|
||||
"@vercel/node": "1.15.4",
|
||||
"@vercel/python": "2.3.4",
|
||||
"@vercel/redwood": "0.8.4",
|
||||
"@vercel/remix": "0.0.2",
|
||||
"@vercel/ruby": "1.3.7",
|
||||
"@vercel/static-build": "0.26.0",
|
||||
"update-notifier": "4.1.0"
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/go": "2.0.0",
|
||||
"@vercel/next": "3.0.0",
|
||||
"@vercel/node": "2.0.0",
|
||||
"@vercel/python": "3.0.0",
|
||||
"@vercel/redwood": "1.0.0",
|
||||
"@vercel/remix": "1.0.0",
|
||||
"@vercel/ruby": "1.3.8",
|
||||
"@vercel/static-build": "1.0.0",
|
||||
"update-notifier": "5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@alex_neo/jest-expect-message": "1.0.5",
|
||||
@@ -95,8 +94,8 @@
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel/client": "11.0.4",
|
||||
"@vercel/frameworks": "1.0.0",
|
||||
"@vercel/client": "12.0.0",
|
||||
"@vercel/frameworks": "1.0.1",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@zeit/fun": "0.11.2",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
writeBuildResult,
|
||||
} from '../util/build/write-build-result';
|
||||
import { importBuilders, BuilderWithPkg } from '../util/build/import-builders';
|
||||
import { initCorepack, cleanupCorepack } from '../util/build/corepack';
|
||||
|
||||
type BuildResult = BuildResultV2 | BuildResultV3;
|
||||
|
||||
@@ -312,6 +313,10 @@ export default async function main(client: Client): Promise<number> {
|
||||
// TODO: parallelize builds
|
||||
const buildResults: Map<Builder, BuildResult> = new Map();
|
||||
const overrides: PathOverride[] = [];
|
||||
const repoRootPath = cwd;
|
||||
const rootPackageJsonPath = repoRootPath || workPath;
|
||||
const corepackShimDir = await initCorepack({ cwd, rootPackageJsonPath });
|
||||
|
||||
for (const build of builds) {
|
||||
if (typeof build.src !== 'string') continue;
|
||||
|
||||
@@ -331,7 +336,6 @@ export default async function main(client: Client): Promise<number> {
|
||||
framework: project.settings.framework,
|
||||
nodeVersion: project.settings.nodeVersion,
|
||||
};
|
||||
const repoRootPath = cwd === workPath ? undefined : cwd;
|
||||
const buildOptions: BuildOptions = {
|
||||
files: filesMap,
|
||||
entrypoint: build.src,
|
||||
@@ -366,6 +370,10 @@ export default async function main(client: Client): Promise<number> {
|
||||
);
|
||||
}
|
||||
|
||||
if (corepackShimDir) {
|
||||
cleanupCorepack(corepackShimDir);
|
||||
}
|
||||
|
||||
// Wait for filesystem operations to complete
|
||||
// TODO render progress bar?
|
||||
let hadError = false;
|
||||
|
||||
@@ -58,6 +58,7 @@ const isCanary = pkg.version.includes('canary');
|
||||
const notifier = updateNotifier({
|
||||
pkg,
|
||||
distTag: isCanary ? 'canary' : 'latest',
|
||||
updateCheckInterval: 1000 * 60 * 60 * 24 * 7, // 1 week
|
||||
});
|
||||
|
||||
const VERCEL_DIR = getGlobalPathConfig();
|
||||
|
||||
82
packages/cli/src/util/build/corepack.ts
Normal file
82
packages/cli/src/util/build/corepack.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { delimiter, join } from 'path';
|
||||
import { PackageJson, spawnAsync } from '@vercel/build-utils';
|
||||
import fs from 'fs-extra';
|
||||
import { CantParseJSONFile } from '../errors-ts';
|
||||
import { VERCEL_DIR } from '../projects/link';
|
||||
import readJSONFile from '../read-json-file';
|
||||
|
||||
export async function initCorepack({
|
||||
cwd,
|
||||
rootPackageJsonPath,
|
||||
}: {
|
||||
cwd: string;
|
||||
rootPackageJsonPath: string;
|
||||
}): Promise<string | null> {
|
||||
if (process.env.ENABLE_EXPERIMENTAL_COREPACK !== '1') {
|
||||
// Since corepack is experimental, we need to exit early
|
||||
// unless the user explicitly enables it with the env var.
|
||||
return null;
|
||||
}
|
||||
const pkg = await readJSONFile<PackageJson>(
|
||||
join(rootPackageJsonPath, 'package.json')
|
||||
);
|
||||
if (pkg instanceof CantParseJSONFile) {
|
||||
console.warn(
|
||||
'Warning: Could not enable corepack because package.json is invalid JSON'
|
||||
);
|
||||
} else if (!pkg?.packageManager) {
|
||||
console.warn(
|
||||
'Warning: Could not enable corepack because package.json is missing "packageManager" property'
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`Detected ENABLE_EXPERIMENTAL_COREPACK=1 and "${pkg.packageManager}" in package.json`
|
||||
);
|
||||
const corepackRootDir = join(cwd, VERCEL_DIR, 'cache', 'corepack');
|
||||
const corepackHomeDir = join(corepackRootDir, 'home');
|
||||
const corepackShimDir = join(corepackRootDir, 'shim');
|
||||
await fs.mkdirp(corepackHomeDir);
|
||||
await fs.mkdirp(corepackShimDir);
|
||||
process.env.COREPACK_HOME = corepackHomeDir;
|
||||
process.env.PATH = `${corepackShimDir}${delimiter}${process.env.PATH}`;
|
||||
process.env.DEBUG = process.env.DEBUG
|
||||
? `corepack,${process.env.DEBUG}`
|
||||
: 'corepack';
|
||||
const pkgManagerName = pkg.packageManager.split('@')[0];
|
||||
// We must explicitly call `corepack enable npm` since `corepack enable`
|
||||
// doesn't work with npm. See https://github.com/nodejs/corepack/pull/24
|
||||
// Also, `corepack enable` is too broad and will change the verison of
|
||||
// yarn & pnpm even though those versions are not specified by the user.
|
||||
// See https://github.com/nodejs/corepack#known-good-releases
|
||||
// Finally, we use `--install-directory` so we can cache the result to
|
||||
// reuse for subsequent builds. See `@vercel/vc-build` for `prepareCache`.
|
||||
await spawnAsync(
|
||||
'corepack',
|
||||
['enable', pkgManagerName, '--install-directory', corepackShimDir],
|
||||
{
|
||||
prettyCommand: `corepack enable ${pkgManagerName}`,
|
||||
}
|
||||
);
|
||||
return corepackShimDir;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function cleanupCorepack(corepackShimDir: string) {
|
||||
if (process.env.COREPACK_HOME) {
|
||||
delete process.env.COREPACK_HOME;
|
||||
}
|
||||
if (process.env.PATH) {
|
||||
process.env.PATH = process.env.PATH.replace(
|
||||
`${corepackShimDir}${delimiter}`,
|
||||
''
|
||||
);
|
||||
}
|
||||
if (process.env.DEBUG) {
|
||||
if (process.env.DEBUG === 'corepack') {
|
||||
delete process.env.DEBUG;
|
||||
} else {
|
||||
process.env.DEBUG = process.env.DEBUG.replace('corepack,', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,9 +106,10 @@ export async function resolveBuilders(
|
||||
// If `pkgPath` wasn't found in `.vercel/builders` then try as a CLI local
|
||||
// dependency. `require.resolve()` will throw if the Builder is not a CLI
|
||||
// dep, in which case we'll install it into `.vercel/builders`.
|
||||
pkgPath = require.resolve(`${name}/package.json`, {
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
pkgPath = eval('require').resolve(`${name}/package.json`, {
|
||||
paths: [__dirname],
|
||||
});
|
||||
}) as string;
|
||||
builderPkg = await readJSON(pkgPath);
|
||||
}
|
||||
|
||||
@@ -148,7 +149,9 @@ export async function resolveBuilders(
|
||||
// TODO: handle `parsed.type === 'tag'` ("latest" vs. anything else?)
|
||||
|
||||
const path = join(dirname(pkgPath), builderPkg.main || 'index.js');
|
||||
const builder = require(path);
|
||||
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
const builder = eval('require')(path);
|
||||
|
||||
builders.set(spec, {
|
||||
builder,
|
||||
|
||||
@@ -142,6 +142,7 @@ export async function executeBuild(
|
||||
files,
|
||||
entrypoint,
|
||||
workPath,
|
||||
repoRootPath: workPath,
|
||||
config,
|
||||
meta: {
|
||||
isDev: true,
|
||||
|
||||
@@ -1735,6 +1735,7 @@ export default class DevServer {
|
||||
entrypoint: match.entrypoint,
|
||||
workPath,
|
||||
config: match.config || {},
|
||||
repoRootPath: this.cwd,
|
||||
meta: {
|
||||
isDev: true,
|
||||
requestPath,
|
||||
|
||||
@@ -19,7 +19,7 @@ const getRevertAliasConfigFile = () => {
|
||||
],
|
||||
});
|
||||
};
|
||||
module.exports = async function prepare(session, binaryPath) {
|
||||
module.exports = async function prepare(session, binaryPath, tmpFixturesDir) {
|
||||
const spec = {
|
||||
'static-single-file': {
|
||||
'first.png': getImageFile(session, { size: 30 }),
|
||||
@@ -440,16 +440,58 @@ module.exports = async function prepare(session, binaryPath) {
|
||||
},
|
||||
}),
|
||||
},
|
||||
'vc-build-corepack-npm': {
|
||||
'.vercel/project.json': JSON.stringify({
|
||||
orgId: '.',
|
||||
projectId: '.',
|
||||
settings: {
|
||||
framework: null,
|
||||
},
|
||||
}),
|
||||
'package.json': JSON.stringify({
|
||||
private: true,
|
||||
packageManager: 'npm@8.1.0',
|
||||
scripts: {
|
||||
build: 'mkdir -p public && npm --version > public/index.txt',
|
||||
},
|
||||
}),
|
||||
},
|
||||
'vc-build-corepack-pnpm': {
|
||||
'.vercel/project.json': JSON.stringify({
|
||||
orgId: '.',
|
||||
projectId: '.',
|
||||
settings: {
|
||||
framework: null,
|
||||
},
|
||||
}),
|
||||
'package.json': JSON.stringify({
|
||||
private: true,
|
||||
packageManager: 'pnpm@7.1.0',
|
||||
scripts: {
|
||||
build: 'mkdir -p public && pnpm --version > public/index.txt',
|
||||
},
|
||||
}),
|
||||
},
|
||||
'vc-build-corepack-yarn': {
|
||||
'.vercel/project.json': JSON.stringify({
|
||||
orgId: '.',
|
||||
projectId: '.',
|
||||
settings: {
|
||||
framework: null,
|
||||
},
|
||||
}),
|
||||
'package.json': JSON.stringify({
|
||||
private: true,
|
||||
packageManager: 'yarn@2.4.3',
|
||||
scripts: {
|
||||
build: 'mkdir -p public && yarn --version > public/index.txt',
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
for (const [typeName, needed] of Object.entries(spec)) {
|
||||
const directory = join(
|
||||
__dirname,
|
||||
'..',
|
||||
'fixtures',
|
||||
'integration',
|
||||
typeName
|
||||
);
|
||||
const directory = join(tmpFixturesDir, typeName);
|
||||
|
||||
await mkdirp(directory);
|
||||
|
||||
|
||||
120
packages/cli/test/integration.js
vendored
120
packages/cli/test/integration.js
vendored
@@ -4,7 +4,7 @@ import { URL, parse as parseUrl } from 'url';
|
||||
import test from 'ava';
|
||||
import semVer from 'semver';
|
||||
import { Readable } from 'stream';
|
||||
import { homedir } from 'os';
|
||||
import { homedir, tmpdir } from 'os';
|
||||
import _execa from 'execa';
|
||||
import XDGAppPaths from 'xdg-app-paths';
|
||||
import fetch from 'node-fetch';
|
||||
@@ -31,7 +31,7 @@ function execa(file, args, options) {
|
||||
}
|
||||
|
||||
function fixture(name) {
|
||||
const directory = path.join(__dirname, 'fixtures', 'integration', name);
|
||||
const directory = path.join(tmpFixturesDir, name);
|
||||
const config = path.join(directory, 'project.json');
|
||||
|
||||
// We need to remove it, otherwise we can't re-use fixtures
|
||||
@@ -146,6 +146,7 @@ let email;
|
||||
let contextName;
|
||||
|
||||
let tmpDir;
|
||||
let tmpFixturesDir = path.join(tmpdir(), 'tmp-fixtures');
|
||||
|
||||
let globalDir = XDGAppPaths('com.vercel.cli').dataDirs()[0];
|
||||
|
||||
@@ -327,7 +328,7 @@ async function setupProject(process, projectName, overrides) {
|
||||
test.before(async () => {
|
||||
try {
|
||||
await createUser();
|
||||
await prepareFixtures(contextName, binaryPath);
|
||||
await prepareFixtures(contextName, binaryPath, tmpFixturesDir);
|
||||
} catch (err) {
|
||||
console.log('Failed `test.before`');
|
||||
console.log(err);
|
||||
@@ -335,6 +336,8 @@ test.before(async () => {
|
||||
});
|
||||
|
||||
test.after.always(async () => {
|
||||
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
|
||||
|
||||
if (loginApiServer) {
|
||||
// Stop mock server
|
||||
loginApiServer.close();
|
||||
@@ -349,6 +352,11 @@ test.after.always(async () => {
|
||||
// Remove config directory entirely
|
||||
tmpDir.removeCallback();
|
||||
}
|
||||
|
||||
if (tmpFixturesDir) {
|
||||
console.log('removing tmpFixturesDir', tmpFixturesDir);
|
||||
fs.removeSync(tmpFixturesDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('default command should prompt login with empty auth.json', async t => {
|
||||
@@ -390,6 +398,99 @@ test('login', async t => {
|
||||
t.is(auth.token, token);
|
||||
});
|
||||
|
||||
test('[vc build] should build project with corepack and select npm@8.1.0', async t => {
|
||||
process.env.ENABLE_EXPERIMENTAL_COREPACK = '1';
|
||||
const directory = fixture('vc-build-corepack-npm');
|
||||
const before = await _execa('npm', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
const output = await execute(['build'], { cwd: directory });
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
t.regex(output.stderr, /Build Completed/gm);
|
||||
const after = await _execa('npm', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
// Ensure global npm didn't change
|
||||
t.is(before.stdout, after.stdout);
|
||||
// Ensure version is correct
|
||||
t.is(
|
||||
await fs.readFile(
|
||||
path.join(directory, '.vercel/output/static/index.txt'),
|
||||
'utf8'
|
||||
),
|
||||
'8.1.0\n'
|
||||
);
|
||||
// Ensure corepack will be cached
|
||||
const contents = fs.readdirSync(
|
||||
path.join(directory, '.vercel/cache/corepack')
|
||||
);
|
||||
t.deepEqual(contents, ['home', 'shim']);
|
||||
});
|
||||
|
||||
test('[vc build] should build project with corepack and select pnpm@7.1.0', async t => {
|
||||
process.env.ENABLE_EXPERIMENTAL_COREPACK = '1';
|
||||
const directory = fixture('vc-build-corepack-pnpm');
|
||||
const before = await _execa('pnpm', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
const output = await execute(['build'], { cwd: directory });
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
t.regex(output.stderr, /Build Completed/gm);
|
||||
const after = await _execa('pnpm', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
// Ensure global pnpm didn't change
|
||||
t.is(before.stdout, after.stdout);
|
||||
// Ensure version is correct
|
||||
t.is(
|
||||
await fs.readFile(
|
||||
path.join(directory, '.vercel/output/static/index.txt'),
|
||||
'utf8'
|
||||
),
|
||||
'7.1.0\n'
|
||||
);
|
||||
// Ensure corepack will be cached
|
||||
const contents = fs.readdirSync(
|
||||
path.join(directory, '.vercel/cache/corepack')
|
||||
);
|
||||
t.deepEqual(contents, ['home', 'shim']);
|
||||
});
|
||||
|
||||
test('[vc build] should build project with corepack and select yarn@2.4.3', async t => {
|
||||
process.env.ENABLE_EXPERIMENTAL_COREPACK = '1';
|
||||
const directory = fixture('vc-build-corepack-yarn');
|
||||
const before = await _execa('yarn', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
const output = await execute(['build'], { cwd: directory });
|
||||
t.is(output.exitCode, 0, formatOutput(output));
|
||||
t.regex(output.stderr, /Build Completed/gm);
|
||||
const after = await _execa('yarn', ['--version'], {
|
||||
cwd: directory,
|
||||
reject: false,
|
||||
});
|
||||
// Ensure global yarn didn't change
|
||||
t.is(before.stdout, after.stdout);
|
||||
// Ensure version is correct
|
||||
t.is(
|
||||
await fs.readFile(
|
||||
path.join(directory, '.vercel/output/static/index.txt'),
|
||||
'utf8'
|
||||
),
|
||||
'2.4.3\n'
|
||||
);
|
||||
// Ensure corepack will be cached
|
||||
const contents = fs.readdirSync(
|
||||
path.join(directory, '.vercel/cache/corepack')
|
||||
);
|
||||
t.deepEqual(contents, ['home', 'shim']);
|
||||
});
|
||||
|
||||
test('default command should deploy directory', async t => {
|
||||
const projectDir = fixture('deploy-default-with-sub-directory');
|
||||
const target = 'output';
|
||||
@@ -1507,7 +1608,7 @@ test('try to purchase a domain', async t => {
|
||||
|
||||
const { stderr, stdout, exitCode } = await execa(
|
||||
binaryPath,
|
||||
['domains', 'buy', `${session}-test.org`, ...defaultArgs],
|
||||
['domains', 'buy', `${session}-test.com`, ...defaultArgs],
|
||||
{
|
||||
reject: false,
|
||||
input: stream,
|
||||
@@ -1522,10 +1623,9 @@ test('try to purchase a domain', async t => {
|
||||
console.log(exitCode);
|
||||
|
||||
t.is(exitCode, 1);
|
||||
t.true(
|
||||
stderr.includes(
|
||||
`Error! Could not purchase domain. Please add a payment method using \`vercel billing add\`.`
|
||||
)
|
||||
t.regex(
|
||||
stderr,
|
||||
/Error! Could not purchase domain\. Please add a payment method using/
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1537,7 +1637,7 @@ test('try to transfer-in a domain with "--code" option', async t => {
|
||||
'transfer-in',
|
||||
'--code',
|
||||
'xyz',
|
||||
`${session}-test.org`,
|
||||
`${session}-test.com`,
|
||||
...defaultArgs,
|
||||
],
|
||||
{
|
||||
@@ -1551,7 +1651,7 @@ test('try to transfer-in a domain with "--code" option', async t => {
|
||||
|
||||
t.true(
|
||||
stderr.includes(
|
||||
`Error! The domain "${session}-test.org" is not transferable.`
|
||||
`Error! The domain "${session}-test.com" is not transferable.`
|
||||
)
|
||||
);
|
||||
t.is(exitCode, 1);
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"target": "es2019",
|
||||
"target": "ES2020",
|
||||
"esModuleInterop": true,
|
||||
"allowJs": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "11.0.4",
|
||||
"version": "12.0.0",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -20,7 +20,7 @@
|
||||
"test-unit": "yarn test tests/unit.*test.*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
"node": ">= 14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/async-retry": "1.4.1",
|
||||
@@ -42,7 +42,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
"async-sema": "3.0.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "dist",
|
||||
@@ -12,7 +12,7 @@
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strict": true,
|
||||
"target": "es2019"
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"main": "./dist/frameworks.js",
|
||||
"types": "./dist/frameworks.d.ts",
|
||||
"files": [
|
||||
@@ -21,7 +21,7 @@
|
||||
"@types/js-yaml": "3.12.1",
|
||||
"@types/node": "12.0.4",
|
||||
"@types/node-fetch": "2.5.8",
|
||||
"@vercel/routing-utils": "1.13.3",
|
||||
"@vercel/routing-utils": "1.13.4",
|
||||
"ajv": "6.12.2",
|
||||
"typescript": "4.3.4"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,7 +13,7 @@
|
||||
"outDir": "./dist",
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "esnext"
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["src/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "1.4.4",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||
@@ -25,7 +25,7 @@
|
||||
"@types/fs-extra": "^5.0.5",
|
||||
"@types/node-fetch": "^2.3.0",
|
||||
"@types/tar": "^4.0.0",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.1",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,6 +13,6 @@
|
||||
"noImplicitThis": false,
|
||||
"types": ["node"],
|
||||
"strict": true,
|
||||
"target": "es2018"
|
||||
"target": "ES2020"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "2.9.0",
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -45,9 +45,9 @@
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/nft": "0.19.1",
|
||||
"@vercel/routing-utils": "1.13.3",
|
||||
"@vercel/routing-utils": "1.13.4",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
|
||||
@@ -56,7 +56,6 @@ import {
|
||||
getExportStatus,
|
||||
getFilesMapFromReasons,
|
||||
getImagesManifest,
|
||||
getMiddlewareManifest,
|
||||
getNextConfig,
|
||||
getPageLambdaGroups,
|
||||
getPrerenderManifest,
|
||||
@@ -131,10 +130,11 @@ function getRealNextVersion(entryPath: string): string | false {
|
||||
// First try to resolve the `next` dependency and get the real version from its
|
||||
// package.json. This allows the builder to be used with frameworks like Blitz that
|
||||
// bundle Next but where Next isn't in the project root's package.json
|
||||
const nextVersion: string = require(resolveFrom(
|
||||
entryPath,
|
||||
'next/package.json'
|
||||
)).version;
|
||||
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
const nextVersion: string = eval('require')(
|
||||
resolveFrom(entryPath, 'next/package.json')
|
||||
).version;
|
||||
console.log(`Detected Next.js version: ${nextVersion}`);
|
||||
return nextVersion;
|
||||
} catch (_ignored) {
|
||||
@@ -1001,11 +1001,7 @@ export const build: BuildV2 = async ({
|
||||
buildId,
|
||||
'pages'
|
||||
);
|
||||
const pages = await getServerlessPages({
|
||||
pagesDir,
|
||||
entryPath,
|
||||
outputDirectory,
|
||||
});
|
||||
const pages = await glob('**/!(_middleware).js', pagesDir);
|
||||
const launcherPath = path.join(__dirname, 'legacy-launcher.js');
|
||||
const launcherData = await readFile(launcherPath, 'utf8');
|
||||
|
||||
@@ -1078,11 +1074,7 @@ export const build: BuildV2 = async ({
|
||||
'pages'
|
||||
);
|
||||
|
||||
const pages = await getServerlessPages({
|
||||
pagesDir,
|
||||
entryPath,
|
||||
outputDirectory,
|
||||
});
|
||||
const pages = await glob('**/!(_middleware).js', pagesDir);
|
||||
const isApiPage = (page: string) =>
|
||||
page
|
||||
.replace(/\\/g, '/')
|
||||
@@ -2583,23 +2575,3 @@ export const prepareCache: PrepareCache = async ({
|
||||
debug('Cache file manifest produced');
|
||||
return cache;
|
||||
};
|
||||
|
||||
async function getServerlessPages(params: {
|
||||
pagesDir: string;
|
||||
entryPath: string;
|
||||
outputDirectory: string;
|
||||
}) {
|
||||
const [pages, middlewareManifest] = await Promise.all([
|
||||
glob('**/!(_middleware).js', params.pagesDir),
|
||||
getMiddlewareManifest(params.entryPath, params.outputDirectory),
|
||||
]);
|
||||
|
||||
// Edge Functions do not consider as Serverless Functions
|
||||
for (const edgeFunctionFile of Object.keys(
|
||||
middlewareManifest?.middleware ?? {}
|
||||
)) {
|
||||
delete pages[edgeFunctionFile.slice(1) + '.js'];
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
@@ -244,9 +244,7 @@ export async function getRoutesManifest(
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const routesManifest: RoutesManifest = require(pathRoutesManifest);
|
||||
|
||||
const routesManifest: RoutesManifest = await fs.readJSON(pathRoutesManifest);
|
||||
// remove temporary array based routeKeys from v1/v2 of routes
|
||||
// manifest since it can result in invalid routes
|
||||
for (const route of routesManifest.dataRoutes || []) {
|
||||
@@ -368,10 +366,10 @@ export async function getDynamicRoutes(
|
||||
let getSortedRoutes: ((normalizedPages: string[]) => string[]) | undefined;
|
||||
|
||||
try {
|
||||
({ getRouteRegex, getSortedRoutes } = require(resolveFrom(
|
||||
entryPath,
|
||||
'next-server/dist/lib/router/utils'
|
||||
)));
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
({ getRouteRegex, getSortedRoutes } = eval('require')(
|
||||
resolveFrom(entryPath, 'next-server/dist/lib/router/utils')
|
||||
));
|
||||
if (typeof getRouteRegex !== 'function') {
|
||||
getRouteRegex = undefined;
|
||||
}
|
||||
@@ -379,10 +377,10 @@ export async function getDynamicRoutes(
|
||||
|
||||
if (!getRouteRegex || !getSortedRoutes) {
|
||||
try {
|
||||
({ getRouteRegex, getSortedRoutes } = require(resolveFrom(
|
||||
entryPath,
|
||||
'next/dist/next-server/lib/router/utils'
|
||||
)));
|
||||
// NOTE: `eval('require')` is necessary to avoid bad transpilation to `__webpack_require__`
|
||||
({ getRouteRegex, getSortedRoutes } = eval('require')(
|
||||
resolveFrom(entryPath, 'next/dist/next-server/lib/router/utils')
|
||||
));
|
||||
if (typeof getRouteRegex !== 'function') {
|
||||
getRouteRegex = undefined;
|
||||
}
|
||||
@@ -536,9 +534,7 @@ export async function getImagesManifest(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const imagesManifest: NextImagesManifest = require(pathImagesManifest);
|
||||
return imagesManifest;
|
||||
return fs.readJson(pathImagesManifest);
|
||||
}
|
||||
|
||||
type FileMap = { [page: string]: FileFsRef };
|
||||
@@ -2128,11 +2124,12 @@ export {
|
||||
interface MiddlewareManifest {
|
||||
version: 1;
|
||||
sortedMiddleware: string[];
|
||||
middleware: { [page: string]: EdgeFunctionInfo };
|
||||
functions?: { [page: string]: EdgeFunctionInfo };
|
||||
middleware: {
|
||||
[page: string]: MiddlewareInfo;
|
||||
};
|
||||
}
|
||||
|
||||
interface EdgeFunctionInfo {
|
||||
interface MiddlewareInfo {
|
||||
env: string[];
|
||||
files: string[];
|
||||
name: string;
|
||||
@@ -2154,34 +2151,16 @@ export async function getMiddlewareBundle({
|
||||
entryPath,
|
||||
outputDirectory
|
||||
);
|
||||
const sortedFunctions = [
|
||||
...(!middlewareManifest
|
||||
? []
|
||||
: middlewareManifest.sortedMiddleware.map(key => ({
|
||||
key,
|
||||
edgeFunction: middlewareManifest?.middleware[key],
|
||||
type: 'middleware' as const,
|
||||
}))),
|
||||
|
||||
...Object.entries(middlewareManifest?.functions ?? {}).map(
|
||||
([key, edgeFunction]) => {
|
||||
return {
|
||||
key,
|
||||
edgeFunction,
|
||||
type: 'function' as const,
|
||||
};
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
if (middlewareManifest && sortedFunctions.length > 0) {
|
||||
if (middlewareManifest && middlewareManifest?.sortedMiddleware.length > 0) {
|
||||
const workerConfigs = await Promise.all(
|
||||
sortedFunctions.map(async ({ key, edgeFunction, type }) => {
|
||||
middlewareManifest.sortedMiddleware.map(async key => {
|
||||
const middleware = middlewareManifest.middleware[key];
|
||||
try {
|
||||
const wrappedModuleSource = await getNextjsEdgeFunctionSource(
|
||||
edgeFunction.files,
|
||||
middleware.files,
|
||||
{
|
||||
name: edgeFunction.name,
|
||||
name: middleware.name,
|
||||
staticRoutes: routesManifest.staticRoutes,
|
||||
dynamicRoutes: routesManifest.dynamicRoutes.filter(
|
||||
r => !('isMiddleware' in r)
|
||||
@@ -2192,19 +2171,18 @@ export async function getMiddlewareBundle({
|
||||
},
|
||||
},
|
||||
path.resolve(entryPath, outputDirectory),
|
||||
edgeFunction.wasm
|
||||
middleware.wasm
|
||||
);
|
||||
|
||||
return {
|
||||
type,
|
||||
page: edgeFunction.page,
|
||||
page: middlewareManifest.middleware[key].page,
|
||||
edgeFunction: (() => {
|
||||
const { source, map } = wrappedModuleSource.sourceAndMap();
|
||||
const transformedMap = stringifySourceMap(
|
||||
transformSourceMap(map)
|
||||
);
|
||||
|
||||
const wasmFiles = (edgeFunction.wasm ?? []).reduce(
|
||||
const wasmFiles = (middleware.wasm ?? []).reduce(
|
||||
(acc: Files, { filePath, name }) => {
|
||||
const fullFilePath = path.join(
|
||||
entryPath,
|
||||
@@ -2223,7 +2201,7 @@ export async function getMiddlewareBundle({
|
||||
|
||||
return new EdgeFunction({
|
||||
deploymentTarget: 'v8-worker',
|
||||
name: edgeFunction.name,
|
||||
name: middleware.name,
|
||||
files: {
|
||||
'index.js': new FileBlob({
|
||||
data: source,
|
||||
@@ -2240,10 +2218,13 @@ export async function getMiddlewareBundle({
|
||||
...wasmFiles,
|
||||
},
|
||||
entrypoint: 'index.js',
|
||||
envVarsInUse: edgeFunction.env,
|
||||
envVarsInUse: middleware.env,
|
||||
});
|
||||
})(),
|
||||
routeSrc: getRouteSrc(edgeFunction, routesManifest),
|
||||
routeSrc: getRouteSrc(
|
||||
middlewareManifest.middleware[key],
|
||||
routesManifest
|
||||
),
|
||||
};
|
||||
} catch (e: any) {
|
||||
e.message = `Can't build edge function ${key}: ${e.message}`;
|
||||
@@ -2264,20 +2245,13 @@ export async function getMiddlewareBundle({
|
||||
|
||||
for (const worker of workerConfigs.values()) {
|
||||
const edgeFile = worker.edgeFunction.name;
|
||||
const shortPath = edgeFile.replace(/^pages\//, '');
|
||||
worker.edgeFunction.name = shortPath;
|
||||
source.edgeFunctions[shortPath] = worker.edgeFunction;
|
||||
const route: Route = {
|
||||
worker.edgeFunction.name = edgeFile.replace(/^pages\//, '');
|
||||
source.edgeFunctions[edgeFile] = worker.edgeFunction;
|
||||
const route = {
|
||||
continue: true,
|
||||
override: true,
|
||||
middlewarePath: edgeFile,
|
||||
src: worker.routeSrc,
|
||||
...(worker.type === 'middleware'
|
||||
? {
|
||||
middlewarePath: shortPath,
|
||||
override: true,
|
||||
}
|
||||
: {
|
||||
dest: shortPath,
|
||||
}),
|
||||
};
|
||||
|
||||
if (routesManifest.version > 3 && isDynamicRoute(worker.page)) {
|
||||
@@ -2302,7 +2276,7 @@ export async function getMiddlewareBundle({
|
||||
* location. If the manifest can't be found it will resolve to
|
||||
* undefined.
|
||||
*/
|
||||
export async function getMiddlewareManifest(
|
||||
async function getMiddlewareManifest(
|
||||
entryPath: string,
|
||||
outputDirectory: string
|
||||
): Promise<MiddlewareManifest | undefined> {
|
||||
@@ -2321,8 +2295,7 @@ export async function getMiddlewareManifest(
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
return require(middlewareManifestPath);
|
||||
return fs.readJSON(middlewareManifestPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2335,7 +2308,7 @@ export async function getMiddlewareManifest(
|
||||
* @returns A regexp string for the middleware route.
|
||||
*/
|
||||
function getRouteSrc(
|
||||
{ regexp, page }: EdgeFunctionInfo,
|
||||
{ regexp, page }: MiddlewareInfo,
|
||||
{ basePath = '', i18n }: RoutesManifest
|
||||
): string {
|
||||
if (page === '/') {
|
||||
|
||||
@@ -4,6 +4,8 @@ const cheerio = require('cheerio');
|
||||
const { check, deployAndTest } = require('../../utils');
|
||||
const fetch = require('../../../../../test/lib/deployment/fetch-retry');
|
||||
|
||||
const ABSOLUTE_URL_PATTERN = /^https?:\/\//i;
|
||||
|
||||
async function checkForChange(url, initialValue, hardError) {
|
||||
return check(
|
||||
async () => {
|
||||
@@ -32,6 +34,13 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
const info = await deployAndTest(__dirname);
|
||||
Object.assign(ctx, info);
|
||||
|
||||
if (!ABSOLUTE_URL_PATTERN.test(ctx.deploymentUrl)) {
|
||||
const details = JSON.stringify(ctx);
|
||||
throw new Error(
|
||||
`Deployment did not result in an absolute deploymentUrl: ${details}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should revalidate content properly from /', async () => {
|
||||
|
||||
8
packages/next/test/fixtures/00-middleware-nested/index.test.js
vendored
Normal file
8
packages/next/test/fixtures/00-middleware-nested/index.test.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const path = require('path');
|
||||
const { deployAndTest } = require('../../utils');
|
||||
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
await deployAndTest(__dirname);
|
||||
});
|
||||
});
|
||||
21
packages/next/test/fixtures/00-middleware-nested/next.config.js
vendored
Normal file
21
packages/next/test/fixtures/00-middleware-nested/next.config.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
module.exports = {
|
||||
redirects() {
|
||||
return [
|
||||
{
|
||||
source: '/redirect-me',
|
||||
destination: '/from-next-config',
|
||||
permanent: false,
|
||||
},
|
||||
];
|
||||
},
|
||||
rewrites() {
|
||||
return {
|
||||
beforeFiles: [
|
||||
{
|
||||
source: '/rewrite-before-files',
|
||||
destination: '/somewhere',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
11
packages/next/test/fixtures/00-middleware-nested/package.json
vendored
Normal file
11
packages/next/test/fixtures/00-middleware-nested/package.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "12.1.6",
|
||||
"react": "latest",
|
||||
"react-dom": "latest"
|
||||
}
|
||||
}
|
||||
226
packages/next/test/fixtures/00-middleware-nested/pages/_middleware.js
vendored
Normal file
226
packages/next/test/fixtures/00-middleware-nested/pages/_middleware.js
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
const ALLOWED = ['allowed'];
|
||||
|
||||
export function middleware(request) {
|
||||
const url = request.nextUrl;
|
||||
const pathname = url.pathname;
|
||||
|
||||
if (process.env.FOO) {
|
||||
console.log(`Includes env variable ${process.env.FOO}`);
|
||||
}
|
||||
|
||||
if (url.pathname === '/redirect-me') {
|
||||
url.pathname = '/from-middleware';
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
|
||||
if (url.pathname === '/next') {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
if (url.pathname === '/version') {
|
||||
return NextResponse.json({
|
||||
enumerable: Object.keys(self).includes('VercelRuntime'),
|
||||
version: self.VercelRuntime.version,
|
||||
});
|
||||
}
|
||||
|
||||
if (url.pathname === '/globals') {
|
||||
const globalThisKeys = Object.keys(globalThis);
|
||||
const globalKeys = globalThisKeys.reduce((acc, globalName) => {
|
||||
const key = globalName.toString();
|
||||
if (global[key]) acc.push(key);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const res = NextResponse.next();
|
||||
res.headers.set(
|
||||
'data',
|
||||
JSON.stringify({ globals: globalKeys, globalThis: globalThisKeys })
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (url.pathname === '/log') {
|
||||
console.log('hi there');
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === '/logs') {
|
||||
console.clear();
|
||||
for (let i = 0; i < 3; i++) console.count();
|
||||
console.count('test');
|
||||
console.count('test');
|
||||
console.dir({ hello: 'world' });
|
||||
console.log('hello');
|
||||
console.log('world');
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === '/greetings') {
|
||||
const data = { message: 'hello world!' };
|
||||
const res = NextResponse.next();
|
||||
res.headers.set('x-example', 'edge');
|
||||
res.headers.set('data', JSON.stringify(data));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (url.pathname === '/rewrite-me-to-about') {
|
||||
url.pathname = '/about';
|
||||
url.searchParams.set('middleware', 'foo');
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
|
||||
if (url.pathname === '/redirect-me-to-about') {
|
||||
url.pathname = '/about';
|
||||
url.searchParams.set('middleware', 'foo');
|
||||
return Response.redirect(url);
|
||||
}
|
||||
|
||||
if (url.pathname === '/rewrite-absolute') {
|
||||
return NextResponse.rewrite('https://example.vercel.sh/foo?foo=bar');
|
||||
}
|
||||
|
||||
if (url.pathname === '/rewrite-relative') {
|
||||
url.pathname = '/foo';
|
||||
url.searchParams.set('foo', 'bar');
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
|
||||
if (url.pathname === '/redirect-absolute') {
|
||||
return Response.redirect('https://vercel.com');
|
||||
}
|
||||
|
||||
if (url.pathname === '/redirect-301') {
|
||||
url.pathname = '/greetings';
|
||||
return NextResponse.redirect(url, 301);
|
||||
}
|
||||
|
||||
if (url.pathname === '/reflect') {
|
||||
const res = NextResponse.next();
|
||||
res.headers.set(
|
||||
'data',
|
||||
JSON.stringify({
|
||||
geo: request.geo,
|
||||
headers: Object.fromEntries(request.headers),
|
||||
ip: request.ip,
|
||||
method: request.method,
|
||||
nextUrl: {
|
||||
hash: request.nextUrl.hash,
|
||||
hostname: request.nextUrl.hostname,
|
||||
pathname: request.nextUrl.pathname,
|
||||
port: request.nextUrl.port,
|
||||
protocol: request.nextUrl.protocol,
|
||||
search: request.nextUrl.search,
|
||||
},
|
||||
url: request.url,
|
||||
})
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (url.pathname === '/stream-response') {
|
||||
const { readable, writable } = new TransformStream();
|
||||
const waitUntil = (async () => {
|
||||
const enc = new TextEncoder();
|
||||
const writer = writable.getWriter();
|
||||
writer.write(enc.encode('this is a streamed '));
|
||||
writer.write(enc.encode('response '));
|
||||
return writer.close();
|
||||
})();
|
||||
|
||||
return {
|
||||
waitUntil,
|
||||
response: NextResponse.next(),
|
||||
};
|
||||
}
|
||||
|
||||
if (url.pathname === '/throw-error') {
|
||||
const error = new Error('oh no!');
|
||||
console.log('This is not worker.js');
|
||||
console.error(error);
|
||||
return new Promise((_, reject) => reject(error));
|
||||
}
|
||||
|
||||
if (url.pathname === '/throw-error-internal') {
|
||||
function myFunctionName() {
|
||||
throw new Error('Oh no!');
|
||||
}
|
||||
|
||||
function anotherFunction() {
|
||||
return myFunctionName();
|
||||
}
|
||||
|
||||
try {
|
||||
anotherFunction();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
return new Promise((_, reject) => reject(new Error('oh no!')));
|
||||
}
|
||||
|
||||
if (url.pathname === '/unhandledrejection') {
|
||||
Promise.reject(new TypeError('captured unhandledrejection error.'));
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
if (pathname.startsWith('/query-params')) {
|
||||
if (pathname.endsWith('/clear')) {
|
||||
const strategy =
|
||||
url.searchParams.get('strategy') === 'rewrite' ? 'rewrite' : 'redirect';
|
||||
|
||||
for (const key of [...url.searchParams.keys()]) {
|
||||
if (!ALLOWED.includes(key)) {
|
||||
url.searchParams.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
const newPath = url.pathname.replace(/\/clear$/, '');
|
||||
url.pathname = newPath;
|
||||
|
||||
if (strategy === 'redirect') {
|
||||
return NextResponse.redirect(url);
|
||||
} else {
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
}
|
||||
|
||||
const obj = Object.fromEntries([...url.searchParams.entries()]);
|
||||
|
||||
const res = NextResponse.next();
|
||||
res.headers.set('data', JSON.stringify(obj));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (pathname.startsWith('/home')) {
|
||||
if (!request.cookies.bucket) {
|
||||
const bucket = Math.random() >= 0.5 ? 'a' : 'b';
|
||||
url.pathname = `/home/${bucket}`;
|
||||
const response = NextResponse.rewrite(url);
|
||||
response.cookie('bucket', bucket);
|
||||
return response;
|
||||
}
|
||||
|
||||
url.pathname = `/home/${request.cookies.bucket}`;
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
|
||||
if (pathname.startsWith('/fetch-subrequest')) {
|
||||
const destinationUrl =
|
||||
url.searchParams.get('url') || 'https://example.vercel.sh';
|
||||
return fetch(destinationUrl, { headers: request.headers });
|
||||
}
|
||||
|
||||
if (url.pathname === '/dynamic/greet') {
|
||||
const res = NextResponse.next();
|
||||
res.headers.set(
|
||||
'data',
|
||||
JSON.stringify({
|
||||
message: url.searchParams.get('greeting') || 'Hi friend',
|
||||
})
|
||||
);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
16
packages/next/test/fixtures/00-middleware-nested/pages/about.js
vendored
Normal file
16
packages/next/test/fixtures/00-middleware-nested/pages/about.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export default function Main({ message, middleware }) {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">About Page</h1>
|
||||
<p className={message}>{message}</p>
|
||||
<p className="middleware">{middleware}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ query }) => ({
|
||||
props: {
|
||||
middleware: query.middleware || '',
|
||||
message: query.message || '',
|
||||
},
|
||||
});
|
||||
6
packages/next/test/fixtures/00-middleware-nested/pages/blog/_middleware.js
vendored
Normal file
6
packages/next/test/fixtures/00-middleware-nested/pages/blog/_middleware.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const middleware = async () => {
|
||||
// Just chillin doing nothing
|
||||
return NextResponse.next();
|
||||
};
|
||||
10
packages/next/test/fixtures/00-middleware-nested/pages/blog/index.js
vendored
Normal file
10
packages/next/test/fixtures/00-middleware-nested/pages/blog/index.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function Page() {
|
||||
return <p>blog</p>;
|
||||
}
|
||||
|
||||
export function getStaticProps() {
|
||||
return {
|
||||
props: {},
|
||||
revalidate: 1,
|
||||
};
|
||||
}
|
||||
3
packages/next/test/fixtures/00-middleware-nested/pages/dynamic/[id]/index.js
vendored
Normal file
3
packages/next/test/fixtures/00-middleware-nested/pages/dynamic/[id]/index.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Index() {
|
||||
return <p className="title">Dynamic route</p>;
|
||||
}
|
||||
16
packages/next/test/fixtures/00-middleware-nested/pages/fetch-subrequest/index.js
vendored
Normal file
16
packages/next/test/fixtures/00-middleware-nested/pages/fetch-subrequest/index.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export default function Main({ message, middleware }) {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">About Page</h1>
|
||||
<p className={message}>{message}</p>
|
||||
<p className="middleware">{middleware}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = ({ query }) => ({
|
||||
props: {
|
||||
middleware: query.middleware || '',
|
||||
message: query.message || '',
|
||||
},
|
||||
});
|
||||
3
packages/next/test/fixtures/00-middleware-nested/pages/home/a.js
vendored
Normal file
3
packages/next/test/fixtures/00-middleware-nested/pages/home/a.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Home() {
|
||||
return <h1>Home A</h1>;
|
||||
}
|
||||
3
packages/next/test/fixtures/00-middleware-nested/pages/home/b.js
vendored
Normal file
3
packages/next/test/fixtures/00-middleware-nested/pages/home/b.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Home() {
|
||||
return <h1>Home B</h1>;
|
||||
}
|
||||
81
packages/next/test/fixtures/00-middleware-nested/pages/index.js
vendored
Normal file
81
packages/next/test/fixtures/00-middleware-nested/pages/index.js
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Demo</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/home">
|
||||
<a>A/B Testing</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/rewrite-me-to-about">
|
||||
<a>Rewrite to existing page</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/redirect-me-to-about">
|
||||
<a>Redirect to existing page</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/rewrite">
|
||||
<a>Rewrite to external site</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/redirect">
|
||||
<a>Redirect to external site</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/greetings">
|
||||
<a>Respond with JSON</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/stream-response">
|
||||
<a>Respond with Stream</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/dynamic/greet?greeting=hola">
|
||||
<a>Dynamic Nested Middleware</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/eval">
|
||||
<a>do a eval</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/logs">
|
||||
<a>print some logs</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/fetch">
|
||||
<a>perform a fetch</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/throw-error">
|
||||
<a>throw an error</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/throw-error-internal">
|
||||
<a>throw a controller error</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/timeout">
|
||||
<a>simulate timeout</a>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
packages/next/test/fixtures/00-middleware-nested/vercel.json
vendored
Normal file
16
packages/next/test/fixtures/00-middleware-nested/vercel.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/redirect-me",
|
||||
"status": 307,
|
||||
"responseHeaders": {
|
||||
"Location": "/from-next-config/"
|
||||
},
|
||||
"fetchOptions": {
|
||||
"redirect": "manual"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"target": "es2018",
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"sourceMap": false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node-bridge",
|
||||
"version": "2.2.2",
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"noEmit": true,
|
||||
"noImplicitReturns": true,
|
||||
"strict": true,
|
||||
"declaration": true
|
||||
"target": "ES2020",
|
||||
"declaration": true,
|
||||
"module": "commonjs"
|
||||
},
|
||||
"include": ["helpers.ts", "bridge.js", "launcher.js"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "1.15.4",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@vercel/node-bridge": "2.2.2",
|
||||
"@vercel/node-bridge": "3.0.0",
|
||||
"ts-node": "8.9.1",
|
||||
"typescript": "4.3.4"
|
||||
},
|
||||
@@ -45,7 +45,7 @@
|
||||
"@types/etag": "1.8.0",
|
||||
"@types/jest": "27.4.1",
|
||||
"@types/test-listen": "1.1.0",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/nft": "0.19.1",
|
||||
"content-type": "1.0.4",
|
||||
|
||||
@@ -450,7 +450,6 @@ export function fixConfig(
|
||||
delete config.compilerOptions.tsBuildInfoFile;
|
||||
delete config.compilerOptions.incremental;
|
||||
|
||||
// Target esnext output by default (instead of ES3).
|
||||
// This will prevent TS from polyfill/downlevel emit.
|
||||
if (config.compilerOptions.target === undefined) {
|
||||
// See https://github.com/tsconfig/bases/tree/main/bases
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"target": "es2018",
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"sourceMap": false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/python",
|
||||
"version": "2.3.4",
|
||||
"version": "3.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
||||
@@ -23,7 +23,7 @@
|
||||
"devDependencies": {
|
||||
"@types/execa": "^0.9.0",
|
||||
"@types/jest": "27.4.1",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "^1.0.0",
|
||||
"typescript": "4.3.4"
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function downloadFilesInWorkPath({
|
||||
workPath,
|
||||
files,
|
||||
meta = {},
|
||||
}: BuildOptions) {
|
||||
}: Pick<BuildOptions, 'entrypoint' | 'workPath' | 'files' | 'meta'>) {
|
||||
debug('Downloading user files...');
|
||||
let downloadedFiles = await download(files, workPath, meta);
|
||||
if (meta.isDev) {
|
||||
@@ -67,7 +67,6 @@ export const build = async ({
|
||||
files: originalFiles,
|
||||
entrypoint,
|
||||
meta,
|
||||
config,
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,7 +13,7 @@
|
||||
"outDir": "dist",
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "es2018"
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/redwood",
|
||||
"version": "0.8.4",
|
||||
"version": "1.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -21,13 +21,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.19.1",
|
||||
"@vercel/routing-utils": "1.13.3",
|
||||
"@vercel/routing-utils": "1.13.4",
|
||||
"semver": "6.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/node": "*",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "3.1.1"
|
||||
"@vercel/build-utils": "4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,6 +13,6 @@
|
||||
"outDir": "dist",
|
||||
"types": ["node"],
|
||||
"strict": true,
|
||||
"target": "es2019"
|
||||
"target": "ES2020"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/remix",
|
||||
"version": "0.0.2",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -27,7 +27,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/remix/test/build.test.ts
vendored
2
packages/remix/test/build.test.ts
vendored
@@ -20,6 +20,7 @@ describe('build()', () => {
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
workPath,
|
||||
repoRootPath: workPath,
|
||||
config: {},
|
||||
});
|
||||
assert('output' in result);
|
||||
@@ -36,6 +37,7 @@ describe('build()', () => {
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
workPath,
|
||||
repoRootPath: workPath,
|
||||
config: {},
|
||||
});
|
||||
const cacheNames = Object.keys(cache);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,7 +13,7 @@
|
||||
"outDir": "./dist",
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "es2019",
|
||||
"target": "ES2020",
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/routing-utils",
|
||||
"version": "1.13.3",
|
||||
"version": "1.13.4",
|
||||
"description": "Vercel routing utilities",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"target": "esnext",
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"sourceMap": false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@vercel/ruby",
|
||||
"author": "Nathan Cahill <nathan@nathancahill.com>",
|
||||
"version": "1.3.7",
|
||||
"version": "1.3.8",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
|
||||
@@ -23,7 +23,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "8.0.0",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "2.0.4",
|
||||
"fs-extra": "^7.0.1",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -12,6 +12,6 @@
|
||||
"noUnusedParameters": true,
|
||||
"outDir": "dist",
|
||||
"strict": true,
|
||||
"target": "esnext"
|
||||
"target": "ES2020"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "0.26.0",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/build-step",
|
||||
@@ -37,10 +37,10 @@
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node-fetch": "2.5.4",
|
||||
"@types/promise-timeout": "1.3.0",
|
||||
"@vercel/build-utils": "3.1.1",
|
||||
"@vercel/frameworks": "1.0.0",
|
||||
"@vercel/build-utils": "4.0.0",
|
||||
"@vercel/frameworks": "1.0.1",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/routing-utils": "1.13.3",
|
||||
"@vercel/routing-utils": "1.13.4",
|
||||
"fs-extra": "10.0.0",
|
||||
"get-port": "5.0.0",
|
||||
"is-port-reachable": "2.0.1",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"lib": ["ES2020"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noEmitOnError": true,
|
||||
@@ -13,7 +13,7 @@
|
||||
"outDir": "dist",
|
||||
"types": ["node", "jest"],
|
||||
"strict": true,
|
||||
"target": "es2018"
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["test/fixtures"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-config",
|
||||
"version": "1.0.1",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"repository": {
|
||||
@@ -23,6 +23,7 @@
|
||||
"ts-morph": "12.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/core": "1.2.182",
|
||||
"@types/jest": "27.4.1",
|
||||
"@types/node": "*"
|
||||
},
|
||||
|
||||
@@ -7,10 +7,8 @@ import {
|
||||
Node,
|
||||
ArrayLiteralExpression,
|
||||
} from 'ts-morph';
|
||||
import Ajv from 'ajv';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
|
||||
const ajv = new Ajv();
|
||||
import { validate } from './validation';
|
||||
|
||||
export const BaseFunctionConfigSchema = {
|
||||
type: 'object',
|
||||
@@ -38,15 +36,6 @@ export function getConfig<
|
||||
return validate(schema || BaseFunctionConfigSchema, config);
|
||||
}
|
||||
|
||||
function validate<T>(schema: T, data: any): FromSchema<T> {
|
||||
const isValid = ajv.compile(schema);
|
||||
if (!isValid(data)) {
|
||||
// TODO: better error message
|
||||
throw new Error('Invalid data');
|
||||
}
|
||||
return data as FromSchema<T>;
|
||||
}
|
||||
|
||||
function getConfigNode(sourceFile: SourceFile) {
|
||||
return sourceFile
|
||||
.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)
|
||||
|
||||
145
packages/static-config/src/swc.ts
Normal file
145
packages/static-config/src/swc.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import type { Expression, Module } from '@swc/core';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
import { validate } from './validation';
|
||||
|
||||
export type Value =
|
||||
| undefined
|
||||
| null
|
||||
| boolean
|
||||
| string
|
||||
| number
|
||||
| any[]
|
||||
| Record<string, any>;
|
||||
export class UnsupportedValueError extends Error {}
|
||||
|
||||
function extractValue(node: Expression): Value {
|
||||
if (node.type === 'NullLiteral') {
|
||||
return null;
|
||||
} else if (node.type === 'BooleanLiteral') {
|
||||
// e.g. true / false
|
||||
return node.value;
|
||||
} else if (node.type === 'StringLiteral') {
|
||||
// e.g. "abc"
|
||||
return node.value;
|
||||
} else if (node.type === 'NumericLiteral') {
|
||||
// e.g. 123
|
||||
return node.value;
|
||||
} else if (node.type === 'Identifier') {
|
||||
switch (node.value) {
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
default:
|
||||
throw new UnsupportedValueError();
|
||||
}
|
||||
} else if (node.type === 'ArrayExpression') {
|
||||
// e.g. [1, 2, 3]
|
||||
const arr = [];
|
||||
for (const elem of node.elements) {
|
||||
if (elem) {
|
||||
if (elem.spread) {
|
||||
// e.g. [ ...a ]
|
||||
throw new UnsupportedValueError();
|
||||
}
|
||||
|
||||
arr.push(extractValue(elem.expression));
|
||||
} else {
|
||||
// e.g. [1, , 2]
|
||||
// ^^
|
||||
arr.push(undefined);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
} else if (node.type === 'ObjectExpression') {
|
||||
// e.g. { a: 1, b: 2 }
|
||||
const obj: Record<string, any> = {};
|
||||
for (const prop of node.properties) {
|
||||
if (prop.type !== 'KeyValueProperty') {
|
||||
// e.g. { ...a }
|
||||
throw new UnsupportedValueError();
|
||||
}
|
||||
|
||||
let key: string;
|
||||
if (prop.key.type === 'Identifier') {
|
||||
// e.g. { a: 1, b: 2 }
|
||||
key = prop.key.value;
|
||||
} else if (prop.key.type === 'StringLiteral') {
|
||||
// e.g. { "a": 1, "b": 2 }
|
||||
key = prop.key.value;
|
||||
} else {
|
||||
throw new UnsupportedValueError();
|
||||
}
|
||||
|
||||
obj[key] = extractValue(prop.value);
|
||||
}
|
||||
|
||||
return obj;
|
||||
} else {
|
||||
throw new UnsupportedValueError();
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts the value of an exported const variable named `exportedName`
|
||||
// (e.g. "export const config = { runtime: 'edge' }") from swc's AST.
|
||||
//
|
||||
// The value must be one of (or throws UnsupportedValueError):
|
||||
//
|
||||
// - string
|
||||
// - boolean
|
||||
// - number
|
||||
// - null
|
||||
// - undefined
|
||||
// - array containing values listed in this list
|
||||
// - object containing values listed in this list
|
||||
//
|
||||
export function extractExportedConstValue(
|
||||
module: Module,
|
||||
exportedName: string
|
||||
): Value | null {
|
||||
for (const moduleItem of module.body) {
|
||||
if (moduleItem.type !== 'ExportDeclaration') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { declaration } = moduleItem;
|
||||
if (declaration.type !== 'VariableDeclaration') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (declaration.kind !== 'const') {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const decl of declaration.declarations) {
|
||||
if (
|
||||
decl.id.type === 'Identifier' &&
|
||||
decl.id.value === exportedName &&
|
||||
decl.init
|
||||
) {
|
||||
return extractValue(decl.init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extracts the value of `export const config` in the given swc AST (`module`).
|
||||
//
|
||||
// Returns null if the declaration is not found.
|
||||
//
|
||||
// Throws exceptions if it contains a syntax node which're not literal or
|
||||
// the validation fails.
|
||||
export function getConfig<T extends JSONSchema>(
|
||||
module: Module,
|
||||
schema?: T
|
||||
): FromSchema<T> | null {
|
||||
const data = extractExportedConstValue(module, 'config');
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (schema) {
|
||||
validate(schema, data);
|
||||
}
|
||||
return data as FromSchema<T>;
|
||||
}
|
||||
13
packages/static-config/src/validation.ts
Normal file
13
packages/static-config/src/validation.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import Ajv from 'ajv';
|
||||
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
|
||||
|
||||
const ajv = new Ajv();
|
||||
|
||||
export function validate<T extends JSONSchema>(schema: T, data: any): FromSchema<T> {
|
||||
const isValid = ajv.compile(schema);
|
||||
if (!isValid(data)) {
|
||||
// TODO: better error message
|
||||
throw new Error('Invalid data');
|
||||
}
|
||||
return data as FromSchema<T>;
|
||||
}
|
||||
140
packages/static-config/test/fixtures/extract-const-value.ts
vendored
Normal file
140
packages/static-config/test/fixtures/extract-const-value.ts
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
export const TEST_CASES = [
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: 'string1', b: "string2" }`,
|
||||
expected: {
|
||||
a: 'string1',
|
||||
b: 'string2',
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { 'a': 'string1', "b": "string2" }`,
|
||||
expected: {
|
||||
a: 'string1',
|
||||
b: 'string2',
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { 'a': '\\tstring1', "b": "\\tstring2" }`,
|
||||
expected: {
|
||||
a: '\tstring1',
|
||||
b: '\tstring2',
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: null, b: undefined }`,
|
||||
expected: {
|
||||
a: null,
|
||||
b: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: true, b: false }`,
|
||||
expected: {
|
||||
a: true,
|
||||
b: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: 123, b: 456.789 }`,
|
||||
expected: {
|
||||
a: 123,
|
||||
b: 456.789,
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: [1, [2, 3]] }`,
|
||||
expected: {
|
||||
a: [1, [2, 3]],
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: [1,,3] }`,
|
||||
expected: {
|
||||
a: [1, undefined, 3],
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: { b: 123, c: { d: 'nested' } } }`,
|
||||
expected: {
|
||||
a: {
|
||||
b: 123,
|
||||
c: {
|
||||
d: 'nested',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
identifier: 'config2',
|
||||
input: `export const config1 = 1; export const config2 = 2;`,
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
identifier: 'runtime',
|
||||
input: `export const runtime = 'edge'`,
|
||||
expected: 'edge',
|
||||
},
|
||||
];
|
||||
|
||||
export const UNSUPPORTED_VALUE_CASES = [
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: 1 + 2 + 3 }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { 123: "a" }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { ["a"]: true }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { a: foo }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { foo }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = { ...foo }`,
|
||||
},
|
||||
{
|
||||
identifier: 'config',
|
||||
input: `export const config = [ ...foo ]`,
|
||||
},
|
||||
];
|
||||
|
||||
export const NO_SUCH_DECLARATION_CASES = [
|
||||
{
|
||||
identifier: 'no_such_identifier',
|
||||
input: `export const runtime = "edge"`,
|
||||
},
|
||||
{
|
||||
identifier: 'runtime',
|
||||
input: `const runtime = "edge"`,
|
||||
},
|
||||
{
|
||||
identifier: 'runtime',
|
||||
input: `export let runtime = "edge"`,
|
||||
},
|
||||
{
|
||||
identifier: 'runtime',
|
||||
input: `export var runtime = "edge"`,
|
||||
},
|
||||
{
|
||||
identifier: 'runtime',
|
||||
input: `export function runtime() {}`,
|
||||
},
|
||||
];
|
||||
97
packages/static-config/test/swc.test.ts
vendored
Normal file
97
packages/static-config/test/swc.test.ts
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as swc from '@swc/core';
|
||||
import {
|
||||
extractExportedConstValue,
|
||||
getConfig,
|
||||
UnsupportedValueError,
|
||||
} from '../src/swc';
|
||||
import {
|
||||
NO_SUCH_DECLARATION_CASES,
|
||||
TEST_CASES,
|
||||
UNSUPPORTED_VALUE_CASES,
|
||||
} from './fixtures/extract-const-value';
|
||||
import { BaseFunctionConfigSchema } from '../src';
|
||||
|
||||
function parse(source: string): swc.Module {
|
||||
return swc.parseSync(source, { syntax: 'typescript' });
|
||||
}
|
||||
|
||||
function parseFixture(filename: string): swc.Module {
|
||||
const sourcePath = path.join(__dirname, filename);
|
||||
const input = fs.readFileSync(sourcePath, { encoding: 'utf-8' });
|
||||
return parse(input);
|
||||
}
|
||||
|
||||
describe('extractExportedConstValue for swc', () => {
|
||||
describe('parses successfully', () => {
|
||||
test.each(TEST_CASES)('$input', ({ input, identifier, expected }) => {
|
||||
const ast = parse(input);
|
||||
const value = extractExportedConstValue(ast, identifier);
|
||||
expect(value).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fails with UnsupportedValueError', () => {
|
||||
test.each(UNSUPPORTED_VALUE_CASES)('$input', ({ input, identifier }) => {
|
||||
const ast = parse(input);
|
||||
expect(() => {
|
||||
extractExportedConstValue(ast, identifier);
|
||||
}).toThrow(UnsupportedValueError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('returns null if the declaration is not found', () => {
|
||||
test.each(NO_SUCH_DECLARATION_CASES)('$input', ({ input, identifier }) => {
|
||||
const ast = parse(input);
|
||||
const value = extractExportedConstValue(ast, identifier);
|
||||
expect(value).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getConfig for swc', () => {
|
||||
it('should parse config from Node.js file', () => {
|
||||
const ast = parseFixture('fixtures/node.js');
|
||||
const config = getConfig(ast, BaseFunctionConfigSchema);
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"memory": 1024,
|
||||
"use": "node",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should parse config from Deno file', () => {
|
||||
const ast = parseFixture('fixtures/deno.ts');
|
||||
const config = getConfig(ast, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
location: { type: 'string' },
|
||||
},
|
||||
} as const);
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"location": "https://example.com/page",
|
||||
"use": "deno",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should return `null` when no config was exported', () => {
|
||||
const ast = parseFixture('fixtures/no-config.js');
|
||||
const config = getConfig(ast, BaseFunctionConfigSchema);
|
||||
expect(config).toBeNull();
|
||||
});
|
||||
|
||||
it('should throw an error upon schema validation failure', () => {
|
||||
const ast = parseFixture('fixtures/invalid-schema.js');
|
||||
let err;
|
||||
try {
|
||||
getConfig(ast, BaseFunctionConfigSchema);
|
||||
} catch (_err) {
|
||||
err = _err;
|
||||
}
|
||||
expect(err.message).toEqual('Invalid data');
|
||||
});
|
||||
});
|
||||
@@ -2,8 +2,8 @@
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["esnext"],
|
||||
"target": "es2018",
|
||||
"lib": ["ES2020"],
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"sourceMap": true,
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
const fetch = require('node-fetch');
|
||||
const retryBailByDefault = require('./retry-bail-by-default.js');
|
||||
|
||||
async function fetchRetry(...args) {
|
||||
const ABSOLUTE_URL_PATTERN = /^https?:\/\//i;
|
||||
|
||||
async function fetchRetry(url, ...rest) {
|
||||
if (!ABSOLUTE_URL_PATTERN.test(url)) {
|
||||
throw new Error(`fetch url must be absolute: "${url}"`);
|
||||
}
|
||||
|
||||
return await retryBailByDefault(
|
||||
async canRetry => {
|
||||
try {
|
||||
return await fetch(...args);
|
||||
return await fetch(url, ...rest);
|
||||
} catch (error) {
|
||||
if (error.type === 'request-timeout') {
|
||||
// FetchError: network timeout at: ...
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"$schema": "https://turborepo.org/schema.json",
|
||||
"baseBranch": "origin/main",
|
||||
"globalDependencies": ["$RUNNER_OS"],
|
||||
"pipeline": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
|
||||
186
yarn.lock
186
yarn.lock
@@ -2056,6 +2056,90 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@swc/core-android-arm-eabi@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.182.tgz#fd9d24fe7fa85a95f9fcca743aeb4680419a394d"
|
||||
integrity sha512-NLjye+oyMoGsGFO+w5Opo9Q55GOZw1bnXhw7MHlGibUIhxkJk3kJ+EgFNdXUPgh2B3c9qsDqY2d6v3WD+N4XyA==
|
||||
|
||||
"@swc/core-android-arm64@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.182.tgz#655ce272d813a333685b6ccc9c9a31fa80a2ac3a"
|
||||
integrity sha512-80wldTfsY3JtSQQkIZKj8Vc9QpKObVapWXBfOrebfN1vJesUN/NSf2RGue8RGGkiqjZI0g4ErVHZXZl1CC3hBw==
|
||||
|
||||
"@swc/core-darwin-arm64@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.182.tgz#b20c2a94cd89586171f68d9f9bf280a9c839540a"
|
||||
integrity sha512-CrJToIWnrh6mPHHxPW8bwAZzlQ85sbQmtWh5/DNWQe3MAtrcPDdxxoEIMu+d+HVFcO24EpqOvxI9ok7Cj0SaLQ==
|
||||
|
||||
"@swc/core-darwin-x64@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.182.tgz#2c3abd7ede4179333041831aa3b14f46ca158690"
|
||||
integrity sha512-FFtLCYcSxJDw6OTQMz8TmfudxwcCuinC4O2qdph5ocOb5fAbw/QQS9M3oYuCPN8KXlLyfQ/2zebaAUbKD1mr7g==
|
||||
|
||||
"@swc/core-freebsd-x64@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.182.tgz#b9bd98923c90962646bdc1ce4e7120483e5136fd"
|
||||
integrity sha512-evWeqrw8HnhZroHhPsiWtCQKSFZ6knQfejeDx8Jqu99NGjYm6WtUKSG+yXPJRhlTTxDB0zj8QzjF1C0HDU1EFw==
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.182.tgz#6711198210836a66688467f248697b4db9993985"
|
||||
integrity sha512-vix9LI1QUkaa33F42t0T4nmk9Yqeyh+P7zkc8STn26sc/mFaJ1T4PrF8rLZfACcX1B1vJxJ3+HoGLdTLqFBPRg==
|
||||
|
||||
"@swc/core-linux-arm64-gnu@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.182.tgz#cc9f2136ace2171911d8f6cadd19de0abf6b9a31"
|
||||
integrity sha512-co6NlUl2gxTUcN3/U5OJMIqUGK1j1OZSI9R2FMknaf0olymtSoRB0ww/+p/PKPD69sl+pZd7DvzeIjFrJKeOPw==
|
||||
|
||||
"@swc/core-linux-arm64-musl@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.182.tgz#85a9fe7f5faed77db6fd2a3d1c684e16adda6941"
|
||||
integrity sha512-NoT9aZjjANCtS/yECBRiwmA2oJjFn6X/NhXcQdapcNk2vVid9Hr3NZD5CgBhs3XncXUF/Fjfn6lbRNgZ4MqDRg==
|
||||
|
||||
"@swc/core-linux-x64-gnu@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.182.tgz#986f7c669073b3bef61d910e3f27a425ff854d07"
|
||||
integrity sha512-Fq7sGcc3NyuEVCFIme5xAJLQ2d27ztAoI9Ct5a3/4mP6+E/uEIPSs9eridOOqedq5bi4ZEPU1GsisLUmkVML0g==
|
||||
|
||||
"@swc/core-linux-x64-musl@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.182.tgz#788ed251972d99962df1d45819706c185fd21c08"
|
||||
integrity sha512-O8nZOXPMTLL4m0AVJPygkxU8pp/Mv7WeNgFlEqYcQbK0ZdmW7jU0ZWwAD+IfgzUhdvy3nezorsBnNCRT/YVLiA==
|
||||
|
||||
"@swc/core-win32-arm64-msvc@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.182.tgz#fa3771cfbbd8a1c36d471bb43f16557048382743"
|
||||
integrity sha512-KAr39wz+H7nqZ3wmzkR1h1FmFJhRNfDDvmBfIcqZCtM45YpeikRgxUrbq+Ph7lUob/6cUIKA8QGP5mHmxxzN1A==
|
||||
|
||||
"@swc/core-win32-ia32-msvc@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.182.tgz#3d5a87d2ca7bfc55a39d2f76aae95fb9ec545572"
|
||||
integrity sha512-Ng2b/AE3CUulaattHo19+xPhCKQ9xjwKUgK8zBzx9h8yU7NdRJw5KCe58lMi5axVF0uIqbu0hFdHfQWQIX+bhQ==
|
||||
|
||||
"@swc/core-win32-x64-msvc@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.182.tgz#be7e9e29b56a7ea601cf1cc29abdfec2d052618b"
|
||||
integrity sha512-GRN6AyTVZsvbfMMXKblf+27kQwFnVguaLYqK1H1xk6UKx0U26wcrCM/01hczcoD3NmIVtljANm3VOqqbwlNAJQ==
|
||||
|
||||
"@swc/core@1.2.182":
|
||||
version "1.2.182"
|
||||
resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.182.tgz#0ad16d2239c18b0f903fc73c9c01b8760d9a6697"
|
||||
integrity sha512-ao/6J7VPS8NElpSElGw5KtAB2aYJriSvRkDdjFnX7N06H3w4qo+CweeS8NXnS2/XCoFuCtPBGEpecuBhfKkHNA==
|
||||
optionalDependencies:
|
||||
"@swc/core-android-arm-eabi" "1.2.182"
|
||||
"@swc/core-android-arm64" "1.2.182"
|
||||
"@swc/core-darwin-arm64" "1.2.182"
|
||||
"@swc/core-darwin-x64" "1.2.182"
|
||||
"@swc/core-freebsd-x64" "1.2.182"
|
||||
"@swc/core-linux-arm-gnueabihf" "1.2.182"
|
||||
"@swc/core-linux-arm64-gnu" "1.2.182"
|
||||
"@swc/core-linux-arm64-musl" "1.2.182"
|
||||
"@swc/core-linux-x64-gnu" "1.2.182"
|
||||
"@swc/core-linux-x64-musl" "1.2.182"
|
||||
"@swc/core-win32-arm64-msvc" "1.2.182"
|
||||
"@swc/core-win32-ia32-msvc" "1.2.182"
|
||||
"@swc/core-win32-x64-msvc" "1.2.182"
|
||||
|
||||
"@szmarczak/http-timer@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
|
||||
@@ -3792,6 +3876,20 @@ boxen@^3.0.0:
|
||||
type-fest "^0.3.0"
|
||||
widest-line "^2.0.0"
|
||||
|
||||
boxen@^5.0.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
|
||||
integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==
|
||||
dependencies:
|
||||
ansi-align "^3.0.0"
|
||||
camelcase "^6.2.0"
|
||||
chalk "^4.1.0"
|
||||
cli-boxes "^2.2.1"
|
||||
string-width "^4.2.2"
|
||||
type-fest "^0.20.2"
|
||||
widest-line "^3.1.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@@ -4140,6 +4238,14 @@ chalk@^4.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^4.1.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chance@1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.7.tgz#e99dde5ac16681af787b5ba94c8277c090d6cfe8"
|
||||
@@ -4269,6 +4375,11 @@ cli-boxes@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
|
||||
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
|
||||
|
||||
cli-boxes@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
||||
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
|
||||
|
||||
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
|
||||
@@ -6561,12 +6672,12 @@ global-dirs@^0.1.0:
|
||||
dependencies:
|
||||
ini "^1.3.4"
|
||||
|
||||
global-dirs@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
|
||||
integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==
|
||||
global-dirs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686"
|
||||
integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==
|
||||
dependencies:
|
||||
ini "^1.3.5"
|
||||
ini "2.0.0"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
@@ -7077,7 +7188,12 @@ inherits@2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
|
||||
ini@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
|
||||
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
|
||||
|
||||
ini@^1.3.2, ini@^1.3.4, ini@~1.3.0:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
||||
integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
|
||||
@@ -7378,13 +7494,13 @@ is-installed-globally@^0.1.0:
|
||||
global-dirs "^0.1.0"
|
||||
is-path-inside "^1.0.0"
|
||||
|
||||
is-installed-globally@^0.3.1:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
|
||||
integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==
|
||||
is-installed-globally@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
|
||||
integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
|
||||
dependencies:
|
||||
global-dirs "^2.0.1"
|
||||
is-path-inside "^3.0.1"
|
||||
global-dirs "^3.0.0"
|
||||
is-path-inside "^3.0.2"
|
||||
|
||||
is-negative-zero@^2.0.2:
|
||||
version "2.0.2"
|
||||
@@ -7396,10 +7512,10 @@ is-npm@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053"
|
||||
integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==
|
||||
|
||||
is-npm@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
|
||||
integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
|
||||
is-npm@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8"
|
||||
integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==
|
||||
|
||||
is-number-object@^1.0.4:
|
||||
version "1.0.7"
|
||||
@@ -7473,6 +7589,11 @@ is-path-inside@^3.0.1:
|
||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017"
|
||||
integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==
|
||||
|
||||
is-path-inside@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||
|
||||
is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
@@ -8312,7 +8433,7 @@ kleur@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
latest-version@^5.0.0:
|
||||
latest-version@^5.0.0, latest-version@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
|
||||
integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
|
||||
@@ -10332,10 +10453,10 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
pupa@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726"
|
||||
integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==
|
||||
pupa@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
|
||||
integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
|
||||
dependencies:
|
||||
escape-goat "^2.0.0"
|
||||
|
||||
@@ -11474,7 +11595,7 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
string-width@^4.2.3:
|
||||
string-width@^4.2.2, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -12476,22 +12597,23 @@ unset-value@^1.0.0:
|
||||
has-value "^0.3.1"
|
||||
isobject "^3.0.0"
|
||||
|
||||
update-notifier@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3"
|
||||
integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==
|
||||
update-notifier@5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9"
|
||||
integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==
|
||||
dependencies:
|
||||
boxen "^4.2.0"
|
||||
chalk "^3.0.0"
|
||||
boxen "^5.0.0"
|
||||
chalk "^4.1.0"
|
||||
configstore "^5.0.1"
|
||||
has-yarn "^2.1.0"
|
||||
import-lazy "^2.1.0"
|
||||
is-ci "^2.0.0"
|
||||
is-installed-globally "^0.3.1"
|
||||
is-npm "^4.0.0"
|
||||
is-installed-globally "^0.4.0"
|
||||
is-npm "^5.0.0"
|
||||
is-yarn-global "^0.3.0"
|
||||
latest-version "^5.0.0"
|
||||
pupa "^2.0.1"
|
||||
latest-version "^5.1.0"
|
||||
pupa "^2.1.1"
|
||||
semver "^7.3.4"
|
||||
semver-diff "^3.1.1"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user