vinext 1.0.0-beta.1 → 1.0.0-beta.3

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 (234) hide show
  1. package/README.md +10 -10
  2. package/dist/build/client-build-config.js +8 -1
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +19 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +35 -122
  9. package/dist/config/next-config.d.ts +15 -5
  10. package/dist/config/next-config.js +7 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-browser-entry.d.ts +4 -10
  14. package/dist/entries/app-browser-entry.js +20 -4
  15. package/dist/entries/app-rsc-entry.js +30 -9
  16. package/dist/entries/app-rsc-manifest.js +36 -0
  17. package/dist/entries/pages-client-entry.js +0 -1
  18. package/dist/entries/pages-server-entry.js +13 -5
  19. package/dist/index.js +194 -101
  20. package/dist/init-cloudflare.d.ts +3 -1
  21. package/dist/init-cloudflare.js +59 -5
  22. package/dist/init.d.ts +6 -4
  23. package/dist/init.js +20 -22
  24. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  25. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  26. package/dist/plugins/import-meta-url.js +17 -6
  27. package/dist/plugins/og-assets.js +1 -1
  28. package/dist/plugins/require-context.js +20 -15
  29. package/dist/plugins/transform-cache.d.ts +19 -0
  30. package/dist/plugins/transform-cache.js +36 -0
  31. package/dist/routing/app-route-graph.d.ts +27 -11
  32. package/dist/routing/app-route-graph.js +158 -22
  33. package/dist/routing/app-router.js +12 -6
  34. package/dist/routing/file-matcher.d.ts +11 -22
  35. package/dist/routing/file-matcher.js +21 -33
  36. package/dist/routing/pages-router.js +23 -29
  37. package/dist/routing/route-matching.d.ts +14 -1
  38. package/dist/routing/route-matching.js +13 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +7 -4
  41. package/dist/routing/route-trie.d.ts +5 -1
  42. package/dist/routing/route-trie.js +5 -2
  43. package/dist/server/api-handler.d.ts +2 -0
  44. package/dist/server/api-handler.js +3 -3
  45. package/dist/server/app-browser-entry.js +110 -37
  46. package/dist/server/app-browser-history-controller.d.ts +1 -1
  47. package/dist/server/app-browser-history-controller.js +3 -3
  48. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  49. package/dist/server/app-browser-navigation-controller.js +2 -2
  50. package/dist/server/app-browser-state.js +1 -1
  51. package/dist/server/app-browser-visible-commit.js +1 -1
  52. package/dist/server/app-fallback-renderer.d.ts +3 -0
  53. package/dist/server/app-fallback-renderer.js +4 -2
  54. package/dist/server/app-middleware.js +2 -1
  55. package/dist/server/app-page-boundary-render.d.ts +12 -1
  56. package/dist/server/app-page-boundary-render.js +84 -2
  57. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  58. package/dist/server/app-page-cache-finalizer.js +1 -1
  59. package/dist/server/app-page-cache.d.ts +2 -2
  60. package/dist/server/app-page-cache.js +16 -2
  61. package/dist/server/app-page-dispatch.d.ts +19 -2
  62. package/dist/server/app-page-dispatch.js +45 -23
  63. package/dist/server/app-page-element-builder.d.ts +9 -2
  64. package/dist/server/app-page-element-builder.js +144 -33
  65. package/dist/server/app-page-head.d.ts +56 -4
  66. package/dist/server/app-page-head.js +216 -85
  67. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  68. package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
  69. package/dist/server/app-page-probe.d.ts +4 -0
  70. package/dist/server/app-page-probe.js +6 -2
  71. package/dist/server/app-page-render.d.ts +2 -2
  72. package/dist/server/app-page-render.js +1 -1
  73. package/dist/server/app-page-request.d.ts +15 -0
  74. package/dist/server/app-page-request.js +134 -14
  75. package/dist/server/app-page-response.js +1 -1
  76. package/dist/server/app-page-route-wiring.d.ts +16 -0
  77. package/dist/server/app-page-route-wiring.js +254 -52
  78. package/dist/server/app-pages-bridge.d.ts +1 -1
  79. package/dist/server/app-pages-bridge.js +2 -1
  80. package/dist/server/app-post-middleware-context.d.ts +1 -1
  81. package/dist/server/app-post-middleware-context.js +1 -1
  82. package/dist/server/app-route-handler-cache.js +4 -0
  83. package/dist/server/app-route-handler-dispatch.js +40 -20
  84. package/dist/server/app-route-handler-execution.d.ts +6 -1
  85. package/dist/server/app-route-handler-execution.js +42 -16
  86. package/dist/server/app-route-handler-policy.d.ts +2 -0
  87. package/dist/server/app-route-handler-policy.js +3 -3
  88. package/dist/server/app-route-handler-response.js +1 -1
  89. package/dist/server/app-route-module-loader.d.ts +9 -1
  90. package/dist/server/app-route-module-loader.js +4 -0
  91. package/dist/server/app-router-entry.js +6 -3
  92. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  93. package/dist/server/app-rsc-errors.d.ts +1 -1
  94. package/dist/server/app-rsc-errors.js +22 -2
  95. package/dist/server/app-rsc-handler.d.ts +10 -5
  96. package/dist/server/app-rsc-handler.js +73 -33
  97. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  98. package/dist/server/app-rsc-request-normalization.js +8 -2
  99. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  100. package/dist/server/app-rsc-response-finalizer.js +5 -11
  101. package/dist/server/app-rsc-route-matching.d.ts +29 -0
  102. package/dist/server/app-rsc-route-matching.js +93 -11
  103. package/dist/server/app-segment-config.js +13 -3
  104. package/dist/server/app-server-action-execution.d.ts +3 -1
  105. package/dist/server/app-server-action-execution.js +9 -7
  106. package/dist/server/app-ssr-entry.js +6 -6
  107. package/dist/server/app-ssr-stream.d.ts +1 -7
  108. package/dist/server/app-ssr-stream.js +2 -10
  109. package/dist/server/cache-control.d.ts +2 -2
  110. package/dist/server/cache-control.js +2 -1
  111. package/dist/server/config-headers.d.ts +24 -0
  112. package/dist/server/config-headers.js +52 -0
  113. package/dist/server/dev-initial-server-error.d.ts +1 -1
  114. package/dist/server/dev-server.d.ts +3 -1
  115. package/dist/server/dev-server.js +170 -321
  116. package/dist/server/headers.d.ts +2 -2
  117. package/dist/server/headers.js +4 -3
  118. package/dist/server/isr-cache.d.ts +11 -34
  119. package/dist/server/isr-cache.js +33 -43
  120. package/dist/server/isr-decision.d.ts +2 -2
  121. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  122. package/dist/server/middleware-matcher-pattern.js +219 -0
  123. package/dist/server/middleware-matcher.d.ts +2 -7
  124. package/dist/server/middleware-matcher.js +13 -60
  125. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  126. package/dist/server/middleware-path-to-regexp.js +228 -0
  127. package/dist/server/middleware-runtime.js +4 -3
  128. package/dist/server/middleware.d.ts +1 -1
  129. package/dist/server/middleware.js +2 -1
  130. package/dist/server/pages-api-route.d.ts +2 -0
  131. package/dist/server/pages-api-route.js +4 -1
  132. package/dist/server/pages-data-route.d.ts +11 -1
  133. package/dist/server/pages-data-route.js +16 -1
  134. package/dist/server/pages-dev-hydration.js +0 -1
  135. package/dist/server/pages-get-initial-props.d.ts +16 -3
  136. package/dist/server/pages-get-initial-props.js +17 -10
  137. package/dist/server/pages-i18n.js +64 -16
  138. package/dist/server/pages-node-compat.d.ts +2 -0
  139. package/dist/server/pages-node-compat.js +7 -3
  140. package/dist/server/pages-page-data.d.ts +64 -10
  141. package/dist/server/pages-page-data.js +349 -80
  142. package/dist/server/pages-page-handler.d.ts +9 -3
  143. package/dist/server/pages-page-handler.js +131 -36
  144. package/dist/server/pages-page-response.d.ts +5 -3
  145. package/dist/server/pages-page-response.js +24 -27
  146. package/dist/server/pages-readiness.d.ts +3 -3
  147. package/dist/server/pages-request-pipeline.d.ts +8 -0
  148. package/dist/server/pages-request-pipeline.js +30 -12
  149. package/dist/server/pages-revalidate.d.ts +1 -1
  150. package/dist/server/pages-revalidate.js +54 -8
  151. package/dist/server/pages-router-entry.d.ts +1 -0
  152. package/dist/server/pages-router-entry.js +16 -4
  153. package/dist/server/prerender-route-params.js +2 -2
  154. package/dist/server/prod-server.d.ts +3 -5
  155. package/dist/server/prod-server.js +72 -35
  156. package/dist/server/request-pipeline.d.ts +15 -29
  157. package/dist/server/request-pipeline.js +24 -59
  158. package/dist/server/revalidation-host.d.ts +11 -0
  159. package/dist/server/revalidation-host.js +19 -0
  160. package/dist/server/rsc-stream-hints.js +122 -18
  161. package/dist/server/worker-revalidation-context.d.ts +13 -0
  162. package/dist/server/worker-revalidation-context.js +29 -0
  163. package/dist/shims/app.d.ts +1 -1
  164. package/dist/shims/cache-handler.d.ts +1 -1
  165. package/dist/shims/cache-handler.js +10 -7
  166. package/dist/shims/cache-request-state.d.ts +27 -1
  167. package/dist/shims/cache-request-state.js +60 -1
  168. package/dist/shims/cache-runtime.d.ts +18 -1
  169. package/dist/shims/cache-runtime.js +26 -8
  170. package/dist/shims/cache.d.ts +5 -5
  171. package/dist/shims/cache.js +27 -11
  172. package/dist/shims/document.d.ts +42 -83
  173. package/dist/shims/document.js +62 -53
  174. package/dist/shims/dynamic.d.ts +5 -25
  175. package/dist/shims/dynamic.js +29 -8
  176. package/dist/shims/error.d.ts +1 -1
  177. package/dist/shims/error.js +2 -2
  178. package/dist/shims/fetch-cache.js +13 -4
  179. package/dist/shims/font-google-base.d.ts +11 -4
  180. package/dist/shims/font-google-base.js +17 -8
  181. package/dist/shims/font-local.d.ts +10 -3
  182. package/dist/shims/font-local.js +41 -10
  183. package/dist/shims/head.d.ts +13 -2
  184. package/dist/shims/head.js +3 -3
  185. package/dist/shims/headers.d.ts +37 -43
  186. package/dist/shims/headers.js +183 -74
  187. package/dist/shims/image.d.ts +27 -37
  188. package/dist/shims/image.js +21 -14
  189. package/dist/shims/internal/cookie-serialize.d.ts +12 -9
  190. package/dist/shims/internal/cookie-serialize.js +10 -7
  191. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  192. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  193. package/dist/shims/internal/interpolate-as.js +27 -2
  194. package/dist/shims/internal/utils.d.ts +3 -3
  195. package/dist/shims/legacy-image.d.ts +3 -37
  196. package/dist/shims/legacy-image.js +6 -16
  197. package/dist/shims/link.d.ts +15 -22
  198. package/dist/shims/link.js +34 -13
  199. package/dist/shims/metadata.d.ts +7 -17
  200. package/dist/shims/metadata.js +74 -24
  201. package/dist/shims/navigation-context-state.d.ts +1 -1
  202. package/dist/shims/navigation.d.ts +7 -3
  203. package/dist/shims/navigation.js +25 -14
  204. package/dist/shims/navigation.react-server.js +1 -1
  205. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  206. package/dist/shims/next-shims-public.d.ts +1 -0
  207. package/dist/shims/public-shim-map.json.js +103 -0
  208. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  209. package/dist/shims/readonly-url-search-params.js +3 -3
  210. package/dist/shims/request-context.d.ts +4 -1
  211. package/dist/shims/request-state-types.d.ts +1 -1
  212. package/dist/shims/router.d.ts +55 -21
  213. package/dist/shims/router.js +180 -44
  214. package/dist/shims/script.d.ts +6 -10
  215. package/dist/shims/script.js +7 -4
  216. package/dist/shims/server.d.ts +50 -26
  217. package/dist/shims/server.js +193 -55
  218. package/dist/shims/unified-request-context.d.ts +22 -3
  219. package/dist/shims/unified-request-context.js +84 -1
  220. package/dist/shims/url-safety.d.ts +1 -1
  221. package/dist/shims/url-safety.js +2 -2
  222. package/dist/typegen.d.ts +8 -2
  223. package/dist/typegen.js +76 -15
  224. package/dist/utils/cache-control-metadata.d.ts +2 -1
  225. package/dist/utils/cache-control-metadata.js +5 -1
  226. package/dist/utils/domain-locale.d.ts +2 -2
  227. package/dist/utils/external-url.d.ts +5 -0
  228. package/dist/utils/external-url.js +7 -0
  229. package/dist/utils/html-limited-bots.js +1 -1
  230. package/dist/utils/protocol-headers.d.ts +7 -1
  231. package/dist/utils/protocol-headers.js +7 -1
  232. package/dist/utils/regex-safety.d.ts +8 -0
  233. package/dist/utils/regex-safety.js +737 -0
  234. package/package.json +13 -2
