vinext 0.1.3 → 0.1.5

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 (185) hide show
  1. package/dist/build/client-build-config.d.ts +11 -2
  2. package/dist/build/client-build-config.js +17 -6
  3. package/dist/build/css-url-assets.d.ts +1 -1
  4. package/dist/build/css-url-assets.js +9 -7
  5. package/dist/build/prerender.js +3 -1
  6. package/dist/cache/cache-adapters-virtual.js +1 -1
  7. package/dist/client/pages-router-link-navigation.d.ts +33 -7
  8. package/dist/client/pages-router-link-navigation.js +32 -2
  9. package/dist/client/vinext-next-data.js +2 -0
  10. package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
  11. package/dist/config/config-matchers.d.ts +11 -1
  12. package/dist/config/config-matchers.js +14 -2
  13. package/dist/config/tsconfig-paths.js +14 -1
  14. package/dist/deploy.js +20 -13
  15. package/dist/entries/app-rsc-entry.js +27 -22
  16. package/dist/entries/pages-client-entry.js +14 -13
  17. package/dist/entries/pages-server-entry.js +8 -27
  18. package/dist/index.js +365 -147
  19. package/dist/plugins/css-data-url.js +30 -26
  20. package/dist/plugins/dynamic-preload-metadata.js +2 -4
  21. package/dist/plugins/extensionless-dynamic-import.js +27 -24
  22. package/dist/plugins/fonts.js +5 -4
  23. package/dist/plugins/import-meta-url.js +21 -15
  24. package/dist/plugins/instrumentation-client.js +1 -1
  25. package/dist/plugins/middleware-server-only.js +7 -6
  26. package/dist/plugins/og-assets.js +48 -46
  27. package/dist/plugins/optimize-imports.js +9 -3
  28. package/dist/plugins/remove-console.d.ts +7 -1
  29. package/dist/plugins/remove-console.js +4 -1
  30. package/dist/plugins/require-context.js +21 -20
  31. package/dist/plugins/strip-server-exports.d.ts +16 -8
  32. package/dist/plugins/strip-server-exports.js +496 -46
  33. package/dist/routing/app-route-graph.js +2 -2
  34. package/dist/server/app-bfcache-identity.d.ts +26 -0
  35. package/dist/server/app-bfcache-identity.js +127 -0
  36. package/dist/server/app-browser-action-result.js +1 -1
  37. package/dist/server/app-browser-entry.js +22 -12
  38. package/dist/server/app-browser-navigation-controller.d.ts +1 -1
  39. package/dist/server/app-browser-navigation-controller.js +1 -1
  40. package/dist/server/app-browser-state.d.ts +3 -22
  41. package/dist/server/app-browser-state.js +23 -139
  42. package/dist/server/app-browser-stream.js +1 -1
  43. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  44. package/dist/server/app-browser-visible-commit.js +3 -2
  45. package/dist/server/app-fallback-renderer.d.ts +1 -1
  46. package/dist/server/app-layout-param-observation.d.ts +1 -1
  47. package/dist/server/app-layout-param-observation.js +1 -1
  48. package/dist/server/app-middleware.js +2 -1
  49. package/dist/server/app-page-boundary-render.d.ts +1 -1
  50. package/dist/server/app-page-boundary.js +1 -1
  51. package/dist/server/app-page-cache-finalizer.d.ts +62 -0
  52. package/dist/server/app-page-cache-finalizer.js +122 -0
  53. package/dist/server/app-page-cache-render.d.ts +2 -2
  54. package/dist/server/app-page-cache-render.js +1 -1
  55. package/dist/server/app-page-cache.d.ts +2 -53
  56. package/dist/server/app-page-cache.js +5 -131
  57. package/dist/server/app-page-dispatch.d.ts +2 -2
  58. package/dist/server/app-page-dispatch.js +10 -8
  59. package/dist/server/app-page-probe.js +3 -2
  60. package/dist/server/app-page-render-observation.js +2 -2
  61. package/dist/server/app-page-render.d.ts +3 -3
  62. package/dist/server/app-page-render.js +3 -2
  63. package/dist/server/app-page-stream.d.ts +2 -9
  64. package/dist/server/app-page-stream.js +1 -35
  65. package/dist/server/app-pages-bridge.d.ts +5 -1
  66. package/dist/server/app-pages-bridge.js +5 -13
  67. package/dist/server/app-request-context.d.ts +1 -2
  68. package/dist/server/app-request-context.js +2 -1
  69. package/dist/server/app-route-handler-dispatch.js +3 -2
  70. package/dist/server/app-route-handler-execution.d.ts +1 -1
  71. package/dist/server/app-route-handler-execution.js +1 -1
  72. package/dist/server/app-route-handler-response.d.ts +1 -1
  73. package/dist/server/app-router-entry.js +2 -1
  74. package/dist/server/app-rsc-handler.d.ts +3 -0
  75. package/dist/server/app-rsc-handler.js +73 -31
  76. package/dist/server/app-rsc-response-finalizer.js +1 -1
  77. package/dist/server/app-rsc-route-matching.js +6 -2
  78. package/dist/server/app-server-action-execution.d.ts +1 -1
  79. package/dist/server/app-server-action-execution.js +10 -6
  80. package/dist/server/app-ssr-entry.d.ts +1 -1
  81. package/dist/server/app-ssr-entry.js +12 -38
  82. package/dist/server/app-ssr-router-instance.d.ts +6 -0
  83. package/dist/server/app-ssr-router-instance.js +24 -0
  84. package/dist/server/app-ssr-stream.js +1 -1
  85. package/dist/server/artifact-compatibility.js +1 -1
  86. package/dist/server/before-interactive-head.d.ts +17 -0
  87. package/dist/server/before-interactive-head.js +35 -0
  88. package/dist/server/client-reuse-manifest.js +1 -1
  89. package/dist/server/csp.js +1 -4
  90. package/dist/server/defer-until-stream-consumed.d.ts +7 -0
  91. package/dist/server/defer-until-stream-consumed.js +34 -0
  92. package/dist/server/dev-server.js +82 -37
  93. package/dist/server/instrumentation.js +1 -1
  94. package/dist/server/isr-cache.d.ts +1 -1
  95. package/dist/server/isr-cache.js +1 -1
  96. package/dist/server/isr-decision.d.ts +1 -1
  97. package/dist/server/middleware-matcher.js +20 -9
  98. package/dist/server/middleware-runtime.d.ts +3 -4
  99. package/dist/server/middleware-runtime.js +4 -2
  100. package/dist/server/navigation-planner.d.ts +3 -12
  101. package/dist/server/navigation-planner.js +24 -0
  102. package/dist/server/navigation-trace.d.ts +2 -1
  103. package/dist/server/navigation-trace.js +1 -0
  104. package/dist/server/open-redirect.d.ts +12 -0
  105. package/dist/server/open-redirect.js +21 -0
  106. package/dist/server/operation-token.d.ts +40 -0
  107. package/dist/server/operation-token.js +85 -0
  108. package/dist/server/pages-data-route.d.ts +1 -1
  109. package/dist/server/pages-data-route.js +7 -4
  110. package/dist/server/pages-dev-module-url.d.ts +4 -0
  111. package/dist/server/pages-dev-module-url.js +15 -0
  112. package/dist/server/pages-document-initial-props.d.ts +4 -15
  113. package/dist/server/pages-document-initial-props.js +27 -56
  114. package/dist/server/pages-i18n.js +2 -2
  115. package/dist/server/pages-page-data.d.ts +1 -1
  116. package/dist/server/pages-page-data.js +3 -1
  117. package/dist/server/pages-page-handler.js +3 -1
  118. package/dist/server/pages-page-response.d.ts +3 -1
  119. package/dist/server/pages-page-response.js +6 -6
  120. package/dist/server/pages-readiness.js +1 -1
  121. package/dist/server/pages-request-pipeline.d.ts +7 -7
  122. package/dist/server/pages-request-pipeline.js +63 -21
  123. package/dist/server/prod-server.d.ts +3 -1
  124. package/dist/server/prod-server.js +43 -11
  125. package/dist/server/request-pipeline.d.ts +1 -24
  126. package/dist/server/request-pipeline.js +1 -33
  127. package/dist/server/seed-cache.d.ts +1 -1
  128. package/dist/server/static-file-cache.js +16 -4
  129. package/dist/shims/before-interactive-context.d.ts +14 -3
  130. package/dist/shims/cache-handler.d.ts +106 -0
  131. package/dist/shims/cache-handler.js +176 -0
  132. package/dist/shims/cache-request-state.d.ts +47 -0
  133. package/dist/shims/cache-request-state.js +126 -0
  134. package/dist/shims/cache-runtime.d.ts +2 -2
  135. package/dist/shims/cache-runtime.js +3 -14
  136. package/dist/shims/cache.d.ts +3 -231
  137. package/dist/shims/cache.js +17 -383
  138. package/dist/shims/cdn-cache.d.ts +1 -1
  139. package/dist/shims/cdn-cache.js +1 -1
  140. package/dist/shims/document.d.ts +15 -20
  141. package/dist/shims/document.js +5 -8
  142. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  143. package/dist/shims/error-boundary-navigation.js +44 -0
  144. package/dist/shims/error-boundary.js +10 -8
  145. package/dist/shims/error.js +2 -1
  146. package/dist/shims/fetch-cache.js +1 -1
  147. package/dist/shims/form.js +1 -1
  148. package/dist/shims/image.js +74 -9
  149. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
  150. package/dist/shims/internal/app-page-props-cache-key.js +16 -0
  151. package/dist/shims/internal/navigation-untracked.js +2 -1
  152. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
  153. package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
  154. package/dist/shims/internal/pages-data-target.js +1 -1
  155. package/dist/shims/layout-segment-context.d.ts +1 -1
  156. package/dist/shims/layout-segment-context.js +2 -1
  157. package/dist/shims/link.js +38 -17
  158. package/dist/shims/metadata.js +4 -4
  159. package/dist/shims/navigation-context-state.d.ts +40 -0
  160. package/dist/shims/navigation-context-state.js +116 -0
  161. package/dist/shims/navigation-errors.d.ts +55 -0
  162. package/dist/shims/navigation-errors.js +110 -0
  163. package/dist/shims/navigation-server.d.ts +3 -0
  164. package/dist/shims/navigation-server.js +3 -0
  165. package/dist/shims/navigation-state.d.ts +1 -2
  166. package/dist/shims/navigation-state.js +2 -1
  167. package/dist/shims/navigation.d.ts +3 -291
  168. package/dist/shims/navigation.js +16 -445
  169. package/dist/shims/navigation.react-server.d.ts +2 -2
  170. package/dist/shims/navigation.react-server.js +3 -1
  171. package/dist/shims/request-state-types.d.ts +3 -3
  172. package/dist/shims/router.d.ts +6 -2
  173. package/dist/shims/router.js +99 -20
  174. package/dist/shims/script.js +9 -5
  175. package/dist/shims/slot.js +3 -1
  176. package/dist/shims/unified-request-context.d.ts +2 -2
  177. package/dist/utils/has-trailing-comma.d.ts +24 -0
  178. package/dist/utils/has-trailing-comma.js +62 -0
  179. package/dist/utils/text-stream.d.ts +1 -1
  180. package/dist/utils/text-stream.js +2 -2
  181. package/dist/utils/virtual-module.d.ts +5 -0
  182. package/dist/utils/virtual-module.js +0 -0
  183. package/dist/utils/vite-version.d.ts +12 -1
  184. package/dist/utils/vite-version.js +9 -1
  185. package/package.json +5 -1
