vinext 1.2.0 → 1.3.0

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 (283) hide show
  1. package/README.md +13 -10
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/output-root-externals.d.ts +21 -0
  13. package/dist/build/output-root-externals.js +40 -0
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/prerender-paths.js +6 -3
  16. package/dist/build/prerender.js +1 -1
  17. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  18. package/dist/build/server-actions-encryption-key.js +101 -0
  19. package/dist/build/ssr-manifest.d.ts +3 -0
  20. package/dist/build/ssr-manifest.js +10 -1
  21. package/dist/check.js +5 -6
  22. package/dist/cli-dev-config.js +3 -3
  23. package/dist/cli.js +1 -1
  24. package/dist/client/client-rewrite-params.d.ts +9 -0
  25. package/dist/client/client-rewrite-params.js +20 -0
  26. package/dist/client/dev-error-overlay.js +2 -1
  27. package/dist/client/navigation-runtime.d.ts +25 -2
  28. package/dist/client/navigation-runtime.js +42 -11
  29. package/dist/client/vinext-next-data.d.ts +0 -1
  30. package/dist/config/config-matchers.d.ts +15 -40
  31. package/dist/config/config-matchers.js +195 -262
  32. package/dist/config/config-source.d.ts +34 -0
  33. package/dist/config/config-source.js +141 -0
  34. package/dist/config/header-params.d.ts +29 -0
  35. package/dist/config/header-params.js +106 -0
  36. package/dist/config/next-config.d.ts +7 -5
  37. package/dist/config/next-config.js +120 -7
  38. package/dist/entries/app-browser-entry.d.ts +14 -1
  39. package/dist/entries/app-browser-entry.js +26 -36
  40. package/dist/entries/app-rsc-entry.d.ts +2 -0
  41. package/dist/entries/app-rsc-entry.js +92 -57
  42. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  43. package/dist/entries/app-rsc-manifest.js +20 -1
  44. package/dist/entries/app-ssr-entry.d.ts +4 -1
  45. package/dist/entries/app-ssr-entry.js +9 -2
  46. package/dist/entries/pages-client-entry.d.ts +1 -0
  47. package/dist/entries/pages-client-entry.js +6 -6
  48. package/dist/entries/pages-server-entry.js +17 -14
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.js +350 -175
  51. package/dist/init.d.ts +1 -1
  52. package/dist/init.js +103 -6
  53. package/dist/plugins/ast-utils.d.ts +53 -2
  54. package/dist/plugins/ast-utils.js +90 -2
  55. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  56. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  57. package/dist/plugins/commonjs-esm-facade.js +2 -2
  58. package/dist/plugins/css-module-imports.js +13 -20
  59. package/dist/plugins/dynamic-preload-metadata.js +2 -3
  60. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  61. package/dist/plugins/fonts.d.ts +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +2 -3
  64. package/dist/plugins/import-meta-url.js +3 -4
  65. package/dist/plugins/instrumentation-client.js +3 -2
  66. package/dist/plugins/middleware-export-validation.js +2 -3
  67. package/dist/plugins/og-harfbuzz.js +2 -3
  68. package/dist/plugins/optimize-imports.d.ts +25 -2
  69. package/dist/plugins/optimize-imports.js +109 -24
  70. package/dist/plugins/pages-node-externals.js +2 -3
  71. package/dist/plugins/remove-console.js +2 -18
  72. package/dist/plugins/require-condition-resolution.js +3 -3
  73. package/dist/plugins/require-context.js +2 -3
  74. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  75. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  76. package/dist/plugins/strip-server-exports.js +3 -4
  77. package/dist/plugins/styled-jsx.js +2 -3
  78. package/dist/plugins/use-cache-callable.d.ts +26 -2
  79. package/dist/plugins/use-cache-callable.js +101 -36
  80. package/dist/plugins/worker-image-imports.d.ts +1 -0
  81. package/dist/plugins/worker-image-imports.js +31 -34
  82. package/dist/plugins/worker-use-server.js +38 -14
  83. package/dist/routing/app-route-graph.d.ts +1 -1
  84. package/dist/routing/browser-route-manifest.d.ts +43 -0
  85. package/dist/routing/browser-route-manifest.js +195 -0
  86. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  87. package/dist/routing/hashed-route-patterns.js +22 -0
  88. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  89. package/dist/routing/optimistic-route-trie.js +102 -0
  90. package/dist/routing/route-validation.d.ts +6 -1
  91. package/dist/routing/route-validation.js +26 -10
  92. package/dist/server/api-handler.js +1 -1
  93. package/dist/server/app-action-forwarding.d.ts +8 -0
  94. package/dist/server/app-action-forwarding.js +17 -3
  95. package/dist/server/app-browser-entry.js +149 -62
  96. package/dist/server/app-browser-error.d.ts +3 -1
  97. package/dist/server/app-browser-error.js +7 -2
  98. package/dist/server/app-browser-interception-context.d.ts +2 -2
  99. package/dist/server/app-browser-interception-context.js +1 -1
  100. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  101. package/dist/server/app-browser-mpa-navigation.js +6 -5
  102. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  103. package/dist/server/app-browser-navigation-controller.js +88 -26
  104. package/dist/server/app-browser-prefetch-response.js +2 -2
  105. package/dist/server/app-browser-state.d.ts +2 -2
  106. package/dist/server/app-browser-state.js +1 -1
  107. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  108. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  109. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  110. package/dist/server/app-client-reference-preloader.js +30 -7
  111. package/dist/server/app-fallback-renderer.js +2 -1
  112. package/dist/server/app-middleware.d.ts +6 -0
  113. package/dist/server/app-middleware.js +8 -10
  114. package/dist/server/app-optimistic-routing.d.ts +8 -10
  115. package/dist/server/app-optimistic-routing.js +4 -95
  116. package/dist/server/app-page-boundary-render.js +8 -1
  117. package/dist/server/app-page-cache-render.js +1 -0
  118. package/dist/server/app-page-dispatch.js +3 -1
  119. package/dist/server/app-page-render.js +4 -2
  120. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  121. package/dist/server/app-page-rsc-render-status.js +1 -0
  122. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  123. package/dist/server/app-page-search-params-observation.js +8 -10
  124. package/dist/server/app-page-stream.d.ts +7 -0
  125. package/dist/server/app-page-stream.js +1 -0
  126. package/dist/server/app-pages-bridge.d.ts +2 -1
  127. package/dist/server/app-pages-bridge.js +12 -8
  128. package/dist/server/app-prerender-endpoints.js +1 -1
  129. package/dist/server/app-prerender-static-params.js +3 -2
  130. package/dist/server/app-render-abort-error.d.ts +19 -0
  131. package/dist/server/app-render-abort-error.js +31 -1
  132. package/dist/server/app-render-dependency.js +42 -2
  133. package/dist/server/app-request-stage-independent-entry.js +7 -7
  134. package/dist/server/app-response-stage-entry.js +5 -5
  135. package/dist/server/app-route-handler-dispatch.js +3 -1
  136. package/dist/server/app-route-handler-execution.d.ts +2 -0
  137. package/dist/server/app-route-handler-execution.js +9 -2
  138. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  139. package/dist/server/app-route-handler-middleware-context.js +3 -3
  140. package/dist/server/app-route-handler-response.d.ts +2 -1
  141. package/dist/server/app-route-handler-response.js +2 -2
  142. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  143. package/dist/server/app-route-handler-runtime.js +21 -4
  144. package/dist/server/app-route-module-loader.js +7 -6
  145. package/dist/server/app-route-tree.d.ts +20 -0
  146. package/dist/server/app-route-tree.js +18 -0
  147. package/dist/server/app-router-entry.js +7 -7
  148. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  149. package/dist/server/app-rsc-cache-busting.js +29 -12
  150. package/dist/server/app-rsc-combined-handler.js +8 -1
  151. package/dist/server/app-rsc-errors.d.ts +7 -0
  152. package/dist/server/app-rsc-errors.js +9 -2
  153. package/dist/server/app-rsc-handler.d.ts +4 -1
  154. package/dist/server/app-rsc-handler.js +151 -135
  155. package/dist/server/app-rsc-request-normalization.js +3 -3
  156. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  157. package/dist/server/app-rsc-response-finalizer.js +4 -1
  158. package/dist/server/app-rsc-response-stage.js +5 -3
  159. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  160. package/dist/server/app-rsc-route-matching.js +1 -1
  161. package/dist/server/app-server-action-execution.d.ts +23 -6
  162. package/dist/server/app-server-action-execution.js +51 -57
  163. package/dist/server/app-ssr-entry.d.ts +6 -0
  164. package/dist/server/app-ssr-entry.js +21 -11
  165. package/dist/server/app-ssr-stream.d.ts +7 -0
  166. package/dist/server/app-ssr-stream.js +13 -1
  167. package/dist/server/app-visited-response-cache.js +2 -2
  168. package/dist/server/config-headers.js +13 -4
  169. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  170. package/dist/server/defer-until-stream-consumed.js +3 -1
  171. package/dist/server/dev-server.js +1 -1
  172. package/dist/server/image-optimization.js +1 -0
  173. package/dist/server/isolate-shared-promise.d.ts +10 -0
  174. package/dist/server/isolate-shared-promise.js +33 -0
  175. package/dist/server/isr-cache.js +3 -2
  176. package/dist/server/metadata-route-response.js +2 -2
  177. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  178. package/dist/server/middleware-matcher-pattern.js +11 -140
  179. package/dist/server/middleware-matcher.js +5 -6
  180. package/dist/server/middleware-response-headers.d.ts +31 -0
  181. package/dist/server/middleware-response-headers.js +57 -1
  182. package/dist/server/middleware-runtime.js +30 -17
  183. package/dist/server/navigation-planner.d.ts +2 -2
  184. package/dist/server/navigation-planner.js +1 -1
  185. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  186. package/dist/server/nitro-public-files-plugin.js +106 -0
  187. package/dist/server/nitro-public-files.d.ts +21 -0
  188. package/dist/server/nitro-public-files.js +39 -0
  189. package/dist/server/open-redirect.d.ts +11 -4
  190. package/dist/server/open-redirect.js +11 -4
  191. package/dist/server/pages-api-route.js +2 -2
  192. package/dist/server/pages-asset-tags.d.ts +5 -0
  193. package/dist/server/pages-asset-tags.js +9 -2
  194. package/dist/server/pages-client-assets.d.ts +4 -1
  195. package/dist/server/pages-data-route.js +2 -1
  196. package/dist/server/pages-i18n.d.ts +18 -0
  197. package/dist/server/pages-i18n.js +18 -2
  198. package/dist/server/pages-node-compat.d.ts +5 -3
  199. package/dist/server/pages-node-compat.js +35 -16
  200. package/dist/server/pages-page-data.js +1 -1
  201. package/dist/server/pages-page-handler.js +1 -1
  202. package/dist/server/pages-page-response.js +1 -1
  203. package/dist/server/pages-request-pipeline.d.ts +6 -1
  204. package/dist/server/pages-request-pipeline.js +35 -39
  205. package/dist/server/pages-request-stage-entry.js +20 -10
  206. package/dist/server/pages-response-stage-entry.js +1 -1
  207. package/dist/server/pages-revalidate.js +3 -2
  208. package/dist/server/pages-router-entry.js +2 -2
  209. package/dist/server/prod-server.d.ts +2 -2
  210. package/dist/server/prod-server.js +74 -36
  211. package/dist/server/proxy-trust.d.ts +6 -0
  212. package/dist/server/proxy-trust.js +12 -6
  213. package/dist/server/request-pipeline.d.ts +5 -0
  214. package/dist/server/request-pipeline.js +12 -1
  215. package/dist/server/rsc-stream-hints.d.ts +1 -1
  216. package/dist/server/rsc-stream-hints.js +21 -3
  217. package/dist/server/server-reference-loader.js +10 -1
  218. package/dist/server/static-file-cache.js +15 -3
  219. package/dist/server/worker-image-optimization.js +19 -6
  220. package/dist/server/worker-utils.js +1 -1
  221. package/dist/shims/cache-handler.js +3 -2
  222. package/dist/shims/cache-request-state.d.ts +40 -3
  223. package/dist/shims/cache-request-state.js +70 -5
  224. package/dist/shims/cache-runtime.js +47 -19
  225. package/dist/shims/cache.d.ts +2 -2
  226. package/dist/shims/cache.js +17 -8
  227. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  228. package/dist/shims/cdn-purge-routes.js +77 -0
  229. package/dist/shims/dynamic.js +17 -4
  230. package/dist/shims/form.js +8 -3
  231. package/dist/shims/head.js +1 -1
  232. package/dist/shims/headers.js +2 -2
  233. package/dist/shims/image-props.d.ts +93 -0
  234. package/dist/shims/image-props.js +323 -0
  235. package/dist/shims/image.d.ts +4 -18
  236. package/dist/shims/image.js +4 -319
  237. package/dist/shims/internal/headers-state.d.ts +7 -0
  238. package/dist/shims/internal/headers-state.js +14 -2
  239. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  240. package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
  241. package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
  242. package/dist/shims/link-prefetch.js +5 -4
  243. package/dist/shims/link.js +7 -5
  244. package/dist/shims/navigation.d.ts +1 -1
  245. package/dist/shims/navigation.js +21 -10
  246. package/dist/shims/og.js +35 -10
  247. package/dist/shims/request-context.d.ts +13 -0
  248. package/dist/shims/router.js +28 -52
  249. package/dist/shims/server.d.ts +42 -8
  250. package/dist/shims/server.js +99 -15
  251. package/dist/shims/thenable-params.d.ts +6 -1
  252. package/dist/shims/thenable-params.js +11 -2
  253. package/dist/shims/unified-request-context.d.ts +5 -0
  254. package/dist/shims/unified-request-context.js +2 -0
  255. package/dist/shims/url-utils.d.ts +7 -0
  256. package/dist/shims/url-utils.js +12 -3
  257. package/dist/utils/asset-prefix.d.ts +7 -0
  258. package/dist/utils/asset-prefix.js +10 -1
  259. package/dist/utils/client-build-manifest.js +12 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  261. package/dist/utils/client-runtime-metadata.js +15 -2
  262. package/dist/utils/domain-locale.js +1 -1
  263. package/dist/utils/lazy-chunks.d.ts +4 -0
  264. package/dist/utils/manifest-paths.d.ts +14 -0
  265. package/dist/utils/manifest-paths.js +22 -1
  266. package/dist/utils/path-to-regexp.d.ts +21 -0
  267. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  268. package/dist/utils/plugin-react-version.d.ts +15 -0
  269. package/dist/utils/plugin-react-version.js +64 -0
  270. package/dist/utils/plugin-rsc-version.d.ts +2 -0
  271. package/dist/utils/plugin-rsc-version.js +28 -2
  272. package/dist/utils/public-routes.d.ts +2 -0
  273. package/dist/utils/public-routes.js +18 -7
  274. package/dist/utils/react-version.d.ts +7 -0
  275. package/dist/utils/react-version.js +39 -16
  276. package/package.json +6 -6
  277. package/dist/build/nitro-route-rules.d.ts +0 -47
  278. package/dist/build/nitro-route-rules.js +0 -79
  279. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  280. package/dist/plugins/cache-flight-codec.js +0 -68
  281. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  282. package/dist/utils/regex-safety.d.ts +0 -17
  283. package/dist/utils/regex-safety.js +0 -789
