mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-12 04:22:14 +00:00
Compare commits
14 Commits
@vercel/py
...
@vercel/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1be7a80bb8 | ||
|
|
0428d4744e | ||
|
|
2a929a4bb9 | ||
|
|
accd308dc5 | ||
|
|
e2d4efab08 | ||
|
|
7e0dd6f808 | ||
|
|
8971e02e49 | ||
|
|
10c91c8579 | ||
|
|
bfdbe58675 | ||
|
|
7bdaf107b7 | ||
|
|
8de100f0e1 | ||
|
|
38a6785859 | ||
|
|
c67d1a8525 | ||
|
|
c5a7c574a2 |
@@ -1,4 +1,5 @@
|
||||
# https://prettier.io/docs/en/ignore.html
|
||||
|
||||
# ignore this file with an intentional syntax error
|
||||
# ignore these files with an intentional syntax error
|
||||
packages/cli/test/dev/fixtures/edge-function-error/api/edge-error-syntax.js
|
||||
packages/cli/test/fixtures/unit/commands/build/node-error/api/typescript.ts
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"prettier": "2.6.2",
|
||||
"ts-eager": "2.0.2",
|
||||
"ts-jest": "28.0.5",
|
||||
"turbo": "1.3.1"
|
||||
"turbo": "1.3.2-canary.1"
|
||||
},
|
||||
"scripts": {
|
||||
"lerna": "lerna",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "27.1.0",
|
||||
"version": "27.1.4",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -45,13 +45,13 @@
|
||||
"@vercel/build-utils": "5.0.2",
|
||||
"@vercel/go": "2.0.6",
|
||||
"@vercel/hydrogen": "0.0.3",
|
||||
"@vercel/next": "3.1.5",
|
||||
"@vercel/next": "3.1.6",
|
||||
"@vercel/node": "2.4.3",
|
||||
"@vercel/python": "3.0.6",
|
||||
"@vercel/redwood": "1.0.7",
|
||||
"@vercel/remix": "1.0.8",
|
||||
"@vercel/ruby": "1.3.14",
|
||||
"@vercel/static-build": "1.0.6",
|
||||
"@vercel/static-build": "1.0.7",
|
||||
"update-notifier": "5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -48,9 +48,17 @@ import {
|
||||
} from '../util/build/write-build-result';
|
||||
import { importBuilders, BuilderWithPkg } from '../util/build/import-builders';
|
||||
import { initCorepack, cleanupCorepack } from '../util/build/corepack';
|
||||
import { sortBuilders } from '../util/build/sort-builders';
|
||||
|
||||
type BuildResult = BuildResultV2 | BuildResultV3;
|
||||
|
||||
interface SerializedBuilder extends Builder {
|
||||
error?: Error;
|
||||
require?: string;
|
||||
requirePath?: string;
|
||||
apiVersion: number;
|
||||
}
|
||||
|
||||
const help = () => {
|
||||
return console.log(`
|
||||
${chalk.bold(`${cli.logo} ${cli.name} build`)}
|
||||
@@ -296,32 +304,36 @@ export default async function main(client: Client): Promise<number> {
|
||||
const ops: Promise<Error | void>[] = [];
|
||||
|
||||
// Write the `detectedBuilders` result to output dir
|
||||
ops.push(
|
||||
fs.writeJSON(
|
||||
join(outputDir, 'builds.json'),
|
||||
{
|
||||
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
|
||||
target,
|
||||
argv: process.argv,
|
||||
builds: builds.map(build => {
|
||||
const builderWithPkg = buildersWithPkgs.get(build.use);
|
||||
if (!builderWithPkg) {
|
||||
throw new Error(`Failed to load Builder "${build.use}"`);
|
||||
}
|
||||
const { builder, pkg: builderPkg } = builderWithPkg;
|
||||
return {
|
||||
require: builderPkg.name,
|
||||
requirePath: builderWithPkg.path,
|
||||
apiVersion: builder.version,
|
||||
...build,
|
||||
};
|
||||
}),
|
||||
},
|
||||
{
|
||||
spaces: 2,
|
||||
const buildsJsonBuilds = new Map<Builder, SerializedBuilder>(
|
||||
builds.map(build => {
|
||||
const builderWithPkg = buildersWithPkgs.get(build.use);
|
||||
if (!builderWithPkg) {
|
||||
throw new Error(`Failed to load Builder "${build.use}"`);
|
||||
}
|
||||
)
|
||||
const { builder, pkg: builderPkg } = builderWithPkg;
|
||||
return [
|
||||
build,
|
||||
{
|
||||
require: builderPkg.name,
|
||||
requirePath: builderWithPkg.path,
|
||||
apiVersion: builder.version,
|
||||
...build,
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
const buildsJson = {
|
||||
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
|
||||
target,
|
||||
argv: process.argv,
|
||||
builds: Array.from(buildsJsonBuilds.values()),
|
||||
};
|
||||
const buildsJsonPath = join(outputDir, 'builds.json');
|
||||
const writeBuildsJsonPromise = fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
});
|
||||
|
||||
ops.push(writeBuildsJsonPromise);
|
||||
|
||||
// The `meta` config property is re-used for each Builder
|
||||
// invocation so that Builders can share state between
|
||||
@@ -332,64 +344,95 @@ export default async function main(client: Client): Promise<number> {
|
||||
};
|
||||
|
||||
// Execute Builders for detected entrypoints
|
||||
// TODO: parallelize builds
|
||||
// TODO: parallelize builds (except for frontend)
|
||||
const sortedBuilders = sortBuilders(builds);
|
||||
const buildResults: Map<Builder, BuildResult> = new Map();
|
||||
const overrides: PathOverride[] = [];
|
||||
const repoRootPath = cwd;
|
||||
const corepackShimDir = await initCorepack({ repoRootPath });
|
||||
|
||||
for (const build of builds) {
|
||||
for (const build of sortedBuilders) {
|
||||
if (typeof build.src !== 'string') continue;
|
||||
|
||||
const builderWithPkg = buildersWithPkgs.get(build.use);
|
||||
if (!builderWithPkg) {
|
||||
throw new Error(`Failed to load Builder "${build.use}"`);
|
||||
}
|
||||
const { builder, pkg: builderPkg } = builderWithPkg;
|
||||
|
||||
const buildConfig: Config = {
|
||||
outputDirectory: project.settings.outputDirectory ?? undefined,
|
||||
...build.config,
|
||||
projectSettings: project.settings,
|
||||
installCommand: project.settings.installCommand ?? undefined,
|
||||
devCommand: project.settings.devCommand ?? undefined,
|
||||
buildCommand: project.settings.buildCommand ?? undefined,
|
||||
framework: project.settings.framework,
|
||||
nodeVersion: project.settings.nodeVersion,
|
||||
};
|
||||
const buildOptions: BuildOptions = {
|
||||
files: filesMap,
|
||||
entrypoint: build.src,
|
||||
workPath,
|
||||
repoRootPath,
|
||||
config: buildConfig,
|
||||
meta,
|
||||
};
|
||||
output.debug(
|
||||
`Building entrypoint "${build.src}" with "${builderPkg.name}"`
|
||||
);
|
||||
const buildResult = await builder.build(buildOptions);
|
||||
try {
|
||||
const { builder, pkg: builderPkg } = builderWithPkg;
|
||||
|
||||
// Store the build result to generate the final `config.json` after
|
||||
// all builds have completed
|
||||
buildResults.set(build, buildResult);
|
||||
const buildConfig: Config = {
|
||||
outputDirectory: project.settings.outputDirectory ?? undefined,
|
||||
...build.config,
|
||||
projectSettings: project.settings,
|
||||
installCommand: project.settings.installCommand ?? undefined,
|
||||
devCommand: project.settings.devCommand ?? undefined,
|
||||
buildCommand: project.settings.buildCommand ?? undefined,
|
||||
framework: project.settings.framework,
|
||||
nodeVersion: project.settings.nodeVersion,
|
||||
};
|
||||
const buildOptions: BuildOptions = {
|
||||
files: filesMap,
|
||||
entrypoint: build.src,
|
||||
workPath,
|
||||
repoRootPath,
|
||||
config: buildConfig,
|
||||
meta,
|
||||
};
|
||||
output.debug(
|
||||
`Building entrypoint "${build.src}" with "${builderPkg.name}"`
|
||||
);
|
||||
const buildResult = await builder.build(buildOptions);
|
||||
|
||||
// Start flushing the file outputs to the filesystem asynchronously
|
||||
ops.push(
|
||||
writeBuildResult(
|
||||
outputDir,
|
||||
buildResult,
|
||||
build,
|
||||
builder,
|
||||
builderPkg,
|
||||
vercelConfig?.cleanUrls
|
||||
).then(
|
||||
override => {
|
||||
if (override) overrides.push(override);
|
||||
},
|
||||
err => err
|
||||
)
|
||||
);
|
||||
// Store the build result to generate the final `config.json` after
|
||||
// all builds have completed
|
||||
buildResults.set(build, buildResult);
|
||||
|
||||
// Start flushing the file outputs to the filesystem asynchronously
|
||||
ops.push(
|
||||
writeBuildResult(
|
||||
outputDir,
|
||||
buildResult,
|
||||
build,
|
||||
builder,
|
||||
builderPkg,
|
||||
vercelConfig?.cleanUrls
|
||||
).then(
|
||||
override => {
|
||||
if (override) overrides.push(override);
|
||||
},
|
||||
err => err
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
const configJson = {
|
||||
version: 3,
|
||||
};
|
||||
const configJsonPromise = fs.writeJSON(
|
||||
join(outputDir, 'config.json'),
|
||||
configJson,
|
||||
{ spaces: 2 }
|
||||
);
|
||||
|
||||
await Promise.all([writeBuildsJsonPromise, configJsonPromise]);
|
||||
|
||||
const buildJsonBuild = buildsJsonBuilds.get(build);
|
||||
if (buildJsonBuild) {
|
||||
buildJsonBuild.error = {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
...err,
|
||||
};
|
||||
|
||||
await fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
});
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (corepackShimDir) {
|
||||
|
||||
@@ -95,6 +95,7 @@ export default async (client: Client) => {
|
||||
// deprecated
|
||||
'--name': String,
|
||||
'-n': '--name',
|
||||
'--no-clipboard': Boolean,
|
||||
'--target': String,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -183,6 +184,17 @@ export default async (client: Client) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (argv['--no-clipboard']) {
|
||||
output.print(
|
||||
`${prependEmoji(
|
||||
`The ${param(
|
||||
'--no-clipboard'
|
||||
)} option was ignored because it is the default behavior. Please remove it.`,
|
||||
emoji('warning')
|
||||
)}\n`
|
||||
);
|
||||
}
|
||||
|
||||
// build `target`
|
||||
const target = parseTarget(output, argv['--target'], argv['--prod']);
|
||||
if (typeof target === 'number') {
|
||||
|
||||
12
packages/cli/src/util/build/sort-builders.ts
Normal file
12
packages/cli/src/util/build/sort-builders.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import frameworkList from '@vercel/frameworks';
|
||||
|
||||
export function sortBuilders<B extends { use: string }>(builds: B[]): B[] {
|
||||
const frontendRuntimeSet = new Set(
|
||||
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
||||
);
|
||||
const toNumber = (build: B) => (frontendRuntimeSet.has(build.use) ? 0 : 1);
|
||||
|
||||
return builds.sort((build1, build2) => {
|
||||
return toNumber(build1) - toNumber(build2);
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
import fs from 'fs-extra';
|
||||
import mimeTypes from 'mime-types';
|
||||
import { basename, dirname, extname, join, relative, resolve } from 'path';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
join,
|
||||
relative,
|
||||
resolve,
|
||||
posix,
|
||||
} from 'path';
|
||||
import {
|
||||
Builder,
|
||||
BuildResultV2,
|
||||
@@ -20,6 +28,7 @@ import pipe from 'promisepipe';
|
||||
import { unzip } from './unzip';
|
||||
import { VERCEL_DIR } from '../projects/link';
|
||||
|
||||
const { normalize } = posix;
|
||||
export const OUTPUT_DIR = join(VERCEL_DIR, 'output');
|
||||
|
||||
export async function writeBuildResult(
|
||||
@@ -67,6 +76,13 @@ export interface PathOverride {
|
||||
path?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove duplicate slashes as well as leading/trailing slashes.
|
||||
*/
|
||||
function stripDuplicateSlashes(path: string): string {
|
||||
return normalize(path).replace(/(^\/|\/$)/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the output from the `build()` return value of a v2 Builder to
|
||||
* the filesystem.
|
||||
@@ -84,16 +100,17 @@ async function writeBuildResultV2(
|
||||
const lambdas = new Map<Lambda, string>();
|
||||
const overrides: Record<string, PathOverride> = {};
|
||||
for (const [path, output] of Object.entries(buildResult.output)) {
|
||||
const normalizedPath = stripDuplicateSlashes(path);
|
||||
if (isLambda(output)) {
|
||||
await writeLambda(outputDir, output, path, lambdas);
|
||||
await writeLambda(outputDir, output, normalizedPath, lambdas);
|
||||
} else if (isPrerender(output)) {
|
||||
await writeLambda(outputDir, output.lambda, path, lambdas);
|
||||
await writeLambda(outputDir, output.lambda, normalizedPath, lambdas);
|
||||
|
||||
// Write the fallback file alongside the Lambda directory
|
||||
let fallback = output.fallback;
|
||||
if (fallback) {
|
||||
const ext = getFileExtension(fallback);
|
||||
const fallbackName = `${path}.prerender-fallback${ext}`;
|
||||
const fallbackName = `${normalizedPath}.prerender-fallback${ext}`;
|
||||
const fallbackPath = join(outputDir, 'functions', fallbackName);
|
||||
const stream = fallback.toStream();
|
||||
await pipe(
|
||||
@@ -109,7 +126,7 @@ async function writeBuildResultV2(
|
||||
const prerenderConfigPath = join(
|
||||
outputDir,
|
||||
'functions',
|
||||
`${path}.prerender-config.json`
|
||||
`${normalizedPath}.prerender-config.json`
|
||||
);
|
||||
const prerenderConfig = {
|
||||
...output,
|
||||
@@ -118,12 +135,20 @@ async function writeBuildResultV2(
|
||||
};
|
||||
await fs.writeJSON(prerenderConfigPath, prerenderConfig, { spaces: 2 });
|
||||
} else if (isFile(output)) {
|
||||
await writeStaticFile(outputDir, output, path, overrides, cleanUrls);
|
||||
await writeStaticFile(
|
||||
outputDir,
|
||||
output,
|
||||
normalizedPath,
|
||||
overrides,
|
||||
cleanUrls
|
||||
);
|
||||
} else if (isEdgeFunction(output)) {
|
||||
await writeEdgeFunction(outputDir, output, path);
|
||||
await writeEdgeFunction(outputDir, output, normalizedPath);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unsupported output type: "${(output as any).type}" for ${path}`
|
||||
`Unsupported output type: "${
|
||||
(output as any).type
|
||||
}" for ${normalizedPath}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -145,9 +170,9 @@ async function writeBuildResultV3(
|
||||
throw new Error(`Expected "build.src" to be a string`);
|
||||
}
|
||||
const ext = extname(src);
|
||||
const path = build.config?.zeroConfig
|
||||
? src.substring(0, src.length - ext.length)
|
||||
: src;
|
||||
const path = stripDuplicateSlashes(
|
||||
build.config?.zeroConfig ? src.substring(0, src.length - ext.length) : src
|
||||
);
|
||||
if (isLambda(output)) {
|
||||
await writeLambda(outputDir, output, path);
|
||||
} else if (isEdgeFunction(output)) {
|
||||
|
||||
7
packages/cli/test/fixtures/unit/commands/build/node-error/.vercel/project.json
vendored
Normal file
7
packages/cli/test/fixtures/unit/commands/build/node-error/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"orgId": ".",
|
||||
"projectId": ".",
|
||||
"settings": {
|
||||
"framework": null
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/es6.js
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/es6.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (req, res) => res.end('Vercel');
|
||||
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/index.js
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = (req, res) => res.end('Vercel');
|
||||
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/mjs.mjs
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/node-error/api/mjs.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default (req, res) => res.end('Vercel');
|
||||
4
packages/cli/test/fixtures/unit/commands/build/node-error/api/typescript.ts
vendored
Normal file
4
packages/cli/test/fixtures/unit/commands/build/node-error/api/typescript.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { IncomingMessage, ServerResponse } from 'http';
|
||||
|
||||
// Intentional syntax error to make the build fail
|
||||
export default (req: IncomingMessage, res: ServerResponse => res.end('Vercel');
|
||||
@@ -1,9 +1,17 @@
|
||||
const { FileBlob } = require('@vercel/build-utils');
|
||||
const { FileBlob, Lambda } = require('@vercel/build-utils');
|
||||
|
||||
exports.build = async () => {
|
||||
const file = new FileBlob({
|
||||
data: Buffer.from('file contents')
|
||||
});
|
||||
const output = { file };
|
||||
const lambda = new Lambda({
|
||||
files: {},
|
||||
runtime: 'provided',
|
||||
handler: 'example.js'
|
||||
})
|
||||
const output = {
|
||||
file,
|
||||
'withTrailingSlash/': lambda
|
||||
};
|
||||
return { output };
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { client } from './client';
|
||||
import { Project } from '../../src/types';
|
||||
import { formatProvider } from '../../src/util/projects/connect-git-provider';
|
||||
|
||||
const envs = [
|
||||
{
|
||||
|
||||
@@ -589,8 +589,6 @@ describe('build', () => {
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
client.stderr.pipe(process.stderr);
|
||||
client.setArgv('build');
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
|
||||
@@ -614,6 +612,40 @@ describe('build', () => {
|
||||
expect(await fs.readFile(join(output, 'static/file'), 'utf8')).toEqual(
|
||||
'file contents'
|
||||
);
|
||||
|
||||
// "functions" directory has output Functions
|
||||
const functions = await fs.readdir(join(output, 'functions'));
|
||||
expect(functions.sort()).toEqual(['withTrailingSlash.func']);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
|
||||
it('should store Builder error in `builds.json`', async () => {
|
||||
const cwd = fixture('node-error');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
|
||||
// `builds.json` contains "error" build
|
||||
const builds = await fs.readJSON(join(output, 'builds.json'));
|
||||
expect(builds.builds).toHaveLength(4);
|
||||
|
||||
const errorBuilds = builds.builds.filter((b: any) => 'error' in b);
|
||||
expect(errorBuilds).toHaveLength(1);
|
||||
|
||||
expect(errorBuilds[0].error.name).toEqual('Error');
|
||||
expect(errorBuilds[0].error.message).toMatch(`TS1005`);
|
||||
expect(errorBuilds[0].error.message).toMatch(`',' expected.`);
|
||||
expect(errorBuilds[0].error.hideStackTrace).toEqual(true);
|
||||
expect(errorBuilds[0].error.code).toEqual('NODE_TYPESCRIPT_ERROR');
|
||||
|
||||
// `config.json`` contains `version`
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
expect(configJson.version).toBe(3);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
|
||||
51
packages/cli/test/unit/util/build/sort-builders.test.ts
Normal file
51
packages/cli/test/unit/util/build/sort-builders.test.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { sortBuilders } from '../../../../src/util/build/sort-builders';
|
||||
|
||||
describe('sortBuilders()', () => {
|
||||
test.each([
|
||||
{
|
||||
name: 'should sort @vercel/next from middle to beginning',
|
||||
input: ['@vercel/node', '@vercel/next', '@vercel/python'],
|
||||
output: ['@vercel/next', '@vercel/node', '@vercel/python'],
|
||||
},
|
||||
{
|
||||
name: 'should sort @vercel/static-build from middle to beginning',
|
||||
input: ['@vercel/node', '@vercel/static-build', '@vercel/python'],
|
||||
output: ['@vercel/static-build', '@vercel/node', '@vercel/python'],
|
||||
},
|
||||
{
|
||||
name: 'should sort @vercel/remix from end to beginning',
|
||||
input: ['@vercel/python', '@vercel/node', '@vercel/remix'],
|
||||
output: ['@vercel/remix', '@vercel/python', '@vercel/node'],
|
||||
},
|
||||
{
|
||||
name: 'should sort @vercel/redwood from beginning to beginning',
|
||||
input: ['@vercel/redwood', '@vercel/python', '@vercel/ruby'],
|
||||
output: ['@vercel/redwood', '@vercel/python', '@vercel/ruby'],
|
||||
},
|
||||
{
|
||||
name: 'should sort @vercel/hydrogen from end to beginning',
|
||||
input: ['@vercel/python', '@vercel/hydrogen'],
|
||||
output: ['@vercel/hydrogen', '@vercel/python'],
|
||||
},
|
||||
{
|
||||
name: 'should sort @vercel/static-build to beginning with many @vercel/node',
|
||||
input: [
|
||||
'@vercel/node',
|
||||
'@vercel/node',
|
||||
'@vercel/node',
|
||||
'@vercel/static-build',
|
||||
'@vercel/node',
|
||||
],
|
||||
output: [
|
||||
'@vercel/static-build',
|
||||
'@vercel/node',
|
||||
'@vercel/node',
|
||||
'@vercel/node',
|
||||
'@vercel/node',
|
||||
],
|
||||
},
|
||||
])('$name', ({ input, output }) => {
|
||||
const builders = sortBuilders(input.map(use => ({ use })));
|
||||
expect(builders.map(b => b.use)).toEqual(output);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "3.1.5",
|
||||
"version": "3.1.6",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
|
||||
@@ -56,6 +56,7 @@ import prettyBytes from 'pretty-bytes';
|
||||
const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
|
||||
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
||||
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
||||
const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
|
||||
|
||||
export async function serverBuild({
|
||||
dynamicPages,
|
||||
@@ -133,6 +134,10 @@ export async function serverBuild({
|
||||
const lambdaPageKeys = Object.keys(lambdaPages);
|
||||
const internalPages = ['_app.js', '_error.js', '_document.js'];
|
||||
const pageBuildTraces = await glob('**/*.js.nft.json', pagesDir);
|
||||
const isEmptyAllowQueryForPrendered = semver.gte(
|
||||
nextVersion,
|
||||
EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION
|
||||
);
|
||||
const isCorrectNotFoundRoutes = semver.gte(
|
||||
nextVersion,
|
||||
CORRECT_NOT_FOUND_ROUTES_VERSION
|
||||
@@ -756,6 +761,7 @@ export async function serverBuild({
|
||||
static404Page,
|
||||
hasPages404: routesManifest.pages404,
|
||||
isCorrectNotFoundRoutes,
|
||||
isEmptyAllowQueryForPrendered,
|
||||
});
|
||||
|
||||
Object.keys(prerenderManifest.staticRoutes).forEach(route =>
|
||||
|
||||
@@ -1665,6 +1665,7 @@ type OnPrerenderRouteArgs = {
|
||||
pageLambdaMap: { [key: string]: string };
|
||||
routesManifest?: RoutesManifest;
|
||||
isCorrectNotFoundRoutes?: boolean;
|
||||
isEmptyAllowQueryForPrendered?: boolean;
|
||||
};
|
||||
let prerenderGroup = 1;
|
||||
|
||||
@@ -1698,6 +1699,7 @@ export const onPrerenderRoute =
|
||||
pageLambdaMap,
|
||||
routesManifest,
|
||||
isCorrectNotFoundRoutes,
|
||||
isEmptyAllowQueryForPrendered,
|
||||
} = prerenderRouteArgs;
|
||||
|
||||
if (isBlocking && isFallback) {
|
||||
@@ -1901,7 +1903,6 @@ export const onPrerenderRoute =
|
||||
// a given path. All other query keys will be striped. We can automatically
|
||||
// detect this for prerender (ISR) pages by reading the routes manifest file.
|
||||
const pageKey = srcRoute || routeKey;
|
||||
const isDynamic = isDynamicRoute(pageKey);
|
||||
const route = routesManifest?.dynamicRoutes.find(
|
||||
(r): r is RoutesManifestRoute =>
|
||||
r.page === pageKey && !('isMiddleware' in r)
|
||||
@@ -1911,14 +1912,33 @@ export const onPrerenderRoute =
|
||||
// we have sufficient information to set it
|
||||
let allowQuery: string[] | undefined;
|
||||
|
||||
if (routeKeys) {
|
||||
// if we have routeKeys in the routes-manifest we use those
|
||||
// for allowQuery for dynamic routes
|
||||
allowQuery = Object.values(routeKeys);
|
||||
} else if (!isDynamic) {
|
||||
// for non-dynamic routes we use an empty array since
|
||||
// no query values bust the cache for non-dynamic prerenders
|
||||
allowQuery = [];
|
||||
if (isEmptyAllowQueryForPrendered) {
|
||||
const isDynamic = isDynamicRoute(routeKey);
|
||||
|
||||
if (!isDynamic) {
|
||||
// for non-dynamic routes we use an empty array since
|
||||
// no query values bust the cache for non-dynamic prerenders
|
||||
// prerendered paths also do not pass allowQuery as they match
|
||||
// during handle: 'filesystem' so should not cache differently
|
||||
// by query values
|
||||
allowQuery = [];
|
||||
} else if (routeKeys) {
|
||||
// if we have routeKeys in the routes-manifest we use those
|
||||
// for allowQuery for dynamic routes
|
||||
allowQuery = Object.values(routeKeys);
|
||||
}
|
||||
} else {
|
||||
const isDynamic = isDynamicRoute(pageKey);
|
||||
|
||||
if (routeKeys) {
|
||||
// if we have routeKeys in the routes-manifest we use those
|
||||
// for allowQuery for dynamic routes
|
||||
allowQuery = Object.values(routeKeys);
|
||||
} else if (!isDynamic) {
|
||||
// for non-dynamic routes we use an empty array since
|
||||
// no query values bust the cache for non-dynamic prerenders
|
||||
allowQuery = [];
|
||||
}
|
||||
}
|
||||
|
||||
prerenders[outputPathPage] = new Prerender({
|
||||
|
||||
@@ -1,8 +1,144 @@
|
||||
/* eslint-env jest */
|
||||
const path = require('path');
|
||||
const { deployAndTest } = require('../../utils');
|
||||
const cheerio = require('cheerio');
|
||||
const { deployAndTest, check, waitFor } = require('../../utils');
|
||||
const fetch = require('../../../../../test/lib/deployment/fetch-retry');
|
||||
|
||||
async function checkForChange(url, initialValue, getNewValue) {
|
||||
return check(async () => {
|
||||
const res = await fetch(url);
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(`Invalid status code ${res.status}`);
|
||||
}
|
||||
const newValue = await getNewValue(res);
|
||||
|
||||
return initialValue !== newValue
|
||||
? 'success'
|
||||
: JSON.stringify({ initialValue, newValue });
|
||||
}, 'success');
|
||||
}
|
||||
|
||||
const ctx = {};
|
||||
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
await deployAndTest(__dirname);
|
||||
const info = await deployAndTest(__dirname);
|
||||
Object.assign(ctx, info);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
title: 'should update content for prerendered path correctly',
|
||||
pathsToCheck: [
|
||||
{ urlPath: '/fallback-blocking/first' },
|
||||
{ urlPath: '/fallback-blocking/first', query: '?slug=first' },
|
||||
{ urlPath: '/fallback-blocking/first', query: '?slug=random' },
|
||||
{ urlPath: '/fallback-blocking/first', query: '?another=value' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'should update content for non-prerendered path correctly',
|
||||
pathsToCheck: [
|
||||
{ urlPath: '/fallback-blocking/on-demand-2' },
|
||||
{
|
||||
urlPath: '/fallback-blocking/on-demand-2',
|
||||
query: '?slug=on-demand-2',
|
||||
},
|
||||
{ urlPath: '/fallback-blocking/on-demand-2', query: '?slug=random' },
|
||||
{ urlPath: '/fallback-blocking/on-demand-2', query: '?another=value' },
|
||||
],
|
||||
},
|
||||
])('$title', async ({ pathsToCheck }) => {
|
||||
let initialRandom;
|
||||
let initialRandomData;
|
||||
let preRevalidateRandom;
|
||||
let preRevalidateRandomData;
|
||||
|
||||
const checkPaths = async pathsToCheck => {
|
||||
for (const { urlPath, query } of pathsToCheck) {
|
||||
console.log('checking', {
|
||||
urlPath,
|
||||
query,
|
||||
initialRandom,
|
||||
preRevalidateRandom,
|
||||
});
|
||||
|
||||
if (preRevalidateRandom) {
|
||||
// wait for change as cache may take a little to propagate
|
||||
const initialUrl = `${ctx.deploymentUrl}${urlPath}${query || ''}`;
|
||||
await checkForChange(initialUrl, preRevalidateRandom, async () => {
|
||||
const res = await fetch(initialUrl);
|
||||
const $ = cheerio.load(await res.text());
|
||||
return JSON.parse($('#props').text()).random;
|
||||
});
|
||||
}
|
||||
|
||||
const res = await fetch(`${ctx.deploymentUrl}${urlPath}${query || ''}`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const $ = await cheerio.load(await res.text());
|
||||
const props = JSON.parse($('#props').text());
|
||||
|
||||
if (initialRandom) {
|
||||
// for fallback paths the initial value is generated
|
||||
// in the foreground and then a revalidation is kicked off
|
||||
// in the background so the initial value will be replaced
|
||||
if (initialRandom !== props.random && urlPath.includes('on-demand')) {
|
||||
initialRandom = props.random;
|
||||
} else {
|
||||
expect(initialRandom).toBe(props.random);
|
||||
}
|
||||
} else {
|
||||
initialRandom = props.random;
|
||||
}
|
||||
expect(isNaN(initialRandom)).toBe(false);
|
||||
|
||||
const dataRes = await fetch(
|
||||
`${ctx.deploymentUrl}/_next/data/testing-build-id${urlPath}.json${
|
||||
query || ''
|
||||
}`
|
||||
);
|
||||
expect(dataRes.status).toBe(200);
|
||||
|
||||
const { pageProps: dataProps } = await dataRes.json();
|
||||
|
||||
if (initialRandomData) {
|
||||
// for fallback paths the initial value is generated
|
||||
// in the foreground and then a revalidation is kicked off
|
||||
// in the background so the initial value will be replaced
|
||||
if (
|
||||
initialRandomData !== dataProps.random &&
|
||||
urlPath.includes('on-demand-2')
|
||||
) {
|
||||
initialRandomData = dataProps.random;
|
||||
} else {
|
||||
expect(initialRandomData).toBe(dataProps.random);
|
||||
}
|
||||
} else {
|
||||
initialRandomData = dataProps.random;
|
||||
}
|
||||
expect(isNaN(initialRandomData)).toBe(false);
|
||||
}
|
||||
};
|
||||
|
||||
await checkPaths(pathsToCheck);
|
||||
|
||||
preRevalidateRandom = initialRandom;
|
||||
preRevalidateRandomData = initialRandomData;
|
||||
|
||||
initialRandom = undefined;
|
||||
initialRandomData = undefined;
|
||||
|
||||
const revalidateRes = await fetch(
|
||||
`${ctx.deploymentUrl}/api/revalidate?urlPath=${pathsToCheck[0].urlPath}`
|
||||
);
|
||||
expect(revalidateRes.status).toBe(200);
|
||||
expect((await revalidateRes.json()).revalidated).toBe(true);
|
||||
|
||||
await checkPaths(pathsToCheck);
|
||||
|
||||
expect(preRevalidateRandom).toBeDefined();
|
||||
expect(preRevalidateRandomData).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
10
packages/next/test/fixtures/00-server-build/pages/api/revalidate.js
vendored
Normal file
10
packages/next/test/fixtures/00-server-build/pages/api/revalidate.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
console.log('revalidating', req.query.urlPath);
|
||||
await res.revalidate(req.query.urlPath);
|
||||
return res.json({ revalidated: true });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return res.json({ revalidated: false });
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ export const getStaticProps = ({ params }) => {
|
||||
|
||||
export const getStaticPaths = () => {
|
||||
return {
|
||||
paths: ['/fallback-blocking/first'],
|
||||
paths: ['/fallback-blocking/first', '/fallback-blocking/on-demand-1'],
|
||||
fallback: 'blocking',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -78,8 +78,20 @@ it('should build using server build', async () => {
|
||||
expect(output['dynamic/[slug]'].maxDuration).toBe(5);
|
||||
expect(output['fallback/[slug]'].type).toBe('Prerender');
|
||||
expect(output['fallback/[slug]'].allowQuery).toEqual(['slug']);
|
||||
expect(output['_next/data/testing-build-id/fallback/[slug].json'].type).toBe(
|
||||
'Prerender'
|
||||
);
|
||||
expect(
|
||||
output['_next/data/testing-build-id/fallback/[slug].json'].allowQuery
|
||||
).toEqual(['slug']);
|
||||
expect(output['fallback/first'].type).toBe('Prerender');
|
||||
expect(output['fallback/first'].allowQuery).toEqual(['slug']);
|
||||
expect(output['fallback/first'].allowQuery).toEqual([]);
|
||||
expect(output['_next/data/testing-build-id/fallback/first.json'].type).toBe(
|
||||
'Prerender'
|
||||
);
|
||||
expect(
|
||||
output['_next/data/testing-build-id/fallback/first.json'].allowQuery
|
||||
).toEqual([]);
|
||||
expect(output['api'].type).toBe('Lambda');
|
||||
expect(output['api'].allowQuery).toBe(undefined);
|
||||
expect(output['api'].memory).toBe(128);
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
module.exports = (phase, { defaultConfig }) => ({
|
||||
pageExtensions: [...defaultConfig.pageExtensions, 'hello.js'],
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
});
|
||||
|
||||
2
packages/next/test/utils.ts
vendored
2
packages/next/test/utils.ts
vendored
@@ -129,7 +129,7 @@ export async function deployAndTest(fixtureDir) {
|
||||
};
|
||||
}
|
||||
|
||||
async function waitFor(milliseconds) {
|
||||
export async function waitFor(milliseconds) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, milliseconds);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/build-step",
|
||||
|
||||
@@ -43,20 +43,15 @@ export function createBuildOutput(
|
||||
buildOutputPath: string,
|
||||
framework?: Framework
|
||||
): BuildResultV2 {
|
||||
if (!meta.cliVersion) {
|
||||
if (meta.isDev) {
|
||||
let buildCommandName: string;
|
||||
|
||||
if (buildCommand) buildCommandName = `"${buildCommand}"`;
|
||||
else if (framework) buildCommandName = framework.name;
|
||||
else buildCommandName = 'the "build" script';
|
||||
|
||||
if (meta.isDev) {
|
||||
throw new Error(
|
||||
`Detected Build Output v3 from ${buildCommandName}, but it is not supported for \`vercel dev\`. Please set the Development Command in your Project Settings.`
|
||||
);
|
||||
}
|
||||
throw new Error(
|
||||
`Detected Build Output v3 from ${buildCommandName}, but this Deployment is not using \`vercel build\`.\nPlease set the \`ENABLE_VC_BUILD=1\` environment variable.`
|
||||
`Detected Build Output v3 from ${buildCommandName}, but it is not supported for \`vercel dev\`. Please set the Development Command in your Project Settings.`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
35
packages/static-build/test/build.test.ts
vendored
35
packages/static-build/test/build.test.ts
vendored
@@ -99,7 +99,7 @@ describe('build()', () => {
|
||||
});
|
||||
|
||||
describe('Build Output API v3', () => {
|
||||
it('should detect the output format', async () => {
|
||||
it('should detect the output format with `vercel build`', async () => {
|
||||
const workPath = path.join(
|
||||
__dirname,
|
||||
'build-fixtures',
|
||||
@@ -125,29 +125,28 @@ describe('build()', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an Error without `vercel build`', async () => {
|
||||
let err;
|
||||
it('should detect the output format without `vercel build`', async () => {
|
||||
const workPath = path.join(
|
||||
__dirname,
|
||||
'build-fixtures',
|
||||
'09-build-output-v3'
|
||||
);
|
||||
try {
|
||||
await build({
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
repoRootPath: workPath,
|
||||
workPath,
|
||||
config: {},
|
||||
meta: {
|
||||
skipDownload: true,
|
||||
},
|
||||
});
|
||||
} catch (_err: any) {
|
||||
err = _err;
|
||||
const buildResult = await build({
|
||||
files: {},
|
||||
entrypoint: 'package.json',
|
||||
repoRootPath: workPath,
|
||||
workPath,
|
||||
config: {},
|
||||
meta: {
|
||||
skipDownload: true,
|
||||
},
|
||||
});
|
||||
if ('output' in buildResult) {
|
||||
throw new Error('Unexpected `output` in build result');
|
||||
}
|
||||
expect(err.message).toEqual(
|
||||
`Detected Build Output v3 from the "build" script, but this Deployment is not using \`vercel build\`.\nPlease set the \`ENABLE_VC_BUILD=1\` environment variable.`
|
||||
expect(buildResult.buildOutputVersion).toEqual(3);
|
||||
expect(buildResult.buildOutputPath).toEqual(
|
||||
path.join(workPath, '.vercel/output')
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
4
utils/update-canary-tag.js
vendored
4
utils/update-canary-tag.js
vendored
@@ -24,7 +24,9 @@ for (const [package, version] of changedPackageVersions) {
|
||||
`skipping ${package}@${version} as it is already a canary version`
|
||||
);
|
||||
} else {
|
||||
console.log(execSync(`npm dist-tag add ${package}@${version} canary`));
|
||||
console.log(
|
||||
execSync(`npm dist-tag add ${package}@${version} canary`).toString()
|
||||
);
|
||||
console.log(`updated canary dist-tag for ${package}@${version}`);
|
||||
}
|
||||
}
|
||||
|
||||
148
yarn.lock
148
yarn.lock
@@ -12245,95 +12245,95 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
turbo-android-arm64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-android-arm64/-/turbo-android-arm64-1.3.1.tgz#dae9bd087d6a17409fbd10ed82489a1ff39cbcc8"
|
||||
integrity sha512-JcnZh9tLbZDpKaXaao/s/k4qXt3TbNEc1xEYYXurVWnqiMueGeS7QAtThVB85ZSqzj7djk+ngSrZabPy5RG25Q==
|
||||
turbo-android-arm64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-android-arm64/-/turbo-android-arm64-1.3.2-canary.1.tgz#a2cc4b76b1b4302f712548a101195f88d0d3646c"
|
||||
integrity sha512-XIX6/7iy7jT8/U3FSmN4HUxNk2/HAeFcYL2A7Vh0wGQ7aVJAqItYxV5Iawf49lokdmdxQnJnttQ2TRIEKH1ITg==
|
||||
|
||||
turbo-darwin-64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.3.1.tgz#efe64b9589f6a0f475b5123538b487d29e00d242"
|
||||
integrity sha512-TIGDradVFoGck86VIuM38KaDeNxdKaP2ti93UpQeFw26ZhPIeTAa6wUgnz4DQP6bjIvQmXlYJ16ETZb4tFYygg==
|
||||
turbo-darwin-64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.3.2-canary.1.tgz#a2ab459ea35021a02bcf7c1226547e6cee9bae82"
|
||||
integrity sha512-h1Dd6qx8L2FZG86zWgafEgw6JwuWI2hla4PNXP/jiLEp7QuALGONJ2jdwNmsuBj0+q47eQjY9Q1tZtVvnY/iKA==
|
||||
|
||||
turbo-darwin-arm64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.3.1.tgz#94a361e4e73ad02995303cf6c3d8cb03e85fcae4"
|
||||
integrity sha512-aLBq8KiMMmop7uKBkvDt/y+eER2UzxZyUzh1KWcZ7DZB5tFZnknEUyf2qggY2vd2WcDVfQ1EUjZ0MFxhhVaVzA==
|
||||
turbo-darwin-arm64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.3.2-canary.1.tgz#fb5672f917de5b72a0e654de0b22bba9dee05b98"
|
||||
integrity sha512-zM5BHkxHJltKK6isJilVL7L3dlYa6WF5VPfYOAekYor3u2ZhNsgFLGom+YXz22LD/csP2giRGokREObA7q0YJQ==
|
||||
|
||||
turbo-freebsd-64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.3.1.tgz#64b8fc1b9f2ad9b76b532ffdcce267b2934ecb86"
|
||||
integrity sha512-BOr/ifmxjlBeuDkDQLUJtzqzXQ2zPHHcI14U9Ys+z4Mza1uzQn/oSJqQvU5RuyRBVai7noMrpPS7QuKtDz0Cyg==
|
||||
turbo-freebsd-64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.3.2-canary.1.tgz#6f3752f8f274463eac4e54d3d0c871866161b058"
|
||||
integrity sha512-ZepqMN1relzuqr3g16wh0bXVKoBKzEivkGh1NVm87sDE5nvwLuB9lOCnxg89xb31PdJAyVr5UGeqVE5SfYltww==
|
||||
|
||||
turbo-freebsd-arm64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.3.1.tgz#b798af9b8898210058ca2752eadb711369f9ecea"
|
||||
integrity sha512-bHPZjK4xnGLz6/oxl5XmWhdYOdtBMSadrGhptWSZ0wBGNn/gQzDTeZAkQeqhh25AD0eM1hzDe8QUz8GlS43lrA==
|
||||
turbo-freebsd-arm64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.3.2-canary.1.tgz#b32ae4452b75ba597f528560f0aacc3dd03ce5f2"
|
||||
integrity sha512-gL/U8Su+GjvdI2yon+revsRFi/GfB/CdWGvDzdsore4eO1/V1DiACDRJDzf+/gvNdUzoD3cwbpiKGFuaZ7wVow==
|
||||
|
||||
turbo-linux-32@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.3.1.tgz#9eecada1c13f6391a7c6267349a0486987144093"
|
||||
integrity sha512-c5okimusfvivu9wS8MKSr+rXpQAV+M4TyR9JX+spIK8B1I7AjfECAqiK2D5WFWO1bQ33bUAuxXOEpUuLpgEm+g==
|
||||
turbo-linux-32@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.3.2-canary.1.tgz#ef8afa121abca9712deb30f1de9931b7f837771f"
|
||||
integrity sha512-8jxYYI4q2AHODKgO1XQ7KL7ufRFfGT4phi0JPs4KilaYEgNvDGSIDr2d8BHPVJr3exlb884ZcAW1tm+0t0WCog==
|
||||
|
||||
turbo-linux-64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.3.1.tgz#eaf195b90a80f238561ab11fbde17c07af481c57"
|
||||
integrity sha512-O0pNX+N5gbmRcyZT+jsCPUNCN3DpIZHqNN35j7MT5nr0IkZa83CGbZnrEc+7Qws//jFJ26EngqD/JyRB2E8nwQ==
|
||||
turbo-linux-64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.3.2-canary.1.tgz#d06932e2820b81e44747221de85903870677be17"
|
||||
integrity sha512-uCHCQ1HZdns78hr2Z6N3zZwFrUYJdyYRIPWj12TwvtTEErTARAcKvtWV9mQkkXvzkkmUDHJoTsSl5cIyhtoreg==
|
||||
|
||||
turbo-linux-arm64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.3.1.tgz#ff9dc17c352c5f59440cb55cff59cb8b23db9d1b"
|
||||
integrity sha512-D6+1MeS/x+/VCCooHPU4NIpB8qI/eW70eMRA79bqTPaxxluP0g2CaxXgucco05P51YtNsSxeVcH7X76iadON6Q==
|
||||
turbo-linux-arm64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.3.2-canary.1.tgz#c127b72925bca97e67f9ac5a31c99ab6eff56a3e"
|
||||
integrity sha512-5JjIQTuDo5RALnKvxPholfljiWxVwhyUpBm8xYNMtufR8CmbkjsNZgNGm8cyFXl3syHdLOhL/PsCpeVaiWDlUw==
|
||||
|
||||
turbo-linux-arm@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.3.1.tgz#6be53e62a60a3c6f3ab33585f0442eb7441ecf3a"
|
||||
integrity sha512-f+r6JIwv/7ylxxJtgVi8cVw+6oNoD/r1IMTU6ejH8bfyMZZko4kkNwH9VYribQ44KDkJEgzdltnzFG5f6Hz10g==
|
||||
turbo-linux-arm@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.3.2-canary.1.tgz#e3323a97c236ebad748cd3e304e20ce7578f69fb"
|
||||
integrity sha512-xEp/twlTo8Q5TaMz3g7UCtbPdO/VZS0ugAZ2egmbBpkEIdSQ7wjME8z7cgjK/Wc2l9y0BEuA/mc/ndmO43LaNw==
|
||||
|
||||
turbo-linux-mips64le@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.3.1.tgz#ceddf8c8e222e66d05f7a68a71f66a2a3a0272a3"
|
||||
integrity sha512-yL64jgwVCziOpBcdpMxIsczkgwwOvmaqKObFKWyCNlk/LOl5NKODLwXEaryLaALtpwUAoS4ltMSI64gKqmLrOA==
|
||||
turbo-linux-mips64le@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.3.2-canary.1.tgz#33bd2a9d35ea4ed46a8aaefac65a629afdae741c"
|
||||
integrity sha512-oOZD03ZyfOxifgi3YAAbtcnZtCA6fpsc2/y6R5sm9jRpXlia7PCbQLiV4H1UWCfmsQzUsLCTTZmO+D8K2rjymg==
|
||||
|
||||
turbo-linux-ppc64le@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.3.1.tgz#aa5658f6d19775e06b9fd136491dceab93ecffb2"
|
||||
integrity sha512-tjnM+8RosykS1lBpOPLDXGOz/Po2h796ty17uBd7IFslWPOI16a/akFOFoLH8PCiGGJMe3CYgRhEKn4sPWNxFA==
|
||||
turbo-linux-ppc64le@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.3.2-canary.1.tgz#f352723088b736179b867de4646e777b0c54e9f5"
|
||||
integrity sha512-JtFMPdO+N6lYCFO7gN042CdzQPWvF2ow77Hv1oOpVkyU2X9seK73XHmv+15dan92/flslZLFAW8T93kiXfsJug==
|
||||
|
||||
turbo-windows-32@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.3.1.tgz#e6e570bb381d9a4f78ea6e72102ab9bf493a3ad2"
|
||||
integrity sha512-Snnv+TVigulqwK6guHKndMlrLw88NXj8BtHRGrEksPR0QkyuHlwLf+tHYB4HmvpUl4W9lnXQf4hsljWP64BEdw==
|
||||
turbo-windows-32@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.3.2-canary.1.tgz#5c9b0c8a65002dfb476e0fc3b7049d02982a5d17"
|
||||
integrity sha512-xDi61dm5CbLGpi2nu20+fWcl7IcSayqQYtQNztVqyAv9TpP84gzItuETOxwNyK7BivZ0BTMuVhtVUfc44ZxG+A==
|
||||
|
||||
turbo-windows-64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.3.1.tgz#f891097331125c935cdaa160cc80c4cfc3e61b0e"
|
||||
integrity sha512-gLeohHG07yIhON1Pp0YNE00i/yzip2GFhkA6HdJaK95uE5bKULpqxuO414hOS/WzGwrGVXBKCImfe24XXh5T+Q==
|
||||
turbo-windows-64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.3.2-canary.1.tgz#8a6ddd2f02a7518c253a19461e3e81e9b01eec62"
|
||||
integrity sha512-uj4RVdVXIffTOeozFk8df+hgLUOZInkFvUTJ9jEKSNR/9zF9QXz7EkeQF8Cq+f840W7zNMDxciGBls3SWWTX0w==
|
||||
|
||||
turbo-windows-arm64@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.3.1.tgz#5abe1743b93e272641018cef213b21ac6c984f04"
|
||||
integrity sha512-0MWcHLvYgs/qdcoTFZ55nu8HhrpeiwXEMw9cbNfgqTlzy3OsrAsovYEJFyQ8KSxeploiD+QJlCdvhxx+5C0tlA==
|
||||
turbo-windows-arm64@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-1.3.2-canary.1.tgz#c7b2449c5aec3d2a14dd0169a0e79e7c7eb57b80"
|
||||
integrity sha512-rtU97ntfMRIr3IscaB3VwCxXCb60CkaM35NdTM3Yr+5H8UplmzQt1iBV8+Zc8/JO5YDfWD82dGZKVw4Oou+f2w==
|
||||
|
||||
turbo@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.3.1.tgz#8091f3c8b654addaac84f9452476204a879b32ea"
|
||||
integrity sha512-DXckoGKlZgvTn/PrHpBI/57aeXR7tfyPf2dK+4LmBczt24ELA3o6eYHeA7KzfpSYhB2LE9qveYFQ6mJ1OzGjjg==
|
||||
turbo@1.3.2-canary.1:
|
||||
version "1.3.2-canary.1"
|
||||
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.3.2-canary.1.tgz#df87f97ea67c4b627a378af941e6238e6122c53b"
|
||||
integrity sha512-qrSrKjkKDn7afDMz++RXg84sXBmd+CprnmJNNQq7l1Ao0eOPRpe//uh4JsULgjxYHHLeB2Re1fJ02HF282Kaww==
|
||||
optionalDependencies:
|
||||
turbo-android-arm64 "1.3.1"
|
||||
turbo-darwin-64 "1.3.1"
|
||||
turbo-darwin-arm64 "1.3.1"
|
||||
turbo-freebsd-64 "1.3.1"
|
||||
turbo-freebsd-arm64 "1.3.1"
|
||||
turbo-linux-32 "1.3.1"
|
||||
turbo-linux-64 "1.3.1"
|
||||
turbo-linux-arm "1.3.1"
|
||||
turbo-linux-arm64 "1.3.1"
|
||||
turbo-linux-mips64le "1.3.1"
|
||||
turbo-linux-ppc64le "1.3.1"
|
||||
turbo-windows-32 "1.3.1"
|
||||
turbo-windows-64 "1.3.1"
|
||||
turbo-windows-arm64 "1.3.1"
|
||||
turbo-android-arm64 "1.3.2-canary.1"
|
||||
turbo-darwin-64 "1.3.2-canary.1"
|
||||
turbo-darwin-arm64 "1.3.2-canary.1"
|
||||
turbo-freebsd-64 "1.3.2-canary.1"
|
||||
turbo-freebsd-arm64 "1.3.2-canary.1"
|
||||
turbo-linux-32 "1.3.2-canary.1"
|
||||
turbo-linux-64 "1.3.2-canary.1"
|
||||
turbo-linux-arm "1.3.2-canary.1"
|
||||
turbo-linux-arm64 "1.3.2-canary.1"
|
||||
turbo-linux-mips64le "1.3.2-canary.1"
|
||||
turbo-linux-ppc64le "1.3.2-canary.1"
|
||||
turbo-windows-32 "1.3.2-canary.1"
|
||||
turbo-windows-64 "1.3.2-canary.1"
|
||||
turbo-windows-arm64 "1.3.2-canary.1"
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
|
||||
Reference in New Issue
Block a user