vinext 0.1.0 → 0.1.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 +2 -5
- package/dist/build/assets-ignore.d.ts +32 -0
- package/dist/build/assets-ignore.js +48 -0
- package/dist/build/client-build-config.d.ts +33 -1
- package/dist/build/client-build-config.js +66 -1
- package/dist/check.js +4 -3
- package/dist/cli.js +2 -0
- package/dist/client/navigation-runtime.d.ts +11 -2
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/client/vinext-next-data.d.ts +2 -1
- package/dist/client/window-next.d.ts +6 -4
- package/dist/config/config-matchers.d.ts +31 -5
- package/dist/config/config-matchers.js +50 -3
- package/dist/config/next-config.d.ts +29 -3
- package/dist/config/next-config.js +32 -2
- package/dist/deploy.js +47 -304
- package/dist/entries/app-rsc-entry.d.ts +8 -2
- package/dist/entries/app-rsc-entry.js +61 -5
- package/dist/entries/app-rsc-manifest.js +20 -2
- package/dist/entries/pages-client-entry.js +1 -1
- package/dist/entries/pages-server-entry.js +16 -7
- package/dist/index.d.ts +0 -2
- package/dist/index.js +233 -280
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +8 -4
- package/dist/plugins/optimize-imports.js +16 -12
- package/dist/plugins/postcss.js +18 -14
- package/dist/plugins/require-context.d.ts +6 -0
- package/dist/plugins/require-context.js +184 -0
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +35 -2
- package/dist/routing/app-route-graph.js +179 -8
- package/dist/routing/file-matcher.js +1 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +16 -1
- package/dist/server/api-handler.js +4 -0
- package/dist/server/app-browser-entry.js +155 -215
- package/dist/server/app-browser-error.d.ts +4 -1
- package/dist/server/app-browser-error.js +7 -1
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-interception-context.d.ts +2 -1
- package/dist/server/app-browser-interception-context.js +15 -2
- package/dist/server/app-browser-navigation-controller.d.ts +13 -2
- package/dist/server/app-browser-navigation-controller.js +83 -4
- package/dist/server/app-browser-popstate.d.ts +12 -3
- package/dist/server/app-browser-popstate.js +19 -4
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-state.d.ts +3 -0
- package/dist/server/app-browser-state.js +10 -10
- package/dist/server/app-browser-visible-commit.js +10 -8
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-history-state.d.ts +45 -1
- package/dist/server/app-history-state.js +109 -1
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +22 -1
- package/dist/server/app-page-boundary-render.d.ts +2 -1
- package/dist/server/app-page-boundary-render.js +45 -21
- package/dist/server/app-page-cache.js +9 -7
- package/dist/server/app-page-dispatch.d.ts +14 -0
- package/dist/server/app-page-dispatch.js +21 -6
- package/dist/server/app-page-element-builder.d.ts +23 -2
- package/dist/server/app-page-element-builder.js +58 -17
- package/dist/server/app-page-execution.d.ts +1 -1
- package/dist/server/app-page-execution.js +32 -17
- package/dist/server/app-page-render.d.ts +7 -1
- package/dist/server/app-page-render.js +11 -16
- package/dist/server/app-page-request.d.ts +9 -6
- package/dist/server/app-page-request.js +14 -10
- package/dist/server/app-page-response.d.ts +2 -2
- package/dist/server/app-page-response.js +2 -2
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +10 -8
- package/dist/server/app-page-stream.d.ts +37 -7
- package/dist/server/app-page-stream.js +36 -6
- package/dist/server/app-pages-bridge.d.ts +16 -0
- package/dist/server/app-pages-bridge.js +23 -3
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +2 -0
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.d.ts +1 -0
- package/dist/server/app-route-handler-runtime.js +15 -3
- package/dist/server/app-rsc-handler.d.ts +1 -0
- package/dist/server/app-rsc-handler.js +5 -4
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.d.ts +20 -1
- package/dist/server/app-rsc-route-matching.js +29 -4
- package/dist/server/app-server-action-execution.d.ts +22 -1
- package/dist/server/app-server-action-execution.js +73 -12
- package/dist/server/app-ssr-entry.d.ts +6 -0
- package/dist/server/app-ssr-entry.js +19 -3
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.d.ts +1 -1
- package/dist/server/dev-server.js +97 -43
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-cache.d.ts +37 -1
- package/dist/server/isr-cache.js +85 -1
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +62 -1
- package/dist/server/navigation-planner.js +193 -3
- package/dist/server/navigation-trace.d.ts +12 -2
- package/dist/server/navigation-trace.js +11 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +14 -3
- package/dist/server/pages-api-route.js +6 -1
- package/dist/server/pages-asset-tags.d.ts +15 -4
- package/dist/server/pages-asset-tags.js +18 -12
- package/dist/server/pages-data-route.js +5 -1
- package/dist/server/pages-node-compat.d.ts +5 -11
- package/dist/server/pages-node-compat.js +175 -118
- package/dist/server/pages-page-data.d.ts +38 -7
- package/dist/server/pages-page-data.js +64 -18
- package/dist/server/pages-page-handler.d.ts +10 -2
- package/dist/server/pages-page-handler.js +49 -20
- package/dist/server/pages-page-response.d.ts +55 -2
- package/dist/server/pages-page-response.js +74 -6
- package/dist/server/pages-readiness.d.ts +36 -0
- package/dist/server/pages-readiness.js +21 -0
- package/dist/server/pages-request-pipeline.d.ts +113 -0
- package/dist/server/pages-request-pipeline.js +230 -0
- package/dist/server/pages-revalidate.d.ts +15 -0
- package/dist/server/pages-revalidate.js +19 -0
- package/dist/server/prod-server.d.ts +45 -3
- package/dist/server/prod-server.js +182 -234
- package/dist/server/socket-error-backstop.d.ts +19 -1
- package/dist/server/socket-error-backstop.js +77 -4
- package/dist/shims/app-router-scroll.js +22 -4
- package/dist/shims/cache-runtime.js +39 -2
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +77 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +17 -7
- package/dist/shims/error-boundary.js +8 -1
- package/dist/shims/error.js +37 -11
- package/dist/shims/fetch-cache.d.ts +22 -1
- package/dist/shims/fetch-cache.js +28 -1
- package/dist/shims/hash-scroll.d.ts +1 -0
- package/dist/shims/hash-scroll.js +3 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +37 -1
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +10 -6
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/internal/link-status-registry.d.ts +43 -0
- package/dist/shims/internal/link-status-registry.js +42 -0
- package/dist/shims/internal/route-pattern-for-warning.d.ts +27 -0
- package/dist/shims/internal/route-pattern-for-warning.js +40 -0
- package/dist/shims/internal/utils.d.ts +1 -0
- package/dist/shims/link.js +20 -6
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +9 -18
- package/dist/shims/navigation.js +96 -23
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router-state.js +2 -0
- package/dist/shims/router.d.ts +6 -3
- package/dist/shims/router.js +156 -22
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +17 -1
- package/dist/shims/server.js +31 -6
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/client-build-manifest.d.ts +8 -1
- package/dist/utils/client-build-manifest.js +41 -6
- package/dist/utils/client-entry-manifest.d.ts +11 -0
- package/dist/utils/client-entry-manifest.js +29 -0
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +5 -1
- package/package.json +6 -2
|
@@ -72,6 +72,12 @@ const CONFIG_FILES = [
|
|
|
72
72
|
];
|
|
73
73
|
const DEFAULT_EXPIRE_TIME = 31536e3;
|
|
74
74
|
/**
|
|
75
|
+
* Default cap for the App Router preload `Link` header length, matching the
|
|
76
|
+
* Next.js `defaultConfig.reactMaxHeadersLength`.
|
|
77
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/reactMaxHeadersLength
|
|
78
|
+
*/
|
|
79
|
+
const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6e3;
|
|
80
|
+
/**
|
|
75
81
|
* Check whether an error indicates a CJS module was loaded in an ESM context
|
|
76
82
|
* (i.e. the file uses `require()` which is not available in ESM).
|
|
77
83
|
*/
|
|
@@ -506,6 +512,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
506
512
|
output: "",
|
|
507
513
|
pageExtensions: normalizePageExtensions(),
|
|
508
514
|
cacheComponents: false,
|
|
515
|
+
gestureTransition: false,
|
|
509
516
|
prefetchInlining: false,
|
|
510
517
|
redirects: [],
|
|
511
518
|
rewrites: {
|
|
@@ -523,7 +530,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
523
530
|
optimizePackageImports: [],
|
|
524
531
|
inlineCss: false,
|
|
525
532
|
serverActionsBodySizeLimit: 1 * 1024 * 1024,
|
|
533
|
+
serverActionsBodySizeLimitLabel: "1 MB",
|
|
526
534
|
expireTime: DEFAULT_EXPIRE_TIME,
|
|
535
|
+
reactMaxHeadersLength: DEFAULT_REACT_MAX_HEADERS_LENGTH,
|
|
527
536
|
htmlLimitedBots: void 0,
|
|
528
537
|
serverExternalPackages: [],
|
|
529
538
|
cacheHandler: void 0,
|
|
@@ -588,7 +597,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
588
597
|
const experimental = readOptionalRecord(config.experimental);
|
|
589
598
|
const serverActionsConfig = readOptionalRecord(experimental?.serverActions);
|
|
590
599
|
const serverActionsAllowedOrigins = readStringArray(serverActionsConfig?.allowedOrigins);
|
|
591
|
-
const
|
|
600
|
+
const serverActionsBodySizeLimitConfig = readOptionalBodySizeLimit(serverActionsConfig?.bodySizeLimit);
|
|
601
|
+
const serverActionsBodySizeLimit = parseBodySizeLimit(serverActionsBodySizeLimitConfig);
|
|
602
|
+
const serverActionsBodySizeLimitLabel = serverActionsBodySizeLimitConfig === void 0 ? "1 MB" : String(serverActionsBodySizeLimitConfig);
|
|
592
603
|
const hashSalt = (readOptionalString(experimental?.outputHashSalt) ?? "") + (process.env.NEXT_HASH_SALT ?? "");
|
|
593
604
|
const htmlLimitedBots = resolveHtmlLimitedBots(config.htmlLimitedBots);
|
|
594
605
|
const rawOptimize = experimental?.optimizePackageImports;
|
|
@@ -645,6 +656,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
645
656
|
pageExtensions,
|
|
646
657
|
instrumentationClientInject: Array.isArray(config.instrumentationClientInject) ? config.instrumentationClientInject.filter((x) => typeof x === "string") : [],
|
|
647
658
|
cacheComponents: config.cacheComponents ?? false,
|
|
659
|
+
gestureTransition: experimental?.gestureTransition === true,
|
|
648
660
|
prefetchInlining,
|
|
649
661
|
redirects,
|
|
650
662
|
rewrites,
|
|
@@ -658,7 +670,9 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
658
670
|
optimizePackageImports,
|
|
659
671
|
inlineCss,
|
|
660
672
|
serverActionsBodySizeLimit,
|
|
673
|
+
serverActionsBodySizeLimitLabel,
|
|
661
674
|
expireTime: typeof config.expireTime === "number" ? config.expireTime : DEFAULT_EXPIRE_TIME,
|
|
675
|
+
reactMaxHeadersLength: typeof config.reactMaxHeadersLength === "number" ? config.reactMaxHeadersLength : DEFAULT_REACT_MAX_HEADERS_LENGTH,
|
|
662
676
|
htmlLimitedBots,
|
|
663
677
|
serverExternalPackages,
|
|
664
678
|
cacheHandler,
|
|
@@ -680,12 +694,28 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
680
694
|
if (resolved.basePath !== "" && resolved.basePath !== "/" && resolved.assetPrefix === "") resolved.assetPrefix = resolved.basePath;
|
|
681
695
|
return resolved;
|
|
682
696
|
}
|
|
697
|
+
/**
|
|
698
|
+
* Whether an alias target is a relative filesystem path (`./foo`, `../foo`,
|
|
699
|
+
* or a bare `.`/`..`) that should be resolved against the project root.
|
|
700
|
+
*
|
|
701
|
+
* Both Next.js Turbopack `resolveAlias` and webpack `resolve.alias` accept two
|
|
702
|
+
* kinds of values: relative/absolute file paths AND bare package specifiers
|
|
703
|
+
* (e.g. `react`, `preact/compat`, `@scope/pkg`). Bare specifiers must be left
|
|
704
|
+
* verbatim so Vite/Rolldown re-resolves them through node_modules — resolving
|
|
705
|
+
* them against `root` mangles them into bogus `<root>/react` paths and breaks
|
|
706
|
+
* the build with "No such file or directory". See cloudflare/vinext#1507.
|
|
707
|
+
*/
|
|
708
|
+
function isRelativeAliasTarget(value) {
|
|
709
|
+
return value === "." || value === ".." || value.startsWith("./") || value.startsWith("../");
|
|
710
|
+
}
|
|
683
711
|
function normalizeAliasEntries(aliases, root) {
|
|
684
712
|
if (!aliases) return {};
|
|
685
713
|
const normalized = {};
|
|
686
714
|
for (const [key, value] of Object.entries(aliases)) {
|
|
687
715
|
if (typeof value !== "string") continue;
|
|
688
|
-
|
|
716
|
+
if (path.isAbsolute(value)) normalized[key] = value;
|
|
717
|
+
else if (isRelativeAliasTarget(value)) normalized[key] = path.resolve(root, value);
|
|
718
|
+
else normalized[key] = value;
|
|
689
719
|
}
|
|
690
720
|
return normalized;
|
|
691
721
|
}
|
package/dist/deploy.js
CHANGED
|
@@ -334,30 +334,14 @@ function generatePagesRouterWorkerEntry() {
|
|
|
334
334
|
* Cloudflare Worker entry point -- auto-generated by vinext deploy.
|
|
335
335
|
* Edit freely or delete to regenerate on next deploy.
|
|
336
336
|
*/
|
|
337
|
+
import { runPagesRequest, wrapMiddlewareWithBasePath } from "vinext/server/pages-request-pipeline";
|
|
338
|
+
import type { PagesPipelineDeps } from "vinext/server/pages-request-pipeline";
|
|
337
339
|
import { handleImageOptimization, DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath } from "vinext/server/image-optimization";
|
|
338
340
|
import type { ImageConfig } from "vinext/server/image-optimization";
|
|
339
|
-
import {
|
|
340
|
-
matchRedirect,
|
|
341
|
-
matchRewrite,
|
|
342
|
-
requestContextFromRequest,
|
|
343
|
-
applyMiddlewareRequestHeaders,
|
|
344
|
-
isExternalUrl,
|
|
345
|
-
proxyExternalRequest,
|
|
346
|
-
sanitizeDestination,
|
|
347
|
-
} from "vinext/config/config-matchers";
|
|
348
|
-
import {
|
|
349
|
-
applyConfigHeadersToHeaderRecord,
|
|
350
|
-
cloneRequestWithHeaders,
|
|
351
|
-
filterInternalHeaders,
|
|
352
|
-
isOpenRedirectShaped,
|
|
353
|
-
normalizeTrailingSlash,
|
|
354
|
-
} from "vinext/server/request-pipeline";
|
|
355
|
-
import { mergeHeaders } from "vinext/server/worker-utils";
|
|
341
|
+
import { cloneRequestWithHeaders, filterInternalHeaders, isOpenRedirectShaped } from "vinext/server/request-pipeline";
|
|
356
342
|
import { notFoundStaticAssetResponse } from "vinext/server/http-error-responses";
|
|
357
343
|
import { assetPrefixPathname, isNextStaticPath } from "vinext/utils/asset-prefix";
|
|
358
344
|
import { hasBasePath, stripBasePath } from "vinext/utils/base-path";
|
|
359
|
-
import { normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "vinext/server/pages-i18n";
|
|
360
|
-
import { mergeRewriteQuery } from "vinext/utils/query";
|
|
361
345
|
|
|
362
346
|
// @ts-expect-error -- virtual module resolved by vinext at build time
|
|
363
347
|
import { renderPage, handleApiRoute, runMiddleware, vinextConfig, matchPageRoute } from "virtual:vinext-server-entry";
|
|
@@ -402,7 +386,6 @@ export default {
|
|
|
402
386
|
try {
|
|
403
387
|
const url = new URL(request.url);
|
|
404
388
|
let pathname = url.pathname;
|
|
405
|
-
let urlWithQuery = pathname + url.search;
|
|
406
389
|
|
|
407
390
|
// Block protocol-relative URL open redirects in all shapes:
|
|
408
391
|
// literal //evil.com, /\\\\evil.com
|
|
@@ -445,11 +428,12 @@ export default {
|
|
|
445
428
|
{
|
|
446
429
|
const stripped = stripBasePath(pathname, basePath);
|
|
447
430
|
if (stripped !== pathname) {
|
|
448
|
-
|
|
431
|
+
const strippedUrl = new URL(request.url);
|
|
432
|
+
strippedUrl.pathname = stripped;
|
|
433
|
+
request = new Request(strippedUrl, request);
|
|
449
434
|
pathname = stripped;
|
|
450
435
|
}
|
|
451
436
|
}
|
|
452
|
-
const basePathState = { basePath, hadBasePath };
|
|
453
437
|
|
|
454
438
|
// ── Image optimization via Cloudflare Images binding ──────────
|
|
455
439
|
// Checked after basePath stripping so /<basePath>/_next/image works.
|
|
@@ -464,291 +448,50 @@ export default {
|
|
|
464
448
|
}, allowedWidths, imageConfig);
|
|
465
449
|
}
|
|
466
450
|
|
|
467
|
-
//
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
// locale: false overrides still match default-locale URLs.
|
|
504
|
-
const matchPathname = i18nConfig
|
|
505
|
-
? normalizeDefaultLocalePathname(pathname, i18nConfig, {
|
|
506
|
-
hostname: url.hostname,
|
|
507
|
-
})
|
|
508
|
-
: pathname;
|
|
509
|
-
|
|
510
|
-
// ── 3. Apply redirects from next.config.js ────────────────────
|
|
511
|
-
if (configRedirects.length) {
|
|
512
|
-
const redirect = matchRedirect(matchPathname, configRedirects, reqCtx, basePathState);
|
|
513
|
-
if (redirect) {
|
|
514
|
-
// Only prepend basePath when the request was actually under basePath.
|
|
515
|
-
// Opt-out rules running on out-of-basepath requests must not receive
|
|
516
|
-
// a basePath prefix.
|
|
517
|
-
const dest = sanitizeDestination(
|
|
518
|
-
basePath &&
|
|
519
|
-
hadBasePath &&
|
|
520
|
-
!isExternalUrl(redirect.destination) &&
|
|
521
|
-
!hasBasePath(redirect.destination, basePath)
|
|
522
|
-
? basePath + redirect.destination
|
|
523
|
-
: redirect.destination,
|
|
524
|
-
);
|
|
525
|
-
return new Response(null, {
|
|
526
|
-
status: redirect.permanent ? 308 : 307,
|
|
527
|
-
headers: { Location: dest },
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// ── 4. Run middleware ──────────────────────────────────────────
|
|
533
|
-
let resolvedUrl = urlWithQuery;
|
|
534
|
-
const middlewareHeaders: Record<string, string | string[]> = {};
|
|
535
|
-
let middlewareRewriteStatus: number | undefined;
|
|
536
|
-
if (typeof runMiddleware === "function") {
|
|
537
|
-
const result = await runMiddleware(request, ctx, { isDataRequest });
|
|
538
|
-
|
|
539
|
-
// Bubble up waitUntil promises (e.g. Clerk telemetry/session sync)
|
|
540
|
-
if (result.waitUntilPromises?.length) {
|
|
541
|
-
for (const p of result.waitUntilPromises) {
|
|
542
|
-
ctx.waitUntil(p);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (!result.continue) {
|
|
547
|
-
if (result.redirectUrl) {
|
|
548
|
-
const redirectHeaders = new Headers({ Location: result.redirectUrl });
|
|
549
|
-
if (result.responseHeaders) {
|
|
550
|
-
for (const [key, value] of result.responseHeaders) {
|
|
551
|
-
redirectHeaders.append(key, value);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
return new Response(null, {
|
|
555
|
-
status: result.redirectStatus ?? 307,
|
|
556
|
-
headers: redirectHeaders,
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
if (result.response) {
|
|
560
|
-
return result.response;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// Collect middleware response headers to merge into final response.
|
|
565
|
-
// Use an array for Set-Cookie to preserve multiple values.
|
|
566
|
-
if (result.responseHeaders) {
|
|
567
|
-
for (const [key, value] of result.responseHeaders) {
|
|
568
|
-
if (key === "set-cookie") {
|
|
569
|
-
const existing = middlewareHeaders[key];
|
|
570
|
-
if (Array.isArray(existing)) {
|
|
571
|
-
existing.push(value);
|
|
572
|
-
} else if (existing) {
|
|
573
|
-
middlewareHeaders[key] = [existing as string, value];
|
|
574
|
-
} else {
|
|
575
|
-
middlewareHeaders[key] = [value];
|
|
576
|
-
}
|
|
577
|
-
} else {
|
|
578
|
-
middlewareHeaders[key] = value;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
// Apply middleware rewrite
|
|
584
|
-
if (result.rewriteUrl) {
|
|
585
|
-
resolvedUrl = result.rewriteUrl;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// Apply custom status code from middleware rewrite
|
|
589
|
-
middlewareRewriteStatus = result.rewriteStatus;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// Unpack x-middleware-request-* headers into the actual request and strip
|
|
593
|
-
// all x-middleware-* internal signals. Rebuilds postMwReqCtx for use by
|
|
594
|
-
// beforeFiles, afterFiles, and fallback config rules (which run after
|
|
595
|
-
// middleware per the Next.js execution order).
|
|
596
|
-
const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, request);
|
|
597
|
-
request = postMwReq;
|
|
598
|
-
|
|
599
|
-
// Config header matching must keep using the original normalized pathname
|
|
600
|
-
// even if middleware rewrites the downstream route/render target.
|
|
601
|
-
let resolvedPathname = resolvedUrl.split("?")[0];
|
|
602
|
-
|
|
603
|
-
// ── 5. Apply custom headers from next.config.js ───────────────
|
|
604
|
-
// Config headers are additive for multi-value headers (Vary,
|
|
605
|
-
// Set-Cookie) and override for everything else. Vary values are
|
|
606
|
-
// comma-joined per HTTP spec. Set-Cookie values are accumulated
|
|
607
|
-
// as arrays (RFC 6265 forbids comma-joining cookies).
|
|
608
|
-
// Middleware headers take precedence: skip config keys already set
|
|
609
|
-
// by middleware so middleware always wins for the same key.
|
|
610
|
-
if (configHeaders.length) {
|
|
611
|
-
applyConfigHeadersToHeaderRecord(middlewareHeaders, {
|
|
612
|
-
configHeaders,
|
|
613
|
-
pathname: matchPathname,
|
|
614
|
-
requestContext: reqCtx,
|
|
615
|
-
basePathState,
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
if (isExternalUrl(resolvedUrl)) {
|
|
620
|
-
const proxyResponse = await proxyExternalRequest(request, resolvedUrl);
|
|
621
|
-
return mergeHeaders(proxyResponse, middlewareHeaders, undefined);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// Default-locale-normalised form of resolvedPathname for matching
|
|
625
|
-
// against next.config.js rewrites (beforeFiles, afterFiles, fallback).
|
|
626
|
-
const matchResolvedPathname = (p: string): string =>
|
|
627
|
-
i18nConfig
|
|
628
|
-
? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: url.hostname })
|
|
629
|
-
: p;
|
|
630
|
-
|
|
631
|
-
// ── 6. Apply beforeFiles rewrites from next.config.js ─────────
|
|
632
|
-
let configRewriteFired = false;
|
|
633
|
-
if (configRewrites.beforeFiles?.length) {
|
|
634
|
-
const rewritten = matchRewrite(
|
|
635
|
-
matchResolvedPathname(resolvedPathname),
|
|
636
|
-
configRewrites.beforeFiles,
|
|
637
|
-
postMwReqCtx,
|
|
638
|
-
basePathState,
|
|
639
|
-
);
|
|
640
|
-
if (rewritten) {
|
|
641
|
-
if (isExternalUrl(rewritten)) {
|
|
642
|
-
return proxyExternalRequest(request, rewritten);
|
|
643
|
-
}
|
|
644
|
-
// Preserve original query params across rewrites (Next.js parity).
|
|
645
|
-
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
646
|
-
resolvedPathname = resolvedUrl.split("?")[0];
|
|
647
|
-
configRewriteFired = true;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Reject out-of-basePath requests that no rule rewrote. See the
|
|
652
|
-
// matching comment in prod-server.ts step 7b.
|
|
653
|
-
if (basePath && !hadBasePath && !configRewriteFired) {
|
|
654
|
-
return new Response("This page could not be found", {
|
|
655
|
-
status: 404,
|
|
656
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
// ── 7. API routes ─────────────────────────────────────────────
|
|
661
|
-
// Forward ctx so handlePagesApiRoute can wrap the user handler in
|
|
662
|
-
// runWithExecutionContext, making ctx.waitUntil() reachable from
|
|
663
|
-
// after() and other shims that schedule deferred work.
|
|
664
|
-
//
|
|
665
|
-
// Strip the i18n locale prefix before the /api/ check so
|
|
666
|
-
// /fr/api/ok resolves to the pages/api/ok handler (Next.js
|
|
667
|
-
// parity -- see base-server.ts's normalizeLocalePath call).
|
|
668
|
-
const apiLookupUrl = stripI18nLocaleForApiRoute(resolvedUrl, vinextConfig?.i18n ?? null);
|
|
669
|
-
const apiLookupPathname = apiLookupUrl.split("?")[0];
|
|
670
|
-
if (apiLookupPathname.startsWith("/api/") || apiLookupPathname === "/api") {
|
|
671
|
-
const response = typeof handleApiRoute === "function"
|
|
672
|
-
? await handleApiRoute(request, apiLookupUrl, ctx)
|
|
673
|
-
: new Response("404 - API route not found", { status: 404 });
|
|
674
|
-
return mergeHeaders(response, middlewareHeaders, middlewareRewriteStatus);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
const pageMatch =
|
|
678
|
-
typeof matchPageRoute === "function" ? matchPageRoute(resolvedPathname, request) : null;
|
|
679
|
-
|
|
680
|
-
// ── 8. Apply afterFiles rewrites from next.config.js ──────────
|
|
681
|
-
// These run after non-dynamic page routes but before dynamic routes.
|
|
682
|
-
if ((!pageMatch || pageMatch.route.isDynamic) && configRewrites.afterFiles?.length) {
|
|
683
|
-
const rewritten = matchRewrite(
|
|
684
|
-
matchResolvedPathname(resolvedPathname),
|
|
685
|
-
configRewrites.afterFiles,
|
|
686
|
-
postMwReqCtx,
|
|
687
|
-
basePathState,
|
|
688
|
-
);
|
|
689
|
-
if (rewritten) {
|
|
690
|
-
if (isExternalUrl(rewritten)) {
|
|
691
|
-
return proxyExternalRequest(request, rewritten);
|
|
692
|
-
}
|
|
693
|
-
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
694
|
-
resolvedPathname = resolvedUrl.split("?")[0];
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
// ── 9. Page routes ────────────────────────────────────────────
|
|
699
|
-
let response: Response | undefined;
|
|
700
|
-
if (typeof renderPage === "function") {
|
|
701
|
-
const renderPageMatch =
|
|
702
|
-
typeof matchPageRoute === "function" ? matchPageRoute(resolvedPathname, request) : null;
|
|
703
|
-
const shouldDeferErrorPageOnMiss =
|
|
704
|
-
!isDataRequest && typeof matchPageRoute === "function" && !renderPageMatch;
|
|
705
|
-
const initialRenderOptions = shouldDeferErrorPageOnMiss
|
|
706
|
-
? { renderErrorPageOnMiss: false }
|
|
707
|
-
: undefined;
|
|
708
|
-
response = await renderPage(request, resolvedUrl, null, ctx, undefined, initialRenderOptions);
|
|
709
|
-
|
|
710
|
-
// ── 10. Fallback rewrites (if SSR returned 404) ─────────────
|
|
711
|
-
let matchedFallbackRewrite = false;
|
|
712
|
-
if (
|
|
713
|
-
response &&
|
|
714
|
-
response.status === 404 &&
|
|
715
|
-
shouldDeferErrorPageOnMiss &&
|
|
716
|
-
configRewrites.fallback?.length
|
|
717
|
-
) {
|
|
718
|
-
const fallbackRewrite = matchRewrite(
|
|
719
|
-
matchResolvedPathname(resolvedPathname),
|
|
720
|
-
configRewrites.fallback,
|
|
721
|
-
postMwReqCtx,
|
|
722
|
-
basePathState,
|
|
723
|
-
);
|
|
724
|
-
if (fallbackRewrite) {
|
|
725
|
-
if (isExternalUrl(fallbackRewrite)) {
|
|
726
|
-
return proxyExternalRequest(request, fallbackRewrite);
|
|
727
|
-
}
|
|
728
|
-
matchedFallbackRewrite = true;
|
|
729
|
-
response = await renderPage(
|
|
730
|
-
request,
|
|
731
|
-
mergeRewriteQuery(resolvedUrl, fallbackRewrite),
|
|
732
|
-
null,
|
|
733
|
-
ctx,
|
|
734
|
-
);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
if (
|
|
738
|
-
response &&
|
|
739
|
-
response.status === 404 &&
|
|
740
|
-
shouldDeferErrorPageOnMiss &&
|
|
741
|
-
!matchedFallbackRewrite
|
|
742
|
-
) {
|
|
743
|
-
response = await renderPage(request, resolvedUrl, null, ctx);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
451
|
+
// Delegate the canonical 9-step Next.js pipeline to the shared owner.
|
|
452
|
+
// The worker adapter is responsible for: open-redirect guard, _next/static
|
|
453
|
+
// 404 short-circuit, header filtering, basePath stripping, and image
|
|
454
|
+
// optimization. runPagesRequest receives a clean, basePath-stripped request.
|
|
455
|
+
const deps: PagesPipelineDeps = {
|
|
456
|
+
basePath,
|
|
457
|
+
trailingSlash,
|
|
458
|
+
i18nConfig,
|
|
459
|
+
configRedirects,
|
|
460
|
+
configRewrites,
|
|
461
|
+
configHeaders,
|
|
462
|
+
hadBasePath,
|
|
463
|
+
// The worker adapter does not do _next/data URL normalization (no
|
|
464
|
+
// buildId available at request time). isDataReq is used by the pipeline
|
|
465
|
+
// only for renderPage options and shouldDeferErrorPageOnMiss -- false
|
|
466
|
+
// is correct here.
|
|
467
|
+
isDataReq: false,
|
|
468
|
+
isDataRequest,
|
|
469
|
+
ctx,
|
|
470
|
+
matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
|
|
471
|
+
// Pass the original (pre-basePath-stripping) URL to middleware so that
|
|
472
|
+
// request.nextUrl.basePath reflects whether the URL actually had the
|
|
473
|
+
// basePath prefix. Matches Next.js behavior and the prod-server.ts
|
|
474
|
+
// equivalent (shared via wrapMiddlewareWithBasePath).
|
|
475
|
+
runMiddleware:
|
|
476
|
+
typeof runMiddleware === "function"
|
|
477
|
+
? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath)
|
|
478
|
+
: null,
|
|
479
|
+
renderPage: typeof renderPage === "function"
|
|
480
|
+
? (req, resolvedUrl, options, stagedHeaders) =>
|
|
481
|
+
renderPage(req, resolvedUrl, null, ctx, stagedHeaders, options)
|
|
482
|
+
: null,
|
|
483
|
+
handleApi: typeof handleApiRoute === "function"
|
|
484
|
+
? (req, apiUrl) => handleApiRoute(req, apiUrl, ctx)
|
|
485
|
+
: null,
|
|
486
|
+
};
|
|
746
487
|
|
|
747
|
-
|
|
748
|
-
|
|
488
|
+
const result = await runPagesRequest(request, deps);
|
|
489
|
+
if (result.type === "response") {
|
|
490
|
+
return result.response;
|
|
749
491
|
}
|
|
492
|
+
// Should not reach here for prod/worker (all callbacks supplied).
|
|
493
|
+
return new Response("This page could not be found", { status: 404 });
|
|
750
494
|
|
|
751
|
-
return mergeHeaders(response, middlewareHeaders, middlewareRewriteStatus);
|
|
752
495
|
} catch (error) {
|
|
753
496
|
console.error("[vinext] Worker error:", error);
|
|
754
497
|
return new Response("Internal Server Error", { status: 500 });
|
|
@@ -17,7 +17,8 @@ type AppRouterConfig = {
|
|
|
17
17
|
headers?: NextHeader[]; /** Extra origins allowed for server action CSRF checks (from experimental.serverActions.allowedOrigins). */
|
|
18
18
|
allowedOrigins?: string[]; /** Extra origins allowed for dev server access (from allowedDevOrigins). */
|
|
19
19
|
allowedDevOrigins?: string[]; /** Body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). */
|
|
20
|
-
bodySizeLimit?: number; /**
|
|
20
|
+
bodySizeLimit?: number; /** Verbatim body size limit config value (e.g. "2mb") for the "Body exceeded {limit} limit" error. */
|
|
21
|
+
bodySizeLimitLabel?: string; /** Serialized next.config htmlLimitedBots regexp source. */
|
|
21
22
|
htmlLimitedBots?: string;
|
|
22
23
|
/**
|
|
23
24
|
* Allow-list of keys (from `experimental.clientTraceMetadata`) to surface
|
|
@@ -34,7 +35,12 @@ type AppRouterConfig = {
|
|
|
34
35
|
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix
|
|
35
36
|
*/
|
|
36
37
|
assetPrefix?: string; /** Route-level expire fallback in seconds for ISR entries with numeric revalidate. */
|
|
37
|
-
expireTime?: number;
|
|
38
|
+
expireTime?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum total length (in characters) of the preload `Link` header emitted
|
|
41
|
+
* during App Router SSR. `0` disables emission. Defaults to 6000.
|
|
42
|
+
*/
|
|
43
|
+
reactMaxHeadersLength?: number; /** Maximum in-memory cache size in bytes. 0 disables the default memory cache. */
|
|
38
44
|
cacheMaxMemorySize?: number; /** Inline app CSS into production HTML (from experimental.inlineCss). */
|
|
39
45
|
inlineCss?: boolean; /** Enables Next.js Cache Components semantics for App Router document HTML. */
|
|
40
46
|
cacheComponents?: boolean; /** Internationalization routing config for middleware matcher locale handling. */
|