@@ -0,0 +1,176 @@
1
+ import { readCacheControlNumberField } from "../utils/cache-control-metadata.js";
2
+ //#region src/shims/cache-handler.ts
3
+ var NoOpCacheHandler = class {
4
+ async get(_key, _ctx) {
5
+ return null;
6
+ }
7
+ async set(_key, _data, _ctx) {}
8
+ async revalidateTag(_tags, _durations) {}
9
+ };
10
+ const DEFAULT_MEMORY_CACHE_MAX_SIZE = 50 * 1024 * 1024;
11
+ const MAX_REVALIDATED_TAG_ENTRIES = 1e4;
12
+ function estimateStringMapSize(map) {
13
+ if (!map) return 0;
14
+ let size = 0;
15
+ for (const [key, value] of Object.entries(map)) {
16
+ size += key.length;
17
+ if (Array.isArray(value)) for (const item of value) size += item.length;
18
+ else size += value.length;
19
+ }
20
+ return size;
21
+ }
22
+ function estimateIncrementalCacheValueSize(value) {
23
+ if (value === null) return 25;
24
+ switch (value.kind) {
25
+ case "FETCH": return JSON.stringify(value.data ?? "").length;
26
+ case "PAGES": return value.html.length + JSON.stringify(value.pageData ?? {}).length + estimateStringMapSize(value.headers);
27
+ case "APP_PAGE": return value.html.length + (value.rscData?.byteLength ?? 0) + (value.postponed?.length ?? 0) + estimateStringMapSize(value.headers);
28
+ case "APP_ROUTE": return value.body.byteLength + estimateStringMapSize(value.headers);
29
+ case "REDIRECT": return JSON.stringify(value.props ?? {}).length;
30
+ case "IMAGE": return value.buffer.byteLength + value.extension.length + value.etag.length;
31
+ default: return JSON.stringify(value).length;
32
+ }
33
+ }
34
+ function resolveMemoryCacheMaxSize(options) {
35
+ if (typeof options === "number") return options;
36
+ if (typeof options?.cacheMaxMemorySize === "number") return options.cacheMaxMemorySize;
37
+ if (typeof options?.maxMemoryCacheSize === "number") return options.maxMemoryCacheSize;
38
+ return DEFAULT_MEMORY_CACHE_MAX_SIZE;
39
+ }
40
+ function readStringArrayField(ctx, field) {
41
+ const value = ctx?.[field];
42
+ if (!Array.isArray(value)) return [];
43
+ return value.filter((item) => typeof item === "string");
44
+ }
45
+ var MemoryCacheHandler = class {
46
+ store = /* @__PURE__ */ new Map();
47
+ tagRevalidatedAt = /* @__PURE__ */ new Map();
48
+ maxMemoryCacheSize;
49
+ currentMemoryCacheSize = 0;
50
+ constructor(options) {
51
+ this.maxMemoryCacheSize = resolveMemoryCacheMaxSize(options);
52
+ }
53
+ estimateEntrySize(entry) {
54
+ return estimateIncrementalCacheValueSize(entry.value) + entry.tags.reduce((sum, tag) => sum + tag.length, 0) + 64;
55
+ }
56
+ deleteEntry(key) {
57
+ const existing = this.store.get(key);
58
+ if (!existing) return;
59
+ this.currentMemoryCacheSize -= this.estimateEntrySize(existing);
60
+ this.store.delete(key);
61
+ }
62
+ touchEntry(key, entry) {
63
+ this.store.delete(key);
64
+ this.store.set(key, entry);
65
+ }
66
+ evictLeastRecentlyUsed() {
67
+ while (this.maxMemoryCacheSize > 0 && this.currentMemoryCacheSize > this.maxMemoryCacheSize) {
68
+ const oldestKey = this.store.keys().next().value;
69
+ if (oldestKey === void 0) return;
70
+ this.deleteEntry(oldestKey);
71
+ }
72
+ }
73
+ async get(key, ctx) {
74
+ const entry = this.store.get(key);
75
+ if (!entry) return null;
76
+ for (const tag of entry.tags) {
77
+ const revalidatedAt = this.tagRevalidatedAt.get(tag);
78
+ if (revalidatedAt && revalidatedAt >= entry.lastModified) {
79
+ this.deleteEntry(key);
80
+ return null;
81
+ }
82
+ }
83
+ for (const tag of readStringArrayField(ctx, "softTags")) {
84
+ const revalidatedAt = this.tagRevalidatedAt.get(tag);
85
+ if (revalidatedAt && revalidatedAt >= entry.lastModified) return null;
86
+ }
87
+ if (entry.expireAt !== null && Date.now() > entry.expireAt) {
88
+ this.deleteEntry(key);
89
+ return null;
90
+ }
91
+ this.touchEntry(key, entry);
92
+ if (entry.revalidateAt !== null && Date.now() > entry.revalidateAt) return {
93
+ lastModified: entry.lastModified,
94
+ value: entry.value,
95
+ cacheState: "stale",
96
+ cacheControl: entry.cacheControl
97
+ };
98
+ return {
99
+ lastModified: entry.lastModified,
100
+ value: entry.value,
101
+ cacheControl: entry.cacheControl
102
+ };
103
+ }
104
+ async set(key, data, ctx) {
105
+ const tagSet = /* @__PURE__ */ new Set();
106
+ if (data && "tags" in data && Array.isArray(data.tags)) for (const tag of data.tags) tagSet.add(tag);
107
+ for (const tag of readStringArrayField(ctx, "tags")) tagSet.add(tag);
108
+ const tags = [...tagSet];
109
+ let effectiveRevalidate = readCacheControlNumberField(ctx, "revalidate");
110
+ const effectiveExpire = readCacheControlNumberField(ctx, "expire");
111
+ if (data && "revalidate" in data && typeof data.revalidate === "number") effectiveRevalidate = data.revalidate;
112
+ if (effectiveRevalidate === 0) return;
113
+ const now = Date.now();
114
+ const revalidateAt = typeof effectiveRevalidate === "number" && effectiveRevalidate > 0 ? now + effectiveRevalidate * 1e3 : null;
115
+ const expireAt = typeof effectiveExpire === "number" && effectiveExpire > 0 ? now + effectiveExpire * 1e3 : null;
116
+ const cacheControl = typeof effectiveRevalidate === "number" ? effectiveExpire === void 0 ? { revalidate: effectiveRevalidate } : {
117
+ revalidate: effectiveRevalidate,
118
+ expire: effectiveExpire
119
+ } : void 0;
120
+ if (this.maxMemoryCacheSize === 0) return;
121
+ const entry = {
122
+ value: data,
123
+ tags,
124
+ lastModified: now,
125
+ revalidateAt,
126
+ expireAt,
127
+ cacheControl
128
+ };
129
+ const entrySize = this.estimateEntrySize(entry);
130
+ if (entrySize > this.maxMemoryCacheSize) {
131
+ this.deleteEntry(key);
132
+ return;
133
+ }
134
+ this.deleteEntry(key);
135
+ this.store.set(key, entry);
136
+ this.currentMemoryCacheSize += entrySize;
137
+ this.evictLeastRecentlyUsed();
138
+ }
139
+ async revalidateTag(tags) {
140
+ const tagList = Array.isArray(tags) ? tags : [tags];
141
+ const now = Date.now();
142
+ for (const tag of tagList) {
143
+ this.tagRevalidatedAt.set(tag, now);
144
+ while (this.tagRevalidatedAt.size > MAX_REVALIDATED_TAG_ENTRIES) {
145
+ const oldest = this.tagRevalidatedAt.keys().next().value;
146
+ if (oldest === void 0) break;
147
+ this.tagRevalidatedAt.delete(oldest);
148
+ }
149
+ }
150
+ }
151
+ resetRequestCache() {}
152
+ };
153
+ const HANDLER_KEY = Symbol.for("vinext.cacheHandler");
154
+ const globalHandlers = globalThis;
155
+ function getActiveHandler() {
156
+ return globalHandlers[HANDLER_KEY] ?? (globalHandlers[HANDLER_KEY] = new MemoryCacheHandler());
157
+ }
158
+ function configureMemoryCacheHandler(options) {
159
+ const current = globalHandlers[HANDLER_KEY];
160
+ if (current && !(current instanceof MemoryCacheHandler)) return;
161
+ globalHandlers[HANDLER_KEY] = new MemoryCacheHandler(options);
162
+ }
163
+ function setDataCacheHandler(handler) {
164
+ globalHandlers[HANDLER_KEY] = handler;
165
+ }
166
+ function getDataCacheHandler() {
167
+ return getActiveHandler();
168
+ }
169
+ function setCacheHandler(handler) {
170
+ setDataCacheHandler(handler);
171
+ }
172
+ function getCacheHandler() {
173
+ return getDataCacheHandler();
174
+ }
175
+ //#endregion
176
+ export { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, setCacheHandler, setDataCacheHandler };
@@ -0,0 +1,47 @@
1
+ //#region src/shims/cache-request-state.d.ts
2
+ type CacheLifeConfig = {
3
+ stale?: number;
4
+ revalidate?: number;
5
+ expire?: number;
6
+ };
7
+ declare const cacheLifeProfiles: Record<string, CacheLifeConfig>;
8
+ type CacheContextLike = {
9
+ tags: string[];
10
+ lifeConfigs: CacheLifeConfig[];
11
+ variant: string;
12
+ hasExplicitRevalidate: boolean;
13
+ hasExplicitExpire: boolean;
14
+ dynamicNestedCacheError: Error | undefined;
15
+ };
16
+ declare function _registerCacheContextAccessor(fn: () => CacheContextLike | null): void;
17
+ declare function getRegisteredCacheContext(): CacheContextLike | null;
18
+ type UnstableCacheRevalidationMode = "foreground" | "background";
19
+ type ActionRevalidationKind = 0 | 1 | 2;
20
+ type UnstableCacheObservation = Readonly<{
21
+ kind: "unstable_cache";
22
+ keyHash: string;
23
+ revalidate: number | false | null;
24
+ tagCount: number;
25
+ tagHash: string | null;
26
+ }>;
27
+ type CacheState = {
28
+ actionRevalidationKind: ActionRevalidationKind;
29
+ requestScopedCacheLife: CacheLifeConfig | null;
30
+ unstableCacheObservations: Map<string, UnstableCacheObservation>;
31
+ unstableCacheRevalidation: UnstableCacheRevalidationMode;
32
+ };
33
+ declare const ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;
34
+ declare const ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;
35
+ declare function _runWithCacheState<T>(fn: () => Promise<T>): Promise<T>;
36
+ declare function _runWithCacheState<T>(fn: () => T | Promise<T>): T | Promise<T>;
37
+ declare function _initRequestScopedCacheState(): void;
38
+ declare function markActionRevalidation(kind: ActionRevalidationKind): void;
39
+ declare function getAndClearActionRevalidationKind(): ActionRevalidationKind;
40
+ declare function _setRequestScopedCacheLife(config: CacheLifeConfig): void;
41
+ declare function _peekRequestScopedCacheLife(): CacheLifeConfig | null;
42
+ declare function _consumeRequestScopedCacheLife(): CacheLifeConfig | null;
43
+ declare function recordUnstableCacheObservation(observation: UnstableCacheObservation): void;
44
+ declare function _peekUnstableCacheObservations(): UnstableCacheObservation[];
45
+ declare function shouldServeStaleUnstableCacheEntry(): boolean;
46
+ //#endregion
47
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry };
@@ -0,0 +1,126 @@
1
+ import { getOrCreateAls } from "./internal/als-registry.js";
2
+ import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
3
+ import { getHeadersAccessPhase } from "./headers.js";
4
+ //#region src/shims/cache-request-state.ts
5
+ const cacheLifeProfiles = {
6
+ default: {
7
+ revalidate: 900,
8
+ expire: 4294967294
9
+ },
10
+ seconds: {
11
+ stale: 30,
12
+ revalidate: 1,
13
+ expire: 60
14
+ },
15
+ minutes: {
16
+ stale: 300,
17
+ revalidate: 60,
18
+ expire: 3600
19
+ },
20
+ hours: {
21
+ stale: 300,
22
+ revalidate: 3600,
23
+ expire: 86400
24
+ },
25
+ days: {
26
+ stale: 300,
27
+ revalidate: 86400,
28
+ expire: 604800
29
+ },
30
+ weeks: {
31
+ stale: 300,
32
+ revalidate: 604800,
33
+ expire: 2592e3
34
+ },
35
+ max: {
36
+ stale: 300,
37
+ revalidate: 2592e3,
38
+ expire: 31536e3
39
+ }
40
+ };
41
+ let getCacheContext = null;
42
+ function _registerCacheContextAccessor(fn) {
43
+ getCacheContext = fn;
44
+ }
45
+ function getRegisteredCacheContext() {
46
+ return getCacheContext?.() ?? null;
47
+ }
48
+ const FALLBACK_KEY = Symbol.for("vinext.cache.fallback");
49
+ const globalState = globalThis;
50
+ const cacheAls = getOrCreateAls("vinext.cache.als");
51
+ const ACTION_DID_NOT_REVALIDATE = 0;
52
+ const ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;
53
+ const ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;
54
+ const fallbackState = globalState[FALLBACK_KEY] ??= {
55
+ actionRevalidationKind: ACTION_DID_NOT_REVALIDATE,
56
+ requestScopedCacheLife: null,
57
+ unstableCacheObservations: /* @__PURE__ */ new Map(),
58
+ unstableCacheRevalidation: "foreground"
59
+ };
60
+ function getCacheState() {
61
+ if (isInsideUnifiedScope()) return getRequestContext();
62
+ return cacheAls.getStore() ?? fallbackState;
63
+ }
64
+ function _runWithCacheState(fn) {
65
+ if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((context) => {
66
+ context.actionRevalidationKind = ACTION_DID_NOT_REVALIDATE;
67
+ context.requestScopedCacheLife = null;
68
+ context.unstableCacheObservations = /* @__PURE__ */ new Map();
69
+ context.unstableCacheRevalidation = "foreground";
70
+ }, fn);
71
+ const state = {
72
+ actionRevalidationKind: ACTION_DID_NOT_REVALIDATE,
73
+ requestScopedCacheLife: null,
74
+ unstableCacheObservations: /* @__PURE__ */ new Map(),
75
+ unstableCacheRevalidation: "foreground"
76
+ };
77
+ return cacheAls.run(state, fn);
78
+ }
79
+ function _initRequestScopedCacheState() {
80
+ const state = getCacheState();
81
+ state.actionRevalidationKind = ACTION_DID_NOT_REVALIDATE;
82
+ state.requestScopedCacheLife = null;
83
+ state.unstableCacheObservations = /* @__PURE__ */ new Map();
84
+ }
85
+ function markActionRevalidation(kind) {
86
+ if (getHeadersAccessPhase() !== "action") return;
87
+ const state = getCacheState();
88
+ state.actionRevalidationKind = state.actionRevalidationKind === 1 ? 1 : kind;
89
+ }
90
+ function getAndClearActionRevalidationKind() {
91
+ const state = getCacheState();
92
+ const kind = state.actionRevalidationKind;
93
+ state.actionRevalidationKind = ACTION_DID_NOT_REVALIDATE;
94
+ return kind;
95
+ }
96
+ function _setRequestScopedCacheLife(config) {
97
+ const state = getCacheState();
98
+ if (state.requestScopedCacheLife === null) {
99
+ state.requestScopedCacheLife = { ...config };
100
+ return;
101
+ }
102
+ if (config.stale !== void 0) state.requestScopedCacheLife.stale = state.requestScopedCacheLife.stale !== void 0 ? Math.min(state.requestScopedCacheLife.stale, config.stale) : config.stale;
103
+ if (config.revalidate !== void 0) state.requestScopedCacheLife.revalidate = state.requestScopedCacheLife.revalidate !== void 0 ? Math.min(state.requestScopedCacheLife.revalidate, config.revalidate) : config.revalidate;
104
+ if (config.expire !== void 0) state.requestScopedCacheLife.expire = state.requestScopedCacheLife.expire !== void 0 ? Math.min(state.requestScopedCacheLife.expire, config.expire) : config.expire;
105
+ }
106
+ function _peekRequestScopedCacheLife() {
107
+ const config = getCacheState().requestScopedCacheLife;
108
+ return config === null ? null : { ...config };
109
+ }
110
+ function _consumeRequestScopedCacheLife() {
111
+ const state = getCacheState();
112
+ const config = state.requestScopedCacheLife;
113
+ state.requestScopedCacheLife = null;
114
+ return config;
115
+ }
116
+ function recordUnstableCacheObservation(observation) {
117
+ getCacheState().unstableCacheObservations.set(observation.keyHash, observation);
118
+ }
119
+ function _peekUnstableCacheObservations() {
120
+ return [...getCacheState().unstableCacheObservations.values()].sort((a, b) => a.keyHash.localeCompare(b.keyHash));
121
+ }
122
+ function shouldServeStaleUnstableCacheEntry() {
123
+ return getCacheState().unstableCacheRevalidation === "background";
124
+ }
125
+ //#endregion
126
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry };
@@ -1,4 +1,5 @@
1
- import { CacheLifeConfig } from "./cache.js";
1
+ import { CacheLifeConfig } from "./cache-request-state.js";
2
+ import { markAppPagePropsForUseCache } from "./internal/app-page-props-cache-key.js";
2
3
 
