vinext 0.1.1 → 0.1.2

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 (147) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/check.js +4 -3
  5. package/dist/client/navigation-runtime.d.ts +3 -2
  6. package/dist/client/window-next.d.ts +6 -4
  7. package/dist/config/config-matchers.d.ts +11 -4
  8. package/dist/config/config-matchers.js +15 -2
  9. package/dist/config/next-config.d.ts +13 -0
  10. package/dist/config/next-config.js +2 -0
  11. package/dist/deploy.js +9 -2
  12. package/dist/entries/app-rsc-entry.js +7 -1
  13. package/dist/entries/pages-client-entry.js +1 -1
  14. package/dist/entries/pages-server-entry.js +7 -6
  15. package/dist/index.d.ts +0 -2
  16. package/dist/index.js +86 -78
  17. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  18. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  19. package/dist/plugins/og-assets.js +2 -2
  20. package/dist/plugins/optimize-imports.d.ts +8 -4
  21. package/dist/plugins/optimize-imports.js +16 -12
  22. package/dist/plugins/sass.d.ts +53 -24
  23. package/dist/plugins/sass.js +249 -1
  24. package/dist/plugins/wasm-module-import.d.ts +15 -0
  25. package/dist/plugins/wasm-module-import.js +50 -0
  26. package/dist/routing/app-route-graph.d.ts +23 -1
  27. package/dist/routing/app-route-graph.js +47 -8
  28. package/dist/routing/file-matcher.js +1 -1
  29. package/dist/server/app-browser-entry.js +108 -213
  30. package/dist/server/app-browser-error.d.ts +4 -1
  31. package/dist/server/app-browser-error.js +7 -1
  32. package/dist/server/app-browser-history-controller.d.ts +104 -0
  33. package/dist/server/app-browser-history-controller.js +210 -0
  34. package/dist/server/app-browser-navigation-controller.d.ts +3 -2
  35. package/dist/server/app-browser-navigation-controller.js +10 -7
  36. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  37. package/dist/server/app-browser-rsc-redirect.js +30 -8
  38. package/dist/server/app-browser-state.js +4 -7
  39. package/dist/server/app-browser-visible-commit.js +1 -1
  40. package/dist/server/app-fallback-renderer.d.ts +2 -1
  41. package/dist/server/app-fallback-renderer.js +3 -1
  42. package/dist/server/app-middleware.js +1 -0
  43. package/dist/server/app-optimistic-routing.js +22 -1
  44. package/dist/server/app-page-boundary-render.d.ts +2 -1
  45. package/dist/server/app-page-boundary-render.js +4 -2
  46. package/dist/server/app-page-cache.js +9 -7
  47. package/dist/server/app-page-dispatch.d.ts +8 -0
  48. package/dist/server/app-page-dispatch.js +18 -5
  49. package/dist/server/app-page-element-builder.d.ts +22 -2
  50. package/dist/server/app-page-element-builder.js +37 -8
  51. package/dist/server/app-page-execution.d.ts +1 -1
  52. package/dist/server/app-page-execution.js +32 -17
  53. package/dist/server/app-page-render.d.ts +1 -1
  54. package/dist/server/app-page-render.js +7 -14
  55. package/dist/server/app-page-request.d.ts +1 -0
  56. package/dist/server/app-page-request.js +3 -2
  57. package/dist/server/app-page-response.js +1 -1
  58. package/dist/server/app-page-route-wiring.d.ts +3 -1
  59. package/dist/server/app-page-route-wiring.js +8 -7
  60. package/dist/server/app-page-stream.d.ts +1 -6
  61. package/dist/server/app-page-stream.js +1 -4
  62. package/dist/server/app-route-handler-response.js +11 -10
  63. package/dist/server/app-route-handler-runtime.js +12 -1
  64. package/dist/server/app-rsc-handler.js +1 -1
  65. package/dist/server/app-rsc-response-finalizer.js +1 -1
  66. package/dist/server/app-server-action-execution.d.ts +11 -0
  67. package/dist/server/app-server-action-execution.js +5 -2
  68. package/dist/server/app-ssr-entry.js +2 -2
  69. package/dist/server/app-ssr-stream.js +9 -1
  70. package/dist/server/dev-lockfile.js +2 -1
  71. package/dist/server/dev-server.js +43 -12
  72. package/dist/server/headers.d.ts +8 -1
  73. package/dist/server/headers.js +8 -1
  74. package/dist/server/instrumentation-runtime.d.ts +6 -0
  75. package/dist/server/instrumentation-runtime.js +8 -0
  76. package/dist/server/isr-decision.d.ts +79 -0
  77. package/dist/server/isr-decision.js +70 -0
  78. package/dist/server/metadata-route-response.js +5 -3
  79. package/dist/server/middleware-runtime.d.ts +13 -0
  80. package/dist/server/middleware-runtime.js +11 -7
  81. package/dist/server/middleware.js +1 -0
  82. package/dist/server/navigation-planner.d.ts +62 -1
  83. package/dist/server/navigation-planner.js +188 -0
  84. package/dist/server/navigation-trace.d.ts +11 -1
  85. package/dist/server/navigation-trace.js +11 -1
  86. package/dist/server/normalize-path.d.ts +0 -8
  87. package/dist/server/normalize-path.js +3 -1
  88. package/dist/server/otel-tracer-extension.d.ts +45 -0
  89. package/dist/server/otel-tracer-extension.js +89 -0
  90. package/dist/server/pages-api-route.d.ts +14 -3
  91. package/dist/server/pages-api-route.js +6 -1
  92. package/dist/server/pages-asset-tags.d.ts +15 -4
  93. package/dist/server/pages-asset-tags.js +18 -12
  94. package/dist/server/pages-data-route.js +5 -1
  95. package/dist/server/pages-node-compat.d.ts +3 -11
  96. package/dist/server/pages-node-compat.js +174 -121
  97. package/dist/server/pages-page-data.d.ts +28 -0
  98. package/dist/server/pages-page-data.js +61 -17
  99. package/dist/server/pages-page-handler.d.ts +1 -0
  100. package/dist/server/pages-page-handler.js +22 -6
  101. package/dist/server/pages-page-response.d.ts +45 -1
  102. package/dist/server/pages-page-response.js +66 -5
  103. package/dist/server/pages-readiness.d.ts +1 -1
  104. package/dist/server/pages-request-pipeline.d.ts +15 -1
  105. package/dist/server/pages-request-pipeline.js +23 -2
  106. package/dist/server/prod-server.d.ts +39 -1
  107. package/dist/server/prod-server.js +98 -34
  108. package/dist/shims/cache-runtime.js +9 -2
  109. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  110. package/dist/shims/dynamic-preload-chunks.js +77 -0
  111. package/dist/shims/dynamic.d.ts +4 -0
  112. package/dist/shims/dynamic.js +4 -2
  113. package/dist/shims/error-boundary.d.ts +4 -4
  114. package/dist/shims/error.js +37 -11
  115. package/dist/shims/fetch-cache.d.ts +9 -1
  116. package/dist/shims/fetch-cache.js +11 -1
  117. package/dist/shims/head.js +6 -1
  118. package/dist/shims/headers.d.ts +16 -2
  119. package/dist/shims/headers.js +37 -1
  120. package/dist/shims/image-config.js +7 -1
  121. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  122. package/dist/shims/internal/app-route-detection.js +10 -6
  123. package/dist/shims/internal/app-router-context.d.ts +5 -0
  124. package/dist/shims/metadata.d.ts +6 -2
  125. package/dist/shims/metadata.js +32 -14
  126. package/dist/shims/navigation.d.ts +7 -16
  127. package/dist/shims/navigation.js +33 -16
  128. package/dist/shims/router.js +28 -1
  129. package/dist/shims/script-nonce-context.d.ts +1 -1
  130. package/dist/shims/script-nonce-context.js +11 -3
  131. package/dist/shims/server.d.ts +17 -1
  132. package/dist/shims/server.js +31 -6
  133. package/dist/shims/slot.js +1 -1
  134. package/dist/shims/unified-request-context.js +1 -0
  135. package/dist/typegen.js +1 -0
  136. package/dist/utils/client-build-manifest.js +15 -5
  137. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  138. package/dist/utils/client-runtime-metadata.js +63 -0
  139. package/dist/utils/hash.d.ts +17 -1
  140. package/dist/utils/hash.js +36 -1
  141. package/dist/utils/lazy-chunks.d.ts +27 -1
  142. package/dist/utils/lazy-chunks.js +65 -1
  143. package/dist/utils/manifest-paths.d.ts +20 -2
  144. package/dist/utils/manifest-paths.js +38 -3
  145. package/dist/utils/path.d.ts +2 -1
  146. package/dist/utils/path.js +5 -1
  147. package/package.json +2 -2
