vinext 0.1.5 → 0.1.7
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 -2
- package/dist/build/client-build-config.d.ts +4 -6
- package/dist/build/client-build-config.js +27 -7
- package/dist/build/google-fonts/find-font-files-in-css.d.ts +16 -0
- package/dist/build/google-fonts/find-font-files-in-css.js +28 -0
- package/dist/build/prerender.js +1 -2
- package/dist/build/report.d.ts +1 -2
- package/dist/build/report.js +2 -11
- package/dist/build/run-prerender.js +1 -1
- package/dist/check.js +3 -3
- package/dist/client/pages-router-link-navigation.d.ts +10 -0
- package/dist/client/pages-router-link-navigation.js +3 -3
- package/dist/deploy.js +3 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +35 -9
- package/dist/entries/app-rsc-manifest.js +76 -46
- package/dist/entries/pages-server-entry.js +1 -0
- package/dist/index.js +116 -74
- package/dist/init.d.ts +5 -4
- package/dist/init.js +27 -8
- package/dist/plugins/fonts.js +3 -1
- package/dist/plugins/middleware-export-validation.d.ts +5 -0
- package/dist/plugins/middleware-export-validation.js +36 -0
- package/dist/plugins/og-asset-ownership.d.ts +27 -0
- package/dist/plugins/og-asset-ownership.js +285 -0
- package/dist/plugins/og-assets.js +28 -10
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/server/accept-encoding.d.ts +29 -0
- package/dist/server/accept-encoding.js +95 -0
- package/dist/server/app-action-request.d.ts +4 -0
- package/dist/server/app-action-request.js +9 -0
- package/dist/server/app-bfcache-identity.d.ts +12 -2
- package/dist/server/app-bfcache-identity.js +52 -23
- package/dist/server/app-browser-entry.js +8 -5
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
- package/dist/server/app-browser-rsc-redirect.js +8 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-history-state.d.ts +1 -2
- package/dist/server/app-history-state.js +1 -1
- package/dist/server/app-middleware.d.ts +1 -0
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-page-dispatch.d.ts +2 -2
- package/dist/server/app-page-head.js +2 -2
- package/dist/server/app-page-method.js +1 -1
- package/dist/server/app-page-request.d.ts +7 -0
- package/dist/server/app-page-request.js +19 -1
- package/dist/server/app-page-stream.js +2 -1
- package/dist/server/app-prerender-endpoints.d.ts +3 -3
- package/dist/server/app-prerender-endpoints.js +3 -4
- package/dist/server/app-route-handler-cache.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +2 -2
- package/dist/server/app-route-handler-execution.js +3 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +1 -6
- package/dist/server/app-route-module-loader.d.ts +62 -14
- package/dist/server/app-route-module-loader.js +61 -10
- package/dist/server/app-rsc-errors.d.ts +12 -1
- package/dist/server/app-rsc-errors.js +22 -2
- package/dist/server/app-rsc-handler.d.ts +16 -14
- package/dist/server/app-rsc-handler.js +47 -44
- package/dist/server/app-rsc-response-finalizer.js +5 -1
- package/dist/server/app-rsc-route-matching.d.ts +9 -0
- package/dist/server/app-rsc-route-matching.js +13 -0
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/headers.d.ts +5 -1
- package/dist/server/headers.js +5 -1
- package/dist/server/metadata-route-response.d.ts +3 -3
- package/dist/server/middleware-runtime.d.ts +2 -1
- package/dist/server/middleware-runtime.js +19 -8
- package/dist/server/middleware.d.ts +2 -2
- package/dist/server/middleware.js +26 -11
- package/dist/server/pages-request-pipeline.d.ts +3 -1
- package/dist/server/pages-request-pipeline.js +4 -2
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +85 -72
- package/dist/shims/dynamic.js +1 -1
- package/dist/shims/font-google-base.d.ts +1 -0
- package/dist/shims/font-google-base.js +6 -21
- package/dist/shims/internal/interpolate-as.d.ts +25 -0
- package/dist/shims/internal/interpolate-as.js +196 -0
- package/dist/shims/link.js +24 -1
- package/dist/shims/navigation.js +1 -1
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/router.d.ts +1 -3
- package/dist/shims/router.js +62 -18
- package/dist/typegen.js +2 -10
- package/dist/utils/project.d.ts +7 -1
- package/dist/utils/project.js +16 -2
- package/package.json +3 -3
|
@@ -1,23 +1,74 @@
|
|
|
1
1
|
//#region src/server/app-route-module-loader.ts
|
|
2
|
+
function pushFieldLoad(loads, target, field, loader) {
|
|
3
|
+
if (!loader || target[field] != null) return;
|
|
4
|
+
loads.push(loader().then((module) => {
|
|
5
|
+
target[field] = module;
|
|
6
|
+
}));
|
|
7
|
+
}
|
|
8
|
+
function pushArrayLoads(loads, target, loaders) {
|
|
9
|
+
if (!target || !loaders) return;
|
|
10
|
+
const slots = target;
|
|
11
|
+
for (const [index, loader] of loaders.entries()) {
|
|
12
|
+
if (index >= slots.length || !loader || slots[index] != null) continue;
|
|
13
|
+
loads.push(loader().then((module) => {
|
|
14
|
+
slots[index] = module;
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function loadAppInterceptLayouts(intercept) {
|
|
19
|
+
const loadState = intercept.__loadState;
|
|
20
|
+
if (loadState?.interceptLayoutsLoading) return loadState.interceptLayoutsLoading;
|
|
21
|
+
const loads = [];
|
|
22
|
+
pushArrayLoads(loads, intercept.interceptLayouts, intercept.__loadInterceptLayouts);
|
|
23
|
+
if (loads.length === 0) return Promise.resolve(intercept.interceptLayouts ?? []);
|
|
24
|
+
const loading = Promise.all(loads).then(() => {
|
|
25
|
+
if (loadState) loadState.interceptLayoutsLoading = null;
|
|
26
|
+
return intercept.interceptLayouts ?? [];
|
|
27
|
+
}).catch((error) => {
|
|
28
|
+
if (loadState) loadState.interceptLayoutsLoading = null;
|
|
29
|
+
throw error;
|
|
30
|
+
});
|
|
31
|
+
if (loadState) loadState.interceptLayoutsLoading = loading;
|
|
32
|
+
return loading;
|
|
33
|
+
}
|
|
2
34
|
/**
|
|
3
|
-
* Resolve a route's lazy
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* routes that have no lazy thunks.
|
|
35
|
+
* Resolve a route's lazy modules and assign them onto the route's synchronous
|
|
36
|
+
* module fields. Returns the same route reference (synchronously when already
|
|
37
|
+
* loaded, otherwise after the in-flight import resolves). Safe to call on
|
|
38
|
+
* `null`/`undefined` routes and on eager routes that have no lazy thunks.
|
|
8
39
|
*/
|
|
9
40
|
function ensureAppRouteModulesLoaded(route) {
|
|
10
41
|
if (!route || route.__loaded) return route;
|
|
11
42
|
if (route.__loading) return route.__loading;
|
|
12
43
|
const loadPage = route.__loadPage;
|
|
13
44
|
const loadRouteHandler = route.__loadRouteHandler;
|
|
14
|
-
|
|
45
|
+
const loads = [];
|
|
46
|
+
pushFieldLoad(loads, route, "page", loadPage);
|
|
47
|
+
pushFieldLoad(loads, route, "routeHandler", loadRouteHandler);
|
|
48
|
+
pushFieldLoad(loads, route, "loading", route.__loadLoading);
|
|
49
|
+
pushFieldLoad(loads, route, "error", route.__loadError);
|
|
50
|
+
pushFieldLoad(loads, route, "notFound", route.__loadNotFound);
|
|
51
|
+
pushFieldLoad(loads, route, "forbidden", route.__loadForbidden);
|
|
52
|
+
pushFieldLoad(loads, route, "unauthorized", route.__loadUnauthorized);
|
|
53
|
+
pushArrayLoads(loads, route.layouts, route.__loadLayouts);
|
|
54
|
+
pushArrayLoads(loads, route.templates, route.__loadTemplates);
|
|
55
|
+
pushArrayLoads(loads, route.errors, route.__loadErrors);
|
|
56
|
+
pushArrayLoads(loads, route.errorPaths, route.__loadErrorPaths);
|
|
57
|
+
pushArrayLoads(loads, route.notFounds, route.__loadNotFounds);
|
|
58
|
+
pushArrayLoads(loads, route.forbiddens, route.__loadForbiddens);
|
|
59
|
+
pushArrayLoads(loads, route.unauthorizeds, route.__loadUnauthorizeds);
|
|
60
|
+
for (const slot of Object.values(route.slots ?? {})) {
|
|
61
|
+
pushFieldLoad(loads, slot, "page", slot.__loadPage);
|
|
62
|
+
pushFieldLoad(loads, slot, "default", slot.__loadDefault);
|
|
63
|
+
pushFieldLoad(loads, slot, "layout", slot.__loadLayout);
|
|
64
|
+
pushFieldLoad(loads, slot, "loading", slot.__loadLoading);
|
|
65
|
+
pushFieldLoad(loads, slot, "error", slot.__loadError);
|
|
66
|
+
}
|
|
67
|
+
if (loads.length === 0) {
|
|
15
68
|
route.__loaded = true;
|
|
16
69
|
return route;
|
|
17
70
|
}
|
|
18
|
-
const loading = Promise.all(
|
|
19
|
-
if (loadPage) route.page = pageModule;
|
|
20
|
-
if (loadRouteHandler) route.routeHandler = routeHandlerModule;
|
|
71
|
+
const loading = Promise.all(loads).then(() => {
|
|
21
72
|
route.__loaded = true;
|
|
22
73
|
route.__loading = null;
|
|
23
74
|
return route;
|
|
@@ -29,4 +80,4 @@ function ensureAppRouteModulesLoaded(route) {
|
|
|
29
80
|
return loading;
|
|
30
81
|
}
|
|
31
82
|
//#endregion
|
|
32
|
-
export { ensureAppRouteModulesLoaded };
|
|
83
|
+
export { ensureAppRouteModulesLoaded, loadAppInterceptLayouts };
|
|
@@ -19,6 +19,17 @@ type CreateRscOnErrorHandlerOptions = {
|
|
|
19
19
|
declare function hasDigest(error: unknown): error is {
|
|
20
20
|
digest: unknown;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
|
|
24
|
+
* string only when the error is a genuine control-flow signal — a redirect,
|
|
25
|
+
* notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
|
|
26
|
+
* dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
|
|
27
|
+
* a real error, or an obfuscated digest transported from a nested boundary)
|
|
28
|
+
* returns undefined so the caller still reports it as a real error. Mere
|
|
29
|
+
* presence of a `digest` field is NOT enough — that conflation swallowed a class
|
|
30
|
+
* of server render errors with no instrumentation/telemetry.
|
|
31
|
+
*/
|
|
32
|
+
declare function getDigestForWellKnownError(error: unknown): string | undefined;
|
|
22
33
|
/**
|
|
23
34
|
* djb2 hash matching Next.js's string-hash package for RSC error digests.
|
|
24
35
|
*/
|
|
@@ -26,4 +37,4 @@ declare function errorDigest(input: string): string;
|
|
|
26
37
|
declare function sanitizeErrorForClient(error: unknown, nodeEnv?: string | undefined): unknown;
|
|
27
38
|
declare function createRscOnErrorHandler(options: CreateRscOnErrorHandlerOptions): (error: unknown) => string | undefined;
|
|
28
39
|
//#endregion
|
|
29
|
-
export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
|
|
40
|
+
export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
1
2
|
import { resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
2
3
|
//#region src/server/app-rsc-errors.ts
|
|
3
4
|
function hasDigest(error) {
|
|
4
5
|
return Boolean(error && typeof error === "object" && "digest" in error);
|
|
5
6
|
}
|
|
7
|
+
const BAILOUT_TO_CSR_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
8
|
+
const DYNAMIC_SERVER_USAGE_DIGEST = "DYNAMIC_SERVER_USAGE";
|
|
9
|
+
/**
|
|
10
|
+
* vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
|
|
11
|
+
* string only when the error is a genuine control-flow signal — a redirect,
|
|
12
|
+
* notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
|
|
13
|
+
* dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
|
|
14
|
+
* a real error, or an obfuscated digest transported from a nested boundary)
|
|
15
|
+
* returns undefined so the caller still reports it as a real error. Mere
|
|
16
|
+
* presence of a `digest` field is NOT enough — that conflation swallowed a class
|
|
17
|
+
* of server render errors with no instrumentation/telemetry.
|
|
18
|
+
*/
|
|
19
|
+
function getDigestForWellKnownError(error) {
|
|
20
|
+
if (!hasDigest(error)) return;
|
|
21
|
+
const digest = String(error.digest);
|
|
22
|
+
if (isNavigationSignalError(error) || digest === BAILOUT_TO_CSR_DIGEST || digest === DYNAMIC_SERVER_USAGE_DIGEST) return digest;
|
|
23
|
+
}
|
|
6
24
|
function getThrownValueMessage(error) {
|
|
7
25
|
return error instanceof Error ? error.message : String(error);
|
|
8
26
|
}
|
|
@@ -27,14 +45,16 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
|
|
|
27
45
|
function createRscOnErrorHandler(options) {
|
|
28
46
|
return (error) => {
|
|
29
47
|
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
|
|
30
|
-
|
|
48
|
+
const wellKnownDigest = getDigestForWellKnownError(error);
|
|
49
|
+
if (wellKnownDigest !== void 0) return wellKnownDigest;
|
|
31
50
|
if (nodeEnv !== "production" && error instanceof Error && error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")) {
|
|
32
51
|
console.error("[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\n\nCommon causes:\n * Passing a module namespace (import * as X) directly as a prop.\n Unlike Next.js (webpack), Vite produces real ESM module namespace objects\n which are not serializable. Fix: pass individual values instead,\n e.g. <Comp value={module.value} />\n * Passing a class instance (new Foo()) as a prop.\n Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\n * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\n * Passing Object.create(null). Use { ...obj } to restore a prototype.\n\nOriginal error:", error.message);
|
|
33
52
|
return;
|
|
34
53
|
}
|
|
35
54
|
if (options.requestInfo && options.errorContext && error) options.reportRequestError(error instanceof Error ? error : new Error(getThrownValueMessage(error)), options.requestInfo, options.errorContext);
|
|
55
|
+
if (hasDigest(error)) return String(error.digest);
|
|
36
56
|
if (nodeEnv === "production" && error) return errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
|
|
37
57
|
};
|
|
38
58
|
}
|
|
39
59
|
//#endregion
|
|
40
|
-
export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
|
|
60
|
+
export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
|
|
@@ -2,21 +2,25 @@ import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config
|
|
|
2
2
|
import { ImageConfig } from "./image-optimization.js";
|
|
3
3
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
4
4
|
import { RootParams } from "../shims/root-params.js";
|
|
5
|
-
import {
|
|
6
|
-
import { AppMiddlewareContext } from "./app-middleware.js";
|
|
5
|
+
import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware.js";
|
|
7
6
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
8
|
-
import {
|
|
9
|
-
import { handleMetadataRouteRequest } from "./metadata-route-response.js";
|
|
7
|
+
import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
|
|
10
8
|
import { ReactFormState } from "react-dom/client";
|
|
11
9
|
|
|
12
10
|
//#region src/server/app-rsc-handler.d.ts
|
|
13
11
|
type AppPageParams = Record<string, string | string[]>;
|
|
14
|
-
type
|
|
15
|
-
type
|
|
16
|
-
type StaticParamsMap = Parameters<typeof handleAppPrerenderEndpoint>[1]["staticParamsMap"];
|
|
17
|
-
type RootParamNamesMap = Parameters<typeof handleAppPrerenderEndpoint>[1]["rootParamNamesByPattern"];
|
|
12
|
+
type StaticParamsMap = AppPrerenderStaticParamsMap;
|
|
13
|
+
type RootParamNamesMap = AppPrerenderRootParamNamesMap;
|
|
18
14
|
type AppRscMiddlewareContext = AppMiddlewareContext;
|
|
15
|
+
type RunAppMiddlewareOptions = {
|
|
16
|
+
cleanPathname: string;
|
|
17
|
+
context: AppRscMiddlewareContext;
|
|
18
|
+
isDataRequest: boolean;
|
|
19
|
+
request: Request;
|
|
20
|
+
};
|
|
19
21
|
type AppRscHandlerRoute = {
|
|
22
|
+
__loadPage?: unknown;
|
|
23
|
+
__loadRouteHandler?: unknown;
|
|
20
24
|
isDynamic: boolean;
|
|
21
25
|
params?: readonly string[];
|
|
22
26
|
page?: unknown;
|
|
@@ -173,17 +177,15 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
173
177
|
* Node server and dev included, not just the Cloudflare worker entry.
|
|
174
178
|
*/
|
|
175
179
|
registerCacheAdapters: (env?: Record<string, unknown>) => void;
|
|
176
|
-
handleProgressiveActionRequest
|
|
177
|
-
|
|
180
|
+
handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
|
|
181
|
+
handleMetadataRouteRequest?: (cleanPathname: string) => Promise<Response | null>;
|
|
182
|
+
handleServerActionRequest?: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
|
|
178
183
|
i18nConfig: NextI18nConfig | null;
|
|
179
184
|
imageConfig?: ImageConfig;
|
|
180
185
|
isDev: boolean;
|
|
181
|
-
isMiddlewareProxy: boolean;
|
|
182
186
|
loadPrerenderPagesRoutes?: () => Promise<unknown>;
|
|
183
|
-
makeThenableParams: MakeThenableParams;
|
|
184
187
|
matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
|
|
185
|
-
|
|
186
|
-
middlewareModule: MiddlewareModule | null;
|
|
188
|
+
runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
|
|
187
189
|
publicFiles: ReadonlySet<string>;
|
|
188
190
|
renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;
|
|
189
191
|
renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
|
|
@@ -18,13 +18,12 @@ import { buildNextDataNotFoundResponse, normalizePagesDataRequest } from "./page
|
|
|
18
18
|
import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
19
19
|
import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
|
|
20
20
|
import { flattenErrorCauses } from "../utils/error-cause.js";
|
|
21
|
+
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
22
|
+
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
|
|
21
23
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
22
24
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
23
|
-
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
24
|
-
import { handleAppPrerenderEndpoint } from "./app-prerender-endpoints.js";
|
|
25
25
|
import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
|
|
26
26
|
import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
|
|
27
|
-
import { handleMetadataRouteRequest } from "./metadata-route-response.js";
|
|
28
27
|
import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
|
|
29
28
|
//#region src/server/app-rsc-handler.ts
|
|
30
29
|
const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = new Set(["cache-control"]);
|
|
@@ -49,6 +48,11 @@ function isExecutionContextLike(value) {
|
|
|
49
48
|
if (!value || typeof value !== "object") return false;
|
|
50
49
|
return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
|
|
51
50
|
}
|
|
51
|
+
function createMissingServerActionResponse(options, actionId) {
|
|
52
|
+
console.warn(getServerActionNotFoundMessage(actionId));
|
|
53
|
+
options.clearRequestContext();
|
|
54
|
+
return createServerActionNotFoundResponse();
|
|
55
|
+
}
|
|
52
56
|
function redirectDestinationWithBasePath(destination, basePath) {
|
|
53
57
|
if (!basePath || isExternalUrl(destination) || hasBasePath(destination, basePath)) return destination;
|
|
54
58
|
return basePath + destination;
|
|
@@ -125,16 +129,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
125
129
|
basePath: options.basePath,
|
|
126
130
|
hadBasePath: true
|
|
127
131
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
if (pathname === "/__vinext/prerender/static-params" || pathname === "/__vinext/prerender/pages-static-paths") {
|
|
133
|
+
const { handleAppPrerenderEndpoint } = await import("./app-prerender-endpoints.js");
|
|
134
|
+
const prerenderEndpointResponse = await handleAppPrerenderEndpoint(request, {
|
|
135
|
+
isPrerenderEnabled() {
|
|
136
|
+
return process.env.VINEXT_PRERENDER === "1";
|
|
137
|
+
},
|
|
138
|
+
loadPagesRoutes: options.loadPrerenderPagesRoutes,
|
|
139
|
+
pathname,
|
|
140
|
+
rootParamNamesByPattern: options.rootParamNamesByPattern,
|
|
141
|
+
staticParamsMap: options.staticParamsMap
|
|
142
|
+
});
|
|
143
|
+
if (prerenderEndpointResponse) return prerenderEndpointResponse;
|
|
144
|
+
}
|
|
138
145
|
const trailingSlashRedirect = normalizeTrailingSlash(pathname, options.basePath, options.trailingSlash, url.search);
|
|
139
146
|
if (trailingSlashRedirect) return trailingSlashRedirect;
|
|
140
147
|
const matchPathname = (p) => normalizeDefaultLocalePathname(p, options.i18nConfig, { hostname: url.hostname });
|
|
@@ -164,18 +171,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
164
171
|
status: null
|
|
165
172
|
};
|
|
166
173
|
let didMiddlewareRewrite = false;
|
|
167
|
-
if (options.
|
|
168
|
-
const
|
|
169
|
-
const middlewareResult = await applyAppMiddleware({
|
|
170
|
-
basePath: options.basePath,
|
|
174
|
+
if (options.runMiddleware) {
|
|
175
|
+
const middlewareResult = await options.runMiddleware({
|
|
171
176
|
cleanPathname,
|
|
172
177
|
context: middlewareContext,
|
|
173
|
-
i18nConfig: options.i18nConfig,
|
|
174
178
|
isDataRequest,
|
|
175
|
-
|
|
176
|
-
module: options.middlewareModule,
|
|
177
|
-
request: userlandRequest,
|
|
178
|
-
trailingSlash: options.trailingSlash
|
|
179
|
+
request: userlandRequest
|
|
179
180
|
});
|
|
180
181
|
if (middlewareResult.kind === "response") return applyConfigHeadersToMiddlewareRedirect(middlewareResult.response, {
|
|
181
182
|
basePathState,
|
|
@@ -209,20 +210,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
209
210
|
if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
|
|
210
211
|
return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
|
|
211
212
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
225
|
-
return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
|
|
213
|
+
if (options.handleMetadataRouteRequest) {
|
|
214
|
+
const metadataRouteResponse = await options.handleMetadataRouteRequest(cleanPathname);
|
|
215
|
+
if (metadataRouteResponse) {
|
|
216
|
+
applyConfigHeadersToResponse(metadataRouteResponse.headers, {
|
|
217
|
+
basePathState,
|
|
218
|
+
configHeaders: options.configHeaders,
|
|
219
|
+
overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
|
|
220
|
+
pathname: matchPathname(cleanPathname),
|
|
221
|
+
requestContext: preMiddlewareRequestContext
|
|
222
|
+
});
|
|
223
|
+
return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
|
|
224
|
+
}
|
|
226
225
|
}
|
|
227
226
|
const publicFileResponse = resolvePublicFileRoute({
|
|
228
227
|
cleanPathname,
|
|
@@ -250,13 +249,16 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
250
249
|
const contentType = request.headers.get("content-type") || "";
|
|
251
250
|
const isPostRequest = request.method.toUpperCase() === "POST";
|
|
252
251
|
let progressiveActionResult = null;
|
|
253
|
-
if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
252
|
+
if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) {
|
|
253
|
+
if (options.handleProgressiveActionRequest) progressiveActionResult = await options.handleProgressiveActionRequest({
|
|
254
|
+
actionId,
|
|
255
|
+
cleanPathname,
|
|
256
|
+
contentType,
|
|
257
|
+
middlewareContext,
|
|
258
|
+
request
|
|
259
|
+
});
|
|
260
|
+
else if (preActionMatch?.route.__loadPage && !preActionMatch.route.__loadRouteHandler) return createMissingServerActionResponse(options, null);
|
|
261
|
+
}
|
|
260
262
|
if (progressiveActionResult instanceof Response) return progressiveActionResult;
|
|
261
263
|
const progressiveActionFormState = progressiveActionResult?.kind === "form-state" ? progressiveActionResult : null;
|
|
262
264
|
const isProgressiveActionRender = progressiveActionFormState !== null;
|
|
@@ -264,7 +266,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
264
266
|
const failedProgressiveActionResult = progressiveActionFormState && "actionError" in progressiveActionFormState ? progressiveActionFormState : null;
|
|
265
267
|
const actionFailed = failedProgressiveActionResult !== null;
|
|
266
268
|
const actionError = failedProgressiveActionResult?.actionError;
|
|
267
|
-
const serverActionResponse = isPostRequest && actionId ? await options.handleServerActionRequest({
|
|
269
|
+
const serverActionResponse = isPostRequest && actionId && options.handleServerActionRequest ? await options.handleServerActionRequest({
|
|
268
270
|
actionId,
|
|
269
271
|
cleanPathname,
|
|
270
272
|
contentType,
|
|
@@ -276,6 +278,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
276
278
|
searchParams: getResolvedSearchParams()
|
|
277
279
|
}) : null;
|
|
278
280
|
if (serverActionResponse) return serverActionResponse;
|
|
281
|
+
if (isPostRequest && actionId && !options.handleServerActionRequest) return createMissingServerActionResponse(options, actionId);
|
|
279
282
|
let match = preActionMatch;
|
|
280
283
|
const renderPagesForMatchKind = async (matchKind) => {
|
|
281
284
|
const response = match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
|
|
@@ -22,7 +22,11 @@ import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
|
22
22
|
*/
|
|
23
23
|
function finalizeAppRscResponse(response, request, options) {
|
|
24
24
|
if (response.status >= 300 && response.status < 400) return response;
|
|
25
|
-
if (!response.headers.has("x-vinext-static-file"))
|
|
25
|
+
if (!response.headers.has("x-vinext-static-file")) {
|
|
26
|
+
const varyHeader = response.headers.get("Vary");
|
|
27
|
+
if (varyHeader === null) response.headers.set("Vary", VINEXT_RSC_VARY_HEADER);
|
|
28
|
+
else if (varyHeader !== VINEXT_RSC_VARY_HEADER) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
|
|
29
|
+
}
|
|
26
30
|
if (!response.headers.has("Cache-Control")) applyCdnResponseHeaders(response.headers, { cacheControl: "" });
|
|
27
31
|
if (!options.configHeaders.length) return response;
|
|
28
32
|
const url = new URL(request.url);
|
|
@@ -31,6 +31,7 @@ type AppRscInterceptForMatching = {
|
|
|
31
31
|
sourceMatchPattern?: string;
|
|
32
32
|
sourcePageSegments?: readonly string[];
|
|
33
33
|
interceptLayouts: readonly unknown[];
|
|
34
|
+
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
34
35
|
page: unknown;
|
|
35
36
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
36
37
|
params: readonly string[];
|
|
@@ -45,6 +46,7 @@ type AppRscSiblingInterceptForMatching = {
|
|
|
45
46
|
sourcePageSegments?: readonly string[];
|
|
46
47
|
slotId: string | null;
|
|
47
48
|
interceptLayouts: readonly unknown[];
|
|
49
|
+
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
48
50
|
page: unknown;
|
|
49
51
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
50
52
|
params: readonly string[];
|
|
@@ -58,6 +60,11 @@ type AppRscRouteForMatching = {
|
|
|
58
60
|
type AppRscInterceptMatch = AppRscInterceptLookupEntry & {
|
|
59
61
|
matchedParams: AppRscRouteParams;
|
|
60
62
|
};
|
|
63
|
+
type AppRscInterceptLoadState = {
|
|
64
|
+
page: unknown;
|
|
65
|
+
pageLoading: Promise<unknown> | null;
|
|
66
|
+
interceptLayoutsLoading: Promise<readonly unknown[]> | null;
|
|
67
|
+
};
|
|
61
68
|
type AppRscInterceptLookupEntry = {
|
|
62
69
|
sourceRouteIndex: number;
|
|
63
70
|
slotKey: string;
|
|
@@ -67,8 +74,10 @@ type AppRscInterceptLookupEntry = {
|
|
|
67
74
|
sourceMatchPatternParts: string[] | null;
|
|
68
75
|
sourcePageSegments: readonly string[] | null;
|
|
69
76
|
interceptLayouts: readonly unknown[];
|
|
77
|
+
__loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
|
|
70
78
|
page: unknown;
|
|
71
79
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
80
|
+
__loadState: AppRscInterceptLoadState;
|
|
72
81
|
params: readonly string[];
|
|
73
82
|
slotId: string | null;
|
|
74
83
|
};
|
|
@@ -39,6 +39,7 @@ function createAppRscRouteMatcher(routes) {
|
|
|
39
39
|
const sourceParams = matchedSourceParams ?? createRouteParams();
|
|
40
40
|
return {
|
|
41
41
|
...entry,
|
|
42
|
+
page: entry.__loadState.page,
|
|
42
43
|
sourceRouteIndex: concreteSourceRouteIndex,
|
|
43
44
|
matchedParams: mergeMatchedParams(sourceParams, params)
|
|
44
45
|
};
|
|
@@ -84,8 +85,14 @@ function createInterceptLookup(routes) {
|
|
|
84
85
|
sourceMatchPatternParts,
|
|
85
86
|
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
86
87
|
interceptLayouts: intercept.interceptLayouts,
|
|
88
|
+
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
87
89
|
page: intercept.page,
|
|
88
90
|
__pageLoader: intercept.__pageLoader,
|
|
91
|
+
__loadState: {
|
|
92
|
+
page: intercept.page,
|
|
93
|
+
pageLoading: null,
|
|
94
|
+
interceptLayoutsLoading: null
|
|
95
|
+
},
|
|
89
96
|
params: intercept.params
|
|
90
97
|
});
|
|
91
98
|
}
|
|
@@ -103,8 +110,14 @@ function createInterceptLookup(routes) {
|
|
|
103
110
|
sourceMatchPatternParts,
|
|
104
111
|
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
105
112
|
interceptLayouts: intercept.interceptLayouts,
|
|
113
|
+
__loadInterceptLayouts: intercept.__loadInterceptLayouts,
|
|
106
114
|
page: intercept.page,
|
|
107
115
|
__pageLoader: intercept.__pageLoader,
|
|
116
|
+
__loadState: {
|
|
117
|
+
page: intercept.page,
|
|
118
|
+
pageLoading: null,
|
|
119
|
+
interceptLayoutsLoading: null
|
|
120
|
+
},
|
|
108
121
|
params: intercept.params
|
|
109
122
|
});
|
|
110
123
|
}
|
|
@@ -377,7 +377,7 @@ async function handleProgressiveServerActionRequest(options) {
|
|
|
377
377
|
options.setHeadersAccessPhase(previousHeadersPhase);
|
|
378
378
|
}
|
|
379
379
|
if (!actionRedirect) {
|
|
380
|
-
const actionPendingCookies = options.getAndClearPendingCookies();
|
|
380
|
+
const actionPendingCookies = dedupePendingCookies(options.getAndClearPendingCookies());
|
|
381
381
|
const actionDraftCookie = options.getDraftModeCookieHeader();
|
|
382
382
|
const revalidationKind = resolveActionRevalidationKind(actionPendingCookies.length > 0 || Boolean(actionDraftCookie));
|
|
383
383
|
if (actionFailed) return {
|
|
@@ -16,12 +16,12 @@ import DefaultGlobalError from "../shims/default-global-error.js";
|
|
|
16
16
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
17
17
|
import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
|
|
18
18
|
import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
|
|
19
|
-
import {
|
|
19
|
+
import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
|
|
20
|
+
import { runWithRootParamsScope } from "../shims/root-params.js";
|
|
21
|
+
import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
|
|
20
22
|
import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
|
|
21
23
|
import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
|
|
22
24
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
23
|
-
import { runWithRootParamsScope } from "../shims/root-params.js";
|
|
24
|
-
import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
|
|
25
25
|
import { renderBeforeInteractiveInlineScripts } from "./before-interactive-head.js";
|
|
26
26
|
import { createInitialDevServerErrorScript } from "./dev-initial-server-error.js";
|
|
27
27
|
import { ssrAppRouterInstance } from "./app-ssr-router-instance.js";
|
|
@@ -186,12 +186,14 @@ async function handleSsr(rscStream, navContext, fontData, options) {
|
|
|
186
186
|
const wireElements = use(flightRoot);
|
|
187
187
|
const elements = AppElementsWire.decode(wireElements);
|
|
188
188
|
const metadata = AppElementsWire.readMetadata(elements);
|
|
189
|
-
const
|
|
190
|
-
const stateKeyTree = createElement(BfcacheStateKeyMapContext.Provider, { value: createBfcacheSegmentStateKeyMap({
|
|
189
|
+
const bfcacheMaps = createInitialBfcacheMaps({
|
|
191
190
|
elements,
|
|
191
|
+
metadata,
|
|
192
192
|
pathname: ssrNavigationContext.pathname
|
|
193
|
-
})
|
|
194
|
-
|
|
193
|
+
});
|
|
194
|
+
const routeTree = createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
|
|
195
|
+
const stateKeyTree = createElement(BfcacheStateKeyMapContext.Provider, { value: bfcacheMaps.stateKeys }, routeTree);
|
|
196
|
+
return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: bfcacheMaps.bfcacheIds }, stateKeyTree) : stateKeyTree;
|
|
195
197
|
}
|
|
196
198
|
const flightRootElement = createElement(VinextFlightRoot);
|
|
197
199
|
const root = AppRouterContext ? createElement(AppRouterContext.Provider, { value: ssrAppRouterInstance }, flightRootElement) : flightRootElement;
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ declare const VINEXT_TIMING_HEADER = "x-vinext-timing";
|
|
|
23
23
|
declare const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
|
|
24
24
|
/** URL-encoded JSON route params for build-time prerender renders. */
|
|
25
25
|
declare const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
|
|
26
|
+
/** Internal endpoint used to evaluate App Router generateStaticParams exports. */
|
|
27
|
+
declare const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
|
|
28
|
+
/** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
|
|
29
|
+
declare const VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH = "/__vinext/prerender/pages-static-paths";
|
|
26
30
|
/** TPR (Tailored Per-Request) revalidation interval in seconds. */
|
|
27
31
|
declare const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
|
|
28
32
|
/** Marker on cached ISR entries indicating RSC payload (value "1"). */
|
|
@@ -107,4 +111,4 @@ declare const INTERNAL_HEADERS: string[];
|
|
|
107
111
|
/** Vinext-only internal headers stripped alongside Next.js protocol internals. */
|
|
108
112
|
declare const VINEXT_INTERNAL_HEADERS: string[];
|
|
109
113
|
//#endregion
|
|
110
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
114
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
package/dist/server/headers.js
CHANGED
|
@@ -23,6 +23,10 @@ const VINEXT_TIMING_HEADER = "x-vinext-timing";
|
|
|
23
23
|
const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
|
|
24
24
|
/** URL-encoded JSON route params for build-time prerender renders. */
|
|
25
25
|
const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
|
|
26
|
+
/** Internal endpoint used to evaluate App Router generateStaticParams exports. */
|
|
27
|
+
const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
|
|
28
|
+
/** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
|
|
29
|
+
const VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH = "/__vinext/prerender/pages-static-paths";
|
|
26
30
|
/** TPR (Tailored Per-Request) revalidation interval in seconds. */
|
|
27
31
|
const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
|
|
28
32
|
/** Marker on cached ISR entries indicating RSC payload (value "1"). */
|
|
@@ -129,4 +133,4 @@ const INTERNAL_HEADERS = [
|
|
|
129
133
|
/** Vinext-only internal headers stripped alongside Next.js protocol internals. */
|
|
130
134
|
const VINEXT_INTERNAL_HEADERS = [VINEXT_PRERENDER_ROUTE_PARAMS_HEADER];
|
|
131
135
|
//#endregion
|
|
132
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
136
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
|
|
@@ -2,15 +2,15 @@ import { MetadataFileRoute } from "./metadata-routes.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/server/metadata-route-response.d.ts
|
|
4
4
|
type AppPageParams = Record<string, string | string[]>;
|
|
5
|
-
type
|
|
5
|
+
type MetadataRouteMakeThenableParams = (params: AppPageParams) => unknown;
|
|
6
6
|
type MetadataRuntimeRoute = MetadataFileRoute & {
|
|
7
7
|
fileDataBase64?: string;
|
|
8
8
|
};
|
|
9
9
|
type MetadataRouteRequestOptions = {
|
|
10
10
|
metadataRoutes: readonly MetadataRuntimeRoute[];
|
|
11
11
|
cleanPathname: string;
|
|
12
|
-
makeThenableParams:
|
|
12
|
+
makeThenableParams: MetadataRouteMakeThenableParams;
|
|
13
13
|
};
|
|
14
14
|
declare function handleMetadataRouteRequest(options: MetadataRouteRequestOptions): Promise<Response | null>;
|
|
15
15
|
//#endregion
|
|
16
|
-
export { handleMetadataRouteRequest };
|
|
16
|
+
export { MetadataRuntimeRoute, handleMetadataRouteRequest };
|
|
@@ -56,6 +56,7 @@ type ExecuteMiddlewareOptions = {
|
|
|
56
56
|
type RunGeneratedMiddlewareOptions = ExecuteMiddlewareOptions & {
|
|
57
57
|
ctx?: ExecutionContextLike;
|
|
58
58
|
};
|
|
59
|
+
declare function createMiddlewareMissingExportError(filePath: string | undefined, isProxy: boolean): Error;
|
|
59
60
|
declare function resolveMiddlewareModuleHandler(mod: MiddlewareModule, options: {
|
|
60
61
|
filePath?: string;
|
|
61
62
|
isProxy: boolean;
|
|
@@ -63,4 +64,4 @@ declare function resolveMiddlewareModuleHandler(mod: MiddlewareModule, options:
|
|
|
63
64
|
declare function executeMiddleware(options: ExecuteMiddlewareOptions): Promise<MiddlewareResult>;
|
|
64
65
|
declare function runGeneratedMiddleware(options: RunGeneratedMiddlewareOptions): Promise<MiddlewareResult>;
|
|
65
66
|
//#endregion
|
|
66
|
-
export { MiddlewareModule, MiddlewareResult, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
|
|
67
|
+
export { MiddlewareModule, MiddlewareResult, createMiddlewareMissingExportError, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
|
|
@@ -9,6 +9,7 @@ import { normalizePath } from "./normalize-path.js";
|
|
|
9
9
|
import { matchesMiddleware } from "./middleware-matcher.js";
|
|
10
10
|
import { badRequestResponse, internalServerErrorResponse } from "./http-error-responses.js";
|
|
11
11
|
import { processMiddlewareHeaders } from "./request-pipeline.js";
|
|
12
|
+
import path from "node:path";
|
|
12
13
|
//#region src/server/middleware-runtime.ts
|
|
13
14
|
function isMiddlewareHandler(value) {
|
|
14
15
|
return typeof value === "function";
|
|
@@ -16,19 +17,29 @@ function isMiddlewareHandler(value) {
|
|
|
16
17
|
function isMiddlewareConfigExport(value) {
|
|
17
18
|
return !!value && typeof value === "object";
|
|
18
19
|
}
|
|
19
|
-
function middlewareFileLabel(isProxy) {
|
|
20
|
-
return isProxy ? "Proxy" : "Middleware";
|
|
21
|
-
}
|
|
22
20
|
function middlewareExpectedExport(isProxy) {
|
|
23
21
|
return isProxy ? "proxy" : "middleware";
|
|
24
22
|
}
|
|
23
|
+
function middlewareDisplayPath(filePath) {
|
|
24
|
+
const fileName = path.basename(filePath);
|
|
25
|
+
return path.basename(path.dirname(filePath)) === "src" ? `./src/${fileName}` : `./${fileName}`;
|
|
26
|
+
}
|
|
27
|
+
function createMiddlewareMissingExportError(filePath, isProxy) {
|
|
28
|
+
const expectedExport = middlewareExpectedExport(isProxy);
|
|
29
|
+
const displayPath = filePath ? middlewareDisplayPath(filePath) : void 0;
|
|
30
|
+
const resolvedPath = displayPath ? ` "${displayPath}"` : "";
|
|
31
|
+
const migrationReason = isProxy ? "- You are migrating from `middleware` to `proxy`, but haven't updated the exported function.\n" : "";
|
|
32
|
+
return /* @__PURE__ */ new Error(`The file${resolvedPath} must export a function, either as a default export or as a named "${expectedExport}" export.\nThis function is what Next.js runs for every request handled by this ${isProxy ? "proxy (previously called middleware)" : "middleware"}.\n\nWhy this happens:\n` + migrationReason + `- The file exists but doesn't export a function.
|
|
33
|
+
- The export is not a function (e.g., an object or constant).
|
|
34
|
+
- There's a syntax error preventing the export from being recognized.
|
|
35
|
+
|
|
36
|
+
To fix it:
|
|
37
|
+
- Ensure this file has either a default or "${expectedExport}" function export.\n\nLearn more: https://nextjs.org/docs/messages/middleware-to-proxy`);
|
|
38
|
+
}
|
|
25
39
|
function resolveMiddlewareModuleHandler(mod, options) {
|
|
26
40
|
const handler = options.isProxy ? mod.proxy ?? mod.default : mod.middleware ?? mod.default;
|
|
27
41
|
if (isMiddlewareHandler(handler)) return handler;
|
|
28
|
-
|
|
29
|
-
const expectedExport = middlewareExpectedExport(options.isProxy);
|
|
30
|
-
const fileSuffix = options.filePath ? ` "${options.filePath}"` : "";
|
|
31
|
-
throw new Error(`The ${fileLabel} file${fileSuffix} must export a function named \`${expectedExport}\` or a \`default\` function.`);
|
|
42
|
+
throw createMiddlewareMissingExportError(options.filePath, options.isProxy);
|
|
32
43
|
}
|
|
33
44
|
function middlewareMatcher(mod) {
|
|
34
45
|
const config = mod.config;
|
|
@@ -226,4 +237,4 @@ async function runGeneratedMiddleware(options) {
|
|
|
226
237
|
return options.ctx ? runWithExecutionContext(options.ctx, run) : run();
|
|
227
238
|
}
|
|
228
239
|
//#endregion
|
|
229
|
-
export { executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
|
|
240
|
+
export { createMiddlewareMissingExportError, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
|