3
4
  //#region src/shims/cache-runtime.d.ts
4
5
  /**
@@ -58,7 +59,6 @@ declare function runWithPrivateCache<T>(fn: () => T | Promise<T>): T | Promise<T
58
59
  * Only needed when not using runWithPrivateCache() (legacy path).
59
60
  */
60
61
  declare function clearPrivateCache(): void;
61
- declare function markAppPagePropsForUseCache<T extends object>(props: T): T;
62
62
  type RegisterCachedFunctionOptions = {
63
63
  /**
64
64
  * Internal transform metadata for file-level `"use cache"` default exports
@@ -1,10 +1,12 @@
1
1
  import { getOrCreateAls } from "./internal/als-registry.js";
2
2
  import { getRequestContext, isInsideUnifiedScope, runWithUnifiedStateMutation } from "./unified-request-context.js";
3
3
  import { VINEXT_RSC_MARKER_HEADER } from "../server/headers.js";
4
+ import { getDataCacheHandler } from "./cache-handler.js";
4
5
  import { trackPprFallbackShellCacheTask } from "./ppr-fallback-shell.js";
5
6
  import { markDynamicUsage } from "./headers.js";
6
- import { _registerCacheContextAccessor, _setRequestScopedCacheLife, cacheLifeProfiles, getDataCacheHandler } from "./cache.js";
7
+ import { _registerCacheContextAccessor, _setRequestScopedCacheLife, cacheLifeProfiles } from "./cache-request-state.js";
7
8
  import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.js";
9
+ import { isMarkedAppPagePropsObject, markAppPagePropsForUseCache } from "./internal/app-page-props-cache-key.js";
8
10
  //#region src/shims/cache-runtime.ts
9
11
  /**
10
12
  * "use cache" runtime
@@ -35,7 +37,6 @@ import { addCollectedRequestTags, getCurrentFetchSoftTags } from "./fetch-cache.
35
37
  * - "use cache: remote" — shared cache (explicit)
36
38
  * - "use cache: private" — per-request cache (not shared across requests)
37
39
  */
38
- const APP_PAGE_PROPS_CACHE_KEY_MARKER = Symbol.for("vinext.appPagePropsCacheKeyMarker");
39
40
  /** Threshold below which expire is considered "dynamic" (5 minutes in seconds). */
40
41
  const DYNAMIC_EXPIRE = 300;
41
42
  /**
@@ -222,15 +223,6 @@ function clearPrivateCache() {
222
223
  if (state) state._privateCache = /* @__PURE__ */ new Map();
223
224
  else _privateFallbackState._privateCache = /* @__PURE__ */ new Map();
224
225
  }