package/README.md CHANGED
@@ -528,22 +528,19 @@ The cache is pluggable. The default `MemoryCacheHandler` works out of the box. S
528
528
 
529
529
  #### Configuring cache adapters from `vite.config`
530
530
 
531
- Instead of wiring up cache handlers imperatively from a worker entry, you can declare them in the `vinext()` plugin config. The `@vinext/cloudflare` package ships two Cloudflare adapters for this:
531
+ Instead of wiring up cache handlers imperatively from a worker entry, you can declare them in the `vinext()` plugin config. The `@vinext/cloudflare` package ships Cloudflare adapters for this:
532
532
 
533
533
  - **`kvDataAdapter()`** (`@vinext/cloudflare/cache/kv-data-adapter`) — backs the `"use cache"` data cache with a Workers KV namespace.
534
- - **`cdnAdapter()`** (`@vinext/cloudflare/cache/cdn-adapter`) — backs full-route CDN caching with the Workers Cache API.
535
534
 
536
535
  ```ts
537
536
  import { defineConfig } from "vite";
538
537
  import vinext from "vinext";
539
- import { cdnAdapter } from "@vinext/cloudflare/cache/cdn-adapter";
540
538
  import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";
541
539
 
542
540
  export default defineConfig({
543
541
  plugins: [
544
542
  vinext({
545
543
  cache: {
546
- cdn: cdnAdapter(),
547
544
  data: kvDataAdapter(),
548
545
  },
549
546
  }),
@@ -559,7 +556,7 @@ The KV data adapter reads `env[binding]` at runtime, so add the matching KV name
559
556
  }
560
557
  ```
561
558
 
562
- `binding` defaults to `VINEXT_KV_CACHE`, so `kvDataAdapter()` with no options works as long as that's your binding name. Other options: `appPrefix` (namespace cache keys to isolate multiple apps in one KV namespace), `ttlSeconds` (default KV `expirationTtl`, default 30 days), and `tagCacheTtlMs` (in-memory tag-invalidation cache TTL, default 5s). `cdnAdapter()` takes no options — it just needs the Workers Cache, which is always available on Workers.
559
+ `binding` defaults to `VINEXT_KV_CACHE`, so `kvDataAdapter()` with no options works as long as that's your binding name. Other options: `appPrefix` (namespace cache keys to isolate multiple apps in one KV namespace), `ttlSeconds` (default KV `expirationTtl`, default 30 days), and `tagCacheTtlMs` (in-memory tag-invalidation cache TTL, default 5s).
563
560
 
564
561
  Each builder returns a plain, serializable `{ adapter, options }` descriptor — **it never touches the Workers runtime**, so nothing throws at build or dev time when bindings aren't available. The actual adapter (and its `env` binding lookup) is instantiated lazily on the first request.
565
562
 
@@ -51,10 +51,16 @@ declare function createClientManualChunks(shimsDir: string): (id: string) => str
51
51
  * compression efficiency — small files restart the compression dictionary,
52
52
  * adding ~5-15% wire overhead vs fewer larger chunks.
53
53
  */
54
+ declare function createClientFileNameConfig(assetsDir: string): {
55
+ entryFileNames: string;
56
+ chunkFileNames: string;
57
+ };
54
58
  declare function createClientOutputConfig(clientManualChunks: (id: string) => string | undefined, assetsDir: string): {
55
59
  assetFileNames: (assetInfo: ClientAssetFileNameInfo) => string;
56
60
  manualChunks: (id: string) => string | undefined;
57
61
  experimentalMinChunkSize: number;
62
+ entryFileNames: string;
63
+ chunkFileNames: string;
58
64
  };
