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.
Files changed (93) hide show
  1. package/README.md +2 -2
  2. package/dist/build/client-build-config.d.ts +4 -6
  3. package/dist/build/client-build-config.js +27 -7
  4. package/dist/build/google-fonts/find-font-files-in-css.d.ts +16 -0
  5. package/dist/build/google-fonts/find-font-files-in-css.js +28 -0
  6. package/dist/build/prerender.js +1 -2
  7. package/dist/build/report.d.ts +1 -2
  8. package/dist/build/report.js +2 -11
  9. package/dist/build/run-prerender.js +1 -1
  10. package/dist/check.js +3 -3
  11. package/dist/client/pages-router-link-navigation.d.ts +10 -0
  12. package/dist/client/pages-router-link-navigation.js +3 -3
  13. package/dist/deploy.js +3 -3
  14. package/dist/entries/app-rsc-entry.d.ts +2 -1
  15. package/dist/entries/app-rsc-entry.js +35 -9
  16. package/dist/entries/app-rsc-manifest.js +76 -46
  17. package/dist/entries/pages-server-entry.js +1 -0
  18. package/dist/index.js +116 -74
  19. package/dist/init.d.ts +5 -4
  20. package/dist/init.js +27 -8
  21. package/dist/plugins/fonts.js +3 -1
  22. package/dist/plugins/middleware-export-validation.d.ts +5 -0
  23. package/dist/plugins/middleware-export-validation.js +36 -0
  24. package/dist/plugins/og-asset-ownership.d.ts +27 -0
  25. package/dist/plugins/og-asset-ownership.js +285 -0
  26. package/dist/plugins/og-assets.js +28 -10
  27. package/dist/plugins/remove-console.js +1 -1
  28. package/dist/plugins/strip-server-exports.js +2 -1
  29. package/dist/server/accept-encoding.d.ts +29 -0
  30. package/dist/server/accept-encoding.js +95 -0
  31. package/dist/server/app-action-request.d.ts +4 -0
  32. package/dist/server/app-action-request.js +9 -0
  33. package/dist/server/app-bfcache-identity.d.ts +12 -2
  34. package/dist/server/app-bfcache-identity.js +52 -23
  35. package/dist/server/app-browser-entry.js +8 -5
  36. package/dist/server/app-browser-navigation-controller.js +1 -1
  37. package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
  38. package/dist/server/app-browser-rsc-redirect.js +8 -1
  39. package/dist/server/app-browser-state.js +1 -1
  40. package/dist/server/app-browser-visible-commit.js +1 -1
  41. package/dist/server/app-history-state.d.ts +1 -2
  42. package/dist/server/app-history-state.js +1 -1
  43. package/dist/server/app-middleware.d.ts +1 -0
  44. package/dist/server/app-middleware.js +1 -0
  45. package/dist/server/app-page-dispatch.d.ts +2 -2
  46. package/dist/server/app-page-head.js +2 -2
  47. package/dist/server/app-page-method.js +1 -1
  48. package/dist/server/app-page-request.d.ts +7 -0
  49. package/dist/server/app-page-request.js +19 -1
  50. package/dist/server/app-page-stream.js +2 -1
  51. package/dist/server/app-prerender-endpoints.d.ts +3 -3
  52. package/dist/server/app-prerender-endpoints.js +3 -4
  53. package/dist/server/app-route-handler-cache.js +1 -1
  54. package/dist/server/app-route-handler-dispatch.js +2 -2
  55. package/dist/server/app-route-handler-execution.js +3 -2
  56. package/dist/server/app-route-handler-policy.d.ts +1 -1
  57. package/dist/server/app-route-handler-policy.js +1 -6
  58. package/dist/server/app-route-module-loader.d.ts +62 -14
  59. package/dist/server/app-route-module-loader.js +61 -10
  60. package/dist/server/app-rsc-errors.d.ts +12 -1
  61. package/dist/server/app-rsc-errors.js +22 -2
  62. package/dist/server/app-rsc-handler.d.ts +16 -14
  63. package/dist/server/app-rsc-handler.js +47 -44
  64. package/dist/server/app-rsc-response-finalizer.js +5 -1
  65. package/dist/server/app-rsc-route-matching.d.ts +9 -0
  66. package/dist/server/app-rsc-route-matching.js +13 -0
  67. package/dist/server/app-server-action-execution.js +1 -1
  68. package/dist/server/app-ssr-entry.js +9 -7
  69. package/dist/server/headers.d.ts +5 -1
  70. package/dist/server/headers.js +5 -1
  71. package/dist/server/metadata-route-response.d.ts +3 -3
  72. package/dist/server/middleware-runtime.d.ts +2 -1
  73. package/dist/server/middleware-runtime.js +19 -8
  74. package/dist/server/middleware.d.ts +2 -2
  75. package/dist/server/middleware.js +26 -11
  76. package/dist/server/pages-request-pipeline.d.ts +3 -1
  77. package/dist/server/pages-request-pipeline.js +4 -2
  78. package/dist/server/prod-server.d.ts +1 -1
  79. package/dist/server/prod-server.js +85 -72
  80. package/dist/shims/dynamic.js +1 -1
  81. package/dist/shims/font-google-base.d.ts +1 -0
  82. package/dist/shims/font-google-base.js +6 -21
  83. package/dist/shims/internal/interpolate-as.d.ts +25 -0
  84. package/dist/shims/internal/interpolate-as.js +196 -0
  85. package/dist/shims/link.js +24 -1
  86. package/dist/shims/navigation.js +1 -1
  87. package/dist/shims/navigation.react-server.js +1 -1
  88. package/dist/shims/router.d.ts +1 -3
  89. package/dist/shims/router.js +62 -18
  90. package/dist/typegen.js +2 -10
  91. package/dist/utils/project.d.ts +7 -1
  92. package/dist/utils/project.js +16 -2
  93. 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 page/route-handler modules and assign them onto the