@@ -8,7 +8,7 @@ import { withBasePath } from "./url-utils.js";
8
8
  import { AppElementsWire } from "../server/app-elements-wire.js";
9
9
  import "../server/app-elements.js";
10
10
  import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
11
- import { hasAppNavigationRuntime } from "../client/navigation-runtime.js";
11
+ import { hasAppNavigationRuntime, loadNavigationRuntimeRouteManifest } from "../client/navigation-runtime.js";
12
12
  import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
13
13
  import { useMergedRef } from "./use-merged-ref.js";
14
14
  import { forwardRef, useActionState, useCallback, useEffect, useRef } from "react";
@@ -145,14 +145,19 @@ const Form = forwardRef(function Form(props, ref) {
145
145
  for (const entry of entries) if (entry.isIntersecting || entry.intersectionRatio > 0) {
146
146
  (async () => {
147
147
  if (isBotUserAgent(window.navigator?.userAgent ?? "")) return;
148
- const interceptionContext = getPrefetchInterceptionContext(actionHref);
148
+ const currentPathname = window.location.pathname;
149
+ const resolvedAction = new URL(actionHref, window.location.href);
150
+ const prefetchHref = resolvedAction.pathname + resolvedAction.search;
149
151
  const mountedSlotsHeader = getMountedSlotsHeader();
152
+ const routeManifestLoad = loadNavigationRuntimeRouteManifest();
153
+ if (routeManifestLoad !== null && !await routeManifestLoad) return;
154
+ const interceptionContext = getPrefetchInterceptionContext(prefetchHref, currentPathname);
150
155
  const headers = createRscRequestHeaders({
151
156
  interceptionContext,
152
157
  renderMode: APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL
153
158
  });
154
159
  if (mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
155
- const rscUrl = await createRscRequestUrl(actionHref, headers);
160
+ const rscUrl = await createRscRequestUrl(prefetchHref, headers);
156
161
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
157
162
  const prefetched = getPrefetchedUrls();
158
163
  if (prefetched.has(cacheKey)) return;
@@ -183,7 +183,7 @@ function reduceHeadChildren(headChildren) {
183
183
  const SAFE_ATTR_NAME_RE = /^[a-zA-Z][a-zA-Z0-9\-:.]*$/;
184
184
  function isSafeAttrName(name) {
185
185
  if (!SAFE_ATTR_NAME_RE.test(name)) return false;
186
- if (name.length > 2 && name[0] === "o" && name[1] === "n" && name[2] >= "A" && name[2] <= "z") return false;
186
+ if (name.length > 2 && (name[0] === "o" || name[0] === "O") && (name[1] === "n" || name[1] === "N")) return false;
187
187
  return true;
188
188
  }
189
189
  /**
@@ -749,8 +749,8 @@ async function draftMode() {
749
749
  }
750
750
  };
751
751
  }
752
- const APPLY_RESPONSE_COOKIE = Symbol("vinext.apply-response-cookie");
753
- const SYNCHRONIZE_REQUEST_COOKIES = Symbol("vinext.synchronize-request-cookies");
752
+ const APPLY_RESPONSE_COOKIE = Symbol.for("vinext.apply-response-cookie");
753
+ const SYNCHRONIZE_REQUEST_COOKIES = Symbol.for("vinext.synchronize-request-cookies");
754
754
  var RequestCookies = class {
755
755
  _cookies;
756
756
  _responseCookies;
@@ -0,0 +1,93 @@
1
+ import React from "react";
2
+ import { ImageProps, ImgProps, StaticImport } from "@vinext/types/next/upstream/dist/shared/lib/get-img-props";
3
+ //#region src/shims/image-props.d.ts
4
+ export declare const __isDev: boolean;
5
+ /**
6
+ * Whether dangerouslyAllowSVG is enabled in next.config.js.
7
+ * When false (default), .svg sources auto-skip the optimization endpoint
8
+ * and are served directly, matching Next.js behavior.
9
+ * When true, .svg sources are routed through the optimizer (served as-is
10
+ * with security headers).
11
+ */
12
+ export declare const __dangerouslyAllowSVG: boolean;
13
+ export declare const __globallyUnoptimized: boolean;
14
+ /**
15
+ * Validate that a remote URL is allowed by the configured remote patterns.
16
+ * Returns true if the URL is allowed, false otherwise.
17
+ *
18
+ * When no remotePatterns/domains are configured, all remote URLs are allowed
19
+ * (backwards-compatible — user hasn't opted into restriction).
20
+ *
21
+ * When patterns ARE configured, only matching URLs are allowed.
22
+ * In development, non-matching URLs produce a console warning.
23
+ * In production, non-matching URLs are blocked (src replaced with empty string).
24
+ *
25
+ * Private-IP hostnames are additionally rejected unless dangerouslyAllowLocalIP
26
+ * is set, mirroring Next.js's fetchExternalImage guard.
27
+ */
28
+ export declare function validateRemoteUrl(src: string): {
29
+ allowed: boolean;
30
+ reason?: string;
31
+ };
32
+ /**
33
+ * Sanitize a blurDataURL to prevent CSS injection.
34
+ *
35
+ * A crafted data URL containing `)` can break out of the `url()` CSS function,
36
+ * allowing injection of arbitrary CSS properties or rules. Characters like `{`,
37
+ * `}`, and `\` can also assist in crafting injection payloads.
38
+ *
39
+ * This validates the URL starts with `data:image/` and rejects characters that
40
+ * could escape the `url()` context. Semicolons are allowed since they're part
41
+ * of valid data URLs (`data:image/png;base64,...`) and harmless inside `url()`.
42
+ *
43
+ * Returns undefined for invalid URLs, which causes the blur placeholder to be
44
+ * skipped gracefully.
45
+ */
46
+ export declare function sanitizeBlurDataURL(url: string): string | undefined;
47
+ /**
48
+ * Determine if a src is a remote URL (CDN-optimizable) or local.
49
+ */
50
+ export declare function isRemoteUrl(src: string): boolean;
51
+ export declare function isSvgUrl(src: string): boolean;
52
+ export declare function getFillStyle(style?: React.CSSProperties, backgroundStyle?: React.CSSProperties): React.CSSProperties;
53
+ /**
54
+ * Resolve src, width, height, blurDataURL from Image props (string or StaticImageData).
55
+ * Shared by the Image component and getImageProps to keep behavior in sync.
56
+ */
57
+ export declare function resolveImageSource(v: {
58
+ src: string | StaticImport;
59
+ width?: number | `${number}`;
60
+ height?: number | `${number}`;
61
+ blurDataURL?: string;
62
+ }): {
63
+ src: string;
64
+ width?: number;
65
+ height?: number;
66
+ blurDataURL?: string;
67
+ };
68
+ /**
69
+ * Responsive image widths matching Next.js's device sizes config.
70
+ * These are the breakpoints used for srcSet generation.
71
+ * Configurable via `images.deviceSizes` in next.config.js.
72
+ */
73
+ export declare const RESPONSIVE_WIDTHS: number[];
74
+ /**
75
+ * Build a `/_next/image` optimization URL.
76
+ *
77
+ * In production (Cloudflare Workers), the worker intercepts this path and uses
78
+ * the Images binding to resize/transcode on the fly. In dev, the Vite dev
79
+ * server handles it as a passthrough (serves the original file).
80
+ */
81
+ export declare function imageOptimizationUrl(src: string, width: number, quality?: number): string;
82
+ export declare function generateImageAttributes(src: string, width: number, quality?: number, sizes?: string): {
83
+ src: string;
84
+ srcSet: string;
85
+ };
86
+ /**
87
+ * getImageProps — for advanced use cases (picture elements, background images).
88
+ * Returns the props that would be passed to the underlying <img> element.
89
+ */
90
+ export declare function getImageProps(props: ImageProps): {
91
+ props: ImgProps;
92
+ };
93
+ //#endregion
@@ -0,0 +1,323 @@
1
+ import { getDeploymentId } from "../utils/deployment-id.js";
2
+ import { hasRemoteMatch, isPrivateIp } from "./image-config.js";
3
+ //#region src/shims/image-props.ts
4
+ /**
5
+ * Image config injected at build time via Vite define.
6
+ * Serialized as JSON — parsed once at module level.
7
+ */
8
+ const __imageRemotePatterns = (() => {
9
+ try {
10
+ return JSON.parse(process.env.__VINEXT_IMAGE_REMOTE_PATTERNS ?? "[]");
11
+ } catch {
12
+ return [];
13
+ }
14
+ })();
15
+ const __imageDomains = (() => {
16
+ try {
17
+ return JSON.parse(process.env.__VINEXT_IMAGE_DOMAINS ?? "[]");
18
+ } catch {
19
+ return [];
20
+ }
21
+ })();
22
+ const __hasImageConfig = __imageRemotePatterns.length > 0 || __imageDomains.length > 0;
23
+ const __isDev = process.env.NODE_ENV !== "production";
24
+ const __imageDeviceSizes = (() => {
25
+ try {
26
+ return JSON.parse(process.env.__VINEXT_IMAGE_DEVICE_SIZES ?? "[640,750,828,1080,1200,1920,2048,3840]");
27
+ } catch {
28
+ return [
29
+ 640,
30
+ 750,
31
+ 828,
32
+ 1080,
33
+ 1200,
34
+ 1920,
35
+ 2048,
36
+ 3840
37
+ ];
38
+ }
39
+ })();
40
+ const __imageSizes = (() => {
41
+ try {
42
+ return JSON.parse(process.env.__VINEXT_IMAGE_SIZES ?? "[32,48,64,96,128,256,384]");
43
+ } catch {
44
+ return [
45
+ 32,
46
+ 48,
47
+ 64,
48
+ 96,
49
+ 128,
50
+ 256,
51
+ 384
52
+ ];
53
+ }
54
+ })();
55
+ /**
56
+ * Whether dangerouslyAllowSVG is enabled in next.config.js.
57
+ * When false (default), .svg sources auto-skip the optimization endpoint
58
+ * and are served directly, matching Next.js behavior.
59
+ * When true, .svg sources are routed through the optimizer (served as-is
60
+ * with security headers).
61
+ */
62
+ const __dangerouslyAllowSVG = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_SVG === "true";
63
+ /**
64
+ * Whether dangerouslyAllowLocalIP is enabled in next.config.js.
65
+ * When false (default), remote image URLs with literal private-IP hostnames
66
+ * are blocked to mitigate SSRF risk.
67
+ */
68
+ const __dangerouslyAllowLocalIP = process.env.__VINEXT_IMAGE_DANGEROUSLY_ALLOW_LOCAL_IP === "true";
69
+ const __globallyUnoptimized = process.env.__VINEXT_IMAGE_UNOPTIMIZED === "true";
70
+ /**
71
+ * Validate that a remote URL is allowed by the configured remote patterns.
72
+ * Returns true if the URL is allowed, false otherwise.
73
+ *
74
+ * When no remotePatterns/domains are configured, all remote URLs are allowed
75
+ * (backwards-compatible — user hasn't opted into restriction).
76
+ *
77
+ * When patterns ARE configured, only matching URLs are allowed.
78
+ * In development, non-matching URLs produce a console warning.
79
+ * In production, non-matching URLs are blocked (src replaced with empty string).
80
+ *
81
+ * Private-IP hostnames are additionally rejected unless dangerouslyAllowLocalIP
82
+ * is set, mirroring Next.js's fetchExternalImage guard.
83
+ */
84
+ function validateRemoteUrl(src) {
85
+ let url;
86
+ try {
87
+ url = new URL(src, "http://n");
88
+ } catch {
89
+ return {
90
+ allowed: false,
91
+ reason: `Invalid URL: ${src}`
92
+ };
93
+ }
94
+ if (!__dangerouslyAllowLocalIP && isPrivateIp(url.hostname)) return {
95
+ allowed: false,
96
+ reason: `Image URL "${src}" resolved to private IP. If this is expected and you understand SSRF risk, use images.dangerouslyAllowLocalIP = true to continue.`
97
+ };
98
+ if (!__hasImageConfig) return { allowed: true };
99
+ if (hasRemoteMatch(__imageDomains, __imageRemotePatterns, url)) return { allowed: true };
100
+ return {
101
+ allowed: false,
102
+ reason: `Image URL "${src}" is not configured in images.remotePatterns or images.domains in next.config.js. See: https://nextjs.org/docs/messages/next-image-unconfigured-host`
103
+ };
104
+ }
105
+ /**
106
+ * Sanitize a blurDataURL to prevent CSS injection.
107
+ *
108
+ * A crafted data URL containing `)` can break out of the `url()` CSS function,
109
+ * allowing injection of arbitrary CSS properties or rules. Characters like `{`,
110
+ * `}`, and `\` can also assist in crafting injection payloads.
111
+ *
112
+ * This validates the URL starts with `data:image/` and rejects characters that
113
+ * could escape the `url()` context. Semicolons are allowed since they're part
114
+ * of valid data URLs (`data:image/png;base64,...`) and harmless inside `url()`.
115
+ *
116
+ * Returns undefined for invalid URLs, which causes the blur placeholder to be
117
+ * skipped gracefully.
118
+ */
119
+ function sanitizeBlurDataURL(url) {
120
+ if (!url.startsWith("data:image/")) return void 0;
121
+ if (/[)(}{\\'"\n\r]/.test(url)) return void 0;
122
+ return url;
123
+ }
124
+ /**
125
+ * Determine if a src is a remote URL (CDN-optimizable) or local.
126
+ */
127
+ function isRemoteUrl(src) {
128
+ return src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//");
129
+ }
130
+ function isSvgUrl(src) {
131
+ try {
132
+ return new URL(src, "http://vinext.local").pathname.toLowerCase().endsWith(".svg");
133
+ } catch {
134
+ return false;
135
+ }
136
+ }
137
+ function getFillStyle(style, backgroundStyle) {
138
+ return {
139
+ position: "absolute",
140
+ inset: 0,
141
+ width: "100%",
142
+ height: "100%",
143
+ objectFit: "cover",
144
+ ...backgroundStyle,
145
+ ...style
146
+ };
147
+ }
148
+ /**
149
+ * Resolve src, width, height, blurDataURL from Image props (string or StaticImageData).
150
+ * Shared by the Image component and getImageProps to keep behavior in sync.
151
+ */
152
+ function resolveImageSource(v) {
153
+ const staticData = typeof v.src === "object" && "default" in v.src ? v.src.default : v.src;
154
+ const src = typeof staticData === "string" ? staticData : staticData.src;
155
+ const sourceWidth = v.width ?? (typeof staticData === "object" ? staticData.width : void 0);
156
+ const sourceHeight = v.height ?? (typeof staticData === "object" ? staticData.height : void 0);
157
+ return {
158
+ src,
159
+ width: typeof sourceWidth === "string" ? Number(sourceWidth) : sourceWidth,
160
+ height: typeof sourceHeight === "string" ? Number(sourceHeight) : sourceHeight,
161
+ blurDataURL: v.blurDataURL ?? (typeof staticData === "object" ? staticData.blurDataURL : void 0)
162
+ };
163
+ }
164
+ /**
165
+ * Responsive image widths matching Next.js's device sizes config.
166
+ * These are the breakpoints used for srcSet generation.
167
+ * Configurable via `images.deviceSizes` in next.config.js.
168
+ */
169
+ const RESPONSIVE_WIDTHS = [...__imageDeviceSizes].sort((left, right) => left - right);
170
+ const ALL_IMAGE_WIDTHS = [...RESPONSIVE_WIDTHS, ...__imageSizes].sort((left, right) => left - right);
171
+ function extractLocalDeploymentId(src) {
172
+ let deploymentId = getDeploymentId();
173
+ if (!src.startsWith("/") || src.startsWith("//")) return {
174
+ src,
175
+ deploymentId
176
+ };
177
+ const queryIndex = src.indexOf("?");
178
+ if (queryIndex === -1) return {
179
+ src,
180
+ deploymentId
181
+ };
182
+ const params = new URLSearchParams(src.slice(queryIndex + 1));
183
+ const sourceDeploymentId = params.get("dpl");
184
+ if (!sourceDeploymentId) return {
185
+ src,
186
+ deploymentId
187
+ };
188
+ deploymentId = sourceDeploymentId;
189
+ params.delete("dpl");
190
+ const remainingQuery = params.toString();
191
+ return {
192
+ src: src.slice(0, queryIndex) + (remainingQuery ? `?${remainingQuery}` : ""),
193
+ deploymentId
194
+ };
195
+ }
196
+ const __imageEndpoint = `${process.env.__NEXT_ROUTER_BASEPATH ?? ""}/_next/image${process.env.__VINEXT_TRAILING_SLASH === "true" ? "/" : ""}`;
197
+ /**
198
+ * Build a `/_next/image` optimization URL.
199
+ *
200
+ * In production (Cloudflare Workers), the worker intercepts this path and uses
201
+ * the Images binding to resize/transcode on the fly. In dev, the Vite dev
202
+ * server handles it as a passthrough (serves the original file).
203
+ */
204
+ function imageOptimizationUrl(src, width, quality = 75) {
205
+ const source = extractLocalDeploymentId(src);
206
+ const deploymentQuery = source.src.startsWith("/") && source.deploymentId ? `&dpl=${source.deploymentId}` : "";
207
+ return `${__imageEndpoint}?url=${encodeURIComponent(source.src)}&w=${width}&q=${quality}${deploymentQuery}`;
208
+ }
209
+ /**
210
+ * Generate a srcSet string for responsive images.
211
+ *
212
+ * Each width points to the `/_next/image` optimization endpoint so the
213
+ * server can resize and transcode the image.
214
+ */
215
+ function getImageWidths(width) {
216
+ return [...new Set([width, width * 2].map((targetWidth) => ALL_IMAGE_WIDTHS.find((configuredWidth) => configuredWidth >= targetWidth) ?? ALL_IMAGE_WIDTHS[ALL_IMAGE_WIDTHS.length - 1]))];
217
+ }
218
+ function generateImageAttributes(src, width, quality = 75, sizes) {
219
+ if (sizes) {
220
+ const viewportPercentages = Array.from(sizes.matchAll(/(^|\s)(1?\d?\d)vw/g), (match) => Number.parseInt(match[2], 10));
221
+ const minimumWidth = viewportPercentages.length > 0 ? RESPONSIVE_WIDTHS[0] * (Math.min(...viewportPercentages) * .01) : 0;
222
+ const candidates = ALL_IMAGE_WIDTHS.filter((candidateWidth) => candidateWidth >= minimumWidth);
223
+ return {
224
+ src: imageOptimizationUrl(src, candidates[candidates.length - 1], quality),
225
+ srcSet: candidates.map((candidateWidth) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${candidateWidth}w`).join(", ")
226
+ };
227
+ }
228
+ const widths = getImageWidths(width);
229
+ return {
230
+ src: imageOptimizationUrl(src, widths[widths.length - 1], quality),
231
+ srcSet: widths.map((candidateWidth, index) => `${imageOptimizationUrl(src, candidateWidth, quality)} ${index + 1}x`).join(", ")
232
+ };
233
+ }
234
+ /**
235
+ * getImageProps — for advanced use cases (picture elements, background images).
236
+ * Returns the props that would be passed to the underlying <img> element.
237
+ */
238
+ function getImageProps(props) {
239
+ const { src: srcProp, alt, width, height, fill, preload: _preload, priority, quality: _quality, placeholder, blurDataURL: blurDataURLProp, loader, sizes, className, style, onLoad: _onLoad, onLoadingComplete: _onLoadingComplete, unoptimized: _unoptimized, overrideSrc, loading, ...rest } = props;
240
+ const { src, width: imgWidth, height: imgHeight, blurDataURL: imgBlurDataURL } = resolveImageSource({
241
+ src: srcProp,
242
+ width,
243
+ height,
244
+ blurDataURL: blurDataURLProp
245
+ });
246
+ const shouldPreload = _preload === true || priority === true;
247
+ if (_unoptimized === true || __globallyUnoptimized) {
248
+ const renderedSrc = overrideSrc || src;
249
+ const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
250
+ const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
251
+ backgroundImage: `url(${sanitizedBlurURL})`,
252
+ backgroundSize: "cover",
253
+ backgroundRepeat: "no-repeat",
254
+ backgroundPosition: "center"
255
+ } : void 0;
256
+ const imageProps = {
257
+ src: renderedSrc,
258
+ alt,
259
+ width: fill ? void 0 : imgWidth,
260
+ height: fill ? void 0 : imgHeight,
261
+ loading: priority ? "eager" : shouldPreload ? loading : loading ?? "lazy",
262
+ fetchPriority: priority ? "high" : void 0,
263
+ decoding: "async",
264
+ className,
265
+ style: fill ? getFillStyle(style, blurStyle) : {
266
+ ...blurStyle,
267
+ ...style
268
+ },
269
+ ...rest,
270
+ sizes: sizes ?? (fill ? "100vw" : void 0),
271
+ srcSet: void 0
272
+ };
273
+ return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
274
+ }
275
+ let blockedInProd = false;
276
+ if (isRemoteUrl(src)) {
277
+ const validation = validateRemoteUrl(src);
278
+ if (!validation.allowed) {
279
+ if (__isDev) console.warn(`[next/image] ${validation.reason}`);
280
+ else {
281
+ console.error(`[next/image] ${validation.reason}`);
282
+ blockedInProd = true;
283
+ }
284
+ }
285
+ }
286
+ const imgQuality = typeof _quality === "string" ? Number(_quality) : _quality ?? 75;
287
+ const resolvedSrc = blockedInProd ? "" : loader ? loader({
288
+ src,
289
+ width: imgWidth ?? 0,
290
+ quality: imgQuality
291
+ }) : src;
292
+ const skipOpt = isSvgUrl(resolvedSrc) && !__dangerouslyAllowSVG || blockedInProd || !!loader || isRemoteUrl(resolvedSrc);
293
+ const optimizedAttributes = imgWidth && !fill && !skipOpt ? generateImageAttributes(resolvedSrc, imgWidth, imgQuality, sizes) : null;
294
+ const optimizedSrc = skipOpt ? resolvedSrc : optimizedAttributes ? optimizedAttributes.src : imageOptimizationUrl(resolvedSrc, RESPONSIVE_WIDTHS[0], imgQuality);
295
+ const srcSet = optimizedAttributes?.srcSet;
296
+ const sanitizedBlurURL = imgBlurDataURL ? sanitizeBlurDataURL(imgBlurDataURL) : void 0;
297
+ const blurStyle = placeholder === "blur" && sanitizedBlurURL ? {
298
+ backgroundImage: `url(${sanitizedBlurURL})`,
299
+ backgroundSize: "cover",
300
+ backgroundRepeat: "no-repeat",
301
+ backgroundPosition: "center"
302
+ } : void 0;
303
+ const imageProps = {
304
+ src: optimizedSrc,
305
+ alt,
306
+ width: fill ? void 0 : imgWidth,
307
+ height: fill ? void 0 : imgHeight,
308
+ loading: priority ? "eager" : shouldPreload ? loading : loading ?? "lazy",
309
+ fetchPriority: priority ? "high" : void 0,
310
+ decoding: "async",
311
+ srcSet,
312
+ sizes: sizes ?? (fill ? "100vw" : void 0),
313
+ className,
314
+ style: fill ? getFillStyle(style, blurStyle) : {
315
+ ...blurStyle,
316
+ ...style
317
+ },
318
+ ...rest
319
+ };
320
+ return { props: Object.assign(imageProps, { "data-nimg": fill ? "fill" : "1" }) };
321
+ }
322
+ //#endregion
323
+ export { RESPONSIVE_WIDTHS, __dangerouslyAllowSVG, __globallyUnoptimized, __isDev, generateImageAttributes, getFillStyle, getImageProps, imageOptimizationUrl, isRemoteUrl, isSvgUrl, resolveImageSource, sanitizeBlurDataURL, validateRemoteUrl };
@@ -1,18 +1,11 @@
1
+ import { getImageProps, imageOptimizationUrl } from "./image-props.js";
1
2
  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";
3
+ import { ImageLoader, ImageProps as ImageProps$1, StaticImageData, StaticRequire } from "@vinext/types/next/upstream/dist/shared/lib/get-img-props";
3
4
  //#region src/shims/image.d.ts
4
5
  export type ImageLoaderProps = Parameters<ImageLoader>[0];
5
6
  export type ImageProps = ImageProps$1;
6
- /**
7
- * Build a `/_next/image` optimization URL.
8
- *
9
- * In production (Cloudflare Workers), the worker intercepts this path and uses
10
- * the Images binding to resize/transcode on the fly. In dev, the Vite dev
11
- * server handles it as a passthrough (serves the original file).
12
- */
13
- export declare function imageOptimizationUrl(src: string, width: number, quality?: number): string;
14
7
  declare const Image: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "alt" | "height" | "loading" | "ref" | "src" | "srcSet" | "width"> & {
15
- src: string | StaticImport;
8
+ src: string | import("@vinext/types/next/upstream/dist/shared/lib/get-img-props").StaticImport;
16
9
  alt: string;
17
10
  width?: number | `${number}`;
18
11
  height?: number | `${number}`;
@@ -33,12 +26,5 @@ declare const Image: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProp
33
26
  lazyBoundary?: string;
34
27
  lazyRoot?: string;
35
28
  } & React.RefAttributes<HTMLImageElement>>;
36
- /**
37
- * getImageProps — for advanced use cases (picture elements, background images).
38
- * Returns the props that would be passed to the underlying <img> element.
39
- */
40
- export declare function getImageProps(props: ImageProps): {
41
- props: ImgProps;
42
- };
43
29
  //#endregion
44
- export { type ImageLoader, type StaticImageData, type StaticRequire, Image as default };
30
+ export { type ImageLoader, type StaticImageData, type StaticRequire, Image as default, getImageProps, imageOptimizationUrl };