vinext 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -21
- package/dist/build/action-owner-manifest.js +1 -0
- package/dist/build/prerender.js +3 -2
- package/dist/check.js +4 -7
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +19 -3
- package/dist/config/config-matchers.js +4 -2
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +55 -2
- package/dist/config/next-config.d.ts +22 -1
- package/dist/config/next-config.js +49 -4
- package/dist/entries/app-rsc-entry.js +41 -19
- package/dist/entries/app-rsc-manifest.js +4 -0
- package/dist/entries/pages-server-entry.js +5 -1
- package/dist/index.js +44 -32
- package/dist/init-cloudflare.js +18 -2
- package/dist/plugins/css-target.d.ts +18 -0
- package/dist/plugins/css-target.js +93 -0
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/routing/app-route-graph.d.ts +10 -0
- package/dist/routing/app-route-graph.js +15 -1
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +5 -6
- package/dist/server/app-action-forwarding.js +3 -1
- package/dist/server/app-browser-entry.js +28 -7
- package/dist/server/app-browser-rsc-redirect.js +3 -3
- package/dist/server/app-browser-server-action-client.js +2 -2
- package/dist/server/app-browser-visible-commit.js +2 -2
- package/dist/server/app-elements.d.ts +3 -0
- package/dist/server/app-elements.js +14 -1
- package/dist/server/app-fallback-renderer.js +2 -2
- package/dist/server/app-optimistic-routing.d.ts +12 -1
- package/dist/server/app-optimistic-routing.js +40 -19
- package/dist/server/app-page-boundary-render.js +7 -12
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +10 -2
- package/dist/server/app-page-dispatch.js +73 -31
- package/dist/server/app-page-element-builder.d.ts +9 -20
- package/dist/server/app-page-element-builder.js +40 -52
- package/dist/server/app-page-execution.js +9 -6
- package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
- package/dist/server/app-page-intercept-segment-config.js +90 -0
- package/dist/server/app-page-navigation-params.d.ts +23 -0
- package/dist/server/app-page-navigation-params.js +49 -0
- package/dist/server/app-page-render.d.ts +5 -3
- package/dist/server/app-page-render.js +31 -17
- package/dist/server/app-page-request.d.ts +24 -2
- package/dist/server/app-page-request.js +10 -10
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +10 -0
- package/dist/server/app-page-route-wiring.js +34 -13
- package/dist/server/app-page-segment-plan.js +9 -1
- package/dist/server/app-page-segment-state.d.ts +9 -0
- package/dist/server/app-page-segment-state.js +54 -1
- package/dist/server/app-page-stream.d.ts +10 -8
- package/dist/server/app-page-stream.js +2 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-response-stage-entry.js +1 -0
- package/dist/server/app-route-handler-execution.js +3 -2
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +11 -7
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +10 -10
- package/dist/server/app-rsc-cache-busting.js +27 -68
- package/dist/server/app-rsc-error-handler.js +1 -1
- package/dist/server/app-rsc-errors.js +4 -1
- package/dist/server/app-rsc-handler.d.ts +10 -1
- package/dist/server/app-rsc-handler.js +126 -103
- package/dist/server/app-rsc-request-normalization.d.ts +10 -12
- package/dist/server/app-rsc-request-normalization.js +11 -14
- package/dist/server/app-rsc-response-finalizer.d.ts +3 -0
- package/dist/server/app-rsc-response-finalizer.js +11 -1
- package/dist/server/app-rsc-response-stage.js +4 -12
- package/dist/server/app-rsc-route-matching.d.ts +14 -0
- package/dist/server/app-rsc-route-matching.js +42 -18
- package/dist/server/app-server-action-execution.js +24 -14
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +13 -8
- package/dist/server/app-worker-stages.d.ts +12 -3
- package/dist/server/app-worker-stages.js +37 -4
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-control.d.ts +2 -0
- package/dist/server/cache-control.js +3 -1
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +2 -1
- package/dist/server/image-local-patterns.d.ts +21 -0
- package/dist/server/image-local-patterns.js +59 -0
- package/dist/server/image-optimization.d.ts +28 -22
- package/dist/server/image-optimization.js +17 -2
- package/dist/server/isr-cache.js +4 -1
- package/dist/server/metadata-route-response.js +25 -7
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +7 -3
- package/dist/server/nitro-public-files-plugin.js +20 -8
- package/dist/server/pages-data-route.d.ts +5 -1
- package/dist/server/pages-data-route.js +14 -6
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +2 -0
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +17 -6
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.js +6 -5
- package/dist/server/pages-request-stage-entry.js +25 -4
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +59 -17
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +14 -4
- package/dist/server/request-pipeline.js +33 -15
- package/dist/server/response-stage-cacheability.d.ts +7 -0
- package/dist/server/response-stage-cacheability.js +6 -5
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-image-optimization.d.ts +2 -2
- package/dist/server/worker-image-optimization.js +18 -3
- package/dist/server/worker-utils.d.ts +8 -0
- package/dist/server/worker-utils.js +19 -2
- package/dist/shims/cache-request-state.d.ts +6 -6
- package/dist/shims/cache-request-state.js +6 -36
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +77 -47
- package/dist/shims/cache.d.ts +10 -5
- package/dist/shims/cache.js +35 -22
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/fetch-cache.js +6 -2
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.js +5 -3
- package/dist/shims/image-props.d.ts +6 -0
- package/dist/shims/image-props.js +39 -3
- package/dist/shims/image.js +3 -3
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/link.js +5 -10
- package/dist/shims/navigation.js +2 -3
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/slot.d.ts +9 -2
- package/dist/shims/slot.js +76 -11
- package/dist/shims/unified-request-context.d.ts +6 -0
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/base-path.d.ts +7 -0
- package/dist/utils/base-path.js +11 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ const _pagesI18nPath = resolveEntryPath("../server/pages-i18n.js", import.meta.u
|
|
|
21
21
|
const _pagesDataRoutePath = resolveEntryPath("../server/pages-data-route.js", import.meta.url);
|
|
22
22
|
const _pagesDefault404Path = resolveEntryPath("../server/pages-default-404.js", import.meta.url);
|
|
23
23
|
const _pagesApiRoutePath = resolveEntryPath("../server/pages-api-route.js", import.meta.url);
|
|
24
|
+
const _requestErrorLogPath = resolveEntryPath("../server/request-error-log.js", import.meta.url);
|
|
24
25
|
const _serverGlobalsPath = resolveEntryPath("../server/server-globals.js", import.meta.url);
|
|
25
26
|
const _queryUtilsPath = resolveEntryPath("../utils/query.js", import.meta.url);
|
|
26
27
|
const _pagesPageHandlerPath = resolveEntryPath("../server/pages-page-handler.js", import.meta.url);
|
|
@@ -103,6 +104,7 @@ async function generatePagesRequestEntry(pagesDir, nextConfig, fileMatcher, midd
|
|
|
103
104
|
deviceSizes: nextConfig?.images?.deviceSizes,
|
|
104
105
|
imageSizes: nextConfig?.images?.imageSizes,
|
|
105
106
|
qualities: nextConfig?.images?.qualities,
|
|
107
|
+
localPatterns: nextConfig?.images?.localPatterns,
|
|
106
108
|
dangerouslyAllowSVG: nextConfig?.images?.dangerouslyAllowSVG,
|
|
107
109
|
dangerouslyAllowLocalIP: nextConfig?.images?.dangerouslyAllowLocalIP,
|
|
108
110
|
contentDispositionType: nextConfig?.images?.contentDispositionType,
|
|
@@ -280,6 +282,7 @@ async function generateServerEntry(pagesDir, nextConfig, fileMatcher, middleware
|
|
|
280
282
|
deviceSizes: nextConfig?.images?.deviceSizes,
|
|
281
283
|
imageSizes: nextConfig?.images?.imageSizes,
|
|
282
284
|
qualities: nextConfig?.images?.qualities,
|
|
285
|
+
localPatterns: nextConfig?.images?.localPatterns,
|
|
283
286
|
dangerouslyAllowSVG: nextConfig?.images?.dangerouslyAllowSVG,
|
|
284
287
|
dangerouslyAllowLocalIP: nextConfig?.images?.dangerouslyAllowLocalIP,
|
|
285
288
|
contentDispositionType: nextConfig?.images?.contentDispositionType,
|
|
@@ -370,6 +373,7 @@ import { buildRouteTrie as _buildRouteTrie, trieMatch as _trieMatch } from ${JSO
|
|
|
370
373
|
import { reportRequestError as _reportRequestError } from "vinext/instrumentation";
|
|
371
374
|
import { resolvePagesI18nRequest } from ${JSON.stringify(_pagesI18nPath)};
|
|
372
375
|
import { handlePagesApiRoute as __handlePagesApiRoute } from ${JSON.stringify(_pagesApiRoutePath)};
|
|
376
|
+
import { logRequestError as __logRequestError } from ${JSON.stringify(_requestErrorLogPath)};
|
|
373
377
|
import { normalizePagesDataRequest as __normalizePagesDataRequest, shouldAddTrailingSlashToPagesDataPath as __shouldAddTrailingSlashToPagesDataPath, buildNextDataNotFoundResponse as __buildNextDataNotFoundResponse } from ${JSON.stringify(_pagesDataRoutePath)};
|
|
374
378
|
import { buildDefaultPagesNotFoundResponse as __buildDefaultPagesNotFoundResponse } from ${JSON.stringify(_pagesDefault404Path)};
|
|
375
379
|
import { createPagesPageHandler as __createPagesPageHandler } from ${JSON.stringify(_pagesPageHandlerPath)};
|
|
@@ -618,7 +622,7 @@ export async function handleApiRoute(request, url, ctx, trustedRevalidateOrigin,
|
|
|
618
622
|
trustedRevalidateOrigin,
|
|
619
623
|
url,
|
|
620
624
|
reportRequestError(error, routePattern) {
|
|
621
|
-
|
|
625
|
+
__logRequestError("[vinext] API error:", error);
|
|
622
626
|
return _reportRequestError(
|
|
623
627
|
error,
|
|
624
628
|
{ path: url, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
|
package/dist/index.js
CHANGED
|
@@ -11,9 +11,10 @@ import { getReactUpgradeDeps, reactUpgradeRequiredMessage } from "./utils/react-
|
|
|
11
11
|
import { resolvePluginReactPath } from "./utils/plugin-react-version.js";
|
|
12
12
|
import { loadDotenv } from "./config/dotenv.js";
|
|
13
13
|
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
|
|
14
|
+
import { serializeCacheLifeProfiles } from "./utils/cache-life-profiles.js";
|
|
14
15
|
import { VINEXT_MW_CTX_HEADER } from "./utils/protocol-headers.js";
|
|
15
16
|
import { encodeMiddlewareRequestHeaders } from "./utils/middleware-request-headers.js";
|
|
16
|
-
import { hasBasePath, stripBasePath } from "./utils/base-path.js";
|
|
17
|
+
import { hasBasePath, restoreBasePath, stripBasePath } from "./utils/base-path.js";
|
|
17
18
|
import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_TIMING_HEADER } from "./server/headers.js";
|
|
18
19
|
import { methodNotAllowedResponse, notFoundStaticAssetResponse } from "./server/http-error-responses.js";
|
|
19
20
|
import { isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./server/open-redirect.js";
|
|
@@ -88,6 +89,7 @@ import { createClientCompileHintsPlugin } from "./plugins/client-compile-hints.j
|
|
|
88
89
|
import { clientReferenceDedupPlugin } from "./plugins/client-reference-dedup.js";
|
|
89
90
|
import { dataUrlCssPlugin } from "./plugins/css-data-url.js";
|
|
90
91
|
import { createCssModuleImportCompatibilityPlugin } from "./plugins/css-module-imports.js";
|
|
92
|
+
import { createCssTargetPlugin } from "./plugins/css-target.js";
|
|
91
93
|
import { createWorkerImageImportsPlugin } from "./plugins/worker-image-imports.js";
|
|
92
94
|
import { assertClientOutDirIsSeparate, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputFileNameDefaults, createMultiStageChunkFileNames, createMultiStageCodeSplittingConfig, createRscFrameworkChunkOutputConfig, createWorkerFileNames, findUnsupportedClientOutputFileNames, getBuildBundlerOptions, getClientTreeshakeConfig, getOutputFileNames, withBuildBundlerOptions } from "./build/client-build-config.js";
|
|
93
95
|
import { createRouteClientReferencesFallbackPlugin, createRscClientReferenceLoadersPlugin } from "./plugins/rsc-client-reference-loaders.js";
|
|
@@ -1373,6 +1375,29 @@ function vinext(options = {}) {
|
|
|
1373
1375
|
});
|
|
1374
1376
|
const plugins = [
|
|
1375
1377
|
buildLifecyclePlugins[0],
|
|
1378
|
+
{
|
|
1379
|
+
name: "vinext:dev-origin-check",
|
|
1380
|
+
apply: "serve",
|
|
1381
|
+
enforce: "pre",
|
|
1382
|
+
configureServer(server) {
|
|
1383
|
+
server.middlewares.use((req, res, next) => {
|
|
1384
|
+
const blockReason = validateDevRequest({
|
|
1385
|
+
origin: req.headers.origin,
|
|
1386
|
+
host: req.headers.host,
|
|
1387
|
+
"x-forwarded-host": req.headers["x-forwarded-host"],
|
|
1388
|
+
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
1389
|
+
"sec-fetch-mode": req.headers["sec-fetch-mode"]
|
|
1390
|
+
}, nextConfig?.allowedDevOrigins);
|
|
1391
|
+
if (blockReason) {
|
|
1392
|
+
console.warn(`[vinext] Blocked dev request: ${blockReason} (${req.url})`);
|
|
1393
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
1394
|
+
res.end("Forbidden");
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
next();
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
},
|
|
1376
1401
|
createStyledJsxPlugin(earlyBaseDir),
|
|
1377
1402
|
mdxProxyPlugin,
|
|
1378
1403
|
reactPluginPromise,
|
|
@@ -1442,6 +1467,7 @@ function vinext(options = {}) {
|
|
|
1442
1467
|
}),
|
|
1443
1468
|
dataUrlCssPlugin(),
|
|
1444
1469
|
createCssModuleImportCompatibilityPlugin(),
|
|
1470
|
+
createCssTargetPlugin(),
|
|
1445
1471
|
createDevServerLifecyclePlugin({}, (config) => config[VINEXT_DEV_CLI_LIFECYCLE] === true),
|
|
1446
1472
|
{
|
|
1447
1473
|
name: "vinext:config",
|
|
@@ -1595,6 +1621,7 @@ function vinext(options = {}) {
|
|
|
1595
1621
|
defines["process.env.__VINEXT_TRAILING_SLASH"] = JSON.stringify(nextConfig.trailingSlash ? "true" : "false");
|
|
1596
1622
|
defines["process.env.__VINEXT_MANUAL_TRAILING_SLASH"] = JSON.stringify(nextConfig.skipTrailingSlashRedirect ? "true" : "false");
|
|
1597
1623
|
defines["process.env.__NEXT_CONFIG_OUTPUT"] = JSON.stringify(nextConfig.output ?? "");
|
|
1624
|
+
defines["process.env.__VINEXT_CACHE_LIFE_PROFILES"] = JSON.stringify(serializeCacheLifeProfiles(nextConfig.cacheLife));
|
|
1598
1625
|
defines["process.env.__VINEXT_IMAGE_REMOTE_PATTERNS"] = JSON.stringify(JSON.stringify(nextConfig.images?.remotePatterns ?? []));
|
|
1599
1626
|
defines["process.env.__VINEXT_IMAGE_DOMAINS"] = JSON.stringify(JSON.stringify(nextConfig.images?.domains ?? []));
|
|
1600
1627
|
{
|
|
@@ -1739,12 +1766,6 @@ function vinext(options = {}) {
|
|
|
1739
1766
|
} } : {},
|
|
1740
1767
|
build: {
|
|
1741
1768
|
ssrEmitAssets: true,
|
|
1742
|
-
cssTarget: [
|
|
1743
|
-
"chrome111",
|
|
1744
|
-
"edge111",
|
|
1745
|
-
"firefox114",
|
|
1746
|
-
"safari15"
|
|
1747
|
-
],
|
|
1748
1769
|
assetsDir: clientAssetsDir,
|
|
1749
1770
|
...!isSSR && !hasClientBuildEnvironment ? { assetsInlineLimit: clientAssetsInlineLimit } : {},
|
|
1750
1771
|
...withBuildBundlerOptions({
|
|
@@ -2428,6 +2449,7 @@ function vinext(options = {}) {
|
|
|
2428
2449
|
deviceSizes: nextConfig?.images?.deviceSizes,
|
|
2429
2450
|
imageSizes: nextConfig?.images?.imageSizes,
|
|
2430
2451
|
qualities: nextConfig?.images?.qualities,
|
|
2452
|
+
localPatterns: nextConfig?.images?.localPatterns,
|
|
2431
2453
|
dangerouslyAllowSVG: nextConfig?.images?.dangerouslyAllowSVG,
|
|
2432
2454
|
dangerouslyAllowLocalIP: nextConfig?.images?.dangerouslyAllowLocalIP,
|
|
2433
2455
|
contentDispositionType: nextConfig?.images?.contentDispositionType,
|
|
@@ -3147,22 +3169,6 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3147
3169
|
}
|
|
3148
3170
|
return isExistingDevPublicFile(pathname);
|
|
3149
3171
|
};
|
|
3150
|
-
server.middlewares.use((req, res, next) => {
|
|
3151
|
-
const blockReason = validateDevRequest({
|
|
3152
|
-
origin: req.headers.origin,
|
|
3153
|
-
host: req.headers.host,
|
|
3154
|
-
"x-forwarded-host": req.headers["x-forwarded-host"],
|
|
3155
|
-
"sec-fetch-site": req.headers["sec-fetch-site"],
|
|
3156
|
-
"sec-fetch-mode": req.headers["sec-fetch-mode"]
|
|
3157
|
-
}, nextConfig?.allowedDevOrigins);
|
|
3158
|
-
if (blockReason) {
|
|
3159
|
-
console.warn(`[vinext] Blocked dev request: ${blockReason} (${req.url})`);
|
|
3160
|
-
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
3161
|
-
res.end("Forbidden");
|
|
3162
|
-
return;
|
|
3163
|
-
}
|
|
3164
|
-
next();
|
|
3165
|
-
});
|
|
3166
3172
|
server.middlewares.use((req, res, next) => {
|
|
3167
3173
|
if (!sendRepeatedSlashRedirect(req.url ?? "/", res)) next();
|
|
3168
3174
|
});
|
|
@@ -3253,7 +3259,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3253
3259
|
if (hasAppDir) server.middlewares.use((req, res, next) => {
|
|
3254
3260
|
const url = req.url ?? "/";
|
|
3255
3261
|
const [pathname] = url.split("?");
|
|
3256
|
-
if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules") || url.includes(".") && !pathname.endsWith(".html")
|
|
3262
|
+
if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules") || url.includes(".") && !pathname.endsWith(".html")) return next();
|
|
3257
3263
|
const _reqStart = now();
|
|
3258
3264
|
const _reqWallStart = Date.now();
|
|
3259
3265
|
let _compileMs;
|
|
@@ -3287,12 +3293,11 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3287
3293
|
return _origWriteHead(statusCode, ...args);
|
|
3288
3294
|
};
|
|
3289
3295
|
res.on("finish", () => {
|
|
3290
|
-
const logUrl = url.replace(/\.rsc(\?|$)/, "$1");
|
|
3291
3296
|
const totalMs = now() - _reqStart;
|
|
3292
3297
|
const resolvedRenderMs = _renderMs !== void 0 ? _renderMs : _compileMs !== void 0 ? Math.max(0, Math.round(totalMs - _compileMs)) : void 0;
|
|
3293
3298
|
logRequest({
|
|
3294
3299
|
method: req.method ?? "GET",
|
|
3295
|
-
url
|
|
3300
|
+
url,
|
|
3296
3301
|
status: res.statusCode,
|
|
3297
3302
|
totalMs,
|
|
3298
3303
|
compileMs: _compileMs,
|
|
@@ -3370,14 +3375,17 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3370
3375
|
const viteBase = server.config.base;
|
|
3371
3376
|
const viteBasePath = viteBase.startsWith("/") && viteBase !== "/" ? viteBase.replace(/\/+$/, "") : "";
|
|
3372
3377
|
const routingBasePath = bp || viteBasePath;
|
|
3378
|
+
const viteStrippedBasePath = originalRequestUrl !== originalEncodedUrl;
|
|
3379
|
+
let originalUrlHadBasePath = false;
|
|
3373
3380
|
if (routingBasePath) {
|
|
3374
|
-
if (hasBasePath(pathname, routingBasePath)) {
|
|
3381
|
+
if (!viteStrippedBasePath && hasBasePath(pathname, routingBasePath)) {
|
|
3375
3382
|
const stripped = stripBasePath(pathname, routingBasePath);
|
|
3376
3383
|
url = stripped + (url.includes("?") ? url.slice(url.indexOf("?")) : "");
|
|
3377
3384
|
pathname = stripped;
|
|
3378
3385
|
}
|
|
3379
3386
|
const middlewarePathname = middlewareUrl.split("?")[0];
|
|
3380
3387
|
if (hasBasePath(middlewarePathname, routingBasePath)) {
|
|
3388
|
+
originalUrlHadBasePath = true;
|
|
3381
3389
|
const middlewareQs = middlewareUrl.includes("?") ? middlewareUrl.slice(middlewareUrl.indexOf("?")) : "";
|
|
3382
3390
|
middlewareUrl = stripBasePath(middlewarePathname, routingBasePath) + middlewareQs;
|
|
3383
3391
|
}
|
|
@@ -3387,7 +3395,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3387
3395
|
routeUrl = stripBasePath(routePathname, routingBasePath) + routeQs;
|
|
3388
3396
|
}
|
|
3389
3397
|
}
|
|
3390
|
-
let configMatchPathname =
|
|
3398
|
+
let configMatchPathname = middlewareUrl.split("?")[0];
|
|
3391
3399
|
if (nextConfig && !nextConfig.skipTrailingSlashRedirect) {
|
|
3392
3400
|
const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
|
|
3393
3401
|
const trailingSlashRedirect = normalizeTrailingSlash(routeUrl.split("?")[0], bp, nextConfig.trailingSlash, qs);
|
|
@@ -3404,7 +3412,7 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3404
3412
|
const rawRoutePathname = routeUrl.split("?")[0];
|
|
3405
3413
|
if (isNextDataPathname(rawRoutePathname)) {
|
|
3406
3414
|
const rawDataMatch = parseNextDataPathname(rawRoutePathname, devBuildId);
|
|
3407
|
-
const dataMatch = rawDataMatch ? parseNextDataPathname(pathname, devBuildId) : null;
|
|
3415
|
+
const dataMatch = rawDataMatch ? parseNextDataPathname(pathname, devBuildId, true) : null;
|
|
3408
3416
|
if (dataMatch && rawDataMatch) {
|
|
3409
3417
|
isDataReq = true;
|
|
3410
3418
|
const qs = url.includes("?") ? url.slice(url.indexOf("?")) : "";
|
|
@@ -3468,11 +3476,15 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3468
3476
|
removeForwardedMiddlewareContext(req);
|
|
3469
3477
|
for (const key of Object.keys(req.headers)) delete req.headers[key];
|
|
3470
3478
|
for (const [key, value] of nextRequestHeaders) req.headers[key] = value;
|
|
3479
|
+
const setCookies = nextRequestHeaders.getSetCookie();
|
|
3480
|
+
if (setCookies.length > 1) req.headers["set-cookie"] = setCookies;
|
|
3471
3481
|
};
|
|
3472
3482
|
const devRunMiddlewareAdapter = capturedMiddlewarePath ? async (_request, _ctx, opts) => {
|
|
3473
3483
|
const rawProto = process.env.VINEXT_TRUST_PROXY === "1" || (process.env.VINEXT_TRUSTED_HOSTS ?? "").split(",").some((h) => h.trim()) ? String(req.headers["x-forwarded-proto"] || "").split(",")[0].trim() : "";
|
|
3474
3484
|
const mwOrigin = `${rawProto === "https" || rawProto === "http" ? rawProto : "http"}://${requestHost}`;
|
|
3475
|
-
const
|
|
3485
|
+
const middlewareRequestUrl = new URL(middlewareUrl, mwOrigin);
|
|
3486
|
+
if (originalUrlHadBasePath) middlewareRequestUrl.pathname = restoreBasePath(middlewareRequestUrl.pathname, bp);
|
|
3487
|
+
const middlewareRequest = new Request(middlewareRequestUrl, {
|
|
3476
3488
|
method: req.method,
|
|
3477
3489
|
headers: nodeRequestHeaders,
|
|
3478
3490
|
signal: webRequest.signal
|
|
@@ -3618,7 +3630,8 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3618
3630
|
trustedRevalidateOrigin: getTrustedDevRevalidateOrigin(),
|
|
3619
3631
|
allowedRevalidateHeaderKeys: nextConfig?.allowedRevalidateHeaderKeys,
|
|
3620
3632
|
trailingSlash: nextConfig?.trailingSlash,
|
|
3621
|
-
skipTrailingSlashRedirect: nextConfig?.skipTrailingSlashRedirect
|
|
3633
|
+
skipTrailingSlashRedirect: nextConfig?.skipTrailingSlashRedirect,
|
|
3634
|
+
requestPathname: originalUrlHadBasePath ? restoreBasePath(routeUrl.split("?")[0], bp) : routeUrl.split("?")[0]
|
|
3622
3635
|
})) return;
|
|
3623
3636
|
if (hasAppDir) {
|
|
3624
3637
|
if (pipelineResult.configRewriteFired) forwardInternalApiRewriteToApp(pipelineResult.apiUrl);
|
|
@@ -3662,7 +3675,6 @@ export const loadServerActionClient = ${hasServerActions ? `() => import(${JSON.
|
|
|
3662
3675
|
const url = req.url ?? "/";
|
|
3663
3676
|
if (!hasPagesDir) return next();
|
|
3664
3677
|
if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules")) return next();
|
|
3665
|
-
if (url.split("?")[0].endsWith(".rsc")) return next();
|
|
3666
3678
|
if (hasCloudflarePlugin) return next();
|
|
3667
3679
|
await pagesInstrumentationReady;
|
|
3668
3680
|
const traceHeaders = new Headers();
|
package/dist/init-cloudflare.js
CHANGED
|
@@ -140,7 +140,7 @@ function setupCloudflarePlatform(context, cloudflare) {
|
|
|
140
140
|
generatedPlatformFiles.push(path.relative(context.root, responseStorePath) || RESPONSE_STORE_WRANGLER_CONFIG);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
const nextSteps = [];
|
|
143
|
+
const nextSteps = !wranglerCode || !findTopLevelJsonProperty(wranglerCode, "main") ? workerEntryWarning(context.root, context.isStaticExport) : [];
|
|
144
144
|
if (cloudflare.cdnCache === "response-store" && (cloudflare.responseStoreMode ?? "service-binding") === "service-binding") nextSteps.push("Deploy Workers Response Store before deploying the application:", ` ${context.packageManager ?? "npm"} run deploy:response-store`);
|
|
145
145
|
if (cloudflare.prerender && cloudflare.cdnCache !== "static-assets") nextSteps.push("Pre-rendered routes are built, but Cloudflare deploys do not serve them.", " Use the Static Assets cache to serve them, or cache warming to fill another cache.");
|
|
146
146
|
return {
|
|
@@ -193,14 +193,15 @@ function setupCfPlatform(context, cloudflare) {
|
|
|
193
193
|
}
|
|
194
194
|
const configPath = path.join(context.root, "cloudflare.config.ts");
|
|
195
195
|
const generatedPlatformFiles = [];
|
|
196
|
+
const nextSteps = [];
|
|
196
197
|
if (!fs.existsSync(configPath)) {
|
|
197
198
|
fs.writeFileSync(configPath, generateTypedCloudflareConfig({
|
|
198
199
|
...projectInfo,
|
|
199
200
|
isStaticExport: context.isStaticExport
|
|
200
201
|
}, cloudflare, context.today));
|
|
201
202
|
generatedPlatformFiles.push("cloudflare.config.ts");
|
|
203
|
+
nextSteps.push(...workerEntryWarning(context.root, context.isStaticExport));
|
|
202
204
|
}
|
|
203
|
-
const nextSteps = [];
|
|
204
205
|
if (serviceBinding) nextSteps.push("After `vinext build`, deploy the Response Store Worker explicitly (and repeat when its code/config changes):", ` ${context.packageManager ?? "npm"} run deploy:response-store`, "vinext-cloudflare deploy only deploys the application Worker.");
|
|
205
206
|
if (cloudflare.prerender && cloudflare.cdnCache !== "static-assets") nextSteps.push("Pre-rendered routes are built, but Cloudflare deploys do not serve them.", " Use the Static Assets cache to serve them, or cache warming to fill another cache.");
|
|
206
207
|
nextSteps.push("For TypeScript, add \".cloudflare/types\" to the include list in tsconfig.json.", "Worker types are generated during dev/build; run `cf workers types` before standalone type-checks.");
|
|
@@ -280,6 +281,21 @@ function resolveWorkerEntry(root) {
|
|
|
280
281
|
return "vinext/server/fetch-handler";
|
|
281
282
|
}
|
|
282
283
|
/**
|
|
284
|
+
* A `worker/index.*` that never reaches vinext's handler (say, a migrated Vite
|
|
285
|
+
* SPA's API Worker) answers every page route itself, so each one 404s (#4460).
|
|
286
|
+
*/
|
|
287
|
+
function workerEntryWarning(root, isStaticExport) {
|
|
288
|
+
if (isStaticExport) return [];
|
|
289
|
+
const entry = resolveWorkerEntry(root);
|
|
290
|
+
if (entry === "vinext/server/fetch-handler") return [];
|
|
291
|
+
if (fs.readFileSync(path.join(root, entry), "utf-8").includes("vinext/server/fetch-handler")) return [];
|
|
292
|
+
return [
|
|
293
|
+
`Warning: ${entry.slice(2)} does not import vinext/server/fetch-handler. As the Worker entry`,
|
|
294
|
+
" it must hand requests to vinext, or every page 404s. Otherwise point the Worker entry",
|
|
295
|
+
" (entrypoint in cloudflare.config.ts, or main in wrangler.jsonc) at vinext/server/fetch-handler."
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
283
299
|
* Next.js runs no middleware for a static export, and an export with
|
|
284
300
|
* `trailingSlash` relies on the default html_handling to serve `/about/` from
|
|
285
301
|
* `about/index.html`, so export apps keep asset-first serving.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
//#region src/plugins/css-target.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Applies {@link DEFAULT_CSS_TARGET} only where nobody chose a target (#4413).
|
|
5
|
+
*
|
|
6
|
+
* Vite merges config by concatenating arrays, and the CSS minifier keeps the
|
|
7
|
+
* oldest version of each browser, so a pin merged onto a chosen target would
|
|
8
|
+
* stop an app from ever raising it. Instead nothing is set while config hooks
|
|
9
|
+
* run, so the app and every plugin hook see and merge plain Vite values. The
|
|
10
|
+
* post-ordered `config` and `configEnvironment` hooks only note where a target
|
|
11
|
+
* was set, and the pin is applied once config is resolved.
|
|
12
|
+
*
|
|
13
|
+
* Both the top-level `build`, which Vite's CSS plugin minifies with (a copy of
|
|
14
|
+
* the environment's in per-environment builds), and every environment's `build`
|
|
15
|
+
* are checked.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createCssTargetPlugin(): Plugin;
|
|
18
|
+
//#endregion
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//#region src/plugins/css-target.ts
|
|
2
|
+
/**
|
|
3
|
+
* CSS minification target. Vite defaults it to the same target as JS
|
|
4
|
+
* (modern evergreens), which lets the CSS minifier (Lightning CSS by
|
|
5
|
+
* default, or esbuild) rewrite
|
|
6
|
+
* `@media (max-width: 768px)` to the Media Queries Level 4 range
|
|
7
|
+
* syntax `@media (width <= 768px)`. Both forms are semantically
|
|
8
|
+
* equivalent in modern browsers, but the rewrite is observable to
|
|
9
|
+
* user code that inspects `cssText` of `CSSMediaRule`s and breaks
|
|
10
|
+
* tools that pattern-match the raw query string. Next.js does not
|
|
11
|
+
* perform this rewrite by default (its webpack/lightningcss CSS
|
|
12
|
+
* pipeline preserves the original syntax), so user code carried
|
|
13
|
+
* over from Next.js can break when migrating to vinext.
|
|
14
|
+
*
|
|
15
|
+
* The minifier lowers a CSS feature when ANY target in the list lacks
|
|
16
|
+
* support, so we only need to pin one engine below the range-syntax
|
|
17
|
+
* baseline. Range syntax shipped in Chrome 104, Edge 104, Firefox 63,
|
|
18
|
+
* and Safari 16.4 (per esbuild's `internal/compat/css_table.go`
|
|
19
|
+
* MediaRange entry — and caniuse). Of those, Safari is the latest:
|
|
20
|
+
* pinning `safari15` (semantically Safari 15.0, which predates
|
|
21
|
+
* Safari 16.4) is sufficient to suppress the rewrite on its own.
|
|
22
|
+
*
|
|
23
|
+
* The other three targets are pinned to ~2023 baselines instead of
|
|
24
|
+
* the absolute oldest supported version so the minifier does NOT
|
|
25
|
+
* collaterally downlevel unrelated modern CSS features. With
|
|
26
|
+
* chrome111/edge111/firefox114 we keep through:
|
|
27
|
+
* - `:is()` pseudo-class (Chrome 88, Firefox 78)
|
|
28
|
+
* - `hwb()` colors (Chrome 101, Firefox 96)
|
|
29
|
+
* - `lab()`, `oklch()`, `color()` (Chrome 111, Firefox 113)
|
|
30
|
+
* - gradient interpolation hints (Chrome 111)
|
|
31
|
+
* CSS Nesting (Chrome 120, Safari 17.2) and Firefox-137 gradient
|
|
32
|
+
* interpolation will still be lowered; that is an intentional
|
|
33
|
+
* trade-off — those features are newer than the baseline and
|
|
34
|
+
* lowering them is the correct behavior for our target audience.
|
|
35
|
+
*
|
|
36
|
+
* Mirrors the Next.js fixture
|
|
37
|
+
* test/e2e/app-dir/css-media-query/css-media-query.test.ts which
|
|
38
|
+
* asserts `cssText` preserves `max-width: 768px`.
|
|
39
|
+
*/
|
|
40
|
+
const DEFAULT_CSS_TARGET = [
|
|
41
|
+
"chrome111",
|
|
42
|
+
"edge111",
|
|
43
|
+
"firefox114",
|
|
44
|
+
"safari15"
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Applies {@link DEFAULT_CSS_TARGET} only where nobody chose a target (#4413).
|
|
48
|
+
*
|
|
49
|
+
* Vite merges config by concatenating arrays, and the CSS minifier keeps the
|
|
50
|
+
* oldest version of each browser, so a pin merged onto a chosen target would
|
|
51
|
+
* stop an app from ever raising it. Instead nothing is set while config hooks
|
|
52
|
+
* run, so the app and every plugin hook see and merge plain Vite values. The
|
|
53
|
+
* post-ordered `config` and `configEnvironment` hooks only note where a target
|
|
54
|
+
* was set, and the pin is applied once config is resolved.
|
|
55
|
+
*
|
|
56
|
+
* Both the top-level `build`, which Vite's CSS plugin minifies with (a copy of
|
|
57
|
+
* the environment's in per-environment builds), and every environment's `build`
|
|
58
|
+
* are checked.
|
|
59
|
+
*/
|
|
60
|
+
function createCssTargetPlugin() {
|
|
61
|
+
let topLevelConfigured = false;
|
|
62
|
+
const configuredEnvironments = /* @__PURE__ */ new Set();
|
|
63
|
+
return {
|
|
64
|
+
name: "vinext:css-target",
|
|
65
|
+
enforce: "post",
|
|
66
|
+
config: {
|
|
67
|
+
order: "post",
|
|
68
|
+
handler(config) {
|
|
69
|
+
topLevelConfigured = config.build?.cssTarget !== void 0;
|
|
70
|
+
configuredEnvironments.clear();
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
configEnvironment: {
|
|
74
|
+
order: "post",
|
|
75
|
+
handler(name, config) {
|
|
76
|
+
if (config.build?.cssTarget !== void 0) configuredEnvironments.add(name);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
configResolved: {
|
|
80
|
+
order: "pre",
|
|
81
|
+
handler(config) {
|
|
82
|
+
pinUnsetCssTarget(config.build, topLevelConfigured);
|
|
83
|
+
for (const [name, environment] of Object.entries(config.environments)) pinUnsetCssTarget(environment.build, configuredEnvironments.has(name));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function pinUnsetCssTarget(build, configured) {
|
|
89
|
+
if (configured || build.cssTarget !== build.target) return;
|
|
90
|
+
build.cssTarget = [...DEFAULT_CSS_TARGET];
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { createCssTargetPlugin };
|
|
@@ -89,7 +89,8 @@ function isReferenceIdentifier(node, parent) {
|
|
|
89
89
|
if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") return false;
|
|
90
90
|
if (parent.type === "ExportSpecifier") return false;
|
|
91
91
|
if (parent.type === "MemberExpression" && parent.property === node && !parent.computed) return false;
|
|
92
|
-
if ((parent.type === "Property" || parent.type === "MethodDefinition") && parent.key === node && !parent.computed && !(parent.type === "Property" && parent.shorthand)) return false;
|
|
92
|
+
if ((parent.type === "Property" || parent.type === "MethodDefinition" || parent.type === "PropertyDefinition" || parent.type === "AccessorProperty" || parent.type === "ImportAttribute") && parent.key === node && !parent.computed && !(parent.type === "Property" && parent.shorthand)) return false;
|
|
93
|
+
if (parent.type === "MetaProperty") return false;
|
|
93
94
|
if ((parent.type === "LabeledStatement" || parent.type === "BreakStatement" || parent.type === "ContinueStatement") && parent.label === node) return false;
|
|
94
95
|
const parameters = "params" in parent ? parent.params : void 0;
|
|
95
96
|
if (Array.isArray(parameters) && parameters.includes(node)) return false;
|
|
@@ -109,6 +109,10 @@ type ParallelSlot = {
|
|
|
109
109
|
loadingTreePositions?: number[];
|
|
110
110
|
/** Absolute path to the slot's error component */
|
|
111
111
|
errorPath: string | null;
|
|
112
|
+
/** Every error convention from the slot root to its active page, outermost first. */
|
|
113
|
+
errorPaths?: string[];
|
|
114
|
+
/** Slot-root-relative tree positions aligned with errorPaths. */
|
|
115
|
+
errorTreePositions?: number[];
|
|
112
116
|
/** Nearest not-found convention for the slot's active branch. */
|
|
113
117
|
notFoundPath?: string | null;
|
|
114
118
|
/** Tree position of that convention relative to the slot root. */
|
|
@@ -167,6 +171,12 @@ export type AppRoute = {
|
|
|
167
171
|
id: string;
|
|
168
172
|
ownerTreePath: string;
|
|
169
173
|
state: "active" | "default" | "unmatched";
|
|
174
|
+
/**
|
|
175
|
+
* Set on a sub-route minted for a slot page with no children page of its
|
|
176
|
+
* own: its children render a default, a sibling catch-all, or nothing, so
|
|
177
|
+
* its route segments don't describe them.
|
|
178
|
+
*/
|
|
179
|
+
synthetic?: true;
|
|
170
180
|
};
|
|
171
181
|
/**
|
|
172
182
|
* Interception markers not wrapped in an `@slot` directory.
|
|
@@ -594,7 +594,8 @@ function discoverSlotSubRoutes(routes, matcher, ghostParents = []) {
|
|
|
594
594
|
childrenSlot: {
|
|
595
595
|
id: childrenSlotId,
|
|
596
596
|
ownerTreePath: childrenOwnerTreePath,
|
|
597
|
-
state: childrenDefault ? "default" : childrenCatchAll ? "active" : "unmatched"
|
|
597
|
+
state: childrenDefault ? "default" : childrenCatchAll ? "active" : "unmatched",
|
|
598
|
+
synthetic: true
|
|
598
599
|
},
|
|
599
600
|
loadingPath: null,
|
|
600
601
|
loadingPaths: parentRoute.loadingPaths,
|
|
@@ -742,10 +743,22 @@ function withSlotLoadingEntries(slot, pagePath, matcher) {
|
|
|
742
743
|
...slot,
|
|
743
744
|
loadingPaths: loadingEntries.map((entry) => entry.path),
|
|
744
745
|
loadingTreePositions: loadingEntries.map((entry) => entry.treePosition),
|
|
746
|
+
...findSlotErrorFields(slot.ownerDir, pagePath, matcher),
|
|
745
747
|
...findSlotNotFoundFields(slot.ownerDir, pagePath, matcher)
|
|
746
748
|
};
|
|
747
749
|
}
|
|
748
750
|
/**
|
|
751
|
+
* Every error convention on the slot's active branch. Each catches errors in
|
|
752
|
+
* its own segment, below that segment's layout.
|
|
753
|
+
*/
|
|
754
|
+
function findSlotErrorFields(slotDir, pagePath, matcher) {
|
|
755
|
+
const entries = findSlotSegmentFileEntries(slotDir, pagePath, "error", matcher);
|
|
756
|
+
return {
|
|
757
|
+
errorPaths: entries.map((entry) => entry.path),
|
|
758
|
+
errorTreePositions: entries.map((entry) => entry.treePosition)
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
749
762
|
* Every not-found convention on the slot's active branch, plus the nearest one,
|
|
750
763
|
* which supplies the slot's not-found metadata.
|
|
751
764
|
*/
|
|
@@ -1347,6 +1360,7 @@ function discoverParallelSlots(dir, appDir, matcher, includeNestedOnlySlots = fa
|
|
|
1347
1360
|
loadingPaths: loadingEntries.map((loading) => loading.path),
|
|
1348
1361
|
loadingTreePositions: loadingEntries.map((loading) => loading.treePosition),
|
|
1349
1362
|
errorPath: findFile(slotDir, "error", matcher),
|
|
1363
|
+
...findSlotErrorFields(slotDir, pagePath, matcher),
|
|
1350
1364
|
...findSlotNotFoundFields(slotDir, pagePath, matcher),
|
|
1351
1365
|
interceptingRoutes,
|
|
1352
1366
|
layoutIndex: -1,
|
|
@@ -14,5 +14,7 @@ export declare function handleApiRoute(runner: ModuleImporter, req: IncomingMess
|
|
|
14
14
|
allowedRevalidateHeaderKeys?: readonly string[];
|
|
15
15
|
trailingSlash?: boolean;
|
|
16
16
|
skipTrailingSlashRedirect?: boolean;
|
|
17
|
+
/** Edge API request pathname, with any basePath the dev server stripped restored. */
|
|
18
|
+
requestPathname?: string;
|
|
17
19
|
}): Promise<boolean>;
|
|
18
20
|
//#endregion
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { hasBasePath } from "../utils/base-path.js";
|
|
2
1
|
import { matchRoute } from "../routing/pages-router.js";
|
|
3
2
|
import "./server-globals.js";
|
|
4
3
|
import { resolveRequestHost, resolveRequestProtocol } from "./proxy-trust.js";
|
|
5
4
|
import { NextRequest } from "../shims/server.js";
|
|
6
5
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
6
|
+
import { logRequestError } from "./request-error-log.js";
|
|
7
7
|
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
8
8
|
import { tracePagesApiHandler } from "./pages-execution-tracing.js";
|
|
9
9
|
import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT, resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
@@ -93,7 +93,7 @@ function readEdgeRequestBody(req) {
|
|
|
93
93
|
req.on("error", (error) => controller.error(error));
|
|
94
94
|
} });
|
|
95
95
|
}
|
|
96
|
-
function createEdgeApiRequest(req, res, url, params,
|
|
96
|
+
function createEdgeApiRequest(req, res, url, params, requestPathname) {
|
|
97
97
|
const headers = new Headers();
|
|
98
98
|
for (const [name, value] of Object.entries(req.headers)) {
|
|
99
99
|
if (name.startsWith(":")) continue;
|
|
@@ -103,8 +103,7 @@ function createEdgeApiRequest(req, res, url, params, nextConfig) {
|
|
|
103
103
|
const proto = resolveRequestProtocol(req);
|
|
104
104
|
const host = resolveRequestHost(req, "localhost");
|
|
105
105
|
const requestUrl = new URL(req.url ?? url, `${proto}://${host}`);
|
|
106
|
-
|
|
107
|
-
if (basePath && !hasBasePath(requestUrl.pathname, basePath)) requestUrl.pathname = `${basePath}${requestUrl.pathname}`;
|
|
106
|
+
if (requestPathname !== void 0) requestUrl.pathname = requestPathname;
|
|
108
107
|
const query = mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
109
108
|
requestUrl.search = urlQueryToSearchParams(query).toString();
|
|
110
109
|
const signal = signalFromNodeResponse(res);
|
|
@@ -249,7 +248,7 @@ async function handleApiRoute(runner, req, res, url, apiRoutes, nextConfig) {
|
|
|
249
248
|
try {
|
|
250
249
|
const apiModule = await importModule(runner, route.filePath);
|
|
251
250
|
if (isEdgeApiRouteModule(apiModule)) {
|
|
252
|
-
const nextRequest = new NextRequest(createEdgeApiRequest(req, res, url, params, nextConfig), nextConfig ? { nextConfig: {
|
|
251
|
+
const nextRequest = new NextRequest(createEdgeApiRequest(req, res, url, params, nextConfig?.requestPathname), nextConfig ? { nextConfig: {
|
|
253
252
|
basePath: nextConfig.basePath,
|
|
254
253
|
i18n: nextConfig.i18n ?? void 0,
|
|
255
254
|
trailingSlash: nextConfig.trailingSlash,
|
|
@@ -287,7 +286,7 @@ async function handleApiRoute(runner, req, res, url, apiRoutes, nextConfig) {
|
|
|
287
286
|
res.end(e.message);
|
|
288
287
|
return true;
|
|
289
288
|
}
|
|
290
|
-
|
|
289
|
+
logRequestError(e);
|
|
291
290
|
await reportRequestError(e, {
|
|
292
291
|
path: url,
|
|
293
292
|
method: req.method ?? "GET",
|
|
@@ -6,6 +6,7 @@ import { RequestCookies, ResponseCookies } from "../shims/server.js";
|
|
|
6
6
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
7
7
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
8
8
|
import "../shims/internal/cookies.js";
|
|
9
|
+
import { isStreamedActionRedirectResponse, markStreamedActionRedirectResponse } from "./app-rsc-response-finalizer.js";
|
|
9
10
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
|
|
10
11
|
//#region src/server/app-action-forwarding.ts
|
|
11
12
|
const ACTION_FORWARD_FORBIDDEN_HEADERS = /* @__PURE__ */ new Set([
|
|
@@ -71,11 +72,12 @@ function filterActionForwardResponse(response, sourceMiddlewareHeaders, sourceMi
|
|
|
71
72
|
for (const [key, value] of response.headers) if (!ACTION_FORWARD_FORBIDDEN_HEADERS.has(key.toLowerCase())) headers.set(key, value);
|
|
72
73
|
for (const setCookie of response.headers.getSetCookie()) headers.append("set-cookie", setCookie);
|
|
73
74
|
const preserveResponseStatus = response.headers.get("x-nextjs-action-not-found") === "1" || response.headers.has("x-action-redirect");
|
|
74
|
-
|
|
75
|
+
const forwardedResponse = new Response(response.body, {
|
|
75
76
|
headers,
|
|
76
77
|
status: preserveResponseStatus ? response.status : sourceMiddlewareStatus ?? response.status,
|
|
77
78
|
statusText: response.statusText
|
|
78
79
|
});
|
|
80
|
+
return isStreamedActionRedirectResponse(response) ? markStreamedActionRedirectResponse(forwardedResponse) : forwardedResponse;
|
|
79
81
|
}
|
|
80
82
|
function emptyActionForwardResponse(middlewareContext) {
|
|
81
83
|
const headers = new Headers(middlewareContext.headers ?? void 0);
|