@@ -42,6 +42,7 @@ type RunAppRouteHandlerOptions = {
42
42
  dynamicConfig?: string;
43
43
  handlerFn: AppRouteHandlerFunction;
44
44
  i18n?: NextI18nConfig | null;
45
+ isDraftMode?: boolean;
45
46
  trailingSlash?: boolean;
46
47
  markDynamicUsage: MarkAppRouteDynamicUsageFn;
47
48
  middlewareRequestHeaders?: Headers | null;
@@ -58,6 +59,7 @@ type RunAppRouteHandlerResult = {
58
59
  dynamicUsedInHandler: boolean;
59
60
  response: Response;
60
61
  };
62
+ declare function applyDraftModeCachePolicy(response: Response, isDraftMode: boolean): Response;
61
63
  type ExecuteAppRouteHandlerOptions = {
62
64
  buildPageCacheTags: (pathname: string, extraTags: string[]) => string[];
63
65
  clearRequestContext: () => void;
@@ -65,9 +67,12 @@ type ExecuteAppRouteHandlerOptions = {
65
67
  executionContext: ExecutionContextLike | null;
66
68
  getAndClearPendingCookies: () => string[];
67
69
  getCollectedFetchTags: () => string[];
70
+ getActiveDraftModeState?: () => boolean | null;
68
71
  getDraftModeCookieHeader: () => string | null | undefined;
69
72
  handler: AppRouteHandlerModule;
70
73
  isAutoHead: boolean;
74
+ initialDraftModeCookie?: string | null;
75
+ isDraftMode?: boolean;
71
76
  isProduction: boolean;
72
77
  isrDebug?: AppRouteDebugLogger;
73
78
  isrRouteKey: (pathname: string) => string;
@@ -83,4 +88,4 @@ type ExecuteAppRouteHandlerOptions = {
83
88
  declare function runAppRouteHandler(options: RunAppRouteHandlerOptions): Promise<RunAppRouteHandlerResult>;
84
89
  declare function executeAppRouteHandler(options: ExecuteAppRouteHandlerOptions): Promise<Response>;
85
90
  //#endregion
86
- export { AppRouteDebugLogger, AppRouteDynamicUsageFn, AppRouteHandlerFunction, AppRouteParams, MarkAppRouteDynamicUsageFn, RouteHandlerCacheSetter, executeAppRouteHandler, runAppRouteHandler };
91
+ export { AppRouteDebugLogger, AppRouteDynamicUsageFn, AppRouteHandlerFunction, AppRouteParams, MarkAppRouteDynamicUsageFn, RouteHandlerCacheSetter, applyDraftModeCachePolicy, executeAppRouteHandler, runAppRouteHandler };
@@ -1,15 +1,27 @@
1
+ import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
1
2
  import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
2
- import { runWithRootParamsUsage } from "../shims/root-params.js";
3
+ import { _drainPendingRevalidations } from "../shims/cache-request-state.js";
3
4
  import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
5
+ import { runWithRootParamsUsage } from "../shims/root-params.js";
4
6
  import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
5
7
  import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
6
8
  import { createStaticGenerationHeadersContext, getAppRouteStaticGenerationErrorMessage } from "./app-static-generation.js";
7
9
  import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
8
10
  //#region src/server/app-route-handler-execution.ts
11
+ function applyDraftModeCachePolicy(response, isDraftMode) {
12
+ if (!isDraftMode) return response;
13
+ const headers = new Headers(response.headers);
14
+ applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
15
+ return new Response(response.body, {
16
+ status: response.status,
17
+ statusText: response.statusText,
18
+ headers
19
+ });
20
+ }
9
21
  function configureAppRouteStaticGenerationContext(options) {
10
22
  if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
11
23
  setHeadersContext(createStaticGenerationHeadersContext({
12
- draftModeEnabled: options.draftModeSecret !== void 0 && isDraftModeRequest(options.request, options.draftModeSecret),
24
+ draftModeEnabled: options.isDraftMode ?? (options.draftModeSecret !== void 0 && isDraftModeRequest(options.request, options.draftModeSecret)),
13
25
  draftModeSecret: options.draftModeSecret,
14
26
  dynamicConfig: options.dynamicConfig,
15
27
  routeKind: "route",
@@ -46,18 +58,30 @@ async function runAppRouteHandler(options) {
46
58
  async function executeAppRouteHandler(options) {
47
59
  const previousHeadersPhase = options.setHeadersAccessPhase("route-handler");
48
60
  try {
49
- const { dynamicUsedInHandler, response } = await runAppRouteHandler({
50
- ...options,
51
- dynamicConfig: options.handler.dynamic
52
- });
61
+ let handlerResult;
62
+ try {
63
+ handlerResult = await runAppRouteHandler({
64
+ ...options,
65
+ dynamicConfig: options.handler.dynamic
66
+ });
67
+ } finally {
68
+ await _drainPendingRevalidations();
69
+ }
70
+ const { dynamicUsedInHandler, response } = handlerResult;
53
71
  assertSupportedAppRouteHandlerResponse(response);
54
72
  const handlerSetCacheControl = response.headers.has("cache-control");
55
73
  if (dynamicUsedInHandler) markKnownDynamicAppRoute(options.routePattern);
74
+ const pendingCookies = options.getAndClearPendingCookies();
75
+ const handlerDraftCookie = options.getDraftModeCookieHeader();
76
+ const draftCookie = handlerDraftCookie ?? options.initialDraftModeCookie;
77
+ const shouldApplyDraftPolicy = (options.getActiveDraftModeState?.() ?? options.isDraftMode === true) || draftCookie != null;
78
+ if (handlerDraftCookie != null) markKnownDynamicAppRoute(options.routePattern);
56
79
  const routeTags = options.buildPageCacheTags(options.cleanPathname, options.getCollectedFetchTags());
57
80
  if (shouldApplyAppRouteHandlerRevalidateHeader({
58
81
  dynamicUsedInHandler,
59
82
  handlerSetCacheControl,
60
83
  isAutoHead: options.isAutoHead,
84
+ isDraftMode: shouldApplyDraftPolicy,
61
85
  method: options.method,
62
86
  revalidateSeconds: options.revalidateSeconds
63
87
  })) {
@@ -70,6 +94,7 @@ async function executeAppRouteHandler(options) {
70
94
  dynamicUsedInHandler,
71
95
  handlerSetCacheControl,
72
96
  isAutoHead: options.isAutoHead,
97
+ isDraftMode: shouldApplyDraftPolicy,
73
98
  isProduction: options.isProduction,
74
99
  method: options.method,
75
100
  revalidateSeconds: options.revalidateSeconds
@@ -90,29 +115,30 @@ async function executeAppRouteHandler(options) {
90
115
  })();
91
116
  options.executionContext?.waitUntil(routeWritePromise);
92
117
  }
93
- const pendingCookies = options.getAndClearPendingCookies();
94
- const draftCookie = options.getDraftModeCookieHeader();
95
118
  options.clearRequestContext();
96
- return applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(response, {
119
+ return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(response, {
97
120
  pendingCookies,
98
121
  draftCookie,
99
122
  isHead: options.isAutoHead
100
- }), options.middlewareContext);
123
+ }), options.middlewareContext), shouldApplyDraftPolicy);
101
124
  } catch (error) {
102
125
  const pendingCookies = options.getAndClearPendingCookies();
103
- const draftCookie = options.getDraftModeCookieHeader();
126
+ const handlerDraftCookie = options.getDraftModeCookieHeader();
127
+ const draftCookie = handlerDraftCookie ?? options.initialDraftModeCookie;
128
+ const shouldApplyDraftPolicy = (options.getActiveDraftModeState?.() ?? options.isDraftMode === true) || draftCookie != null;
129
+ if (handlerDraftCookie != null) markKnownDynamicAppRoute(options.routePattern);
104
130
  const specialError = resolveAppRouteHandlerSpecialError(error, options.request.url, { isAction: isPossibleAppRouteActionRequest(options.request) });
105
131
  options.clearRequestContext();
106
132
  if (specialError) {
107
- if (specialError.kind === "redirect") return applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(new Response(null, {
133
+ if (specialError.kind === "redirect") return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(finalizeRouteHandlerResponse(new Response(null, {
108
134
  status: specialError.statusCode,
109
135
  headers: { Location: specialError.location }
110
136
  }), {
111
137
  pendingCookies,
112
138
  draftCookie,
113
139
  isHead: options.isAutoHead
114
- }), options.middlewareContext);
115
- return applyRouteHandlerMiddlewareContext(new Response(null, { status: specialError.statusCode }), options.middlewareContext);
140
+ }), options.middlewareContext), shouldApplyDraftPolicy);
141
+ return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(new Response(null, { status: specialError.statusCode }), options.middlewareContext), shouldApplyDraftPolicy);
116
142
  }
117
143
  console.error("[vinext] Route handler error:", error);
118
144
  options.reportRequestError(error instanceof Error ? error : new Error(String(error)), {
@@ -124,10 +150,10 @@ async function executeAppRouteHandler(options) {
124
150
  routePath: options.routePattern,
125
151
  routeType: "route"
126
152
  });
127
- return applyRouteHandlerMiddlewareContext(new Response(null, { status: 500 }), options.middlewareContext);
153
+ return applyDraftModeCachePolicy(applyRouteHandlerMiddlewareContext(new Response(null, { status: 500 }), options.middlewareContext), shouldApplyDraftPolicy);
128
154
  } finally {
129
155
  options.setHeadersAccessPhase(previousHeadersPhase);
130
156
  }
131
157
  }
132
158
  //#endregion
133
- export { executeAppRouteHandler, runAppRouteHandler };
159
+ export { applyDraftModeCachePolicy, executeAppRouteHandler, runAppRouteHandler };
@@ -20,6 +20,7 @@ type AppRouteHandlerCacheReadOptions = {
20
20
  handlerFn: unknown;
21
21
  isAutoHead: boolean;
22
22
  isKnownDynamic: boolean;
23
+ isDraftMode?: boolean;
23
24
  isProduction: boolean;
24
25
  method: string;
25
26
  revalidateSeconds: number | null;
@@ -29,6 +30,7 @@ type AppRouteHandlerResponseCacheOptions = {
29
30
  dynamicUsedInHandler: boolean;
30
31
  handlerSetCacheControl: boolean;
31
32
  isAutoHead: boolean;
33
+ isDraftMode?: boolean;
32
34
  isProduction: boolean;
33
35
  method: string;
34
36
  revalidateSeconds: number | null;
@@ -30,13 +30,13 @@ function resolveAppRouteHandlerMethod(handler, method) {
30
30
  };
31
31
  }
32
32
  function shouldReadAppRouteHandlerCache(options) {
33
- return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && !options.isKnownDynamic && (options.method === "GET" || options.isAutoHead) && typeof options.handlerFn === "function";
33
+ return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && !options.isKnownDynamic && (options.method === "GET" || options.isAutoHead) && typeof options.handlerFn === "function";
34
34
  }
35
35
  function shouldApplyAppRouteHandlerRevalidateHeader(options) {
36
- return options.revalidateSeconds !== null && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead) && !options.handlerSetCacheControl;
36
+ return options.revalidateSeconds !== null && !options.isDraftMode && !options.dynamicUsedInHandler && (options.method === "GET" || options.isAutoHead) && !options.handlerSetCacheControl;
37
37
  }
38
38
  function shouldWriteAppRouteHandlerCache(options) {
39
- return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && shouldApplyAppRouteHandlerRevalidateHeader(options);
39
+ return options.isProduction && options.revalidateSeconds !== null && options.revalidateSeconds > 0 && options.revalidateSeconds !== Infinity && options.dynamicConfig !== "force-dynamic" && !options.isDraftMode && shouldApplyAppRouteHandlerRevalidateHeader(options);
40
40
  }
41
41
  function resolveAppRouteHandlerSpecialError(error, requestUrl, options) {
42
42
  if (!(error && typeof error === "object" && "digest" in error)) return null;
@@ -1,9 +1,9 @@
1
1
  import "../utils/protocol-headers.js";
2
2
  import "./headers.js";
3
3
  import { processMiddlewareHeaders } from "./request-pipeline.js";
4
- import { setCacheStateHeaders } from "./cache-headers.js";
5
4
  import { applyCdnResponseHeaders } from "./cache-control.js";
6
5
  import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
6
+ import { setCacheStateHeaders } from "./cache-headers.js";
7
7
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
8
8
  import { getSetCookieName } from "./cookie-utils.js";
9
9
  //#region src/server/app-route-handler-response.ts
@@ -28,6 +28,8 @@ type LazyModuleLoaderArray = readonly (LazyModuleThunk | null | undefined)[];
28
28
  type LazyLoadableIntercept = {
29
29
  interceptLayouts?: readonly unknown[] | null;
30
30
  __loadInterceptLayouts?: LazyModuleLoaderArray | null;
31
+ interceptLoadings?: readonly unknown[] | null;
32
+ __loadInterceptLoadings?: LazyModuleLoaderArray | null;
31
33
  __loadState?: {
32
34
  interceptLayoutsLoading: Promise<readonly unknown[]> | null;
33
35
  };
@@ -38,13 +40,17 @@ type LazyLoadableSlot = {
38
40
  layout?: unknown;
39
41
  configLayouts?: readonly unknown[];
40
42
  loading?: unknown;
43
+ loadings?: readonly unknown[];
41
44
  error?: unknown;
45
+ notFound?: unknown;
42
46
  __loadPage?: LazyModuleThunk | null;
43
47
  __loadDefault?: LazyModuleThunk | null;
44
48
  __loadLayout?: LazyModuleThunk | null;
45
49
  __loadConfigLayouts?: LazyModuleLoaderArray | null;
46
50
  __loadLoading?: LazyModuleThunk | null;
47
- __loadError?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
51
+ __loadLoadings?: LazyModuleLoaderArray | null;
52
+ __loadError?: LazyModuleThunk | null;
53
+ __loadNotFound?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
48
54
  intercepts?: LazyLoadableIntercept[];
49
55
  };
50
56
  type LazyLoadableRoute = {
@@ -52,6 +58,7 @@ type LazyLoadableRoute = {
52
58
  routeHandler?: unknown;
53
59
  layouts?: unknown[];
54
60
  templates?: unknown[];
61
+ loadings?: unknown[];
55
62
  errors?: unknown[];
56
63
  errorPaths?: unknown[];
57
64
  notFounds?: unknown[];
@@ -68,6 +75,7 @@ type LazyLoadableRoute = {
68
75
  __loadRouteHandler?: LazyModuleThunk | null;
69
76
  __loadLayouts?: LazyModuleLoaderArray | null;
70
77
  __loadTemplates?: LazyModuleLoaderArray | null;
78
+ __loadLoadings?: LazyModuleLoaderArray | null;
71
79
  __loadErrors?: LazyModuleLoaderArray | null;
72
80
  __loadErrorPaths?: LazyModuleLoaderArray | null;
73
81
  __loadNotFounds?: LazyModuleLoaderArray | null;
@@ -20,6 +20,7 @@ function loadAppInterceptLayouts(intercept) {
20
20
  if (loadState?.interceptLayoutsLoading) return loadState.interceptLayoutsLoading;
21
21
  const loads = [];
22
22
  pushArrayLoads(loads, intercept.interceptLayouts, intercept.__loadInterceptLayouts);
23
+ pushArrayLoads(loads, intercept.interceptLoadings, intercept.__loadInterceptLoadings);
23
24
  if (loads.length === 0) return Promise.resolve(intercept.interceptLayouts ?? []);
24
25
  const loading = Promise.all(loads).then(() => {
25
26
  if (loadState) loadState.interceptLayoutsLoading = null;
@@ -52,6 +53,7 @@ function ensureAppRouteModulesLoaded(route) {
52
53
  pushFieldLoad(loads, route, "unauthorized", route.__loadUnauthorized);
53
54
  pushArrayLoads(loads, route.layouts, route.__loadLayouts);
54
55
  pushArrayLoads(loads, route.templates, route.__loadTemplates);
56
+ pushArrayLoads(loads, route.loadings, route.__loadLoadings);
55
57
  pushArrayLoads(loads, route.errors, route.__loadErrors);
56
58
  pushArrayLoads(loads, route.errorPaths, route.__loadErrorPaths);
57
59
  pushArrayLoads(loads, route.notFounds, route.__loadNotFounds);
@@ -63,7 +65,9 @@ function ensureAppRouteModulesLoaded(route) {
63
65
  pushFieldLoad(loads, slot, "layout", slot.__loadLayout);
64
66
  pushArrayLoads(loads, slot.configLayouts, slot.__loadConfigLayouts);
65
67
  pushFieldLoad(loads, slot, "loading", slot.__loadLoading);
68
+ pushArrayLoads(loads, slot.loadings, slot.__loadLoadings);
66
69
  pushFieldLoad(loads, slot, "error", slot.__loadError);
70
+ pushFieldLoad(loads, slot, "notFound", slot.__loadNotFound);
67
71
  }
68
72
  if (loads.length === 0) {
69
73
  route.__loaded = true;
@@ -1,6 +1,6 @@
1
1
  import "./server-globals.js";
2
2
  import { runWithExecutionContext } from "../shims/request-context.js";
3
- import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "../utils/protocol-headers.js";
3
+ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
4
4
  import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
5
5
  import { isOpenRedirectShaped } from "./open-redirect.js";
6
6
  import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
@@ -8,6 +8,7 @@ import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js"
8
8
  import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
9
9
  import { finalizeMissingStaticAssetResponse, resolveStaticAssetSignal } from "./worker-utils.js";
10
10
  import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
11
+ import { createWorkerRevalidationContext } from "./worker-revalidation-context.js";
11
12
  import rscHandler, { __assetPrefix, __basePath, __imageAllowedWidths, __imageConfig } from "virtual:vinext-rsc-entry";
12
13
  import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
13
14
  import { registerConfiguredImageOptimizer } from "virtual:vinext-image-adapters";
@@ -17,7 +18,8 @@ const __workerAssetPathPrefix = assetPrefixPathname(typeof __assetPrefix === "st
17
18
  var app_router_entry_default = { async fetch(request, env, ctx) {
18
19
  return handleRequest(request, env, ctx);
19
20
  } };
20
- async function handleRequest(request, env, ctx) {
21
+ async function handleRequest(request, env, platformCtx) {
22
+ const ctx = platformCtx?.trustedRevalidateOrigin ? platformCtx : createWorkerRevalidationContext(platformCtx, (internalRequest, internalCtx) => handleRequest(internalRequest, env, internalCtx));
21
23
  registerConfiguredCacheAdapters(env);
22
24
  registerConfiguredImageOptimizer(env);
23
25
  const url = new URL(request.url);
@@ -34,7 +36,8 @@ async function handleRequest(request, env, ctx) {
34
36
  const missingBuildAsset = isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix);
35
37
  {
36
38
  const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
37
- const filteredHeaders = filterInternalHeaders(request.headers);
39
+ const filteredHeaders = ctx.isInternalPagesRevalidation ? new Headers(request.headers) : filterInternalHeaders(request.headers);
40
+ filteredHeaders.delete(VINEXT_REVALIDATE_HOST_HEADER);
38
41
  const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
39
42
  if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
40
43
  request = cloneRequestWithHeaders(request, filteredHeaders);
@@ -1,5 +1,5 @@
1
- import { VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
2
1
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
2
+ import { VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
3
3
 
4
4
  //#region src/server/app-rsc-cache-busting.d.ts
5
5
  /**
@@ -34,7 +34,7 @@ declare function getDigestForWellKnownError(error: unknown): string | undefined;
34
34
  * djb2 hash matching Next.js's string-hash package for RSC error digests.
35
35
  */
36
36
  declare function errorDigest(input: string): string;
37
- declare function sanitizeErrorForClient(error: unknown, nodeEnv?: string | undefined): unknown;
37
+ declare function sanitizeErrorForClient(error: unknown, nodeEnv?: "development" | "production" | "test"): unknown;
38
38
  declare function createRscOnErrorHandler(options: CreateRscOnErrorHandlerOptions): (error: unknown) => string | undefined;
39
39
  //#endregion
40
40
  export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
@@ -1,11 +1,17 @@
1
1
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
2
2
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
3
3
  //#region src/server/app-rsc-errors.ts
4
+ const ORIGINAL_SERVER_ERROR = Symbol.for("vinext.originalServerError");
4
5
  function hasDigest(error) {
5
6
  return Boolean(error && typeof error === "object" && "digest" in error);
6
7
  }
7
8
  const BAILOUT_TO_CSR_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
8
9
  const DYNAMIC_SERVER_USAGE_DIGEST = "DYNAMIC_SERVER_USAGE";
10
+ function isAbortError(error) {
11
+ if (!error || typeof error !== "object") return false;
12
+ const name = Reflect.get(error, "name");
13
+ return name === "AbortError" || name === "ResponseAborted";
14
+ }
9
15
  /**
10
16
  * vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
11
17
  * string only when the error is a genuine control-flow signal — a redirect,
@@ -39,19 +45,33 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
39
45
  if (resolveAppPageSpecialError(error)) return error;
40
46
  if (nodeEnv !== "production") return error;
41
47
  const sanitized = /* @__PURE__ */ new Error("An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.");
42
- sanitized.digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
48
+ sanitized.digest = hasDigest(error) ? String(error.digest) : errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
49
+ Object.defineProperty(sanitized, ORIGINAL_SERVER_ERROR, {
50
+ configurable: false,
51
+ enumerable: false,
52
+ value: error,
53
+ writable: false
54
+ });
43
55
  return sanitized;
44
56
  }
45
57
  function createRscOnErrorHandler(options) {
46
58
  return (error) => {
47
59
  const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
60
+ if (isAbortError(error)) return;
48
61
  const wellKnownDigest = getDigestForWellKnownError(error);
49
62
  if (wellKnownDigest !== void 0) return wellKnownDigest;
50
63
  if (nodeEnv !== "production" && error instanceof Error && error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")) {
51
64
  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);
52
65
  return;
53
66
  }
54
- if (options.requestInfo && options.errorContext && error) options.reportRequestError(error instanceof Error ? error : new Error(getThrownValueMessage(error)), options.requestInfo, options.errorContext);
67
+ if (options.requestInfo && options.errorContext && error) {
68
+ const reportableError = typeof error === "object" && ORIGINAL_SERVER_ERROR in error ? Reflect.get(error, ORIGINAL_SERVER_ERROR) : error;
69
+ options.reportRequestError(reportableError instanceof Error ? reportableError : new Error(getThrownValueMessage(reportableError)), options.requestInfo, options.errorContext);
70
+ }
71
+ if (nodeEnv !== "production" && error && !hasDigest(error)) {
72
+ const loggableError = typeof error === "object" && ORIGINAL_SERVER_ERROR in error ? Reflect.get(error, ORIGINAL_SERVER_ERROR) : error;
73
+ console.error("[vinext] Server render error:", loggableError);
74
+ }
55
75
  if (hasDigest(error)) return String(error.digest);
56
76
  if (error) {
57
77
  const digest = errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
@@ -1,9 +1,9 @@
1
1
  import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config/next-config.js";
2
2
  import { ImageConfig } from "./image-optimization.js";
3
3
  import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
4
+ import { AppRscRenderMode } from "./app-rsc-render-mode.js";
4
5
  import { RootParams } from "../shims/root-params.js";
5
6
  import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware.js";
6
- import { AppRscRenderMode } from "./app-rsc-render-mode.js";
7
7
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
8
8
  import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
9
9
  import { AppRouteTreePrefetchRoute, PrefetchInliningConfig } from "./app-route-tree-prefetch.js";
@@ -48,6 +48,7 @@ type DispatchMatchedPageOptions<TRoute> = {
48
48
  actionFailed?: boolean;
49
49
  handlerStart: number;
50
50
  interceptionContext: string | null;
51
+ interceptionPathname: string;
51
52
  isProgressiveActionRender: boolean;
52
53
  isRscRequest: boolean;
53
54
  middlewareContext: AppRscMiddlewareContext;
@@ -87,12 +88,13 @@ type DispatchMatchedRouteHandlerOptions<TRoute> = {
87
88
  route: TRoute;
88
89
  searchParams: URLSearchParams;
89
90
  };
90
- type HandleProgressiveActionRequestOptions = {
91
+ type HandleProgressiveActionRequestOptions<TRoute> = {
91
92
  actionId: string | null;
92
93
  cleanPathname: string;
93
94
  contentType: string;
94
95
  middlewareContext: AppRscMiddlewareContext;
95
96
  request: Request;
97
+ routeMatch: AppRscRouteMatch<TRoute> | null;
96
98
  };
97
99
  /**
98
100
  * Side-effect headers captured during a progressive (no-JS) server action's
@@ -114,7 +116,7 @@ type ProgressiveActionFormStateResult = ({
114
116
  formState: null;
115
117
  kind: "form-state";
116
118
  } & ProgressiveActionSideEffects);
117
- type HandleServerActionRequestOptions = {
119
+ type HandleServerActionRequestOptions<TRoute> = {
118
120
  actionId: string | null;
119
121
  cleanPathname: string;
120
122
  contentType: string;
@@ -123,6 +125,8 @@ type HandleServerActionRequestOptions = {
123
125
  middlewareContext: AppRscMiddlewareContext;
124
126
  mountedSlotsHeader: string | null;
125
127
  request: Request;
128
+ routeMatch: AppRscRouteMatch<TRoute> | null;
129
+ routePathname: string;
126
130
  searchParams: URLSearchParams;
127
131
  };
128
132
  type RenderNotFoundOptions<TRoute> = {
@@ -183,15 +187,16 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
183
187
  * Node server and dev included, not just the Cloudflare worker entry.
184
188
  */
185
189
  registerCacheAdapters: (env?: Record<string, unknown>) => void;
186
- handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
190
+ handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions<TRoute>) => Promise<Response | ProgressiveActionFormStateResult | null>;
187
191
  handleMetadataRouteRequest?: (cleanPathname: string) => Promise<Response | null>;
188
192
  createPprFallbackShells?: (route: Pick<AppRscHandlerRoute, "params" | "pattern" | "rootParamNames">, params: AppPageParams) => AppPagePprFallbackCacheShell[];
189
- handleServerActionRequest?: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
193
+ handleServerActionRequest?: (options: HandleServerActionRequestOptions<TRoute>) => Promise<Response | null>;
190
194
  i18nConfig: NextI18nConfig | null;
191
195
  imageConfig?: ImageConfig;
192
196
  isDev: boolean;
193
197
  loadPrerenderPagesRoutes?: () => Promise<unknown>;
194
198
  matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
199
+ matchRequestRoute?: (pathname: string) => AppRscRouteMatch<TRoute> | null;
195
200
  runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
196
201
  publicFiles: ReadonlySet<string>;
197
202
  prefetchInlining?: PrefetchInliningConfig;