mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 04:22:13 +00:00
Compare commits
38 Commits
@vercel/no
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d6088e0b5 | ||
|
|
c925dc4a1b | ||
|
|
21444a38e5 | ||
|
|
fa9789a93e | ||
|
|
5c12ed6950 | ||
|
|
06d2d860e4 | ||
|
|
b735f37fd9 | ||
|
|
d91f3afcbf | ||
|
|
58d9789e60 | ||
|
|
7457767a77 | ||
|
|
5dedc7b2ce | ||
|
|
4337ea0654 | ||
|
|
a26cbd8199 | ||
|
|
3eb9d8c892 | ||
|
|
83741a0eb9 | ||
|
|
9db0298981 | ||
|
|
af29e9be49 | ||
|
|
c9d53d4e3e | ||
|
|
a26ea7bf12 | ||
|
|
866d0c173d | ||
|
|
5f561f8cfa | ||
|
|
139e8cdb17 | ||
|
|
6529a9ab9c | ||
|
|
61e6af3740 | ||
|
|
8e44ef5b9d | ||
|
|
fe9e27c459 | ||
|
|
8a6dc204fd | ||
|
|
73e558913a | ||
|
|
464cb26255 | ||
|
|
80e0bab0ec | ||
|
|
f900ca8daf | ||
|
|
9ee7d31957 | ||
|
|
1eb76a3ae7 | ||
|
|
ccd7eb1fb7 | ||
|
|
41c44d6594 | ||
|
|
446ac49e2b | ||
|
|
d3c1267e24 | ||
|
|
b09d7b6130 |
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -63,16 +63,21 @@ updates:
|
||||
allow:
|
||||
- dependency-name: '@remix-run*'
|
||||
- dependency-name: '@shopify*'
|
||||
- dependency-name: 'remix*'
|
||||
ignore:
|
||||
- dependency-name: '@remix-run*'
|
||||
update-types:
|
||||
['version-update:semver-major', 'version-update:semver-patch']
|
||||
- dependency-name: 'remix*'
|
||||
update-types:
|
||||
['version-update:semver-major', 'version-update:semver-patch']
|
||||
- dependency-name: '@shopify*'
|
||||
update-types:
|
||||
['version-update:semver-major', 'version-update:semver-patch']
|
||||
groups:
|
||||
core:
|
||||
patterns:
|
||||
- 'remix*'
|
||||
- '@remix-run*'
|
||||
- '@shopify*'
|
||||
update-types:
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -99,7 +99,7 @@ jobs:
|
||||
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
|
||||
- name: 'Upload Test Report to Datadog'
|
||||
if: ${{ steps['turbo-summary'].outputs.misses != '0' && !cancelled() }}
|
||||
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
|
||||
run: 'npx @datadog/datadog-ci@2.36.0 junit upload --service vercel-cli .junit-reports'
|
||||
env:
|
||||
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}
|
||||
DD_ENV: ci
|
||||
|
||||
6
examples/CHANGELOG.md
vendored
6
examples/CHANGELOG.md
vendored
@@ -4,6 +4,12 @@
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- examples: Update Astro template. ([#11687](https://github.com/vercel/vercel/pull/11687))
|
||||
|
||||
## null
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- chore: update Nuxt example ([#10869](https://github.com/vercel/vercel/pull/10869))
|
||||
|
||||
## null
|
||||
|
||||
4
examples/astro/.gitignore
vendored
4
examples/astro/.gitignore
vendored
@@ -1,3 +1,6 @@
|
||||
# astro
|
||||
.astro
|
||||
|
||||
# build output
|
||||
dist/
|
||||
.output/
|
||||
@@ -11,7 +14,6 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases:
|
||||
|
||||
- `/` - A static page (pre-rendered)
|
||||
- `/ssr` - A page that uses server-side rendering (through [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions))
|
||||
- `/ssr` - A page that uses server-side rendering (through [Vercel Functions](https://vercel.com/docs/functions))
|
||||
- `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the [Vercel Edge Network](https://vercel.com/docs/edge-network/overview) using `cache-control` headers
|
||||
- `/image` - Astro [Asset](https://docs.astro.build/en/guides/assets/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
|
||||
- `/edge.json` - An Astro API Endpoint that returns JSON data using [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions)
|
||||
- `/image` - Astro [Asset](https://docs.astro.build/en/guides/images/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
|
||||
|
||||
Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro).
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
// Use Vercel Edge Functions (Recommended)
|
||||
import vercel from '@astrojs/vercel/edge';
|
||||
// Can also use Serverless Functions
|
||||
// import vercel from '@astrojs/vercel/serverless';
|
||||
// Or a completely static build
|
||||
// import vercel from '@astrojs/vercel/static';
|
||||
|
||||
export default defineConfig({
|
||||
output: 'server',
|
||||
experimental: {
|
||||
assets: true
|
||||
},
|
||||
adapter: vercel({
|
||||
imageService: true,
|
||||
}),
|
||||
});
|
||||
9
examples/astro/astro.config.ts
Normal file
9
examples/astro/astro.config.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import vercelServerless from '@astrojs/vercel/serverless';
|
||||
|
||||
export default defineConfig({
|
||||
output: 'server',
|
||||
adapter: vercelServerless({
|
||||
imageService: true,
|
||||
}),
|
||||
});
|
||||
@@ -8,9 +8,9 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/vercel": "3.8.2",
|
||||
"astro": "^2.10.14",
|
||||
"react": "18.2.0",
|
||||
"web-vitals": "^3.3.1"
|
||||
"@astrojs/vercel": "7.6.0",
|
||||
"astro": "^4.9.2",
|
||||
"react": "18.3.1",
|
||||
"web-vitals": "^4.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
export async function get() {
|
||||
return new Response(JSON.stringify({ time: new Date() }), {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': 's-maxage=10, stale-while-revalidate',
|
||||
},
|
||||
});
|
||||
}
|
||||
2
examples/package.json
vendored
2
examples/package.json
vendored
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.4.1",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/frameworks": "3.0.2"
|
||||
},
|
||||
"version": null
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @vercel-internals/types
|
||||
|
||||
## 1.0.38
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
|
||||
- @vercel/build-utils@8.2.2
|
||||
|
||||
## 1.0.37
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
|
||||
- @vercel/build-utils@8.2.1
|
||||
|
||||
## 1.0.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d3c1267e2`](https://github.com/vercel/vercel/commit/d3c1267e24082789ea6382cf6af81dd40df288ff), [`ccd7eb1fb`](https://github.com/vercel/vercel/commit/ccd7eb1fb78f7ac9effdbe1935de3bda82c97fe3)]:
|
||||
- @vercel/build-utils@8.2.0
|
||||
|
||||
## 1.0.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@vercel-internals/types",
|
||||
"version": "1.0.35",
|
||||
"version": "1.0.38",
|
||||
"types": "index.d.ts",
|
||||
"main": "index.d.ts",
|
||||
"files": [
|
||||
@@ -10,7 +10,7 @@
|
||||
"dependencies": {
|
||||
"@types/node": "14.14.31",
|
||||
"@vercel-internals/constants": "1.0.4",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/routing-utils": "3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# @vercel/build-utils
|
||||
|
||||
## 8.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Change node 16.x EOL for Vercel ([#11704](https://github.com/vercel/vercel/pull/11704))
|
||||
|
||||
- Improve error message and refactor ([#11706](https://github.com/vercel/vercel/pull/11706))
|
||||
|
||||
- [built-utils] Handle case of not having lockfile when corepack is enabled ([#11697](https://github.com/vercel/vercel/pull/11697))
|
||||
|
||||
## 8.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [node] update node@16 deprecation day ([#11671](https://github.com/vercel/vercel/pull/11671))
|
||||
|
||||
## 8.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- fix corepack detection for package manager version determination ([#11596](https://github.com/vercel/vercel/pull/11596))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix triggering of ignored project settings node version warning ([#11550](https://github.com/vercel/vercel/pull/11550))
|
||||
|
||||
## 8.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "8.1.3",
|
||||
"version": "8.2.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -13,7 +13,7 @@ export const NODE_VERSIONS: NodeVersion[] = [
|
||||
major: 16,
|
||||
range: '16.x',
|
||||
runtime: 'nodejs16.x',
|
||||
discontinueDate: new Date('2024-06-15'),
|
||||
discontinueDate: new Date('2025-01-31'),
|
||||
},
|
||||
{
|
||||
major: 14,
|
||||
|
||||
@@ -240,38 +240,51 @@ export function getSpawnOptions(
|
||||
|
||||
export async function getNodeVersion(
|
||||
destPath: string,
|
||||
nodeVersionFallback = process.env.VERCEL_PROJECT_SETTINGS_NODE_VERSION,
|
||||
fallbackVersion = process.env.VERCEL_PROJECT_SETTINGS_NODE_VERSION,
|
||||
config: Config = {},
|
||||
meta: Meta = {},
|
||||
availableVersions = getAvailableNodeVersions()
|
||||
): Promise<NodeVersion> {
|
||||
const latest = getLatestNodeVersion(availableVersions);
|
||||
const latestVersion = getLatestNodeVersion(availableVersions);
|
||||
if (meta.isDev) {
|
||||
// Use the system-installed version of `node` in PATH for `vercel dev`
|
||||
return { ...latest, runtime: 'nodejs' };
|
||||
return { ...latestVersion, runtime: 'nodejs' };
|
||||
}
|
||||
const { packageJson } = await scanParentDirs(destPath, true);
|
||||
let nodeVersion = config.nodeVersion || nodeVersionFallback;
|
||||
let isAuto = true;
|
||||
const configuredVersion = config.nodeVersion || fallbackVersion;
|
||||
|
||||
const packageJsonVersion = packageJson?.engines?.node;
|
||||
const supportedNodeVersion = await getSupportedNodeVersion(
|
||||
packageJsonVersion || configuredVersion,
|
||||
!packageJsonVersion,
|
||||
availableVersions
|
||||
);
|
||||
|
||||
if (packageJson?.engines?.node) {
|
||||
const { node } = packageJson.engines;
|
||||
if (nodeVersion && validRange(node) && !intersects(nodeVersion, node)) {
|
||||
if (
|
||||
configuredVersion &&
|
||||
!intersects(configuredVersion, supportedNodeVersion.range)
|
||||
) {
|
||||
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`
|
||||
`Warning: Due to "engines": { "node": "${node}" } in your \`package.json\` file, the Node.js Version defined in your Project Settings ("${configuredVersion}") will not apply. Learn More: http://vercel.link/node-version`
|
||||
);
|
||||
} else if (coerce(node)?.raw === node) {
|
||||
}
|
||||
|
||||
if (coerce(node)?.raw === node) {
|
||||
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)) {
|
||||
} else if (
|
||||
validRange(node) &&
|
||||
intersects(`${latestVersion.major + 1}.x`, node)
|
||||
) {
|
||||
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;
|
||||
}
|
||||
return getSupportedNodeVersion(nodeVersion, isAuto, availableVersions);
|
||||
return supportedNodeVersion;
|
||||
}
|
||||
|
||||
export async function scanParentDirs(
|
||||
@@ -340,7 +353,9 @@ export async function scanParentDirs(
|
||||
// TODO: read "bun-lockfile-format-v0"
|
||||
lockfileVersion = 0;
|
||||
} else {
|
||||
cliType = 'npm';
|
||||
cliType = packageJson
|
||||
? detectPackageManagerNameWithoutLockfile(packageJson)
|
||||
: 'npm';
|
||||
}
|
||||
|
||||
const packageJsonPath = pkgJsonPath || undefined;
|
||||
@@ -353,6 +368,37 @@ export async function scanParentDirs(
|
||||
};
|
||||
}
|
||||
|
||||
function detectPackageManagerNameWithoutLockfile(packageJson: PackageJson) {
|
||||
const packageJsonPackageManager = packageJson.packageManager;
|
||||
if (usingCorepack(process.env, packageJsonPackageManager)) {
|
||||
const corepackPackageManager = validateVersionSpecifier(
|
||||
packageJsonPackageManager
|
||||
);
|
||||
switch (corepackPackageManager?.packageName) {
|
||||
case 'npm':
|
||||
case 'pnpm':
|
||||
case 'yarn':
|
||||
case 'bun':
|
||||
return corepackPackageManager.packageName;
|
||||
case undefined:
|
||||
return 'npm';
|
||||
default:
|
||||
throw new Error(
|
||||
`Unknown package manager "${corepackPackageManager?.packageName}". Change your package.json "packageManager" field to a known package manager: npm, pnpm, yarn, bun.`
|
||||
);
|
||||
}
|
||||
}
|
||||
return 'npm';
|
||||
}
|
||||
|
||||
function usingCorepack(
|
||||
env: { [x: string]: string | undefined },
|
||||
packageJsonPackageManager: string | undefined
|
||||
) {
|
||||
const corepackFlagged = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
||||
return corepackFlagged && Boolean(packageJsonPackageManager);
|
||||
}
|
||||
|
||||
export async function walkParentDirs({
|
||||
base,
|
||||
start,
|
||||
@@ -413,9 +459,8 @@ export async function runNpmInstall(
|
||||
|
||||
try {
|
||||
await runNpmInstallSema.acquire();
|
||||
const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(
|
||||
destPath
|
||||
);
|
||||
const { cliType, packageJsonPath, packageJson, lockfileVersion } =
|
||||
await scanParentDirs(destPath, true);
|
||||
|
||||
if (!packageJsonPath) {
|
||||
debug(
|
||||
@@ -450,6 +495,7 @@ export async function runNpmInstall(
|
||||
opts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager: packageJson?.packageManager,
|
||||
nodeVersion,
|
||||
env,
|
||||
});
|
||||
@@ -534,14 +580,18 @@ export async function runNpmInstall(
|
||||
export function getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager,
|
||||
nodeVersion,
|
||||
env,
|
||||
}: {
|
||||
cliType: CliType;
|
||||
lockfileVersion: number | undefined;
|
||||
packageJsonPackageManager?: string | undefined;
|
||||
nodeVersion: NodeVersion | undefined;
|
||||
env: { [x: string]: string | undefined };
|
||||
}) {
|
||||
const corepackEnabled = usingCorepack(env, packageJsonPackageManager);
|
||||
|
||||
const {
|
||||
detectedLockfile,
|
||||
detectedPackageManager,
|
||||
@@ -549,14 +599,19 @@ export function getEnvForPackageManager({
|
||||
} = getPathOverrideForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
corepackEnabled,
|
||||
nodeVersion,
|
||||
env,
|
||||
});
|
||||
|
||||
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
||||
debug(
|
||||
`Detected ${detectedPackageManager} given lockfileVersion "${lockfileVersion}", package manager cli "${cliType}", and corepack enabled? ${corepackEnabled}: ${newPath}`
|
||||
);
|
||||
if (corepackEnabled) {
|
||||
debug(
|
||||
`Detected corepack use for "${packageJsonPackageManager}". Not overriding package manager version.`
|
||||
);
|
||||
} else {
|
||||
debug(
|
||||
`Detected ${detectedPackageManager}. Added "${newPath}" to path. Based on assumed package manager "${cliType}", lockfile "${detectedLockfile}", and lockfileVersion "${lockfileVersion}"`
|
||||
);
|
||||
}
|
||||
|
||||
const newEnv: { [x: string]: string | undefined } = {
|
||||
...env,
|
||||
@@ -642,13 +697,13 @@ function shouldUseNpm7(
|
||||
export function getPathOverrideForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
corepackEnabled,
|
||||
nodeVersion,
|
||||
env,
|
||||
}: {
|
||||
cliType: CliType;
|
||||
lockfileVersion: number | undefined;
|
||||
corepackEnabled: boolean;
|
||||
nodeVersion: NodeVersion | undefined;
|
||||
env: { [x: string]: string | undefined };
|
||||
}): {
|
||||
/**
|
||||
* Which lockfile was detected.
|
||||
@@ -670,8 +725,6 @@ export function getPathOverrideForPackageManager({
|
||||
path: undefined,
|
||||
};
|
||||
|
||||
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
||||
|
||||
switch (cliType) {
|
||||
case 'npm':
|
||||
switch (true) {
|
||||
@@ -732,9 +785,43 @@ export function getPathOverrideForPackageManager({
|
||||
}
|
||||
}
|
||||
|
||||
function validateVersionSpecifier(version?: string) {
|
||||
if (!version) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [before, after, ...extra] = version.split('@');
|
||||
|
||||
if (extra.length) {
|
||||
// should not have more than one `@`
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!before) {
|
||||
// should have a package before the `@`
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!after) {
|
||||
// should have a version after the `@`
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!validRange(after)) {
|
||||
// the version after the `@` should be a valid semver value
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
packageName: before,
|
||||
packageVersionRange: after,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get the binary paths that link to the used package manager.
|
||||
* Note: Make sure it doesn't contain any `console.log` calls.
|
||||
* @deprecated use `getEnvForPackageManager` instead
|
||||
*/
|
||||
export function getPathForPackageManager({
|
||||
cliType,
|
||||
@@ -766,11 +853,16 @@ export function getPathForPackageManager({
|
||||
*/
|
||||
yarnNodeLinker: string | undefined;
|
||||
} {
|
||||
// This is not the correct check for whether or not corepack is being used. For that, you'd have to check
|
||||
// the package.json's `packageManager` property. However, this deprecated function is keeping it's old,
|
||||
// broken behavior.
|
||||
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
|
||||
|
||||
const overrides = getPathOverrideForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
corepackEnabled,
|
||||
nodeVersion,
|
||||
env,
|
||||
});
|
||||
|
||||
const alreadyInPath = (newPath: string) => {
|
||||
@@ -805,10 +897,14 @@ export async function runCustomInstallCommand({
|
||||
spawnOpts?: SpawnOptions;
|
||||
}) {
|
||||
console.log(`Running "install" command: \`${installCommand}\`...`);
|
||||
const { cliType, lockfileVersion } = await scanParentDirs(destPath);
|
||||
const { cliType, lockfileVersion, packageJson } = await scanParentDirs(
|
||||
destPath,
|
||||
true
|
||||
);
|
||||
const env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager: packageJson?.packageManager,
|
||||
nodeVersion,
|
||||
env: spawnOpts?.env || {},
|
||||
});
|
||||
@@ -846,6 +942,7 @@ export async function runPackageJsonScript(
|
||||
env: getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager: packageJson?.packageManager,
|
||||
nodeVersion: undefined,
|
||||
env: cloneEnv(process.env, spawnOpts?.env),
|
||||
}),
|
||||
|
||||
@@ -35,6 +35,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 1,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -51,6 +52,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -69,6 +71,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: 'pnpm@latest',
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -87,6 +90,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -105,6 +109,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -123,6 +128,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'yarn',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -140,6 +146,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'yarn',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -158,6 +165,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 5.4,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -177,6 +185,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 6.0,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -196,6 +205,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 9.0,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -215,6 +225,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'bun',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 0,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -234,6 +245,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: 'npm@latest',
|
||||
lockfileVersion: 5.4,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -252,6 +264,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 5.4,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -270,6 +283,7 @@ describe('Test `getEnvForPackageManager()`', () => {
|
||||
getEnvForPackageManager({
|
||||
cliType: args.cliType,
|
||||
lockfileVersion: args.lockfileVersion,
|
||||
packageJsonPackageManager: args.packageJsonPackageManager,
|
||||
nodeVersion: args.nodeVersion,
|
||||
env: args.env,
|
||||
})
|
||||
@@ -302,6 +316,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 1,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -318,6 +333,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -335,6 +351,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 14, range: '14.x', runtime: 'nodejs14.x' },
|
||||
packageJsonPackageManager: 'pnpm@latest',
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -353,6 +370,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'npm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 2,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -370,6 +388,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 5.3, // detects as pnpm@6, which is the default
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -387,6 +406,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 5.4,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -404,6 +424,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 6.1,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -421,6 +442,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 7.0,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -438,6 +460,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'bun',
|
||||
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
|
||||
packageJsonPackageManager: undefined,
|
||||
lockfileVersion: 0,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -455,6 +478,7 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
args: {
|
||||
cliType: 'pnpm',
|
||||
nodeVersion: { major: 16, range: '16.x', runtime: 'nodejs16.x' },
|
||||
packageJsonPackageManager: 'npm@latest',
|
||||
lockfileVersion: 5.4,
|
||||
env: {
|
||||
FOO: 'bar',
|
||||
@@ -472,16 +496,18 @@ describe('Test `getPathOverrideForPackageManager()`', () => {
|
||||
getPathOverrideForPackageManager({
|
||||
cliType: args.cliType,
|
||||
lockfileVersion: args.lockfileVersion,
|
||||
// naive assumption that enabling corepack as a feature means it's used, but this is fine for tests
|
||||
corepackEnabled: Boolean(args.env.ENABLE_EXPERIMENTAL_COREPACK),
|
||||
nodeVersion: args.nodeVersion,
|
||||
env: args.env,
|
||||
})
|
||||
).toStrictEqual(want);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test `getPathForPackageManager()`', () => {
|
||||
test.each<{
|
||||
name: string;
|
||||
args: Parameters<typeof getEnvForPackageManager>[0];
|
||||
args: Parameters<typeof getPathForPackageManager>[0];
|
||||
want: unknown;
|
||||
}>([
|
||||
{
|
||||
|
||||
21
packages/build-utils/test/unit.test.ts
vendored
21
packages/build-utils/test/unit.test.ts
vendored
@@ -221,6 +221,21 @@ it('should warn when package.json engines is greater than', async () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when project settings gets overrided', async () => {
|
||||
expect(
|
||||
await getNodeVersion(
|
||||
path.join(__dirname, 'pkg-engine-node-greaterthan'),
|
||||
undefined,
|
||||
{ nodeVersion: '16.x' },
|
||||
{}
|
||||
)
|
||||
).toHaveProperty('range', '20.x');
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Due to "engines": { "node": ">=16" } in your `package.json` file, the Node.js Version defined in your Project Settings ("16.x") will not apply. Learn More: http://vercel.link/node-version',
|
||||
'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(
|
||||
@@ -271,7 +286,7 @@ it('should throw for discontinued versions', async () => {
|
||||
// Mock a future date so that Node 16 becomes discontinued
|
||||
const realDateNow = Date.now;
|
||||
try {
|
||||
global.Date.now = () => new Date('2024-07-16').getTime();
|
||||
global.Date.now = () => new Date('2025-03-01').getTime();
|
||||
|
||||
expect(getSupportedNodeVersion('8.10.x', false)).rejects.toThrow();
|
||||
expect(getSupportedNodeVersion('8.10.x', true)).rejects.toThrow();
|
||||
@@ -341,8 +356,8 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
|
||||
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
|
||||
'Error: Node.js version 14.x has reached End-of-Life. Deployments created on or after 2023-08-15 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-06-15 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2024-06-15 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2025-01-31 will fail to build. Please set "engines": { "node": "20.x" } in your `package.json` file to use Node.js 20.',
|
||||
'Error: Node.js version 16.x has reached End-of-Life. Deployments created on or after 2025-01-31 will fail to build. Please set Node.js Version to 20.x in your Project Settings to use Node.js 20.',
|
||||
]);
|
||||
} finally {
|
||||
global.Date.now = realDateNow;
|
||||
|
||||
@@ -1,5 +1,78 @@
|
||||
# vercel
|
||||
|
||||
## 34.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [built-utils] Handle case of not having lockfile when corepack is enabled ([#11697](https://github.com/vercel/vercel/pull/11697))
|
||||
|
||||
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`fa9789a93`](https://github.com/vercel/vercel/commit/fa9789a93ebe64c4246f441590cb695d296af336), [`c925dc4a1`](https://github.com/vercel/vercel/commit/c925dc4a1bf3a47b684b5f7fd788ddd24ba1ed1e), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab), [`b735f37fd`](https://github.com/vercel/vercel/commit/b735f37fd92c707040e72084b0fdb4f8fd01dd51)]:
|
||||
- @vercel/build-utils@8.2.2
|
||||
- @vercel/next@4.2.16
|
||||
- @vercel/redwood@2.0.10
|
||||
- @vercel/remix-builder@2.1.7
|
||||
- @vercel/node@3.1.7
|
||||
- @vercel/static-build@2.5.11
|
||||
|
||||
## 34.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Adds a route for the `.rsc` pathname as well when app has ppr enabled but not all routes. ([#11681](https://github.com/vercel/vercel/pull/11681))
|
||||
|
||||
- Updated dependencies [[`7457767a7`](https://github.com/vercel/vercel/commit/7457767a77b03662c103a658273a46cf78359068), [`4337ea065`](https://github.com/vercel/vercel/commit/4337ea0654c4ee2c91c4464540f879d43da6696f)]:
|
||||
- @vercel/next@4.2.15
|
||||
|
||||
## 34.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`3eb9d8c89`](https://github.com/vercel/vercel/commit/3eb9d8c8929592960d88e0395e2a2443f7304d6b), [`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
|
||||
- @vercel/python@4.3.0
|
||||
- @vercel/build-utils@8.2.1
|
||||
- @vercel/node@3.1.6
|
||||
- @vercel/static-build@2.5.10
|
||||
|
||||
## 34.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Don't create streaming lambdas for pages router routes ([#11660](https://github.com/vercel/vercel/pull/11660))
|
||||
|
||||
- Updated dependencies [[`c9d53d4e3`](https://github.com/vercel/vercel/commit/c9d53d4e3e4591b9b6bde86100564c9ee4c6d1d4), [`5f561f8cf`](https://github.com/vercel/vercel/commit/5f561f8cfa4720801a5cf4598f193ab34539abb9)]:
|
||||
- @vercel/next@4.2.14
|
||||
|
||||
## 34.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix related to erroring when a prefetch route is not provided but the route is PPR enabled ([#11638](https://github.com/vercel/vercel/pull/11638))
|
||||
|
||||
- Updated dependencies [[`8e44ef5b9`](https://github.com/vercel/vercel/commit/8e44ef5b9d2cdbe743c7f1e3534f182465fed9bf), [`61e6af374`](https://github.com/vercel/vercel/commit/61e6af3740296c11015d0c3da84ee205020b0ea6)]:
|
||||
- @vercel/next@4.2.13
|
||||
|
||||
## 34.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Support incremental PPR for large applications ([#11625](https://github.com/vercel/vercel/pull/11625))
|
||||
|
||||
- Updated dependencies [[`73e558913`](https://github.com/vercel/vercel/commit/73e558913ab30ba097d7536a12fa8a7c967479f0)]:
|
||||
- @vercel/next@4.2.12
|
||||
|
||||
## 34.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Stop sending system environment variables in dev ([#11526](https://github.com/vercel/vercel/pull/11526))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d3c1267e2`](https://github.com/vercel/vercel/commit/d3c1267e24082789ea6382cf6af81dd40df288ff), [`ccd7eb1fb`](https://github.com/vercel/vercel/commit/ccd7eb1fb78f7ac9effdbe1935de3bda82c97fe3)]:
|
||||
- @vercel/build-utils@8.2.0
|
||||
- @vercel/node@3.1.5
|
||||
- @vercel/static-build@2.5.9
|
||||
|
||||
## 34.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "34.1.14",
|
||||
"version": "34.2.6",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -12,8 +12,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
|
||||
"vitest-unit-run": "pnpm vitest",
|
||||
"vitest-unit": "pnpm jest test/unit/ --listTests",
|
||||
"vitest-run": "vitest",
|
||||
"vitest-unit": "jest test/unit/ --listTests",
|
||||
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
|
||||
"test-dev": "pnpm test test/dev/",
|
||||
"coverage": "codecov",
|
||||
@@ -32,17 +32,17 @@
|
||||
"node": ">= 16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/fun": "1.1.0",
|
||||
"@vercel/go": "3.1.1",
|
||||
"@vercel/hydrogen": "1.0.2",
|
||||
"@vercel/next": "4.2.11",
|
||||
"@vercel/node": "3.1.4",
|
||||
"@vercel/python": "4.2.0",
|
||||
"@vercel/redwood": "2.0.9",
|
||||
"@vercel/remix-builder": "2.1.6",
|
||||
"@vercel/next": "4.2.16",
|
||||
"@vercel/node": "3.1.7",
|
||||
"@vercel/python": "4.3.0",
|
||||
"@vercel/redwood": "2.0.10",
|
||||
"@vercel/remix-builder": "2.1.7",
|
||||
"@vercel/ruby": "2.1.0",
|
||||
"@vercel/static-build": "2.5.8",
|
||||
"@vercel/static-build": "2.5.11",
|
||||
"chokidar": "3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -92,11 +92,11 @@
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel-internals/constants": "1.0.4",
|
||||
"@vercel-internals/get-package-json": "1.0.0",
|
||||
"@vercel-internals/types": "1.0.35",
|
||||
"@vercel/client": "13.2.6",
|
||||
"@vercel-internals/types": "1.0.38",
|
||||
"@vercel/client": "13.2.9",
|
||||
"@vercel/error-utils": "2.0.2",
|
||||
"@vercel/frameworks": "3.0.2",
|
||||
"@vercel/fs-detectors": "5.2.3",
|
||||
"@vercel/fs-detectors": "5.2.4",
|
||||
"@vercel/routing-utils": "3.1.0",
|
||||
"@vitest/expect": "1.4.0",
|
||||
"ajv": "6.12.2",
|
||||
|
||||
2
packages/cli/src/util/env/get-env-records.ts
vendored
2
packages/cli/src/util/env/get-env-records.ts
vendored
@@ -70,7 +70,7 @@ export async function pullEnvRecords(
|
||||
);
|
||||
const query = new URLSearchParams();
|
||||
|
||||
let url = `/v1/env/pull/${projectId}`;
|
||||
let url = `/v2/env/pull/${projectId}`;
|
||||
|
||||
if (target) {
|
||||
url += `/${encodeURIComponent(target)}`;
|
||||
|
||||
32
packages/cli/test/fixtures/e2e/cli-extension-exit-code/package-lock.json
generated
vendored
Normal file
32
packages/cli/test/fixtures/e2e/cli-extension-exit-code/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "cli-extension-exit-code",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"cli-extension-fail": "file:../cli-extension-fail"
|
||||
}
|
||||
},
|
||||
"../cli-extension-fail": {
|
||||
"bin": {
|
||||
"vercel-fail": "bin.js"
|
||||
}
|
||||
},
|
||||
"../cli-extension-whoami": {
|
||||
"extraneous": true,
|
||||
"bin": {
|
||||
"vercel-mywhoami": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-extension-fail": {
|
||||
"resolved": "../cli-extension-fail",
|
||||
"link": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"cli-extension-fail": {
|
||||
"version": "file:../cli-extension-fail"
|
||||
}
|
||||
}
|
||||
}
|
||||
6
packages/cli/test/fixtures/e2e/cli-extension-exit-code/package.json
vendored
Normal file
6
packages/cli/test/fixtures/e2e/cli-extension-exit-code/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"cli-extension-fail": "file:../cli-extension-fail"
|
||||
}
|
||||
}
|
||||
2
packages/cli/test/fixtures/e2e/cli-extension-fail/bin.js
vendored
Executable file
2
packages/cli/test/fixtures/e2e/cli-extension-fail/bin.js
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
process.exit(6);
|
||||
6
packages/cli/test/fixtures/e2e/cli-extension-fail/package.json
vendored
Normal file
6
packages/cli/test/fixtures/e2e/cli-extension-fail/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "cli-extension-fail",
|
||||
"bin": {
|
||||
"vercel-fail": "bin.js"
|
||||
}
|
||||
}
|
||||
32
packages/cli/test/integration-1.test.ts
vendored
32
packages/cli/test/integration-1.test.ts
vendored
@@ -263,6 +263,7 @@ test('[vc build] should build project with corepack and select pnpm@7.1.0', asyn
|
||||
path.join(directory, '.vercel/cache/corepack')
|
||||
);
|
||||
expect(contents).toEqual(['home', 'shim']);
|
||||
expect(output.stdout).toMatch(/Running "pnpm run build"/gm);
|
||||
} finally {
|
||||
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
|
||||
}
|
||||
@@ -291,6 +292,7 @@ test('[vc build] should build project with corepack and select yarn@2.4.3', asyn
|
||||
path.join(directory, '.vercel/cache/corepack')
|
||||
);
|
||||
expect(contents).toEqual(['home', 'shim']);
|
||||
expect(output.stdout).toMatch(/Running "yarn run build"/gm);
|
||||
} finally {
|
||||
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
|
||||
}
|
||||
@@ -917,9 +919,9 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
expect(homeJson['MY_STDIN_VAR']).toBe('{"expect":"quotes"}');
|
||||
expect(homeJson['MY_DECRYPTABLE_SECRET_ENV']).toBe('decryptable value');
|
||||
|
||||
// system env vars are automatically exposed
|
||||
expect(apiJson['VERCEL']).toBe('1');
|
||||
expect(homeJson['VERCEL']).toBe('1');
|
||||
// system env vars are hidden in dev
|
||||
expect(apiJson['VERCEL']).toBeUndefined();
|
||||
expect(homeJson['VERCEL']).toBeUndefined();
|
||||
|
||||
// sleep before kill, otherwise the dev process doesn't clean up and exit properly
|
||||
await sleep(100);
|
||||
@@ -949,7 +951,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
async function vcEnvPullFetchSystemVars() {
|
||||
const { exitCode, stdout, stderr } = await execCli(
|
||||
binaryPath,
|
||||
['env', 'pull', '-y'],
|
||||
['env', 'pull', '-y', '--environment', 'production'],
|
||||
{
|
||||
cwd: target,
|
||||
}
|
||||
@@ -963,7 +965,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
|
||||
expect(lines).toContain('VERCEL="1"');
|
||||
expect(lines).toContain('VERCEL_URL=""');
|
||||
expect(lines).toContain('VERCEL_ENV="development"');
|
||||
expect(lines).toContain('VERCEL_ENV="production"');
|
||||
expect(lines).toContain('VERCEL_GIT_PROVIDER=""');
|
||||
expect(lines).toContain('VERCEL_GIT_REPO_SLUG=""');
|
||||
}
|
||||
@@ -980,22 +982,24 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
const localhostNoProtocol = localhost[0].slice('http://'.length);
|
||||
|
||||
const apiJson = await apiRes.json();
|
||||
expect(apiJson['VERCEL']).toBe('1');
|
||||
// environment variables are not set in dev
|
||||
expect(apiJson['VERCEL']).toBeUndefined();
|
||||
expect(apiJson['VERCEL_ENV']).toBeUndefined();
|
||||
expect(apiJson['VERCEL_GIT_PROVIDER']).toBeUndefined();
|
||||
expect(apiJson['VERCEL_GIT_REPO_SLUG']).toBeUndefined();
|
||||
// except for these because vc dev
|
||||
expect(apiJson['VERCEL_URL']).toBe(localhostNoProtocol);
|
||||
expect(apiJson['VERCEL_ENV']).toBe('development');
|
||||
expect(apiJson['VERCEL_REGION']).toBe('dev1');
|
||||
expect(apiJson['VERCEL_GIT_PROVIDER']).toBe('');
|
||||
expect(apiJson['VERCEL_GIT_REPO_SLUG']).toBe('');
|
||||
|
||||
const homeUrl = localhost[0];
|
||||
const homeRes = await fetch(homeUrl);
|
||||
const homeJson = await homeRes.json();
|
||||
expect(homeJson['VERCEL']).toBe('1');
|
||||
expect(homeJson['VERCEL']).toBeUndefined();
|
||||
expect(homeJson['VERCEL_URL']).toBe(localhostNoProtocol);
|
||||
expect(homeJson['VERCEL_ENV']).toBe('development');
|
||||
expect(homeJson['VERCEL_REGION']).toBe(undefined);
|
||||
expect(homeJson['VERCEL_GIT_PROVIDER']).toBe('');
|
||||
expect(homeJson['VERCEL_GIT_REPO_SLUG']).toBe('');
|
||||
expect(homeJson['VERCEL_ENV']).toBeUndefined();
|
||||
expect(homeJson['VERCEL_REGION']).toBeUndefined();
|
||||
expect(homeJson['VERCEL_GIT_PROVIDER']).toBeUndefined();
|
||||
expect(homeJson['VERCEL_GIT_REPO_SLUG']).toBeUndefined();
|
||||
|
||||
// sleep before kill, otherwise the dev process doesn't clean up and exit properly
|
||||
await sleep(100);
|
||||
|
||||
13
packages/cli/test/integration-3.test.ts
vendored
13
packages/cli/test/integration-3.test.ts
vendored
@@ -1327,6 +1327,19 @@ test('should invoke CLI extension', async () => {
|
||||
expect(output.stdout, formatted).toContain(`Username: ${contextName}`);
|
||||
});
|
||||
|
||||
test('should pass through exit code for CLI extension', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures/e2e/cli-extension-exit-code');
|
||||
|
||||
// Ensure the `.bin` is populated in the fixture
|
||||
await runNpmInstall(fixture);
|
||||
|
||||
const output = await execCli(binaryPath, ['fail'], {
|
||||
cwd: fixture,
|
||||
reject: false,
|
||||
});
|
||||
expect(output.exitCode).toEqual(6);
|
||||
});
|
||||
|
||||
// NOTE: Order matters here. This must be the last test in the file.
|
||||
test('default command should prompt login with empty auth.json', async () => {
|
||||
await clearAuthConfig();
|
||||
|
||||
@@ -216,7 +216,7 @@ export function useProject(
|
||||
res.json(project);
|
||||
});
|
||||
client.scenario.get(
|
||||
`/v1/env/pull/${project.id}/:target?/:gitBranch?`,
|
||||
`/v2/env/pull/${project.id}/:target?/:gitBranch?`,
|
||||
(req, res) => {
|
||||
const target =
|
||||
typeof req.params.target === 'string'
|
||||
@@ -390,7 +390,7 @@ function exposeSystemEnvs(
|
||||
) {
|
||||
const envs: Env = {};
|
||||
|
||||
if (autoExposeSystemEnvs) {
|
||||
if (autoExposeSystemEnvs && target !== 'development') {
|
||||
envs['VERCEL'] = '1';
|
||||
envs['VERCEL_ENV'] = target || 'development';
|
||||
|
||||
|
||||
@@ -205,10 +205,17 @@ describe('env', () => {
|
||||
});
|
||||
const cwd = setupUnitFixture('vercel-env-pull');
|
||||
client.cwd = cwd;
|
||||
client.setArgv('env', 'pull', 'other.env', '--yes');
|
||||
client.setArgv(
|
||||
'env',
|
||||
'pull',
|
||||
'other.env',
|
||||
'--yes',
|
||||
'--environment',
|
||||
'production'
|
||||
);
|
||||
const exitCodePromise = env(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `development` Environment Variables for Project vercel-env-pull'
|
||||
'Downloading `production` Environment Variables for Project vercel-env-pull'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created other.env file');
|
||||
await expect(client.stderr).not.toOutput('and added it to .gitignore');
|
||||
@@ -218,10 +225,44 @@ describe('env', () => {
|
||||
|
||||
const productionFileHasVercelEnv = rawDevEnv
|
||||
.toString()
|
||||
.includes('VERCEL_ENV="development"');
|
||||
.includes('VERCEL_ENV="production"');
|
||||
expect(productionFileHasVercelEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not expose system env variables in dev', async () => {
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
autoExposeSystemEnvs: true,
|
||||
});
|
||||
const cwd = setupUnitFixture('vercel-env-pull');
|
||||
client.cwd = cwd;
|
||||
client.setArgv('env', 'pull', 'other.env', '--yes');
|
||||
const exitCodePromise = env(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `development` Environment Variables for Project vercel-env-pull'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created other.env file');
|
||||
await expect(client.stderr).not.toOutput('and added it to .gitignore');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
const devEnv = (
|
||||
await fs.readFile(path.join(cwd, 'other.env'))
|
||||
).toString();
|
||||
|
||||
const devFileHasVercelEnv = [
|
||||
'VERCEL',
|
||||
'VERCEL_ENV',
|
||||
'VERCEL_URL',
|
||||
'VERCEL_REGION',
|
||||
'VERCEL_DEPLOYMENT_ID',
|
||||
].some(envVar => devEnv.includes(envVar));
|
||||
expect(devFileHasVercelEnv).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show a delta string', async () => {
|
||||
const cwd = setupUnitFixture('vercel-env-pull-delta');
|
||||
client.cwd = cwd;
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @vercel/client
|
||||
|
||||
## 13.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
|
||||
- @vercel/build-utils@8.2.2
|
||||
|
||||
## 13.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
|
||||
- @vercel/build-utils@8.2.1
|
||||
|
||||
## 13.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d3c1267e2`](https://github.com/vercel/vercel/commit/d3c1267e24082789ea6382cf6af81dd40df288ff), [`ccd7eb1fb`](https://github.com/vercel/vercel/commit/ccd7eb1fb78f7ac9effdbe1935de3bda82c97fe3)]:
|
||||
- @vercel/build-utils@8.2.0
|
||||
|
||||
## 13.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "13.2.6",
|
||||
"version": "13.2.9",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -37,7 +37,7 @@
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/error-utils": "2.0.2",
|
||||
"@vercel/routing-utils": "3.1.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @vercel/fs-detectors
|
||||
|
||||
## 5.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add support for detecting Turborepo 2 ([#11680](https://github.com/vercel/vercel/pull/11680))
|
||||
|
||||
## 5.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/fs-detectors",
|
||||
"version": "5.2.3",
|
||||
"version": "5.2.4",
|
||||
"description": "Vercel filesystem detectors",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -37,7 +37,7 @@
|
||||
"@types/minimatch": "3.0.5",
|
||||
"@types/node": "14.18.33",
|
||||
"@types/semver": "7.3.10",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"jest-junit": "16.0.0",
|
||||
"typescript": "4.9.5"
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ import JSON5 from 'json5';
|
||||
import semver from 'semver';
|
||||
|
||||
export class MissingBuildPipeline extends Error {
|
||||
constructor() {
|
||||
super(
|
||||
'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.'
|
||||
);
|
||||
constructor(usesTasks: boolean) {
|
||||
const message = usesTasks
|
||||
? 'Missing required `build` task in turbo.json.'
|
||||
: 'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.';
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +66,15 @@ export async function getMonorepoDefaultSettings(
|
||||
]);
|
||||
|
||||
let hasBuildPipeline = false;
|
||||
let hasTurboTasks = false;
|
||||
let turboSemVer = null;
|
||||
|
||||
if (turboJSONBuf !== null) {
|
||||
const turboJSON = JSON5.parse(turboJSONBuf.toString('utf-8'));
|
||||
|
||||
if (turboJSON?.pipeline?.build) {
|
||||
hasTurboTasks = 'tasks' in (turboJSON || {});
|
||||
|
||||
if (turboJSON?.pipeline?.build || turboJSON?.tasks?.build) {
|
||||
hasBuildPipeline = true;
|
||||
}
|
||||
}
|
||||
@@ -89,7 +93,7 @@ export async function getMonorepoDefaultSettings(
|
||||
}
|
||||
|
||||
if (!hasBuildPipeline) {
|
||||
throw new MissingBuildPipeline();
|
||||
throw new MissingBuildPipeline(hasTurboTasks);
|
||||
}
|
||||
|
||||
if (projectPath === '/') {
|
||||
|
||||
9
packages/fs-detectors/test/fixtures/get-monorepo-default-settings/turbo-2/package.json
vendored
Normal file
9
packages/fs-detectors/test/fixtures/get-monorepo-default-settings/turbo-2/package.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"turbo": "latest"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "app-14",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js"
|
||||
}
|
||||
2
packages/fs-detectors/test/fixtures/get-monorepo-default-settings/turbo-2/turbo.json
vendored
Normal file
2
packages/fs-detectors/test/fixtures/get-monorepo-default-settings/turbo-2/turbo.json
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// TEST COMMENT TO VERIFY JSON5 SUPPORT
|
||||
{ "tasks": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] } } }
|
||||
@@ -17,11 +17,17 @@ describe('getMonorepoDefaultSettings', () => {
|
||||
);
|
||||
});
|
||||
test('MissingBuildPipeline is an error', () => {
|
||||
const missingBuildPipeline = new MissingBuildPipeline();
|
||||
const missingBuildPipeline = new MissingBuildPipeline(false);
|
||||
expect(missingBuildPipeline).toBeInstanceOf(Error);
|
||||
expect(missingBuildPipeline.message).toBe(
|
||||
'Missing required `build` pipeline in turbo.json or package.json Turbo configuration.'
|
||||
);
|
||||
|
||||
const missingBuildTask = new MissingBuildPipeline(true);
|
||||
expect(missingBuildTask).toBeInstanceOf(Error);
|
||||
expect(missingBuildTask.message).toBe(
|
||||
'Missing required `build` task in turbo.json.'
|
||||
);
|
||||
});
|
||||
|
||||
test.each([
|
||||
@@ -31,6 +37,7 @@ describe('getMonorepoDefaultSettings', () => {
|
||||
['turbo-npm', 'turbo', true, 'app-15', false, false],
|
||||
['turbo-npm-root-proj', 'turbo', true, 'app-root-proj', true, false],
|
||||
['turbo-latest', 'turbo', false, 'app-14', false, false],
|
||||
['turbo-2', 'turbo', false, 'app-14', false, false],
|
||||
['nx', 'nx', false, 'app-12', false, false],
|
||||
['nx-package-config', 'nx', false, 'app-11', false, false],
|
||||
['nx-project-and-package-config-1', 'nx', false, 'app-10', false, false],
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @vercel/gatsby-plugin-vercel-builder
|
||||
|
||||
## 2.0.33
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5c12ed695`](https://github.com/vercel/vercel/commit/5c12ed69500ceff6a9dc544eab0acd7af64c044a), [`21444a38e`](https://github.com/vercel/vercel/commit/21444a38e50ed680c91b0e3955f15e378eeda64b), [`06d2d860e`](https://github.com/vercel/vercel/commit/06d2d860e47aed792247bf929805b180ed6e2dab)]:
|
||||
- @vercel/build-utils@8.2.2
|
||||
|
||||
## 2.0.32
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`83741a0eb`](https://github.com/vercel/vercel/commit/83741a0eb9e44457b083e8790a11eb89984e6357)]:
|
||||
- @vercel/build-utils@8.2.1
|
||||
|
||||
## 2.0.31
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d3c1267e2`](https://github.com/vercel/vercel/commit/d3c1267e24082789ea6382cf6af81dd40df288ff), [`ccd7eb1fb`](https://github.com/vercel/vercel/commit/ccd7eb1fb78f7ac9effdbe1935de3bda82c97fe3)]:
|
||||
- @vercel/build-utils@8.2.0
|
||||
|
||||
## 2.0.30
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/gatsby-plugin-vercel-builder",
|
||||
"version": "2.0.30",
|
||||
"version": "2.0.33",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist",
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sinclair/typebox": "0.25.24",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/routing-utils": "3.1.0",
|
||||
"esbuild": "0.14.47",
|
||||
"etag": "1.8.1",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@types/node-fetch": "^2.3.0",
|
||||
"@types/tar": "6.1.5",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"async-retry": "1.3.3",
|
||||
"execa": "^1.0.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "14.18.33",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"execa": "3.2.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"jest-junit": "16.0.0"
|
||||
|
||||
@@ -51,11 +51,15 @@ export const build: BuildV2 = async ({
|
||||
);
|
||||
|
||||
const spawnOpts = getSpawnOptions(meta, nodeVersion);
|
||||
const { cliType, lockfileVersion } = await scanParentDirs(entrypointDir);
|
||||
const { cliType, lockfileVersion, packageJson } = await scanParentDirs(
|
||||
entrypointDir,
|
||||
true
|
||||
);
|
||||
|
||||
spawnOpts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager: packageJson?.packageManager,
|
||||
nodeVersion,
|
||||
env: spawnOpts.env || {},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
# @vercel/next
|
||||
|
||||
## 4.2.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- prevent /index from being incorrectly normalized in rewrites ([#11707](https://github.com/vercel/vercel/pull/11707))
|
||||
|
||||
- Upgrade to @vercel/nft 0.27.2 with browser remapping support ([#11700](https://github.com/vercel/vercel/pull/11700))
|
||||
|
||||
- ensure unmatched rsc rewrites are routed to correct handler ([#11688](https://github.com/vercel/vercel/pull/11688))
|
||||
|
||||
## 4.2.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ensure unmatched action rewrites are routed to correct handler ([#11686](https://github.com/vercel/vercel/pull/11686))
|
||||
|
||||
- Adds a route for the `.rsc` pathname as well when app has ppr enabled but not all routes. ([#11681](https://github.com/vercel/vercel/pull/11681))
|
||||
|
||||
## 4.2.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Don't create streaming lambdas for pages router routes ([#11660](https://github.com/vercel/vercel/pull/11660))
|
||||
|
||||
- Ensure user rewrites still match to action outputs ([#11628](https://github.com/vercel/vercel/pull/11628))
|
||||
|
||||
## 4.2.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix static case for detecting when a page supports PPR ([#11635](https://github.com/vercel/vercel/pull/11635))
|
||||
|
||||
- Fix related to erroring when a prefetch route is not provided but the route is PPR enabled ([#11638](https://github.com/vercel/vercel/pull/11638))
|
||||
|
||||
## 4.2.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Support incremental PPR for large applications ([#11625](https://github.com/vercel/vercel/pull/11625))
|
||||
|
||||
## 4.2.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "4.2.11",
|
||||
"version": "4.2.16",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -23,7 +23,7 @@
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.27.0"
|
||||
"@vercel/nft": "0.27.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
@@ -40,7 +40,7 @@
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "8.1.3",
|
||||
"@vercel/build-utils": "8.2.2",
|
||||
"@vercel/routing-utils": "3.1.0",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
|
||||
@@ -257,10 +257,15 @@ export const build: BuildV2 = async ({
|
||||
const nextVersionRange = await getNextVersionRange(entryPath);
|
||||
const nodeVersion = await getNodeVersion(entryPath, undefined, config, meta);
|
||||
const spawnOpts = getSpawnOptions(meta, nodeVersion);
|
||||
const { cliType, lockfileVersion } = await scanParentDirs(entryPath);
|
||||
const { cliType, lockfileVersion, packageJson } = await scanParentDirs(
|
||||
entryPath,
|
||||
true
|
||||
);
|
||||
|
||||
spawnOpts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
packageJsonPackageManager: packageJson?.packageManager,
|
||||
nodeVersion,
|
||||
env: spawnOpts.env || {},
|
||||
});
|
||||
@@ -1353,6 +1358,11 @@ export const build: BuildV2 = async ({
|
||||
experimentalPPRRoutes.add(route);
|
||||
}
|
||||
|
||||
const isAppPPREnabled = requiredServerFilesManifest
|
||||
? requiredServerFilesManifest.config.experimental?.ppr === true ||
|
||||
requiredServerFilesManifest.config.experimental?.ppr === 'incremental'
|
||||
: false;
|
||||
|
||||
if (requiredServerFilesManifest) {
|
||||
if (!routesManifest) {
|
||||
throw new Error(
|
||||
@@ -1408,6 +1418,7 @@ export const build: BuildV2 = async ({
|
||||
hasIsr500Page,
|
||||
variantsManifest,
|
||||
experimentalPPRRoutes,
|
||||
isAppPPREnabled,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1927,7 +1938,7 @@ export const build: BuildV2 = async ({
|
||||
canUsePreviewMode,
|
||||
bypassToken: prerenderManifest.bypassToken || '',
|
||||
isServerMode,
|
||||
experimentalPPRRoutes,
|
||||
isAppPPREnabled: false,
|
||||
hasActionOutputSupport: false,
|
||||
}).then(arr =>
|
||||
localizeDynamicRoutes(
|
||||
@@ -1958,7 +1969,7 @@ export const build: BuildV2 = async ({
|
||||
canUsePreviewMode,
|
||||
bypassToken: prerenderManifest.bypassToken || '',
|
||||
isServerMode,
|
||||
experimentalPPRRoutes,
|
||||
isAppPPREnabled: false,
|
||||
hasActionOutputSupport: false,
|
||||
}).then(arr =>
|
||||
arr.map(route => {
|
||||
@@ -2157,6 +2168,7 @@ export const build: BuildV2 = async ({
|
||||
appPathRoutesManifest,
|
||||
isSharedLambdas,
|
||||
canUsePreviewMode,
|
||||
isAppPPREnabled: false,
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
|
||||
@@ -144,6 +144,7 @@ export async function serverBuild({
|
||||
requiredServerFilesManifest,
|
||||
variantsManifest,
|
||||
experimentalPPRRoutes,
|
||||
isAppPPREnabled,
|
||||
}: {
|
||||
appPathRoutesManifest?: Record<string, string>;
|
||||
dynamicPages: string[];
|
||||
@@ -185,7 +186,15 @@ export async function serverBuild({
|
||||
requiredServerFilesManifest: NextRequiredServerFilesManifest;
|
||||
variantsManifest: VariantsManifest | null;
|
||||
experimentalPPRRoutes: ReadonlySet<string>;
|
||||
isAppPPREnabled: boolean;
|
||||
}): Promise<BuildResult> {
|
||||
if (isAppPPREnabled) {
|
||||
debug(
|
||||
'experimentalPPRRoutes',
|
||||
JSON.stringify(Array.from(experimentalPPRRoutes))
|
||||
);
|
||||
}
|
||||
|
||||
lambdaPages = Object.assign({}, lambdaPages, lambdaAppPaths);
|
||||
|
||||
const experimentalAllowBundling = Boolean(
|
||||
@@ -203,7 +212,8 @@ export async function serverBuild({
|
||||
);
|
||||
const hasActionOutputSupport =
|
||||
semver.gte(nextVersion, ACTION_OUTPUT_SUPPORT_VERSION) &&
|
||||
Boolean(process.env.NEXT_EXPERIMENTAL_STREAMING_ACTIONS);
|
||||
Boolean(process.env.NEXT_EXPERIMENTAL_STREAMING_ACTIONS) &&
|
||||
!routesManifest.i18n;
|
||||
const projectDir = requiredServerFilesManifest.relativeAppDir
|
||||
? path.join(baseDir, requiredServerFilesManifest.relativeAppDir)
|
||||
: requiredServerFilesManifest.appDir || entryPath;
|
||||
@@ -217,12 +227,6 @@ export async function serverBuild({
|
||||
}
|
||||
}
|
||||
|
||||
const experimental = {
|
||||
ppr:
|
||||
requiredServerFilesManifest.config.experimental?.ppr === true ||
|
||||
requiredServerFilesManifest.config.experimental?.ppr === 'incremental',
|
||||
};
|
||||
|
||||
let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {};
|
||||
let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {};
|
||||
let appDir: string | null = null;
|
||||
@@ -230,7 +234,7 @@ export async function serverBuild({
|
||||
if (appPathRoutesManifest) {
|
||||
appDir = path.join(pagesDir, '../app');
|
||||
appBuildTraces = await glob('**/*.js.nft.json', appDir);
|
||||
appRscPrefetches = experimental.ppr
|
||||
appRscPrefetches = isAppPPREnabled
|
||||
? {}
|
||||
: await glob(`**/*${RSC_PREFETCH_SUFFIX}`, appDir);
|
||||
|
||||
@@ -249,9 +253,19 @@ export async function serverBuild({
|
||||
|
||||
for (const rewrite of afterFilesRewrites) {
|
||||
if (rewrite.src && rewrite.dest) {
|
||||
// ensures that userland rewrites are still correctly matched to their special outputs
|
||||
// PPR should match .prefetch.rsc, .rsc, and .action
|
||||
// non-PPR should match .rsc and .action
|
||||
// we only add `.action` handling to the regex if flagged on in the build
|
||||
const rscSuffix = isAppPPREnabled
|
||||
? `(\\.prefetch)?\\.rsc${hasActionOutputSupport ? '|\\.action' : ''}`
|
||||
: hasActionOutputSupport
|
||||
? '(\\.action|\\.rsc)'
|
||||
: '\\.rsc';
|
||||
|
||||
rewrite.src = rewrite.src.replace(
|
||||
/\/?\(\?:\/\)\?/,
|
||||
`(?<rscsuff>${experimental.ppr ? '(\\.prefetch)?' : ''}\\.rsc)?(?:/)?`
|
||||
`(?<rscsuff>${rscSuffix})?(?:/)?`
|
||||
);
|
||||
let destQueryIndex = rewrite.dest.indexOf('?');
|
||||
|
||||
@@ -937,6 +951,7 @@ export async function serverBuild({
|
||||
if (!group.isPrerenders || group.isExperimentalPPR) {
|
||||
group.isStreaming = true;
|
||||
}
|
||||
|
||||
group.isAppRouter = true;
|
||||
|
||||
// We create a streaming variant of the Prerender lambda group
|
||||
@@ -984,18 +999,24 @@ export async function serverBuild({
|
||||
apiLambdaGroups: apiLambdaGroups.map(group => ({
|
||||
pages: group.pages,
|
||||
isPrerender: group.isPrerenders,
|
||||
isStreaming: group.isStreaming,
|
||||
isExperimentalPPR: group.isExperimentalPPR,
|
||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||
})),
|
||||
pageLambdaGroups: pageLambdaGroups.map(group => ({
|
||||
pages: group.pages,
|
||||
isPrerender: group.isPrerenders,
|
||||
isStreaming: group.isStreaming,
|
||||
isExperimentalPPR: group.isExperimentalPPR,
|
||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||
})),
|
||||
appRouterLambdaGroups: appRouterLambdaGroups.map(group => ({
|
||||
pages: group.pages,
|
||||
isPrerender: group.isPrerenders,
|
||||
isStreaming: group.isStreaming,
|
||||
isExperimentalPPR: group.isExperimentalPPR,
|
||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||
})),
|
||||
@@ -1003,6 +1024,8 @@ export async function serverBuild({
|
||||
appRouterStreamingActionLambdaGroups.map(group => ({
|
||||
pages: group.pages,
|
||||
isPrerender: group.isPrerenders,
|
||||
isStreaming: group.isStreaming,
|
||||
isExperimentalPPR: group.isExperimentalPPR,
|
||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||
})),
|
||||
@@ -1010,6 +1033,8 @@ export async function serverBuild({
|
||||
group => ({
|
||||
pages: group.pages,
|
||||
isPrerender: group.isPrerenders,
|
||||
isStreaming: group.isStreaming,
|
||||
isExperimentalPPR: group.isExperimentalPPR,
|
||||
pseudoLayerBytes: group.pseudoLayerBytes,
|
||||
uncompressedLayerBytes: group.pseudoLayerUncompressedBytes,
|
||||
})
|
||||
@@ -1189,15 +1214,10 @@ export async function serverBuild({
|
||||
|
||||
const lambda = await createLambdaFromPseudoLayers(options);
|
||||
|
||||
// This is a PPR lambda if it's an App Page with the PPR experimental flag
|
||||
// enabled.
|
||||
const isPPR =
|
||||
experimental.ppr && group.isAppRouter && !group.isAppRouteHandler;
|
||||
|
||||
// If PPR is enabled and this is an App Page, create the non-streaming
|
||||
// lambda for the page for revalidation.
|
||||
let revalidate: NodejsLambda | undefined;
|
||||
if (isPPR) {
|
||||
if (group.isExperimentalPPR) {
|
||||
if (!options.isStreaming) {
|
||||
throw new Error("Invariant: PPR lambda isn't streaming");
|
||||
}
|
||||
@@ -1214,14 +1234,11 @@ export async function serverBuild({
|
||||
// This is the name of the page, where the root is `index`.
|
||||
const pageName = pageFilename.replace(/\.js$/, '');
|
||||
|
||||
// This is the name of the page prefixed with a `/`, where the root is
|
||||
// `/index`.
|
||||
const pagePath = path.posix.join('/', pageName);
|
||||
|
||||
// This is the routable pathname for the page, where the root is `/`.
|
||||
const pagePathname = pagePath === '/index' ? '/' : pagePath;
|
||||
const pagePathname = normalizePage(pageName);
|
||||
|
||||
let isPrerender = prerenderRoutes.has(pagePathname);
|
||||
const isRoutePPREnabled = experimentalPPRRoutes.has(pagePathname);
|
||||
|
||||
if (!isPrerender && routesManifest?.i18n) {
|
||||
isPrerender = routesManifest.i18n.locales.some(locale => {
|
||||
@@ -1239,7 +1256,7 @@ export async function serverBuild({
|
||||
}
|
||||
|
||||
// If this is a PPR page, then we should prefix the output name.
|
||||
if (isPPR) {
|
||||
if (isRoutePPREnabled) {
|
||||
if (!revalidate) {
|
||||
throw new Error("Invariant: PPR lambda isn't set");
|
||||
}
|
||||
@@ -1320,6 +1337,13 @@ export async function serverBuild({
|
||||
console.timeEnd(lambdaCreationLabel);
|
||||
}
|
||||
|
||||
if (isAppPPREnabled) {
|
||||
debug(
|
||||
'experimentalStreamingLambdaPaths',
|
||||
JSON.stringify(Array.from(experimentalStreamingLambdaPaths))
|
||||
);
|
||||
}
|
||||
|
||||
const prerenderRoute = onPrerenderRoute({
|
||||
appDir,
|
||||
pagesDir,
|
||||
@@ -1339,6 +1363,7 @@ export async function serverBuild({
|
||||
hasPages404: routesManifest.pages404,
|
||||
isCorrectNotFoundRoutes,
|
||||
isEmptyAllowQueryForPrendered,
|
||||
isAppPPREnabled,
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
@@ -1407,7 +1432,7 @@ export async function serverBuild({
|
||||
bypassToken: prerenderManifest.bypassToken || '',
|
||||
isServerMode: true,
|
||||
dynamicMiddlewareRouteMap: middleware.dynamicRouteMap,
|
||||
experimentalPPRRoutes,
|
||||
isAppPPREnabled,
|
||||
hasActionOutputSupport,
|
||||
}).then(arr =>
|
||||
localizeDynamicRoutes(
|
||||
@@ -1589,7 +1614,7 @@ export async function serverBuild({
|
||||
if (lambdas[pathname]) {
|
||||
lambdas[`${pathname}.rsc`] = lambdas[pathname];
|
||||
|
||||
if (experimental.ppr) {
|
||||
if (isAppPPREnabled) {
|
||||
lambdas[`${pathname}${RSC_PREFETCH_SUFFIX}`] = lambdas[pathname];
|
||||
}
|
||||
}
|
||||
@@ -1597,7 +1622,7 @@ export async function serverBuild({
|
||||
if (edgeFunctions[pathname]) {
|
||||
edgeFunctions[`${pathname}.rsc`] = edgeFunctions[pathname];
|
||||
|
||||
if (experimental.ppr) {
|
||||
if (isAppPPREnabled) {
|
||||
edgeFunctions[`${pathname}${RSC_PREFETCH_SUFFIX}`] =
|
||||
edgeFunctions[pathname];
|
||||
}
|
||||
@@ -1616,7 +1641,7 @@ export async function serverBuild({
|
||||
'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
|
||||
const appNotFoundPath = path.posix.join('.', entryDirectory, '_not-found');
|
||||
|
||||
if (experimental.ppr && !rscPrefetchHeader) {
|
||||
if (isAppPPREnabled && !rscPrefetchHeader) {
|
||||
throw new Error("Invariant: cannot use PPR without 'rsc.prefetchHeader'");
|
||||
}
|
||||
|
||||
@@ -1624,7 +1649,7 @@ export async function serverBuild({
|
||||
// all the routes that support it (and are listed) have configured lambdas.
|
||||
// This only applies to routes that do not have fallbacks enabled (these are
|
||||
// routes that have `dynamicParams = false` defined.
|
||||
if (experimental.ppr) {
|
||||
if (isAppPPREnabled) {
|
||||
for (const { srcRoute, dataRoute, experimentalPPR } of Object.values(
|
||||
prerenderManifest.staticRoutes
|
||||
)) {
|
||||
@@ -1907,7 +1932,7 @@ export async function serverBuild({
|
||||
|
||||
...(appDir
|
||||
? [
|
||||
...(rscPrefetchHeader && experimental.ppr
|
||||
...(rscPrefetchHeader && isAppPPREnabled
|
||||
? [
|
||||
{
|
||||
src: `^${path.posix.join('/', entryDirectory, '/')}`,
|
||||
@@ -2061,10 +2086,45 @@ export async function serverBuild({
|
||||
]
|
||||
: []),
|
||||
|
||||
// before processing rewrites, remove any special `/index` routes that were added
|
||||
// as these won't be properly normalized by `afterFilesRewrites` / `dynamicRoutes`
|
||||
...(appPathRoutesManifest
|
||||
? [
|
||||
{
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/index(\\.action|\\.rsc)'
|
||||
),
|
||||
dest: path.posix.join('/', entryDirectory),
|
||||
continue: true,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
// These need to come before handle: miss or else they are grouped
|
||||
// with that routing section
|
||||
...afterFilesRewrites,
|
||||
|
||||
// Ensure that after we normalize `afterFilesRewrites`, unmatched actions are routed to the correct handler
|
||||
// e.g. /foo/.action -> /foo.action. This should only ever match in cases where we're routing to an action handler
|
||||
// and the rewrite normalization led to something like /foo/$1$rscsuff, and $1 had no match.
|
||||
// This is meant to have parity with the .rsc handling below.
|
||||
...(hasActionOutputSupport
|
||||
? [
|
||||
{
|
||||
src: `${path.posix.join('/', entryDirectory, '/\\.action$')}`,
|
||||
dest: `${path.posix.join('/', entryDirectory, '/index.action')}`,
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
src: `${path.posix.join('/', entryDirectory, '(.+)/\\.action$')}`,
|
||||
dest: `${path.posix.join('/', entryDirectory, '$1.action')}`,
|
||||
check: true,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
// ensure non-normalized /.rsc from rewrites is handled
|
||||
...(appPathRoutesManifest
|
||||
? [
|
||||
@@ -2077,11 +2137,29 @@ export async function serverBuild({
|
||||
),
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'(.+)/\\.prefetch\\.rsc$'
|
||||
),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`$1${RSC_PREFETCH_SUFFIX}`
|
||||
),
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
src: path.posix.join('/', entryDirectory, '/\\.rsc$'),
|
||||
dest: path.posix.join('/', entryDirectory, `/index.rsc`),
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
src: path.posix.join('/', entryDirectory, '(.+)/\\.rsc$'),
|
||||
dest: path.posix.join('/', entryDirectory, '$1.rsc'),
|
||||
check: true,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
|
||||
@@ -192,8 +192,12 @@ function normalizePage(page: string): string {
|
||||
if (!page.startsWith('/')) {
|
||||
page = `/${page}`;
|
||||
}
|
||||
// remove '/index' from the end
|
||||
page = page.replace(/\/index$/, '/');
|
||||
|
||||
// Replace the `/index` with `/`
|
||||
if (page === '/index') {
|
||||
page = '/';
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -320,8 +324,8 @@ export async function getDynamicRoutes({
|
||||
bypassToken,
|
||||
isServerMode,
|
||||
dynamicMiddlewareRouteMap,
|
||||
experimentalPPRRoutes,
|
||||
hasActionOutputSupport,
|
||||
isAppPPREnabled,
|
||||
}: {
|
||||
entryPath: string;
|
||||
entryDirectory: string;
|
||||
@@ -333,8 +337,8 @@ export async function getDynamicRoutes({
|
||||
bypassToken?: string;
|
||||
isServerMode?: boolean;
|
||||
dynamicMiddlewareRouteMap?: ReadonlyMap<string, RouteWithSrc>;
|
||||
experimentalPPRRoutes: ReadonlySet<string>;
|
||||
hasActionOutputSupport: boolean;
|
||||
isAppPPREnabled: boolean;
|
||||
}): Promise<RouteWithSrc[]> {
|
||||
if (routesManifest) {
|
||||
switch (routesManifest.version) {
|
||||
@@ -408,7 +412,7 @@ export async function getDynamicRoutes({
|
||||
];
|
||||
}
|
||||
|
||||
if (experimentalPPRRoutes.has(page)) {
|
||||
if (isAppPPREnabled) {
|
||||
let dest = route.dest?.replace(/($|\?)/, '.prefetch.rsc$1');
|
||||
|
||||
if (page === '/' || page === '/index') {
|
||||
@@ -1505,8 +1509,8 @@ export type LambdaGroup = {
|
||||
isAppRouter?: boolean;
|
||||
isAppRouteHandler?: boolean;
|
||||
isStreaming?: boolean;
|
||||
isPrerenders?: boolean;
|
||||
isExperimentalPPR?: boolean;
|
||||
readonly isPrerenders: boolean;
|
||||
readonly isExperimentalPPR: boolean;
|
||||
isActionLambda?: boolean;
|
||||
isPages?: boolean;
|
||||
isApiLambda: boolean;
|
||||
@@ -1948,6 +1952,7 @@ type OnPrerenderRouteArgs = {
|
||||
routesManifest?: RoutesManifest;
|
||||
isCorrectNotFoundRoutes?: boolean;
|
||||
isEmptyAllowQueryForPrendered?: boolean;
|
||||
isAppPPREnabled: boolean;
|
||||
};
|
||||
let prerenderGroup = 1;
|
||||
|
||||
@@ -1984,6 +1989,7 @@ export const onPrerenderRoute =
|
||||
routesManifest,
|
||||
isCorrectNotFoundRoutes,
|
||||
isEmptyAllowQueryForPrendered,
|
||||
isAppPPREnabled,
|
||||
} = prerenderRouteArgs;
|
||||
|
||||
if (isBlocking && isFallback) {
|
||||
@@ -2104,14 +2110,14 @@ export const onPrerenderRoute =
|
||||
|
||||
// If enabled, try to get the postponed route information from the file
|
||||
// system and use it to assemble the prerender.
|
||||
let prerender: string | undefined;
|
||||
let postponedPrerender: string | undefined;
|
||||
if (experimentalPPR && appDir) {
|
||||
const htmlPath = path.join(appDir, `${routeFileNoExt}.html`);
|
||||
const metaPath = path.join(appDir, `${routeFileNoExt}.meta`);
|
||||
if (fs.existsSync(htmlPath) && fs.existsSync(metaPath)) {
|
||||
const meta = JSON.parse(await fs.readFile(metaPath, 'utf8'));
|
||||
if ('postponed' in meta && typeof meta.postponed === 'string') {
|
||||
prerender = meta.postponed;
|
||||
postponedPrerender = meta.postponed;
|
||||
|
||||
// Assign the headers Content-Type header to the prerendered type.
|
||||
initialHeaders ??= {};
|
||||
@@ -2121,7 +2127,7 @@ export const onPrerenderRoute =
|
||||
|
||||
// Read the HTML file and append it to the prerendered content.
|
||||
const html = await fs.readFileSync(htmlPath, 'utf8');
|
||||
prerender += html;
|
||||
postponedPrerender += html;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2138,14 +2144,14 @@ export const onPrerenderRoute =
|
||||
}
|
||||
}
|
||||
|
||||
if (prerender) {
|
||||
if (postponedPrerender) {
|
||||
const contentType = initialHeaders?.['content-type'];
|
||||
if (!contentType) {
|
||||
throw new Error("Invariant: contentType can't be undefined");
|
||||
}
|
||||
|
||||
// Assemble the prerendered file.
|
||||
htmlFsRef = new FileBlob({ contentType, data: prerender });
|
||||
htmlFsRef = new FileBlob({ contentType, data: postponedPrerender });
|
||||
} else if (
|
||||
appDir &&
|
||||
!dataRoute &&
|
||||
@@ -2209,7 +2215,14 @@ export const onPrerenderRoute =
|
||||
? addLocaleOrDefault('/404.html', routesManifest, locale)
|
||||
: '/404.html'
|
||||
: isAppPathRoute
|
||||
? prefetchDataRoute || dataRoute
|
||||
? // When experimental PPR is enabled, we expect that the data
|
||||
// that should be served as a part of the prerender should
|
||||
// be from the prefetch data route. If this isn't enabled
|
||||
// for ppr, the only way to get the data is from the data
|
||||
// route.
|
||||
experimentalPPR
|
||||
? prefetchDataRoute
|
||||
: dataRoute
|
||||
: routeFileNoExt + '.json'
|
||||
}`
|
||||
),
|
||||
@@ -2219,22 +2232,6 @@ export const onPrerenderRoute =
|
||||
initialStatus = 404;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the route key had an `/index` suffix added, we need to note it so we
|
||||
* can remove it from the output path later accurately.
|
||||
*/
|
||||
let addedIndexSuffix = false;
|
||||
|
||||
if (isAppPathRoute) {
|
||||
// for literal index routes we need to append an additional /index
|
||||
// due to the proxy's normalizing for /index routes
|
||||
if (routeKey !== '/index' && routeKey.endsWith('/index')) {
|
||||
routeKey = `${routeKey}/index`;
|
||||
routeFileNoExt = routeKey;
|
||||
addedIndexSuffix = true;
|
||||
}
|
||||
}
|
||||
|
||||
let outputPathPage = path.posix.join(entryDirectory, routeFileNoExt);
|
||||
|
||||
if (!isAppPathRoute) {
|
||||
@@ -2271,7 +2268,7 @@ export const onPrerenderRoute =
|
||||
|
||||
let outputPathPrefetchData: null | string = null;
|
||||
if (prefetchDataRoute) {
|
||||
if (!experimentalPPR) {
|
||||
if (!isAppPPREnabled) {
|
||||
throw new Error(
|
||||
"Invariant: prefetchDataRoute can't be set without PPR"
|
||||
);
|
||||
@@ -2282,10 +2279,6 @@ export const onPrerenderRoute =
|
||||
throw new Error('Invariant: expected to find prefetch data route PPR');
|
||||
}
|
||||
|
||||
// When the prefetch data path is available, use it for the prerender,
|
||||
// otherwise use the data path.
|
||||
const outputPrerenderPathData = outputPathPrefetchData || outputPathData;
|
||||
|
||||
if (isSharedLambdas) {
|
||||
const outputSrcPathPage = normalizeIndexOutput(
|
||||
path.join(
|
||||
@@ -2338,8 +2331,14 @@ export const onPrerenderRoute =
|
||||
htmlFsRef.contentType = htmlContentType;
|
||||
prerenders[outputPathPage] = htmlFsRef;
|
||||
|
||||
if (outputPrerenderPathData) {
|
||||
prerenders[outputPrerenderPathData] = jsonFsRef;
|
||||
if (outputPathPrefetchData) {
|
||||
prerenders[outputPathPrefetchData] = jsonFsRef;
|
||||
}
|
||||
|
||||
// If experimental ppr is not enabled for this route, then add the data
|
||||
// route as a target for the prerender as well.
|
||||
if (outputPathData && !experimentalPPR) {
|
||||
prerenders[outputPathData] = jsonFsRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2428,7 +2427,7 @@ export const onPrerenderRoute =
|
||||
// static route first, then try the srcRoute if it doesn't exist. If we
|
||||
// can't find it at all, this constitutes an error.
|
||||
experimentalStreamingLambdaPath = experimentalStreamingLambdaPaths.get(
|
||||
pathnameToOutputName(entryDirectory, routeKey, addedIndexSuffix)
|
||||
pathnameToOutputName(entryDirectory, routeKey)
|
||||
);
|
||||
if (!experimentalStreamingLambdaPath && srcRoute) {
|
||||
experimentalStreamingLambdaPath =
|
||||
@@ -2475,21 +2474,20 @@ export const onPrerenderRoute =
|
||||
: {}),
|
||||
});
|
||||
|
||||
if (outputPrerenderPathData) {
|
||||
let normalizedPathData = outputPrerenderPathData;
|
||||
|
||||
const normalizePathData = (pathData: string) => {
|
||||
if (
|
||||
(srcRoute === '/' || srcRoute == '/index') &&
|
||||
outputPrerenderPathData.endsWith(RSC_PREFETCH_SUFFIX)
|
||||
pathData.endsWith(RSC_PREFETCH_SUFFIX)
|
||||
) {
|
||||
delete lambdas[normalizedPathData];
|
||||
normalizedPathData = normalizedPathData.replace(
|
||||
/([^/]+\.prefetch\.rsc)$/,
|
||||
'__$1'
|
||||
);
|
||||
delete lambdas[pathData];
|
||||
return pathData.replace(/([^/]+\.prefetch\.rsc)$/, '__$1');
|
||||
}
|
||||
|
||||
prerenders[normalizedPathData] = new Prerender({
|
||||
return pathData;
|
||||
};
|
||||
|
||||
if (outputPathData || outputPathPrefetchData) {
|
||||
const prerender = new Prerender({
|
||||
expiration: initialRevalidate,
|
||||
lambda,
|
||||
allowQuery,
|
||||
@@ -2510,21 +2508,30 @@ export const onPrerenderRoute =
|
||||
...initialHeaders,
|
||||
'content-type': rscContentTypeHeader,
|
||||
vary: rscVaryHeader,
|
||||
// If it contains a pre-render, then it was postponed.
|
||||
...(prerender && rscDidPostponeHeader
|
||||
...(postponedPrerender && rscDidPostponeHeader
|
||||
? { [rscDidPostponeHeader]: '1' }
|
||||
: {}),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
|
||||
if (outputPathPrefetchData) {
|
||||
prerenders[normalizePathData(outputPathPrefetchData)] = prerender;
|
||||
}
|
||||
|
||||
// If experimental ppr is not enabled for this route, then add the data
|
||||
// route as a target for the prerender as well.
|
||||
if (outputPathData && !experimentalPPR) {
|
||||
prerenders[normalizePathData(outputPathData)] = prerender;
|
||||
}
|
||||
}
|
||||
|
||||
// we need to ensure all prerenders have a matching .rsc output
|
||||
// otherwise routing could fall through unexpectedly for the
|
||||
// fallback: false case as it doesn't have a dynamic route
|
||||
// to catch the `.rsc` request for app -> pages routing
|
||||
if (outputPrerenderPathData?.endsWith('.json') && appDir) {
|
||||
if (outputPathData?.endsWith('.json') && appDir) {
|
||||
const dummyOutput = new FileBlob({
|
||||
data: '{}',
|
||||
contentType: 'application/json',
|
||||
@@ -2689,19 +2696,10 @@ export function getNextServerPath(nextVersion: string) {
|
||||
: 'next/dist/next-server/server';
|
||||
}
|
||||
|
||||
function pathnameToOutputName(
|
||||
entryDirectory: string,
|
||||
pathname: string,
|
||||
addedIndexSuffix = false
|
||||
) {
|
||||
function pathnameToOutputName(entryDirectory: string, pathname: string) {
|
||||
if (pathname === '/') {
|
||||
pathname = '/index';
|
||||
}
|
||||
// If the `/index` was added for a route that ended in `/index` we need to
|
||||
// strip the second one off before joining it with the entryDirectory.
|
||||
else if (addedIndexSuffix) {
|
||||
pathname = pathname.replace(/\/index$/, '');
|
||||
}
|
||||
|
||||
return path.posix.join(entryDirectory, pathname);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
'use server';
|
||||
|
||||
export async function increment(value) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
return value + 1;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export default function Root({ children }) {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello World</title>
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { increment } from "../actions";
|
||||
|
||||
export default function Home() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{count}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const actionResult = await increment(count);
|
||||
// @ts-ignore
|
||||
setCount(actionResult);
|
||||
console.log(actionResult);
|
||||
}}
|
||||
>
|
||||
Trigger
|
||||
</button>
|
||||
Static
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/* eslint-env jest */
|
||||
const path = require('path');
|
||||
const { deployAndTest } = require('../../utils');
|
||||
const fetch = require('../../../../../test/lib/deployment/fetch-retry');
|
||||
|
||||
const ctx = {};
|
||||
|
||||
function findActionId(page, runtime) {
|
||||
page = `app${page}/page`; // add /app prefix and /page suffix
|
||||
|
||||
for (const [actionId, details] of Object.entries(
|
||||
ctx.actionManifest[runtime]
|
||||
)) {
|
||||
if (details.workers[page]) {
|
||||
return actionId;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Couldn't find action ID");
|
||||
}
|
||||
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
beforeAll(async () => {
|
||||
const info = await deployAndTest(__dirname);
|
||||
|
||||
const actionManifest = await fetch(
|
||||
`${info.deploymentUrl}/server-reference-manifest.json`
|
||||
).then(res => res.json());
|
||||
|
||||
ctx.actionManifest = actionManifest;
|
||||
|
||||
Object.assign(ctx, info);
|
||||
});
|
||||
|
||||
it('should work when there is a rewrite targeting the root page', async () => {
|
||||
const actionId = findActionId('/static', 'node');
|
||||
|
||||
const res = await fetch(ctx.deploymentUrl, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([1337]),
|
||||
headers: {
|
||||
'Content-Type': 'text/plain;charset=UTF-8',
|
||||
'Next-Action': actionId,
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe('/static/');
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('BYPASS');
|
||||
|
||||
const body = await res.text();
|
||||
// The action incremented the provided count by 1
|
||||
expect(body).toContain('1338');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/:path*',
|
||||
destination: '/static/:path*',
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "next build && cp .next/server/server-reference-manifest.json public/"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
14
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming-index-handling/vercel.json
vendored
Normal file
14
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming-index-handling/vercel.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
"env": {
|
||||
"NEXT_EXPERIMENTAL_STREAMING_ACTIONS": "1"
|
||||
}
|
||||
},
|
||||
"probes": []
|
||||
}
|
||||
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/edge/static/page.js
vendored
Normal file
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/edge/static/page.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { increment } from "../../actions";
|
||||
|
||||
export default function Home() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{count}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const actionResult = await increment(count);
|
||||
// @ts-ignore
|
||||
setCount(actionResult);
|
||||
console.log(actionResult);
|
||||
}}
|
||||
>
|
||||
Trigger
|
||||
</button>
|
||||
Static
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/page.js
vendored
Normal file
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/page.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { increment } from "./actions";
|
||||
|
||||
export default function Home() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{count}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const actionResult = await increment(count);
|
||||
// @ts-ignore
|
||||
setCount(actionResult);
|
||||
console.log(actionResult);
|
||||
}}
|
||||
>
|
||||
Trigger
|
||||
</button>
|
||||
Static
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/static/page.js
vendored
Normal file
25
packages/next/test/fixtures/00-app-dir-actions-experimental-streaming/app/static/page.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { increment } from "../actions";
|
||||
|
||||
export default function Home() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{count}
|
||||
<button
|
||||
onClick={async () => {
|
||||
const actionResult = await increment(count);
|
||||
// @ts-ignore
|
||||
setCount(actionResult);
|
||||
console.log(actionResult);
|
||||
}}
|
||||
>
|
||||
Trigger
|
||||
</button>
|
||||
Static
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -15,7 +15,8 @@ function findActionId(page, runtime) {
|
||||
return actionId;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
throw new Error("Couldn't find action ID");
|
||||
}
|
||||
|
||||
function generateFormDataPayload(actionId) {
|
||||
@@ -273,6 +274,100 @@ describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
expect(body).toContain(JSON.stringify(['id', '1', 'd']));
|
||||
expect(body).not.toContain(JSON.stringify(['id', '1.action', 'd']));
|
||||
});
|
||||
|
||||
it('should work when a rewrite targets an action', async () => {
|
||||
const targetPath = `${basePath}/rsc/static`;
|
||||
const canonicalPath = `/rewrite/${basePath}/rsc/static`;
|
||||
const actionId = findActionId(targetPath, runtime);
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}${canonicalPath}`,
|
||||
generateFormDataPayload(actionId)
|
||||
);
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe(targetPath + '.action');
|
||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||
if (runtime === 'node') {
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||
} else {
|
||||
expect(res.headers.get('x-edge-runtime')).toBe('1');
|
||||
}
|
||||
});
|
||||
|
||||
it('should work when a rewrite greedy matches an action rewrite', async () => {
|
||||
const targetPath = `${basePath}/static`;
|
||||
const canonicalPath = `/greedy-rewrite/${basePath}/static`;
|
||||
const actionId = findActionId(targetPath, runtime);
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}${canonicalPath}`,
|
||||
generateFormDataPayload(actionId)
|
||||
);
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe(targetPath + '.action');
|
||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||
if (runtime === 'node') {
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||
} else {
|
||||
expect(res.headers.get('x-edge-runtime')).toBe('1');
|
||||
}
|
||||
});
|
||||
|
||||
it('should work on the index route', async () => {
|
||||
const canonicalPath = '/';
|
||||
const actionId = findActionId('', 'node');
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}${canonicalPath}`,
|
||||
generateFormDataPayload(actionId)
|
||||
);
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe('/index.action');
|
||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||
});
|
||||
});
|
||||
|
||||
describe('rewrite to index', () => {
|
||||
it('should work when user has a rewrite to the index route', async () => {
|
||||
const canonicalPath = '/rewritten-to-index';
|
||||
const actionId = findActionId('', 'node');
|
||||
|
||||
const res = await fetch(
|
||||
`${ctx.deploymentUrl}${canonicalPath}`,
|
||||
generateFormDataPayload(actionId)
|
||||
);
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe('/index.action');
|
||||
expect(res.headers.get('content-type')).toBe('text/x-component');
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||
});
|
||||
|
||||
it('should work when entire path is rewritten', async () => {
|
||||
const actionId = findActionId('/static', 'node');
|
||||
|
||||
const res = await fetch(ctx.deploymentUrl, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify([1337]),
|
||||
headers: {
|
||||
'Content-Type': 'text/plain;charset=UTF-8',
|
||||
'Next-Action': actionId,
|
||||
'x-rewrite-me': '1',
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers.get('x-matched-path')).toBe('/index.action');
|
||||
expect(res.headers.get('x-vercel-cache')).toBe('MISS');
|
||||
|
||||
const body = await res.text();
|
||||
// The action incremented the provided count by 1
|
||||
expect(body).toContain('1338');
|
||||
});
|
||||
});
|
||||
|
||||
describe('pages', () => {
|
||||
|
||||
@@ -1 +1,36 @@
|
||||
module.exports = {};
|
||||
module.exports = {
|
||||
rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/rewrite/rsc/static',
|
||||
destination: '/rsc/static',
|
||||
},
|
||||
{
|
||||
source: '/rewrite/edge/rsc/static',
|
||||
destination: '/edge/rsc/static',
|
||||
},
|
||||
{
|
||||
source: '/greedy-rewrite/static/:path*',
|
||||
destination: '/static/:path*',
|
||||
},
|
||||
{
|
||||
source: '/greedy-rewrite/edge/static/:path*',
|
||||
destination: '/edge/static/:path*',
|
||||
},
|
||||
{
|
||||
source: '/rewritten-to-index',
|
||||
destination: '/?fromRewrite=1',
|
||||
},
|
||||
{
|
||||
source: '/:path*',
|
||||
destination: '/static/:path*',
|
||||
has: [
|
||||
{
|
||||
type: 'header',
|
||||
key: 'x-rewrite-me',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
14
packages/next/test/fixtures/00-app-dir-catchall-index-handling/app/[[...slug]]/page.js
vendored
Normal file
14
packages/next/test/fixtures/00-app-dir-catchall-index-handling/app/[[...slug]]/page.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
const Page = ({ params }) => {
|
||||
return (
|
||||
<div>
|
||||
<div id="page-param">page-param-{params.slug?.[0] ?? ''}</div>
|
||||
<Link href="/">Home</Link>
|
||||
<Link href="/foo">Foo</Link>
|
||||
<Link href="/bar">Bar</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
10
packages/next/test/fixtures/00-app-dir-catchall-index-handling/app/layout.js
vendored
Normal file
10
packages/next/test/fixtures/00-app-dir-catchall-index-handling/app/layout.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function Root({ children }) {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello World</title>
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
12
packages/next/test/fixtures/00-app-dir-catchall-index-handling/index.test.js
vendored
Normal file
12
packages/next/test/fixtures/00-app-dir-catchall-index-handling/index.test.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/* eslint-env jest */
|
||||
const path = require('path');
|
||||
const { deployAndTest } = require('../../utils');
|
||||
|
||||
const ctx = {};
|
||||
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
const info = await deployAndTest(__dirname);
|
||||
Object.assign(ctx, info);
|
||||
});
|
||||
});
|
||||
1
packages/next/test/fixtures/00-app-dir-catchall-index-handling/next.config.js
vendored
Normal file
1
packages/next/test/fixtures/00-app-dir-catchall-index-handling/next.config.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
8
packages/next/test/fixtures/00-app-dir-catchall-index-handling/package.json
vendored
Normal file
8
packages/next/test/fixtures/00-app-dir-catchall-index-handling/package.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
27
packages/next/test/fixtures/00-app-dir-catchall-index-handling/vercel.json
vendored
Normal file
27
packages/next/test/fixtures/00-app-dir-catchall-index-handling/vercel.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "\"page-param-\",\"\"",
|
||||
"mustNotContain": "\"page-param-\",\"index\"",
|
||||
"headers": {
|
||||
"RSC": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/foo",
|
||||
"status": 200,
|
||||
"mustContain": "\"page-param-\",\"foo\"",
|
||||
"headers": {
|
||||
"RSC": "1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
3
packages/next/test/fixtures/00-app-dir-incremental-ppr/app/static/page.jsx
vendored
Normal file
3
packages/next/test/fixtures/00-app-dir-incremental-ppr/app/static/page.jsx
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return <div id="sentinel:static">Static</div>;
|
||||
}
|
||||
@@ -4,8 +4,7 @@ const { deployAndTest } = require('../../utils');
|
||||
|
||||
const ctx = {};
|
||||
|
||||
// TODO: investigate invariant
|
||||
describe.skip(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
const info = await deployAndTest(__dirname);
|
||||
Object.assign(ctx, info);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -56,6 +56,28 @@
|
||||
"status": 200,
|
||||
"mustContain": "sentinel:dynamic"
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"mustContain": "sentinel:static"
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"mustContain": "sentinel:static",
|
||||
"headers": {
|
||||
"RSC": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"mustContain": "sentinel:static",
|
||||
"headers": {
|
||||
"RSC": "1",
|
||||
"Next-Router-Prefetch": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/disabled",
|
||||
"headers": {
|
||||
@@ -63,7 +85,7 @@
|
||||
"Next-Router-Prefetch": "1"
|
||||
},
|
||||
"status": 200,
|
||||
"mustContain": "sentinel:dynamic"
|
||||
"mustNotContain": "sentinel:dynamic"
|
||||
},
|
||||
{
|
||||
"path": "/disabled",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export const metadata = {
|
||||
metadataBase: new URL(process.env.VERCEL_PROJECT_PRODUCTION_URL ?? 'http://localhost:3000'),
|
||||
};
|
||||
|
||||
export default function Root({ children }) {
|
||||
return (
|
||||
<html className="this-is-the-document-html">
|
||||
|
||||
@@ -17,6 +17,10 @@ module.exports = {
|
||||
source: '/to-product/:productId.html',
|
||||
destination: '/products/:productId',
|
||||
},
|
||||
{
|
||||
source: '/greedy-rewrite/test-page/:path*',
|
||||
destination: '/test-page/:path*',
|
||||
}
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -429,6 +429,31 @@
|
||||
},
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html"
|
||||
},
|
||||
{
|
||||
"path": "/greedy-rewrite/test-page",
|
||||
"status": 200,
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html",
|
||||
"responseHeaders": {
|
||||
"x-matched-path": "/test-page.rsc"
|
||||
},
|
||||
"headers": {
|
||||
"RSC": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/greedy-rewrite/test-page",
|
||||
"status": 200,
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html",
|
||||
"responseHeaders": {
|
||||
"x-matched-path": "/test-page.rsc"
|
||||
},
|
||||
"headers": {
|
||||
"RSC": "1",
|
||||
"Next-Router-Prefetch": "1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.4.5",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
3
packages/next/test/fixtures/00-app-dir-ppr/app/static/page.js
vendored
Normal file
3
packages/next/test/fixtures/00-app-dir-ppr/app/static/page.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return <p>static page</p>;
|
||||
}
|
||||
@@ -14,6 +14,10 @@ module.exports = {
|
||||
source: '/rewritten-to-index',
|
||||
destination: '/?fromRewrite=1',
|
||||
},
|
||||
{
|
||||
source: '/greedy-rewrite/test-page/:path*',
|
||||
destination: '/test-page/:path*',
|
||||
}
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -349,6 +349,55 @@
|
||||
"path": "/api/pages-headers",
|
||||
"status": 200,
|
||||
"mustContain": "{\"port\":\"443\"}"
|
||||
},
|
||||
{
|
||||
"path": "/greedy-rewrite/test-page",
|
||||
"status": 200,
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html",
|
||||
"responseHeaders": {
|
||||
"x-matched-path": "/test-page.rsc"
|
||||
},
|
||||
"headers": {
|
||||
"RSC": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/greedy-rewrite/test-page",
|
||||
"status": 200,
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html",
|
||||
"responseHeaders": {
|
||||
"x-matched-path": "/test-page.prefetch.rsc"
|
||||
},
|
||||
"headers": {
|
||||
"RSC": "1",
|
||||
"Next-Router-Prefetch": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"mustContain": "static page"
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"RSC": "1"
|
||||
},
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html"
|
||||
},
|
||||
{
|
||||
"path": "/static",
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"RSC": "1",
|
||||
"Next-Router-Prefetch": "1"
|
||||
},
|
||||
"mustContain": ":{",
|
||||
"mustNotContain": "<html"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "19.0.0-beta-4508873393-20240430",
|
||||
"react-dom": "19.0.0-beta-4508873393-20240430"
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522"
|
||||
},
|
||||
"ignoreNextjsUpdates": true
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user