225
- function markAppPagePropsForUseCache(props) {
226
- Object.defineProperty(props, APP_PAGE_PROPS_CACHE_KEY_MARKER, {
227
- configurable: false,
228
- enumerable: false,
229
- value: true,
230
- writable: false
231
- });
232
- return props;
233
- }
234
226
  /**
235
227
  * Register a function as a cached function. This is called by the Vite
236
228
  * transform for each "use cache" function.
@@ -429,9 +421,6 @@ function unwrapThenableObjects(value, options = {}) {
429
421
  }
430
422
  return result;
431
423
  }
432
- function isMarkedAppPagePropsObject(value) {
433
- return Reflect.get(value, APP_PAGE_PROPS_CACHE_KEY_MARKER) === true;
434
- }
435
424
  function unwrapThenableObjectArray(values, options) {
436
425
  return values.map((value, index) => unwrapThenableObjects(value, { omitAppPageSearchParamsAtRoot: index === 0 && options.omitAppPageSearchParamsFromFirstArg }));
437
426
  }
@@ -1,175 +1,8 @@
1
- import { CacheContext } from "./cache-runtime.js";
2
- import { RenderObservation } from "../server/cache-proof.js";
1
+ import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, getRegisteredCacheContext, markActionRevalidation, recordUnstableCacheObservation, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
2
+ import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
3
3
  import { ExecutionContextLike, getRequestExecutionContext, runWithExecutionContext } from "./request-context.js";
4
4
 
5
5
  //#region src/shims/cache.d.ts
6
- type CacheContextLike = {
7
- tags: string[];
8
- lifeConfigs: CacheContext["lifeConfigs"];
9
- variant: string;
10
- hasExplicitRevalidate: boolean;
11
- hasExplicitExpire: boolean;
12
- dynamicNestedCacheError: Error | undefined;
13
- };
14
- /**
15
- * Register the cache context accessor. Called by cache-runtime.ts on load.
16
- * @internal
17
- */
18
- declare function _registerCacheContextAccessor(fn: () => CacheContextLike | null): void;
19
- type CacheHandlerValue = {
20
- lastModified: number;
21
- age?: number;
22
- cacheState?: string;
23
- cacheControl?: CacheControlMetadata;
24
- value: IncrementalCacheValue | null;
25
- };
26
- type CacheControlMetadata = {
27
- revalidate: number;
28
- expire?: number;
29
- };
30
- /** Discriminated union of cache value types. */
31
- type IncrementalCacheValue = CachedFetchValue | CachedAppPageValue | CachedPagesValue | CachedRouteValue | CachedRedirectValue | CachedImageValue;
32
- type CachedFetchValue = {
33
- kind: "FETCH";
34
- data: {
35
- headers: Record<string, string>;
36
- body: string;
37
- url: string;
38
- status?: number;
39
- };
40
- tags?: string[];
41
- revalidate: number | false;
42
- };
43
- type CachedAppPageValue = {
44
- kind: "APP_PAGE";
45
- html: string;
46
- rscData: ArrayBuffer | undefined;
47
- headers: Record<string, string | string[]> | undefined;
48
- postponed: string | undefined;
49
- renderObservation?: RenderObservation;
50
- status: number | undefined;
51
- };
52
- type CachedPagesValue = {
53
- kind: "PAGES";
54
- html: string;
55
- pageData: object;
56
- generatedFromDataRequest?: boolean;
57
- headers: Record<string, string | string[]> | undefined;
58
- status: number | undefined;
59
- };
60
- type CachedRouteValue = {
61
- kind: "APP_ROUTE";
62
- body: ArrayBuffer;
63
- status: number;
64
- headers: Record<string, string | string[]>;
65
- };
66
- type CachedRedirectValue = {
67
- kind: "REDIRECT";
68
- props: object;
69
- };
70
- type CachedImageValue = {
71
- kind: "IMAGE";
72
- etag: string;
73
- buffer: ArrayBuffer;
74
- extension: string;
75
- revalidate?: number;
76
- };
77
- type CacheHandlerContext = {
78
- dev?: boolean;
79
- maxMemoryCacheSize?: number;
80
- revalidatedTags?: string[];
81
- [key: string]: unknown;
82
- };
83
- type CacheHandler = {
84
- get(key: string, ctx?: Record<string, unknown>): Promise<CacheHandlerValue | null>;
85
- set(key: string, data: IncrementalCacheValue | null, ctx?: Record<string, unknown>): Promise<void>;
86
- revalidateTag(tags: string | string[], durations?: {
87
- expire?: number;
88
- }): Promise<void>;
89
- resetRequestCache?(): void;
90
- };
91
- declare class NoOpCacheHandler implements CacheHandler {
92
- get(_key: string, _ctx?: Record<string, unknown>): Promise<CacheHandlerValue | null>;
93
- set(_key: string, _data: IncrementalCacheValue | null, _ctx?: Record<string, unknown>): Promise<void>;
94
- revalidateTag(_tags: string | string[], _durations?: {
95
- expire?: number;
96
- }): Promise<void>;
97
- }
98
- type MemoryCacheHandlerOptions = Pick<CacheHandlerContext, "maxMemoryCacheSize"> & {
99
- cacheMaxMemorySize?: number;
100
- };
101
- /**
102
- * In-memory data cache handler. This is the built-in default — vinext installs
103
- * it automatically, so consumers should not construct or register it by hand.
104
- *
105
- * @deprecated Consumers should not instantiate cache handlers directly.
106
- * Configure caching declaratively via the `cache` option on the `vinext()`
107
- * plugin (see {@link setDataCacheHandler}); the in-memory handler is the
108
- * default when nothing is configured, and its size is tuned via the
109
- * `cacheMaxMemorySize` plugin option.
110
- */
111
- declare class MemoryCacheHandler implements CacheHandler {
112
- private store;
113
- private tagRevalidatedAt;
114
- private readonly maxMemoryCacheSize;
115
- private currentMemoryCacheSize;
116
- constructor(options?: number | MemoryCacheHandlerOptions);
117
- private estimateEntrySize;
118
- private deleteEntry;
119
- private touchEntry;
120
- private evictLeastRecentlyUsed;
121
- get(key: string, _ctx?: Record<string, unknown>): Promise<CacheHandlerValue | null>;
122
- set(key: string, data: IncrementalCacheValue | null, ctx?: Record<string, unknown>): Promise<void>;
123
- revalidateTag(tags: string | string[], _durations?: {
124
- expire?: number;
125
- }): Promise<void>;
126
- resetRequestCache(): void;
127
- }
128
- declare function configureMemoryCacheHandler(options?: MemoryCacheHandlerOptions): void;
129
- /**
130
- * Set the **data cache** handler. This backs all data-cache concerns —
131
- * `fetch` caching, `"use cache"`, `unstable_cache` — and is also the default
132
- * underlying store for page-level ISR (via the default CDN cache adapter).
133
- *
134
- * The handler must implement the CacheHandler interface (same shape as
135
- * Next.js 16's CacheHandler class).
136
- *
137
- * @deprecated Don't wire up the data cache imperatively. Configure it
138
- * declaratively via the `cache.data` option on the `vinext()` plugin in your
139
- * `vite.config.ts`, using a config-time adapter builder. On Cloudflare Workers:
140
- *
141
- * ```ts
142
- * import { vinext } from "vinext";
143
- * import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";
144
- *
145
- * export default defineConfig({
146
- * plugins: [vinext({ cache: { data: kvDataAdapter({ binding: "VINEXT_KV_CACHE" }) } })],
147
- * });
148
- * ```
149
- *
150
- * The plugin defers instantiation to the first request and registers the
151
- * handler across every runtime/router entry, so you don't have to call this
152
- * from a worker entry. This setter remains as the internal registration target
153
- * and for backwards compatibility, but is not the recommended consumer API.
154
- */
155
- declare function setDataCacheHandler(handler: CacheHandler): void;
156
- /**
157
- * Get the active data cache handler (for internal use or testing).
158
- */
159
- declare function getDataCacheHandler(): CacheHandler;
160
- /**
161
- * @deprecated Don't wire up the data cache imperatively. Configure it
162
- * declaratively via the `cache.data` option on the `vinext()` plugin (e.g.
163
- * `kvDataAdapter()` from `@vinext/cloudflare/cache/kv-data-adapter`). See
164
- * {@link setDataCacheHandler} for the migration example. Retained as a
165
- * backwards-compatible alias — `setCacheHandler` has always configured the
166
- * data cache handler.
167
- */
168
- declare function setCacheHandler(handler: CacheHandler): void;
169
- /**
170
- * @deprecated Prefer {@link getDataCacheHandler}.
171
- */
172
- declare function getCacheHandler(): CacheHandler;
173
6
  /**
174
7
  * Revalidate cached data associated with a specific cache tag.
175
8
  *
@@ -264,67 +97,6 @@ declare function io(): Promise<void>;
264
97
  * removed in a future minor.
265
98
  */
