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
@@ -3,7 +3,7 @@ import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation }
3
3
  import { MIDDLEWARE_SET_COOKIE_HEADER } from "../utils/protocol-headers.js";
4
4
  import { FLIGHT_HEADERS, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER } from "../server/headers.js";
5
5
  import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
6
- import { serializeSetCookie, validateCookieAttributeValue, validateCookieName } from "./internal/cookie-serialize.js";
6
+ import { serializeSetCookie, validateCookieName } from "./internal/cookie-serialize.js";
7
7
  import { parseEdgeRequestCookieHeader } from "../utils/parse-cookie.js";
8
8
  import { createPprFallbackShellSuspensePromise } from "./ppr-fallback-shell.js";
9
9
  //#region src/shims/headers.ts
@@ -29,7 +29,6 @@ const _fallbackState = _g[_FALLBACK_KEY] ??= {
29
29
  draftModeCookieHeader: null,
30
30
  phase: "render"
31
31
  };
32
- const EXPIRED_COOKIE_DATE = (/* @__PURE__ */ new Date(0)).toUTCString();
33
32
  function splitMiddlewareSetCookieHeader(value) {
34
33
  const cookies = [];
35
34
  let start = 0;
@@ -114,6 +113,52 @@ function markDynamicUsage() {
114
113
  const state = _getState();
115
114
  if (state.headersContext?.forceStatic) return;
116
115
  state.dynamicUsageDetected = true;
116
+ forEachConnectionProbeTarget(state, (target) => {
117
+ target.dynamicUsageDetected = true;
118
+ });
119
+ }
120
+ function forEachConnectionProbeTarget(state, visit) {
121
+ let target = state.connectionProbe?.dynamicUsageTarget ?? null;
122
+ const seen = /* @__PURE__ */ new Set([state]);
123
+ while (target && !seen.has(target)) {
124
+ seen.add(target);
125
+ visit(target);
126
+ target = target.connectionProbe?.dynamicUsageTarget ?? null;
127
+ }
128
+ }
129
+ function propagateInvalidDynamicUsageError(state, error) {
130
+ forEachConnectionProbeTarget(state, (target) => {
131
+ if (target.invalidDynamicUsageError == null) target.invalidDynamicUsageError = error;
132
+ });
133
+ }
134
+ /**
135
+ * Measure dynamic usage in a child async scope without clearing the parent.
136
+ * Concurrent work that already belongs to the request (such as deferred
137
+ * metadata) keeps writing to the parent state and therefore remains visible
138
+ * to the final cache policy.
139
+ */
140
+ async function runWithIsolatedDynamicUsage(fn) {
141
+ const runInChildState = async (childState) => {
142
+ return {
143
+ result: await fn(),
144
+ dynamicDetected: childState.dynamicUsageDetected
145
+ };
146
+ };
147
+ if (isInsideUnifiedScope()) {
148
+ let childState = null;
149
+ return await runWithUnifiedStateMutation((context) => {
150
+ context.dynamicUsageDetected = false;
151
+ childState = context;
152
+ }, () => {
153
+ if (!childState) throw new Error("Dynamic usage scope was not initialized");
154
+ return runInChildState(childState);
155
+ });
156
+ }
157
+ const childState = {
158
+ ..._getState(),
159
+ dynamicUsageDetected: false
160
+ };
161
+ return await _als.run(childState, () => runInChildState(childState));
117
162
  }
118
163
  function markRenderRequestApiUsage(kind) {
119
164
  _getState().renderRequestApiUsage.add(kind);
@@ -123,13 +168,15 @@ function throwIfStaticGenerationAccessError() {
123
168
  if (accessError) throw accessError;
124
169
  }
125
170
  async function runWithConnectionProbe(fn) {
126
- const state = _getState();
127
- const previousProbe = state.connectionProbe;
171
+ const parentState = _getState();
172
+ const parentInvalidDynamicUsageError = parentState.invalidDynamicUsageError;
128
173
  let interruptProbe = () => {};
129
174
  const interrupted = new Promise((resolve) => {
130
175
  interruptProbe = () => resolve({ completed: false });
131
176
  });
132
177
  const probe = {
178
+ active: true,
179
+ dynamicUsageTarget: parentState,
133
180
  interrupted: false,
134
181
  interrupt() {
135
182
  if (probe.interrupted) return;
@@ -138,20 +185,39 @@ async function runWithConnectionProbe(fn) {
138
185
  },
139
186
  pending: new Promise(() => {})
140
187
  };
141
- state.connectionProbe = probe;
142
- try {
143
- const completed = Promise.resolve().then(fn).then((result) => ({
144
- completed: true,
145
- result
146
- }));
147
- return await Promise.race([completed, interrupted]);
148
- } finally {
149
- state.connectionProbe = previousProbe;
188
+ const runInChildState = async (childState) => {
189
+ try {
190
+ const completed = Promise.resolve().then(fn).then((result) => ({
191
+ completed: true,
192
+ result
193
+ }));
194
+ return await Promise.race([completed, interrupted]);
195
+ } finally {
196
+ probe.active = false;
197
+ childState.connectionProbe = parentState.connectionProbe ?? probe;
198
+ if (childState.dynamicUsageDetected) parentState.dynamicUsageDetected = true;
199
+ if (childState.invalidDynamicUsageError !== parentInvalidDynamicUsageError && parentState.invalidDynamicUsageError === parentInvalidDynamicUsageError) parentState.invalidDynamicUsageError = childState.invalidDynamicUsageError;
200
+ }
201
+ };
202
+ if (isInsideUnifiedScope()) {
203
+ let childState = null;
204
+ return await runWithUnifiedStateMutation((context) => {
205
+ context.connectionProbe = probe;
206
+ childState = context;
207
+ }, () => {
208
+ if (!childState) throw new Error("Connection probe scope was not initialized");
209
+ return runInChildState(childState);
210
+ });
150
211
  }
212
+ const childState = {
213
+ ...parentState,
214
+ connectionProbe: probe
215
+ };
216
+ return await _als.run(childState, () => runInChildState(childState));
151
217
  }
152
218
  function suspendConnectionProbe() {
153
219
  const probe = _getState().connectionProbe;
154
- if (!probe) return null;
220
+ if (!probe?.active) return null;
155
221
  probe.interrupt();
156
222
  return probe.pending;
157
223
  }
@@ -202,6 +268,7 @@ function throwIfInsideCacheScope(apiName) {
202
268
  if (cacheCtx) cacheCtx.invalidDynamicUsageError = error;
203
269
  const ctx = getRequestContext();
204
270
  if (ctx) ctx.invalidDynamicUsageError = error;
271
+ propagateInvalidDynamicUsageError(_getState(), error);
205
272
  } catch {}
206
273
  throw error;
207
274
  }
@@ -210,6 +277,7 @@ function throwIfInsideCacheScope(apiName) {
210
277
  try {
211
278
  const ctx = getRequestContext();
212
279
  if (ctx) ctx.invalidDynamicUsageError = error;
280
+ propagateInvalidDynamicUsageError(_getState(), error);
213
281
  } catch {}
214
282
  throw error;
215
283
  }
@@ -251,6 +319,7 @@ function peekDynamicUsage() {
251
319
  }
252
320
  function _setStatePhase(state, phase) {
253
321
  const previous = state.phase;
322
+ if (previous === "action" && phase === "render") state.headersContext?.mutableCookies?.[SYNCHRONIZE_REQUEST_COOKIES]();
254
323
  state.phase = phase;
255
324
  return previous;
256
325
  }
@@ -465,7 +534,7 @@ function _sealCookies(cookies) {
465
534
  } });
466
535
  }
467
536
  function _getMutableCookies(ctx) {
468
- if (!ctx.mutableCookies) ctx.mutableCookies = _wrapMutableCookies(new RequestCookies(ctx.cookies));
537
+ if (!ctx.mutableCookies) ctx.mutableCookies = _wrapMutableCookies(new RequestCookies(ctx.cookies, true));
469
538
  return ctx.mutableCookies;
470
539
  }
471
540
  function _getReadonlyCookies(ctx) {
@@ -553,7 +622,7 @@ function headers() {
553
622
  * Cookie jar from the incoming request.
554
623
  * Returns a ReadonlyRequestCookies-like object.
555
624
  */
556
- function cookies() {
625
+ function cookiesImpl() {
557
626
  markRenderRequestApiUsage("cookies");
558
627
  try {
559
628
  throwIfInsideCacheScope("cookies()");
@@ -569,6 +638,9 @@ function cookies() {
569
638
  const cookieStore = _areCookiesMutableInCurrentPhase() ? _getMutableCookies(state.headersContext) : _getReadonlyCookies(state.headersContext);
570
639
  return _getOrCreateDecoratedRequestApiPromise(_decoratedCookiesPromises, cookieStore);
571
640
  }
641
+ function cookies() {
642
+ return cookiesImpl();
643
+ }
572
644
  /** Accumulated Set-Cookie headers from cookies().set() / .delete() calls */
573
645
  /**
574
646
  * Get and clear all pending Set-Cookie headers generated by cookies().set()/delete().
@@ -581,7 +653,6 @@ function getAndClearPendingCookies() {
581
653
  return cookies;
582
654
  }
583
655
  const DRAFT_MODE_COOKIE = "__prerender_bypass";
584
- const DRAFT_MODE_EXPIRED_DATE = (/* @__PURE__ */ new Date(0)).toUTCString();
585
656
  /**
586
657
  * Get any Set-Cookie header generated by draftMode().enable()/disable().
587
658
  * Called by the framework after rendering to attach the header to the response.
@@ -613,21 +684,25 @@ function isDraftModeRequest(request, draftModeSecret) {
613
684
  return parseEdgeRequestCookieHeader(cookieHeader).get(DRAFT_MODE_COOKIE) === validateDraftModeSecret(draftModeSecret);
614
685
  }
615
686
  /**
616
- * Read the active request's draft-mode state without recording request API usage.
617
- * Internal cache implementations use this to bypass persistent reads and writes,
618
- * matching Next.js's request-level `workStore.isDraftMode` guard.
687
+ * Read draft mode from the live request context without recording request API
688
+ * usage. `null` means there is no active request context, which lets framework
689
+ * callers fall back to an explicitly supplied request when needed.
619
690
  */
620
- function isDraftModeEnabled() {
691
+ function getActiveDraftModeState() {
621
692
  const context = _getState().headersContext;
622
- if (!context) return false;
693
+ if (!context) return null;
623
694
  if (context.draftModeEnabled !== void 0) return context.draftModeEnabled;
624
695
  const secret = context.draftModeSecret;
625
696
  if (secret === void 0) return false;
626
697
  return context.cookies.get(DRAFT_MODE_COOKIE) === validateDraftModeSecret(secret);
627
698
  }
628
- function draftModeCookieAttributes() {
629
- if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") return "Path=/; HttpOnly; SameSite=Lax";
630
- return "Path=/; HttpOnly; SameSite=None; Secure";
699
+ /**
700
+ * Read the active request's draft-mode state without recording request API usage.
701
+ * Internal cache implementations use this to bypass persistent reads and writes,
702
+ * matching Next.js's request-level `workStore.isDraftMode` guard.
703
+ */
704
+ function isDraftModeEnabled() {
705
+ return getActiveDraftModeState() ?? false;
631
706
  }
632
707
  function createDraftModeScopeError(expression) {
633
708
  return /* @__PURE__ */ new Error(`${expression} can only be called from a Server Component, Route Handler, or Server Action.`);
@@ -666,26 +741,38 @@ async function draftMode() {
666
741
  throwIfInsideCacheScope("draftMode().enable()");
667
742
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().enable()");
668
743
  markDynamicUsage();
744
+ const cookie = createDraftModeCookie(secret);
745
+ const serialized = serializeMutableCookie(cookie);
746
+ _getMutableCookies(activeContext)[APPLY_RESPONSE_COOKIE](cookie);
669
747
  activeContext.draftModeEnabled = true;
670
- activeContext.cookies.set(DRAFT_MODE_COOKIE, secret);
671
- state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=${secret}; ${draftModeCookieAttributes()}`;
748
+ state.draftModeCookieHeader = serialized;
672
749
  },
673
750
  disable() {
674
751
  throwIfInsideCacheScope("draftMode().disable()");
675
752
  const activeContext = requireActiveDraftModeContext(state, context, "draftMode().disable()");
676
753
  markDynamicUsage();
754
+ const cookie = createDraftModeCookie("", /* @__PURE__ */ new Date(0));
755
+ const serialized = serializeMutableCookie(cookie);
756
+ _getMutableCookies(activeContext)[APPLY_RESPONSE_COOKIE](cookie);
677
757
  activeContext.draftModeEnabled = false;
678
- activeContext.cookies.delete(DRAFT_MODE_COOKIE);
679
- state.draftModeCookieHeader = `${DRAFT_MODE_COOKIE}=; ${draftModeCookieAttributes()}; Expires=${DRAFT_MODE_EXPIRED_DATE}`;
758
+ state.draftModeCookieHeader = serialized;
680
759
  }
681
760
  };
682
761
  }
762
+ const APPLY_RESPONSE_COOKIE = Symbol("vinext.apply-response-cookie");
763
+ const SYNCHRONIZE_REQUEST_COOKIES = Symbol("vinext.synchronize-request-cookies");
683
764
  var RequestCookies = class {
684
765
  _cookies;
685
- constructor(cookies) {
766
+ _responseCookies;
767
+ constructor(cookies, mutable = false) {
686
768
  this._cookies = cookies;
769
+ this._responseCookies = mutable ? new Map(Array.from(cookies, ([name, value]) => [name, normalizeMutableCookie({
770
+ name,
771
+ value
772
+ })])) : null;
687
773
  }
688
774
  get(name) {
775
+ if (this._responseCookies) return this._responseCookies.get(name);
689
776
  const value = this._cookies.get(name);
690
777
  if (value === void 0) return void 0;
691
778
  return {
@@ -695,6 +782,10 @@ var RequestCookies = class {
695
782
  }
696
783
  getAll(nameOrOptions) {
697
784
  const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions?.name;
785
+ if (this._responseCookies) {
786
+ const responseCookies = [...this._responseCookies.values()];
787
+ return name === void 0 ? responseCookies : responseCookies.filter((cookie) => cookie.name === name);
788
+ }
698
789
  const result = [];
699
790
  for (const [cookieName, value] of this._cookies) if (name === void 0 || cookieName === name) result.push({
700
791
  name: cookieName,
@@ -703,12 +794,8 @@ var RequestCookies = class {
703
794
  return result;
704
795
  }
705
796
  has(name) {
706
- return this._cookies.has(name);
797
+ return this._responseCookies?.has(name) ?? this._cookies.has(name);
707
798
  }
708
- /**
709
- * Set a cookie. In Route Handlers and Server Actions, this produces
710
- * a Set-Cookie header on the response.
711
- */
712
799
  set(nameOrOptions, value, options) {
713
800
  let cookieName;
714
801
  let cookieValue;
@@ -723,59 +810,81 @@ var RequestCookies = class {
723
810
  opts = nameOrOptions;
724
811
  }
725
812
  validateCookieName(cookieName);
726
- this._cookies.set(cookieName, cookieValue);
727
- _getState().pendingSetCookies.push(serializeSetCookie(cookieName, cookieValue, opts));
813
+ const responseCookie = normalizeMutableCookie({
814
+ name: cookieName,
815
+ value: cookieValue,
816
+ ...opts
817
+ });
818
+ const serialized = serializeMutableCookie(responseCookie);
819
+ this[APPLY_RESPONSE_COOKIE](responseCookie);
820
+ _getState().pendingSetCookies.push(serialized);
728
821
  return this;
729
822
  }
730
- /**
731
- * Delete a cookie by emitting an expired Set-Cookie header.
732
- */
733
823
  delete(nameOrOptions) {
734
824
  const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions.name;
735
- const path = typeof nameOrOptions === "string" ? "/" : nameOrOptions.path ?? "/";
736
- const domain = typeof nameOrOptions === "string" ? void 0 : nameOrOptions.domain;
737
825
  validateCookieName(name);
738
- validateCookieAttributeValue(path, "Path");
739
- if (domain) validateCookieAttributeValue(domain, "Domain");
740
- this._cookies.delete(name);
741
- const parts = [`${name}=`, `Path=${path}`];
742
- if (domain) parts.push(`Domain=${domain}`);
743
- parts.push(`Expires=${EXPIRED_COOKIE_DATE}`);
744
- _getState().pendingSetCookies.push(parts.join("; "));
826
+ const responseCookie = normalizeMutableCookie({
827
+ ...typeof nameOrOptions === "string" ? void 0 : nameOrOptions,
828
+ name,
829
+ value: "",
830
+ expires: /* @__PURE__ */ new Date(0)
831
+ });
832
+ const serialized = serializeMutableCookie(responseCookie);
833
+ this[APPLY_RESPONSE_COOKIE](responseCookie);
834
+ _getState().pendingSetCookies.push(serialized);
745
835
  return this;
746
836
  }
747
837
  get size() {
748
- return this._cookies.size;
838
+ return this._responseCookies?.size ?? this._cookies.size;
749
839
  }
750
840
  [Symbol.iterator]() {
751
- const entries = this._cookies.entries();
752
- const iter = {
753
- [Symbol.iterator]() {
754
- return iter;
755
- },
756
- next() {
757
- const { value, done } = entries.next();
758
- if (done) return {
759
- value: void 0,
760
- done: true
761
- };
762
- const [name, val] = value;
763
- return {
764
- value: [name, {
765
- name,
766
- value: val
767
- }],
768
- done: false
769
- };
770
- }
771
- };
772
- return iter;
841
+ return new Map(this.getAll().map((cookie) => [cookie.name, cookie])).entries();
773
842
  }
774
843
  toString() {
844
+ if (this._responseCookies) return [...this._responseCookies.values()].map(serializeMutableCookie).join("; ");
775
845
  const parts = [];
776
- for (const [name, value] of this._cookies) parts.push(`${name}=${value}`);
846
+ for (const [name, value] of this._cookies) parts.push(`${name}=${encodeURIComponent(value)}`);
777
847
  return parts.join("; ");
778
848
  }
849
+ _ensureResponseCookies() {
850
+ if (!this._responseCookies) this._responseCookies = new Map(Array.from(this._cookies, ([name, value]) => [name, normalizeMutableCookie({
851
+ name,
852
+ value
853
+ })]));
854
+ return this._responseCookies;
855
+ }
856
+ [APPLY_RESPONSE_COOKIE](cookie) {
857
+ this._ensureResponseCookies().set(cookie.name, cookie);
858
+ }
859
+ [SYNCHRONIZE_REQUEST_COOKIES]() {
860
+ this._cookies.clear();
861
+ for (const cookie of this._ensureResponseCookies().values()) this._cookies.set(cookie.name, cookie.value);
862
+ }
779
863
  };
864
+ function createDraftModeCookie(value, expires) {
865
+ const isDevelopment = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
866
+ return normalizeMutableCookie({
867
+ name: DRAFT_MODE_COOKIE,
868
+ value,
869
+ ...expires === void 0 ? {} : { expires },
870
+ httpOnly: true,
871
+ sameSite: isDevelopment ? "lax" : "none",
872
+ secure: !isDevelopment,
873
+ path: "/"
874
+ });
875
+ }
876
+ function normalizeMutableCookie(cookie) {
877
+ const normalized = { ...cookie };
878
+ if (typeof normalized.expires === "number") normalized.expires = new Date(normalized.expires);
879
+ if (normalized.maxAge) normalized.expires = new Date(Date.now() + normalized.maxAge * 1e3);
880
+ if (normalized.path == null) normalized.path = "/";
881
+ return normalized;
882
+ }
883
+ function serializeMutableCookie(cookie) {
884
+ return serializeSetCookie(cookie.name, cookie.value, {
885
+ ...cookie,
886
+ expires: typeof cookie.expires === "number" ? new Date(cookie.expires) : cookie.expires
887
+ });
888
+ }
780
889
  //#endregion
781
- export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
890
+ export { applyMiddlewareRequestHeaders, consumeDynamicUsage, consumeInvalidDynamicUsageError, consumeRenderRequestApiUsage, cookies, draftMode, getActiveDraftModeState, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersAccessPhase, getHeadersContext, headers, headersContextFromRequest, isDraftModeEnabled, isDraftModeRequest, markDynamicUsage, markRenderRequestApiUsage, peekDynamicUsage, peekRenderRequestApiUsage, runWithConnectionProbe, runWithHeadersContext, runWithIsolatedDynamicUsage, setHeadersAccessPhase, setHeadersContext, suspendConnectionProbe, throwIfInsideCacheScope, throwIfStaticGenerationAccessError };
@@ -1,40 +1,9 @@
1
1
  import React from "react";
2
+ import { ImageLoader, ImageProps as ImageProps$1, ImgProps, StaticImageData, StaticImport, StaticRequire } from "@vinext/types/next/upstream/dist/shared/lib/get-img-props";
2
3
 
3
4
  //#region src/shims/image.d.ts
4
- type StaticImageData = {
5
- src: string;
6
- height: number;
7
- width: number;
8
- blurDataURL?: string;
9
- };
10
- type ImageProps = {
11
- src: string | StaticImageData;
12
- alt: string;
13
- width?: number;
14
- height?: number;
15
- fill?: boolean;
16
- preload?: boolean;
17
- priority?: boolean;
18
- quality?: number;
19
- placeholder?: "blur" | "empty";
20
- blurDataURL?: string;
21
- loader?: (params: {
22
- src: string;
23
- width: number;
24
- quality?: number;
25
- }) => string;
26
- sizes?: string;
27
- className?: string;
28
- style?: React.CSSProperties;
29
- onLoad?: React.ReactEventHandler<HTMLImageElement>; /** @deprecated Use onLoad instead. Still supported for migration compat. */
30
- onLoadingComplete?: (img: HTMLImageElement) => void;
31
- onError?: React.ReactEventHandler<HTMLImageElement>;
32
- onClick?: React.MouseEventHandler<HTMLImageElement>;
33
- id?: string;
34
- unoptimized?: boolean;
35
- overrideSrc?: string;
36
- loading?: "lazy" | "eager";
37
- };
5
+ type ImageLoaderProps = Parameters<ImageLoader>[0];
6
+ type ImageProps = ImageProps$1;
38
7
  /**
39
8
  * Build a `/_next/image` optimization URL.
40
9
  *
@@ -43,13 +12,34 @@ type ImageProps = {
43
12
  * server handles it as a passthrough (serves the original file).
44
13
  */
45
14
  declare function imageOptimizationUrl(src: string, width: number, quality?: number): string;
46
- declare const Image: React.ForwardRefExoticComponent<ImageProps & React.RefAttributes<HTMLImageElement>>;
15
+ declare const Image: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "alt" | "height" | "loading" | "ref" | "src" | "srcSet" | "width"> & {
16
+ src: string | StaticImport;
17
+ alt: string;
18
+ width?: number | `${number}`;
19
+ height?: number | `${number}`;
20
+ fill?: boolean;
21
+ loader?: ImageLoader;
22
+ quality?: number | `${number}`;
23
+ preload?: boolean;
24
+ priority?: boolean;
25
+ loading?: "eager" | "lazy" | undefined;
26
+ placeholder?: import("@vinext/types/next/upstream/dist/shared/lib/get-img-props").PlaceholderValue;
27
+ blurDataURL?: string;
28
+ unoptimized?: boolean;
29
+ overrideSrc?: string;
30
+ onLoadingComplete?: import("@vinext/types/next/upstream/dist/shared/lib/get-img-props").OnLoadingComplete;
31
+ layout?: string;
32
+ objectFit?: string;
33
+ objectPosition?: string;
34
+ lazyBoundary?: string;
35
+ lazyRoot?: string;
36
+ } & React.RefAttributes<HTMLImageElement>>;
47
37
  /**
48
38
  * getImageProps — for advanced use cases (picture elements, background images).
49
39
  * Returns the props that would be passed to the underlying <img> element.
50
40
  */
51
41
  declare function getImageProps(props: ImageProps): {
52
- props: React.ImgHTMLAttributes<HTMLImageElement>;
42
+ props: ImgProps;
53
43
  };
54
44
  //#endregion
55
- export { StaticImageData, Image as default, getImageProps, imageOptimizationUrl };
45
+ export { type ImageLoader, ImageLoaderProps, ImageProps, type StaticImageData, type StaticRequire, Image as default, getImageProps, imageOptimizationUrl };
@@ -216,11 +216,15 @@ function getFillStyle(style, backgroundStyle) {
216
216
  * Shared by the Image component and getImageProps to keep behavior in sync.
217
217
  */
218
218
  function resolveImageSource(v) {
219
+ const staticData = typeof v.src === "object" && "default" in v.src ? v.src.default : v.src;
220
+ const src = typeof staticData === "string" ? staticData : staticData.src;
221
+ const sourceWidth = v.width ?? (typeof staticData === "object" ? staticData.width : void 0);
222
+ const sourceHeight = v.height ?? (typeof staticData === "object" ? staticData.height : void 0);
219
223
  return {
220
- src: typeof v.src === "string" ? v.src : v.src.src,
221
- width: v.width ?? (typeof v.src === "object" ? v.src.width : void 0),
222
- height: v.height ?? (typeof v.src === "object" ? v.src.height : void 0),
223
- blurDataURL: v.blurDataURL ?? (typeof v.src === "object" ? v.src.blurDataURL : void 0)
224
+ src,
225
+ width: typeof sourceWidth === "string" ? Number(sourceWidth) : sourceWidth,
226
+ height: typeof sourceHeight === "string" ? Number(sourceHeight) : sourceHeight,
227
+ blurDataURL: v.blurDataURL ?? (typeof staticData === "object" ? staticData.blurDataURL : void 0)
224
228
  };
225
229
  }
226
230
  /**
@@ -420,10 +424,11 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
420
424
  });
421
425
  }
422
426
  if (loader) {
427
+ const resolvedQuality = typeof quality === "string" ? Number(quality) : quality ?? 75;
423
428
  const resolvedSrc = loader({
424
429
  src,
425
430
  width: imgWidth ?? 0,
426
- quality: quality ?? 75
431
+ quality: resolvedQuality
427
432
  });
428
433
  preloadImageResource({
429
434
  shouldPreload,
@@ -513,7 +518,7 @@ const Image = forwardRef(function Image({ src: srcProp, alt, width, height, fill
513
518
  });
514
519
  }
515
520
  }
516
- const imgQuality = quality ?? 75;
521
+ const imgQuality = typeof quality === "string" ? Number(quality) : quality ?? 75;
517
522
  const skipOptimization = isSvgUrl(src) && !__dangerouslyAllowSVG;
518
523
  const optimizedAttributes = imgWidth && !fill && !skipOptimization ? generateImageAttributes(src, imgWidth, imgQuality, sizes) : void 0;
519
524
  const srcSet = optimizedAttributes ? optimizedAttributes.srcSet : imgWidth && !fill ? RESPONSIVE_WIDTHS.filter((w) => w <= imgWidth * 2).map((w) => `${src} ${w}w`).join(", ") || `${src} ${imgWidth}w` : void 0;
@@ -577,7 +582,7 @@ function getImageProps(props) {
577
582
  backgroundRepeat: "no-repeat",
578
583
  backgroundPosition: "center"
579
584
  } : void 0;
580
- return { props: {
585
+ const imageProps = {
581
586
  src: renderedSrc,
582
587
  alt,
583
588
  width: fill ? void 0 : imgWidth,
@@ -586,13 +591,15 @@ function getImageProps(props) {
586
591
  fetchPriority: priority ? "high" : void 0,
587
592
  decoding: "async",
588
593
  className,
589
- "data-nimg": fill ? "fill" : "1",
590
594
  style: fill ? getFillStyle(style, blurStyle) : {
591
595
  ...blurStyle,
592
596
  ...style
593
597
  },
594
- ...rest
595
- } };
598
+ ...rest,
599
+ sizes: sizes ?? (fill ? "100vw" : void 0),
600
+ srcSet: void 0
601
+ };
602
+ return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
596
603
  }
597
604
  let blockedInProd = false;
598
605
  if (isRemoteUrl(src)) {
@@ -603,7 +610,7 @@ function getImageProps(props) {
603
610
  blockedInProd = true;
604
611
  }
605
612
  }
606
- const imgQuality = _quality ?? 75;
613
+ const imgQuality = typeof _quality === "string" ? Number(_quality) : _quality ?? 75;
607
614
  const resolvedSrc = blockedInProd ? "" : loader ? loader({
608
615
  src,
609
616
  width: imgWidth ?? 0,
@@ -620,7 +627,7 @@ function getImageProps(props) {
620
627
  backgroundRepeat: "no-repeat",
621
628
  backgroundPosition: "center"
622
629
  } : void 0;
623
- return { props: {
630
+ const imageProps = {
624
631
  src: optimizedSrc,
625
632
  alt,
626
633
  width: fill ? void 0 : imgWidth,
@@ -631,13 +638,13 @@ function getImageProps(props) {
631
638
  srcSet,
632
639
  sizes: sizes ?? (fill ? "100vw" : void 0),
633
640
  className,
634
- "data-nimg": fill ? "fill" : "1",
635
641
  style: fill ? getFillStyle(style, blurStyle) : {
636
642
  ...blurStyle,
637
643
  ...style
638
644
  },
639
645
  ...rest
640
- } };
646
+ };
647
+ return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
641
648
  }
642
649
  //#endregion
643
650
  export { Image as default, getImageProps, imageOptimizationUrl };
@@ -1,11 +1,11 @@
1
1
  //#region src/shims/internal/cookie-serialize.d.ts
2
2
  /**
3
- * Shared Set-Cookie serialization for the next/headers and next/server shims.
3
+ * Set-Cookie serialization for the mutable next/headers shim.
4
4
  *
5
- * Two call sites — `cookies().set()` in headers.ts and `ResponseCookies.set()`
6
- * in server.ts produce identical Set-Cookie header strings. Keep the
7
- * encoding, attribute order, and validation in one place so subtle RFC 6265
8
- * details (escaping, attribute ordering, etc.) cannot drift between them.
5
+ * `ResponseCookies` in server.ts deliberately uses the exact
6
+ * @edge-runtime/cookies serialization order and casing instead. It also has to
7
+ * preserve the absence of a default path when parsing an existing Set-Cookie
8
+ * header, while this helper always defaults new mutable cookies to `Path=/`.
9
9
  *
10
10
  * Note: this is a value-encoding helper for response cookies only. The
11
11
  * request `Cookie:` header serialization in `RequestCookies._serialize`
@@ -20,7 +20,9 @@ type SerializeSetCookieOptions = {
20
20
  expires?: Date;
21
21
  httpOnly?: boolean;
22
22
  secure?: boolean;
23
- sameSite?: "Strict" | "Lax" | "None";
23
+ sameSite?: true | false | "strict" | "lax" | "none" | "Strict" | "Lax" | "None";
24
+ partitioned?: boolean;
25
+ priority?: "low" | "medium" | "high";
24
26
  };
25
27
  declare function validateCookieName(name: string): void;
26
28
  /**
@@ -34,12 +36,13 @@ declare function validateCookieAttributeValue(value: string, attributeName: stri
34
36
  * - Encodes the value with `encodeURIComponent`.
35
37
  * - Defaults `Path` to `/` (matching @edge-runtime/cookies and Next.js).
36
38
  * - Validates path/domain to reject control characters and semicolons.
37
- * - Emits attributes in the order: Path, Domain, Max-Age, Expires, HttpOnly,
38
- * Secure, SameSite.
39
+ * - Emits attributes in the same order and casing as Next.js's compiled
40
+ * `@edge-runtime/cookies` serializer: Path, Expires, Max-Age, Domain,
41
+ * Secure, HttpOnly, SameSite, Partitioned, Priority.
39
42
  *
40
43
  * The caller is responsible for validating the cookie name (typically before
41
44
  * mutating any internal state) via `validateCookieName`.
42
45
  */
43
- declare function serializeSetCookie(name: string, value: string, options?: SerializeSetCookieOptions): string;
46
+ declare function serializeSetCookie(name: string, value: string | null | undefined, options?: SerializeSetCookieOptions): string;
44
47
  //#endregion
45
48
  export { serializeSetCookie, validateCookieAttributeValue, validateCookieName };