59
65
  declare function createClientCodeSplittingConfig(clientManualChunks: (id: string) => string | undefined): {
60
66
  minSize: number;
@@ -155,4 +161,4 @@ type VinextBuildConfigWithLegacy = VinextBuildConfig & {
155
161
  declare function getBuildBundlerOptions(build: UserConfig["build"] | undefined): VinextBuildBundlerOptions | undefined;
156
162
  declare function withBuildBundlerOptions(viteMajorVersion: number, bundlerOptions: VinextBuildBundlerOptions): Partial<VinextBuildConfigWithLegacy>;
157
163
  //#endregion
158
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
164
+ export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
@@ -89,8 +89,16 @@ function createClientManualChunks(shimsDir) {
89
89
  * compression efficiency — small files restart the compression dictionary,
90
90
  * adding ~5-15% wire overhead vs fewer larger chunks.
91
91
  */
92
+ function createClientFileNameConfig(assetsDir) {
93
+ const chunksDir = `${assetsDir}/chunks`;
94
+ return {
95
+ entryFileNames: `${chunksDir}/[name]-[hash].js`,
96
+ chunkFileNames: `${chunksDir}/[name]-[hash].js`
97
+ };
98
+ }
92
99
  function createClientOutputConfig(clientManualChunks, assetsDir) {
93
100
  return {
101
+ ...createClientFileNameConfig(assetsDir),
94
102
  assetFileNames: createClientAssetFileNames(assetsDir),
95
103
  manualChunks: clientManualChunks,
96
104
  experimentalMinChunkSize: 1e4
@@ -228,4 +236,4 @@ function withBuildBundlerOptions(viteMajorVersion, bundlerOptions) {
228
236
  return viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
229
237
  }
230
238
  //#endregion
231
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
239
+ export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
package/dist/check.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { detectPackageManager } from "./utils/project.js";
2
+ import { normalizePathSeparators } from "./utils/path.js";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import { parseAst } from "vite";
@@ -342,7 +343,7 @@ function findSourceFiles(dir, extensions = [
342
343
  if (!fs.existsSync(dir)) return results;
343
344
  const entries = fs.readdirSync(dir, { withFileTypes: true });
344
345
  for (const entry of entries) {
345
- const fullPath = path.join(dir, entry.name);
346
+ const fullPath = normalizePathSeparators(path.join(dir, entry.name));
346
347
  if (entry.isDirectory()) {
347
348
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist" || entry.name === ".git") continue;
348
349
  results.push(...findSourceFiles(fullPath, extensions));
@@ -563,7 +564,7 @@ function scanImports(root) {
563
564
  if (mod.startsWith("next/") || mod === "next" || mod === "server-only" || mod === "client-only") {
564
565
  const normalized = mod === "next" ? "next" : mod;
565
566
  if (!importUsage.has(normalized)) importUsage.set(normalized, []);
566
- const relFile = path.relative(root, file);
567
+ const relFile = normalizePathSeparators(path.relative(root, file));
567
568
  const usedInFiles = importUsage.get(normalized) ?? [];
568
569
  if (!usedInFiles.includes(relFile)) usedInFiles.push(relFile);
569
570
  }
@@ -876,7 +877,7 @@ function checkConventions(root) {
876
877
  const cjsGlobalFiles = [];
877
878
  for (const file of allSourceFiles) {
878
879
  const content = fs.readFileSync(file, "utf-8");
879
- const rel = path.relative(root, file);
880
+ const rel = normalizePathSeparators(path.relative(root, file));
880
881
  if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
881
882
  if (hasFreeCjsGlobal(content)) cjsGlobalFiles.push(rel);
882
883
  }
@@ -15,12 +15,13 @@ type NavigationRuntimeRscBootstrap = {
15
15
  };
16
16
  type NavigationRuntimeKind = "navigate" | "traverse" | "refresh";
17
17
  type NavigationRuntimeHistoryUpdateMode = "push" | "replace";
18
+ type NavigationRuntimeVisibleCommitMode = "transition" | "synchronous";
18
19
  type NavigationRuntimeTraversalIntent = {
19
20
  direction: "back" | "forward" | "unknown";
20
21
  historyState: unknown;
21
22
  targetHistoryIndex: number | null;
22
23
  };
23
- type NavigationRuntimeNavigate = (href: string, redirectDepth?: number, navigationKind?: NavigationRuntimeKind, historyUpdateMode?: NavigationRuntimeHistoryUpdateMode, previousNextUrlOverride?: string | null, programmaticTransition?: boolean, traversalIntent?: NavigationRuntimeTraversalIntent, scrollIntent?: AppRouterScrollIntent | null) => Promise<void>;
24
+ type NavigationRuntimeNavigate = (href: string, redirectDepth?: number, navigationKind?: NavigationRuntimeKind, historyUpdateMode?: NavigationRuntimeHistoryUpdateMode, previousNextUrlOverride?: string | null, programmaticTransition?: boolean, traversalIntent?: NavigationRuntimeTraversalIntent, scrollIntent?: AppRouterScrollIntent | null, visibleCommitMode?: NavigationRuntimeVisibleCommitMode) => Promise<void>;
24
25
  type NavigationRuntimeFunctions = {
25
26
  clearNavigationCaches?: () => void;
26
27
  commitHashNavigation?: (href: string, historyUpdateMode: NavigationRuntimeHistoryUpdateMode, scroll: boolean) => void;
@@ -66,4 +67,4 @@ declare function hasAppNavigationRuntime(): boolean;
66
67
  */
67
68
  declare function hasAppNavigationRuntimeBootstrap(): boolean;
68
69
  //#endregion
69
- export { NAVIGATION_RUNTIME_KEY, NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION, NavigationRuntime, NavigationRuntimeBootstrap, NavigationRuntimeFunctions, NavigationRuntimeNavigate, NavigationRuntimeRscBootstrap, NavigationRuntimeRscChunk, NavigationRuntimeSnapshot, ensureNavigationRuntimeRscBootstrap, getNavigationRuntime, hasAppNavigationRuntime, hasAppNavigationRuntimeBootstrap, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions, subscribeNavigationRuntimeRscChunk };
70
+ export { NAVIGATION_RUNTIME_KEY, NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION, NavigationRuntime, NavigationRuntimeBootstrap, NavigationRuntimeFunctions, NavigationRuntimeNavigate, NavigationRuntimeRscBootstrap, NavigationRuntimeRscChunk, NavigationRuntimeSnapshot, NavigationRuntimeVisibleCommitMode, ensureNavigationRuntimeRscBootstrap, getNavigationRuntime, hasAppNavigationRuntime, hasAppNavigationRuntimeBootstrap, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions, subscribeNavigationRuntimeRscChunk };
@@ -40,10 +40,9 @@
40
40
  * `window.next.router`. Mirrors the `publicAppRouterInstance` shape from
41
41
  * `packages/next/src/client/components/app-router-instance.ts`.
42
42
  *
43
- * `hmrRefresh` and `experimental_gesturePush` are intentionally omitted —
44
- * vinext does not implement them. Library callers that branch on their
45
- * presence (`typeof router.hmrRefresh === "function"`) will skip the
46
- * branch, matching what they would do on a production Next.js build.
43
+ * `hmrRefresh` is intentionally omitted — vinext does not implement it.
44
+ * `experimental_gesturePush` is attached only when
45
+ * `experimental.gestureTransition` is enabled, matching Next.js.
47
46
  */
48
47
  type AppRouterPublicInstance = {
49
48
  push: (href: string, options?: {
@@ -57,6 +56,9 @@ type AppRouterPublicInstance = {
57
56
  refresh: () => void;
58
57
  prefetch: (href: string, options?: {
59
58
  onInvalidate?: () => void;
59
+ }) => void;
60
+ experimental_gesturePush?: (href: string, options?: {
61
+ scroll?: boolean;
60
62
  }) => void; /** Default placeholder, matches Next.js. */
61
63
  bfcacheId?: string;
62
64
  };
@@ -32,10 +32,10 @@ declare function escapeHeaderSource(source: string): string;
32
32
  * Callers extract the relevant parts from the incoming Request.
33
33
  */
34
34
  type RequestContext = {
35
- headers: Headers;
36
- cookies: Record<string, string>;
37
- query: URLSearchParams;
38
- host: string;
35
+ readonly headers: Headers;
36
+ readonly cookies: Record<string, string>;
37
+ readonly query: URLSearchParams;
38
+ readonly host: string;
39
39
  };
40
40
  /**
41
41
  * basePath gating state passed alongside the pathname to every matcher.
@@ -65,6 +65,13 @@ type BasePathMatchState = {
65
65
  declare function parseCookies(cookieHeader: string | null): Record<string, string>;
66
66
  /**
67
67
  * Build a RequestContext from a Web Request object.
68
+ *
69
+ * `cookies` and `query` are lazy memoized getters: they are consumed only by
70
+ * `has`/`missing` condition evaluation (`checkHasConditions` /
71
+ * `matchesRuleConditions`), and most apps configure no such conditions. The
72
+ * cookie split and `searchParams` access are therefore deferred until first
73
+ * read and computed at most once. Mirrors `headersContextFromRequest` in
74
+ * `shims/headers.ts`.
68
75
  */
69
76
  declare function requestContextFromRequest(request: Request): RequestContext;
70
77
  declare function normalizeHost(hostHeader: string | null, fallbackHostname: string): string;
@@ -356,13 +356,26 @@ function parseCookies(cookieHeader) {
356
356
  }
357
357
  /**
358
358
  * Build a RequestContext from a Web Request object.
359
+ *
360
+ * `cookies` and `query` are lazy memoized getters: they are consumed only by
361
+ * `has`/`missing` condition evaluation (`checkHasConditions` /
362
+ * `matchesRuleConditions`), and most apps configure no such conditions. The
363
+ * cookie split and `searchParams` access are therefore deferred until first
364
+ * read and computed at most once. Mirrors `headersContextFromRequest` in
365
+ * `shims/headers.ts`.
359
366
  */
360
367
  function requestContextFromRequest(request) {
361
368
  const url = new URL(request.url);
369
+ let cookies;
370
+ let query;
362
371
  return {
363
372
  headers: request.headers,
364
- cookies: parseCookies(request.headers.get("cookie")),
365
- query: url.searchParams,
373
+ get cookies() {
374
+ return cookies ??= parseCookies(request.headers.get("cookie"));
375
+ },
376
+ get query() {
377
+ return query ??= url.searchParams;
378
+ },
366
379
  host: normalizeHost(request.headers.get("host"), url.hostname)
367
380
  };
368
381
  }
@@ -181,6 +181,14 @@ type NextConfig = {
181
181
  */
182
182
  defineServer?: Record<string, string | number | boolean>;
183
183
  };
184
+ experimental?: {
185
+ /**
186
+ * Enables the experimental App Router gesture transition API:
187
+ * `useRouter().experimental_gesturePush()`.
188
+ */
189
+ gestureTransition?: boolean;
190
+ [key: string]: unknown;
191
+ };
184
192
  /**
185
193
  * Path to a custom cache handler module (e.g., KV, Redis, DynamoDB).
186
194
  * Accepts relative paths, absolute paths, or file:// URLs from import.meta.resolve().
@@ -230,6 +238,11 @@ type ResolvedNextConfig = {
230
238
  pageExtensions: string[];
231
239
  instrumentationClientInject: string[];
232
240
  cacheComponents: boolean;
241
+ /**
242
+ * Enables the experimental App Router gesture transition API:
243
+ * `useRouter().experimental_gesturePush()`.
244
+ */
245
+ gestureTransition: boolean;
233
246
  /**
234
247
  * Whether `experimental.prefetchInlining` is configured. Next.js uses this
235
248
  * with the Segment Cache to fetch the route tree before the bundled inlined
@@ -512,6 +512,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
512
512
  output: "",
513
513
  pageExtensions: normalizePageExtensions(),
514
514
  cacheComponents: false,
515
+ gestureTransition: false,
515
516
  prefetchInlining: false,
516
517
  redirects: [],
517
518
  rewrites: {
@@ -655,6 +656,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
655
656
  pageExtensions,
656
657
  instrumentationClientInject: Array.isArray(config.instrumentationClientInject) ? config.instrumentationClientInject.filter((x) => typeof x === "string") : [],
657
658
  cacheComponents: config.cacheComponents ?? false,
659
+ gestureTransition: experimental?.gestureTransition === true,
658
660
  prefetchInlining,
659
661
  redirects,
660
662
  rewrites,
package/dist/deploy.js CHANGED
@@ -334,7 +334,7 @@ function generatePagesRouterWorkerEntry() {
334
334
  * Cloudflare Worker entry point -- auto-generated by vinext deploy.
335
335
  * Edit freely or delete to regenerate on next deploy.
336
336
  */
337
- import { runPagesRequest } from "vinext/server/pages-request-pipeline";
337
+ import { runPagesRequest, wrapMiddlewareWithBasePath } from "vinext/server/pages-request-pipeline";
338
338
  import type { PagesPipelineDeps } from "vinext/server/pages-request-pipeline";
339
339
  import { handleImageOptimization, DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath } from "vinext/server/image-optimization";
340
340
  import type { ImageConfig } from "vinext/server/image-optimization";
@@ -468,7 +468,14 @@ export default {
468
468
  isDataRequest,
469
469
  ctx,
470
470
  matchPageRoute: typeof matchPageRoute === "function" ? matchPageRoute : null,
471
- runMiddleware: typeof runMiddleware === "function" ? runMiddleware : null,
471
+ // Pass the original (pre-basePath-stripping) URL to middleware so that
472
+ // request.nextUrl.basePath reflects whether the URL actually had the
473
+ // basePath prefix. Matches Next.js behavior and the prod-server.ts
474
+ // equivalent (shared via wrapMiddlewareWithBasePath).
475
+ runMiddleware:
476
+ typeof runMiddleware === "function"
477
+ ? wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath)
478
+ : null,
472
479
  renderPage: typeof renderPage === "function"
473
480
  ? (req, resolvedUrl, options, stagedHeaders) =>
474
481
  renderPage(req, resolvedUrl, null, ctx, stagedHeaders, options)
@@ -275,6 +275,10 @@ ${metaRouteEntries.join(",\n")}
275
275
  // recognising /_next/static/* paths (parity with __assetPrefix below).
276
276
  export const __basePath = ${JSON.stringify(bp)};
277
277
 
278
+ // Hoisted alongside __basePath so __fallbackRenderer / buildPageElements can
279
+ // thread the configured trailingSlash flag through canonical URL rendering.
280
+ const __trailingSlash = ${JSON.stringify(ts)};
281
+
278
282
  const rootNotFoundModule = ${rootNotFoundVar ? rootNotFoundVar : "null"};
279
283
  const rootForbiddenModule = ${rootForbiddenVar ? rootForbiddenVar : "null"};
280
284
  const rootUnauthorizedModule = ${rootUnauthorizedVar ? rootUnauthorizedVar : "null"};
@@ -298,6 +302,7 @@ const createRscOnErrorHandler = (request, pathname, routePath) =>
298
302
 
299
303
  const __fallbackRenderer = __createAppFallbackRenderer({
300
304
  basePath: __basePath,
305
+ trailingSlash: __trailingSlash,
301
306
  rootBoundaries: {
302
307
  rootForbiddenModule,
303
308
  rootLayouts,
@@ -357,11 +362,11 @@ async function buildPageElements(route, params, routePath, pageRequest, layoutPa
357
362
  metadataRoutes,
358
363
  layoutParamAccess,
359
364
  basePath: __basePath,
365
+ trailingSlash: __trailingSlash,
360
366
  htmlLimitedBots: __htmlLimitedBots,
361
367
  });
362
368
  }
363
369
 
364
- const __trailingSlash = ${JSON.stringify(ts)};
365
370
  const __i18nConfig = ${JSON.stringify(i18nConfig)};
366
371
  const __configRedirects = ${JSON.stringify(redirects)};
367
372
  const __configRewrites = ${JSON.stringify(rewrites)};
@@ -484,6 +489,7 @@ export default __createAppRscHandler({
484
489
  },
485
490
  clientReuseManifest,
486
491
  cleanPathname,
492
+ displayPathname,
487
493
  clearRequestContext() {
488
494
  __clearRequestContext();
489
495
  },
@@ -1,7 +1,7 @@
1
+ import { normalizePathSeparators } from "../utils/path.js";
1
2
  import { findFileWithExts } from "../routing/file-matcher.js";
2
3
  import { patternToNextFormat } from "../routing/route-validation.js";
3
4
  import { pagesRouter } from "../routing/pages-router.js";
4
- import { normalizePathSeparators } from "../utils/path.js";
5
5
  //#region src/entries/pages-client-entry.ts
6
6
  /**
7
7
  * Pages Router client hydration entry generator.
@@ -1,6 +1,6 @@
1
+ import { normalizePathSeparators } from "../utils/path.js";
1
2
  import { findFileWithExts } from "../routing/file-matcher.js";
2
3
  import { apiRouter, pagesRouter } from "../routing/pages-router.js";
3
- import { normalizePathSeparators } from "../utils/path.js";
4
4
  import { resolveEntryPath } from "./runtime-entry-module.js";
5
5
  import { isProxyFile } from "../server/middleware.js";
6
6
  //#region src/entries/pages-server-entry.ts
@@ -46,11 +46,11 @@ async function generateServerEntry(pagesDir, nextConfig, fileMatcher, middleware
46
46
  const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
47
47
  const docFilePath = findFileWithExts(pagesDir, "_document", fileMatcher);
48
48
  const errorFilePath = findFileWithExts(pagesDir, "_error", fileMatcher);
49
- const appAssetPathJson = appFilePath !== null ? JSON.stringify(normalizePathSeparators(appFilePath)) : "null";
50
- const appImportCode = appFilePath !== null ? `import { default as AppComponent } from ${JSON.stringify(normalizePathSeparators(appFilePath))};` : `const AppComponent = null;`;
51
- const docImportCode = docFilePath !== null ? `import { default as DocumentComponent } from ${JSON.stringify(normalizePathSeparators(docFilePath))};` : `const DocumentComponent = null;`;
52
- const errorAssetPathJson = errorFilePath !== null ? JSON.stringify(normalizePathSeparators(errorFilePath)) : "null";
53
- const errorImportCode = errorFilePath !== null ? `import * as ErrorPageModule from ${JSON.stringify(normalizePathSeparators(errorFilePath))};` : `const ErrorPageModule = null;`;
49
+ const appAssetPathJson = appFilePath !== null ? JSON.stringify(appFilePath) : "null";
50
+ const appImportCode = appFilePath !== null ? `import { default as AppComponent } from ${JSON.stringify(appFilePath)};` : `const AppComponent = null;`;
51
+ const docImportCode = docFilePath !== null ? `import { default as DocumentComponent } from ${JSON.stringify(docFilePath)};` : `const DocumentComponent = null;`;
52
+ const errorAssetPathJson = errorFilePath !== null ? JSON.stringify(errorFilePath) : "null";
53
+ const errorImportCode = errorFilePath !== null ? `import * as ErrorPageModule from ${JSON.stringify(errorFilePath)};` : `const ErrorPageModule = null;`;
54
54
  const i18nConfigJson = nextConfig?.i18n ? JSON.stringify({
55
55
  locales: nextConfig.i18n.locales,
56
56
  defaultLocale: nextConfig.i18n.defaultLocale,
@@ -279,6 +279,7 @@ const _renderPage = __createPagesPageHandler({
279
279
  i18nConfig,
280
280
  vinextConfig: {
281
281
  basePath: vinextConfig.basePath,
282
+ assetPrefix: vinextConfig.assetPrefix,
282
283
  trailingSlash: vinextConfig.trailingSlash,
283
284
  expireTime: vinextConfig.expireTime,
284
285
  clientTraceMetadata: vinextConfig.clientTraceMetadata,
package/dist/index.d.ts CHANGED
@@ -88,12 +88,10 @@ type VinextOptions = {
88
88
  * need a binding — e.g. a KV namespace — can read it.
89
89
  *
90
90
  * @example
91
- * import { cdnAdapter } from "@vinext/cloudflare/cache/cdn-adapter";
92
91
  * import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";
93
92
  *
94
93
  * vinext({
95
94
  * cache: {
96
- * cdn: cdnAdapter(),
97
95
  * data: kvDataAdapter({ binding: "MY_KV" }),
98
96
  * },
99
97
  * })