4
- * route's synchronous `page` / `routeHandler` fields. Returns the same route
5
- * reference (synchronously when already loaded, otherwise after the in-flight
6
- * import resolves). Safe to call on `null`/`undefined` routes and on eager
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
- if (!loadPage && !loadRouteHandler) {
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([loadPage ? loadPage() : void 0, loadRouteHandler ? loadRouteHandler() : void 0]).then(([pageModule, routeHandlerModule]) => {
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
- if (hasDigest(error)) return String(error.digest);
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 { MiddlewareModule } from "./middleware-runtime.js";
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 { handleAppPrerenderEndpoint } from "./app-prerender-endpoints.js";
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 MetadataRoutes = Parameters<typeof handleMetadataRouteRequest>[0]["metadataRoutes"];
15
- type MakeThenableParams = Parameters<typeof handleMetadataRouteRequest>[0]["makeThenableParams"];
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: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
177
- handleServerActionRequest: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
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
- metadataRoutes: MetadataRoutes;
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
- const prerenderEndpointResponse = await handleAppPrerenderEndpoint(request, {
129
- isPrerenderEnabled() {
130
- return process.env.VINEXT_PRERENDER === "1";
131
- },
132
- loadPagesRoutes: options.loadPrerenderPagesRoutes,
133
- pathname,
134
- rootParamNamesByPattern: options.rootParamNamesByPattern,
135
- staticParamsMap: options.staticParamsMap
136
- });
137
- if (prerenderEndpointResponse) return prerenderEndpointResponse;
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.middlewareModule) {
168
- const { applyAppMiddleware } = await import("./app-middleware.js");
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
- isProxy: options.isMiddlewareProxy,
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
- const metadataRouteResponse = await handleMetadataRouteRequest({
213
- metadataRoutes: options.metadataRoutes,
214
- cleanPathname,
215
- makeThenableParams: options.makeThenableParams
216
- });
217
- if (metadataRouteResponse) {
218
- applyConfigHeadersToResponse(metadataRouteResponse.headers, {
219
- basePathState,
220
- configHeaders: options.configHeaders,
221
- overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
222
- pathname: matchPathname(cleanPathname),
223
- requestContext: preMiddlewareRequestContext
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) progressiveActionResult = await options.handleProgressiveActionRequest({
254
- actionId,
255
- cleanPathname,
256
- contentType,
257
- middlewareContext,
258
- request
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")) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
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 { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
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 routeTree = createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
190
- const stateKeyTree = createElement(BfcacheStateKeyMapContext.Provider, { value: createBfcacheSegmentStateKeyMap({
189
+ const bfcacheMaps = createInitialBfcacheMaps({
191
190
  elements,
191
+ metadata,
192
192
  pathname: ssrNavigationContext.pathname
193
- }) }, routeTree);
194
- return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: createInitialBfcacheIdMap(elements) }, stateKeyTree) : stateKeyTree;
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;
@@ -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 };
@@ -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 MakeThenableParams = (params: AppPageParams) => unknown;
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: 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
- const fileLabel = middlewareFileLabel(options.isProxy);
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 };