266
99
  declare function unstable_io(): Promise<void>;
267
- type UnstableCacheRevalidationMode = "foreground" | "background";
268
- type ActionRevalidationKind = 0 | 1 | 2;
269
- type UnstableCacheObservation = Readonly<{
270
- kind: "unstable_cache";
271
- keyHash: string;
272
- revalidate: number | false | null;
273
- tagCount: number;
274
- tagHash: string | null;
275
- }>;
276
- type CacheState = {
277
- actionRevalidationKind: ActionRevalidationKind;
278
- requestScopedCacheLife: CacheLifeConfig | null;
279
- unstableCacheObservations: Map<string, UnstableCacheObservation>;
280
- unstableCacheRevalidation: UnstableCacheRevalidationMode;
281
- };
282
- /**
283
- * Run a function within a cache state ALS scope.
284
- * Ensures per-request isolation for request-scoped cacheLife config
285
- * on concurrent runtimes.
286
- * @internal
287
- */
288
- declare function _runWithCacheState<T>(fn: () => Promise<T>): Promise<T>;
289
- declare function _runWithCacheState<T>(fn: () => T | Promise<T>): T | Promise<T>;
290
- /**
291
- * Initialize cache ALS for a new request. Call at request entry.
292
- * Only needed when not using _runWithCacheState() (legacy path).
293
- * @internal
294
- */
295
- declare function _initRequestScopedCacheState(): void;
296
- declare function getAndClearActionRevalidationKind(): ActionRevalidationKind;
297
- /**
298
- * Set a request-scoped cache life config. Called by cacheLife() so the route
299
- * render can inherit cache policy from file-level and nested "use cache" work.
300
- * @internal
301
- */
302
- declare function _setRequestScopedCacheLife(config: CacheLifeConfig): void;
303
- /**
304
- * Read the request-scoped cache life without clearing it. Prerender response
305
- * shaping needs the metadata before the manifest writer consumes it after the
306
- * body has been fully rendered.
307
- * @internal
308
- */
309
- declare function _peekRequestScopedCacheLife(): CacheLifeConfig | null;
310
- /**
311
- * Consume and reset the request-scoped cache life. Returns null if none was set.
312
- * @internal
313
- */
314
- declare function _consumeRequestScopedCacheLife(): CacheLifeConfig | null;
315
- declare function _peekUnstableCacheObservations(): UnstableCacheObservation[];
316
- /**
317
- * Cache life configuration. Controls stale-while-revalidate behavior.
318
- */
319
- type CacheLifeConfig = {
320
- /** How long (seconds) the client can cache without checking the server */stale?: number; /** How frequently (seconds) the server cache refreshes */
321
- revalidate?: number; /** Max staleness (seconds) before deoptimizing to dynamic */
322
- expire?: number;
323
- };
324
- /**
325
- * Built-in cache life profiles matching Next.js 16.
326
- */
327
- declare const cacheLifeProfiles: Record<string, CacheLifeConfig>;
328
100
  /**
329
101
  * Set the cache lifetime for a "use cache" function.
330
102
  *
@@ -370,4 +142,4 @@ type UnstableCacheOptions = {
370
142
  */
371
143
  declare function unstable_cache<T extends (...args: any[]) => Promise<any>>(fn: T, keyParts?: string[], options?: UnstableCacheOptions): T;
372
144
  //#endregion
373
- export { ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRequestExecutionContext, io, isInsideUnstableCacheScope, unstable_noStore as noStore, unstable_noStore, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
145
+ export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, UnstableCacheObservation, UnstableCacheRevalidationMode, _consumeRequestScopedCacheLife, _initRequestScopedCacheState, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _registerCacheContextAccessor, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, recordUnstableCacheObservation, refresh, revalidatePath, revalidateTag, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };