vinext 0.0.0 → 0.0.1

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 (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/build/static-export.d.ts +78 -0
  4. package/dist/build/static-export.d.ts.map +1 -0
  5. package/dist/build/static-export.js +553 -0
  6. package/dist/build/static-export.js.map +1 -0
  7. package/dist/check.d.ts +52 -0
  8. package/dist/check.d.ts.map +1 -0
  9. package/dist/check.js +483 -0
  10. package/dist/check.js.map +1 -0
  11. package/dist/cli.d.ts +15 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +565 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/client/entry.d.ts +2 -0
  16. package/dist/client/entry.d.ts.map +1 -0
  17. package/dist/client/entry.js +85 -0
  18. package/dist/client/entry.js.map +1 -0
  19. package/dist/cloudflare/index.d.ts +8 -0
  20. package/dist/cloudflare/index.d.ts.map +1 -0
  21. package/dist/cloudflare/index.js +8 -0
  22. package/dist/cloudflare/index.js.map +1 -0
  23. package/dist/cloudflare/kv-cache-handler.d.ts +68 -0
  24. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -0
  25. package/dist/cloudflare/kv-cache-handler.js +304 -0
  26. package/dist/cloudflare/kv-cache-handler.js.map +1 -0
  27. package/dist/cloudflare/tpr.d.ts +78 -0
  28. package/dist/cloudflare/tpr.d.ts.map +1 -0
  29. package/dist/cloudflare/tpr.js +672 -0
  30. package/dist/cloudflare/tpr.js.map +1 -0
  31. package/dist/config/config-matchers.d.ts +106 -0
  32. package/dist/config/config-matchers.d.ts.map +1 -0
  33. package/dist/config/config-matchers.js +499 -0
  34. package/dist/config/config-matchers.js.map +1 -0
  35. package/dist/config/next-config.d.ts +153 -0
  36. package/dist/config/next-config.d.ts.map +1 -0
  37. package/dist/config/next-config.js +274 -0
  38. package/dist/config/next-config.js.map +1 -0
  39. package/dist/deploy.d.ts +87 -0
  40. package/dist/deploy.d.ts.map +1 -0
  41. package/dist/deploy.js +644 -0
  42. package/dist/deploy.js.map +1 -0
  43. package/dist/index.d.ts +156 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +3287 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/init.d.ts +55 -0
  48. package/dist/init.d.ts.map +1 -0
  49. package/dist/init.js +201 -0
  50. package/dist/init.js.map +1 -0
  51. package/dist/routing/app-router.d.ts +96 -0
  52. package/dist/routing/app-router.d.ts.map +1 -0
  53. package/dist/routing/app-router.js +815 -0
  54. package/dist/routing/app-router.js.map +1 -0
  55. package/dist/routing/pages-router.d.ts +52 -0
  56. package/dist/routing/pages-router.d.ts.map +1 -0
  57. package/dist/routing/pages-router.js +239 -0
  58. package/dist/routing/pages-router.js.map +1 -0
  59. package/dist/server/api-handler.d.ts +18 -0
  60. package/dist/server/api-handler.d.ts.map +1 -0
  61. package/dist/server/api-handler.js +169 -0
  62. package/dist/server/api-handler.js.map +1 -0
  63. package/dist/server/app-dev-server.d.ts +42 -0
  64. package/dist/server/app-dev-server.d.ts.map +1 -0
  65. package/dist/server/app-dev-server.js +2718 -0
  66. package/dist/server/app-dev-server.js.map +1 -0
  67. package/dist/server/app-router-entry.d.ts +18 -0
  68. package/dist/server/app-router-entry.d.ts.map +1 -0
  69. package/dist/server/app-router-entry.js +34 -0
  70. package/dist/server/app-router-entry.js.map +1 -0
  71. package/dist/server/dev-server.d.ts +40 -0
  72. package/dist/server/dev-server.d.ts.map +1 -0
  73. package/dist/server/dev-server.js +758 -0
  74. package/dist/server/dev-server.js.map +1 -0
  75. package/dist/server/html.d.ts +22 -0
  76. package/dist/server/html.d.ts.map +1 -0
  77. package/dist/server/html.js +29 -0
  78. package/dist/server/html.js.map +1 -0
  79. package/dist/server/image-optimization.d.ts +56 -0
  80. package/dist/server/image-optimization.d.ts.map +1 -0
  81. package/dist/server/image-optimization.js +103 -0
  82. package/dist/server/image-optimization.js.map +1 -0
  83. package/dist/server/instrumentation.d.ts +68 -0
  84. package/dist/server/instrumentation.d.ts.map +1 -0
  85. package/dist/server/instrumentation.js +90 -0
  86. package/dist/server/instrumentation.js.map +1 -0
  87. package/dist/server/isr-cache.d.ts +61 -0
  88. package/dist/server/isr-cache.d.ts.map +1 -0
  89. package/dist/server/isr-cache.js +134 -0
  90. package/dist/server/isr-cache.js.map +1 -0
  91. package/dist/server/metadata-routes.d.ts +103 -0
  92. package/dist/server/metadata-routes.d.ts.map +1 -0
  93. package/dist/server/metadata-routes.js +270 -0
  94. package/dist/server/metadata-routes.js.map +1 -0
  95. package/dist/server/middleware.d.ts +77 -0
  96. package/dist/server/middleware.d.ts.map +1 -0
  97. package/dist/server/middleware.js +228 -0
  98. package/dist/server/middleware.js.map +1 -0
  99. package/dist/server/prod-server.d.ts +78 -0
  100. package/dist/server/prod-server.d.ts.map +1 -0
  101. package/dist/server/prod-server.js +712 -0
  102. package/dist/server/prod-server.js.map +1 -0
  103. package/dist/shims/amp.d.ts +17 -0
  104. package/dist/shims/amp.d.ts.map +1 -0
  105. package/dist/shims/amp.js +21 -0
  106. package/dist/shims/amp.js.map +1 -0
  107. package/dist/shims/app.d.ts +12 -0
  108. package/dist/shims/app.d.ts.map +1 -0
  109. package/dist/shims/app.js +2 -0
  110. package/dist/shims/app.js.map +1 -0
  111. package/dist/shims/cache-runtime.d.ts +68 -0
  112. package/dist/shims/cache-runtime.d.ts.map +1 -0
  113. package/dist/shims/cache-runtime.js +437 -0
  114. package/dist/shims/cache-runtime.js.map +1 -0
  115. package/dist/shims/cache.d.ts +243 -0
  116. package/dist/shims/cache.d.ts.map +1 -0
  117. package/dist/shims/cache.js +415 -0
  118. package/dist/shims/cache.js.map +1 -0
  119. package/dist/shims/client-only.d.ts +18 -0
  120. package/dist/shims/client-only.d.ts.map +1 -0
  121. package/dist/shims/client-only.js +18 -0
  122. package/dist/shims/client-only.js.map +1 -0
  123. package/dist/shims/config.d.ts +27 -0
  124. package/dist/shims/config.d.ts.map +1 -0
  125. package/dist/shims/config.js +30 -0
  126. package/dist/shims/config.js.map +1 -0
  127. package/dist/shims/constants.d.ts +13 -0
  128. package/dist/shims/constants.d.ts.map +1 -0
  129. package/dist/shims/constants.js +13 -0
  130. package/dist/shims/constants.js.map +1 -0
  131. package/dist/shims/document.d.ts +33 -0
  132. package/dist/shims/document.d.ts.map +1 -0
  133. package/dist/shims/document.js +32 -0
  134. package/dist/shims/document.js.map +1 -0
  135. package/dist/shims/dynamic.d.ts +33 -0
  136. package/dist/shims/dynamic.d.ts.map +1 -0
  137. package/dist/shims/dynamic.js +148 -0
  138. package/dist/shims/dynamic.js.map +1 -0
  139. package/dist/shims/error-boundary.d.ts +33 -0
  140. package/dist/shims/error-boundary.d.ts.map +1 -0
  141. package/dist/shims/error-boundary.js +88 -0
  142. package/dist/shims/error-boundary.js.map +1 -0
  143. package/dist/shims/error.d.ts +16 -0
  144. package/dist/shims/error.d.ts.map +1 -0
  145. package/dist/shims/error.js +45 -0
  146. package/dist/shims/error.js.map +1 -0
  147. package/dist/shims/fetch-cache.d.ts +61 -0
  148. package/dist/shims/fetch-cache.d.ts.map +1 -0
  149. package/dist/shims/fetch-cache.js +307 -0
  150. package/dist/shims/fetch-cache.js.map +1 -0
  151. package/dist/shims/font-google.d.ts +122 -0
  152. package/dist/shims/font-google.d.ts.map +1 -0
  153. package/dist/shims/font-google.js +387 -0
  154. package/dist/shims/font-google.js.map +1 -0
  155. package/dist/shims/font-local.d.ts +61 -0
  156. package/dist/shims/font-local.d.ts.map +1 -0
  157. package/dist/shims/font-local.js +303 -0
  158. package/dist/shims/font-local.js.map +1 -0
  159. package/dist/shims/form.d.ts +30 -0
  160. package/dist/shims/form.d.ts.map +1 -0
  161. package/dist/shims/form.js +78 -0
  162. package/dist/shims/form.js.map +1 -0
  163. package/dist/shims/head-state.d.ts +11 -0
  164. package/dist/shims/head-state.d.ts.map +1 -0
  165. package/dist/shims/head-state.js +47 -0
  166. package/dist/shims/head-state.js.map +1 -0
  167. package/dist/shims/head.d.ts +28 -0
  168. package/dist/shims/head.d.ts.map +1 -0
  169. package/dist/shims/head.js +148 -0
  170. package/dist/shims/head.js.map +1 -0
  171. package/dist/shims/headers.d.ts +150 -0
  172. package/dist/shims/headers.d.ts.map +1 -0
  173. package/dist/shims/headers.js +412 -0
  174. package/dist/shims/headers.js.map +1 -0
  175. package/dist/shims/image-config.d.ts +30 -0
  176. package/dist/shims/image-config.d.ts.map +1 -0
  177. package/dist/shims/image-config.js +91 -0
  178. package/dist/shims/image-config.js.map +1 -0
  179. package/dist/shims/image.d.ts +63 -0
  180. package/dist/shims/image.d.ts.map +1 -0
  181. package/dist/shims/image.js +284 -0
  182. package/dist/shims/image.js.map +1 -0
  183. package/dist/shims/internal/api-utils.d.ts +12 -0
  184. package/dist/shims/internal/api-utils.d.ts.map +1 -0
  185. package/dist/shims/internal/api-utils.js +7 -0
  186. package/dist/shims/internal/api-utils.js.map +1 -0
  187. package/dist/shims/internal/app-router-context.d.ts +21 -0
  188. package/dist/shims/internal/app-router-context.d.ts.map +1 -0
  189. package/dist/shims/internal/app-router-context.js +15 -0
  190. package/dist/shims/internal/app-router-context.js.map +1 -0
  191. package/dist/shims/internal/cookies.d.ts +9 -0
  192. package/dist/shims/internal/cookies.d.ts.map +1 -0
  193. package/dist/shims/internal/cookies.js +9 -0
  194. package/dist/shims/internal/cookies.js.map +1 -0
  195. package/dist/shims/internal/router-context.d.ts +2 -0
  196. package/dist/shims/internal/router-context.d.ts.map +1 -0
  197. package/dist/shims/internal/router-context.js +9 -0
  198. package/dist/shims/internal/router-context.js.map +1 -0
  199. package/dist/shims/internal/utils.d.ts +48 -0
  200. package/dist/shims/internal/utils.d.ts.map +1 -0
  201. package/dist/shims/internal/utils.js +35 -0
  202. package/dist/shims/internal/utils.js.map +1 -0
  203. package/dist/shims/internal/work-unit-async-storage.d.ts +12 -0
  204. package/dist/shims/internal/work-unit-async-storage.d.ts.map +1 -0
  205. package/dist/shims/internal/work-unit-async-storage.js +13 -0
  206. package/dist/shims/internal/work-unit-async-storage.js.map +1 -0
  207. package/dist/shims/layout-segment-context.d.ts +21 -0
  208. package/dist/shims/layout-segment-context.d.ts.map +1 -0
  209. package/dist/shims/layout-segment-context.js +27 -0
  210. package/dist/shims/layout-segment-context.js.map +1 -0
  211. package/dist/shims/legacy-image.d.ts +52 -0
  212. package/dist/shims/legacy-image.d.ts.map +1 -0
  213. package/dist/shims/legacy-image.js +46 -0
  214. package/dist/shims/legacy-image.js.map +1 -0
  215. package/dist/shims/link.d.ts +48 -0
  216. package/dist/shims/link.d.ts.map +1 -0
  217. package/dist/shims/link.js +395 -0
  218. package/dist/shims/link.js.map +1 -0
  219. package/dist/shims/metadata.d.ts +184 -0
  220. package/dist/shims/metadata.d.ts.map +1 -0
  221. package/dist/shims/metadata.js +472 -0
  222. package/dist/shims/metadata.js.map +1 -0
  223. package/dist/shims/navigation-state.d.ts +14 -0
  224. package/dist/shims/navigation-state.d.ts.map +1 -0
  225. package/dist/shims/navigation-state.js +77 -0
  226. package/dist/shims/navigation-state.js.map +1 -0
  227. package/dist/shims/navigation.d.ts +201 -0
  228. package/dist/shims/navigation.d.ts.map +1 -0
  229. package/dist/shims/navigation.js +672 -0
  230. package/dist/shims/navigation.js.map +1 -0
  231. package/dist/shims/og.d.ts +20 -0
  232. package/dist/shims/og.d.ts.map +1 -0
  233. package/dist/shims/og.js +19 -0
  234. package/dist/shims/og.js.map +1 -0
  235. package/dist/shims/router-state.d.ts +11 -0
  236. package/dist/shims/router-state.d.ts.map +1 -0
  237. package/dist/shims/router-state.js +56 -0
  238. package/dist/shims/router-state.js.map +1 -0
  239. package/dist/shims/router.d.ts +103 -0
  240. package/dist/shims/router.d.ts.map +1 -0
  241. package/dist/shims/router.js +536 -0
  242. package/dist/shims/router.js.map +1 -0
  243. package/dist/shims/script.d.ts +58 -0
  244. package/dist/shims/script.d.ts.map +1 -0
  245. package/dist/shims/script.js +163 -0
  246. package/dist/shims/script.js.map +1 -0
  247. package/dist/shims/server-only.d.ts +19 -0
  248. package/dist/shims/server-only.d.ts.map +1 -0
  249. package/dist/shims/server-only.js +19 -0
  250. package/dist/shims/server-only.js.map +1 -0
  251. package/dist/shims/server.d.ts +178 -0
  252. package/dist/shims/server.d.ts.map +1 -0
  253. package/dist/shims/server.js +377 -0
  254. package/dist/shims/server.js.map +1 -0
  255. package/dist/shims/web-vitals.d.ts +24 -0
  256. package/dist/shims/web-vitals.d.ts.map +1 -0
  257. package/dist/shims/web-vitals.js +17 -0
  258. package/dist/shims/web-vitals.js.map +1 -0
  259. package/dist/utils/hash.d.ts +6 -0
  260. package/dist/utils/hash.d.ts.map +1 -0
  261. package/dist/utils/hash.js +20 -0
  262. package/dist/utils/hash.js.map +1 -0
  263. package/dist/utils/project.d.ts +36 -0
  264. package/dist/utils/project.d.ts.map +1 -0
  265. package/dist/utils/project.js +112 -0
  266. package/dist/utils/project.js.map +1 -0
  267. package/dist/utils/query.d.ts +10 -0
  268. package/dist/utils/query.d.ts.map +1 -0
  269. package/dist/utils/query.js +27 -0
  270. package/dist/utils/query.js.map +1 -0
  271. package/package.json +65 -7
  272. package/index.js +0 -1
@@ -0,0 +1,8 @@
1
+ /**
2
+ * vinext/cloudflare — Cloudflare Workers integration.
3
+ *
4
+ * Provides cache handlers and utilities for running vinext on Cloudflare Workers.
5
+ */
6
+ export { KVCacheHandler } from "./kv-cache-handler.js";
7
+ export { runTPR, type TPROptions, type TPRResult } from "./tpr.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * vinext/cloudflare — Cloudflare Workers integration.
3
+ *
4
+ * Provides cache handlers and utilities for running vinext on Cloudflare Workers.
5
+ */
6
+ export { KVCacheHandler } from "./kv-cache-handler.js";
7
+ export { runTPR } from "./tpr.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cloudflare/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAmC,MAAM,UAAU,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Cloudflare KV-backed CacheHandler for vinext.
3
+ *
4
+ * Provides persistent ISR caching on Cloudflare Workers using KV as the
5
+ * storage backend. Supports time-based expiry (stale-while-revalidate)
6
+ * and tag-based invalidation.
7
+ *
8
+ * Usage in worker/index.ts:
9
+ *
10
+ * import { KVCacheHandler } from "vinext/cloudflare";
11
+ * import { setCacheHandler } from "vinext/shims/cache";
12
+ *
13
+ * export default {
14
+ * async fetch(request: Request, env: Env) {
15
+ * setCacheHandler(new KVCacheHandler(env.VINEXT_CACHE));
16
+ * // ... rest of worker handler
17
+ * }
18
+ * };
19
+ *
20
+ * Wrangler config (wrangler.jsonc):
21
+ *
22
+ * {
23
+ * "kv_namespaces": [
24
+ * { "binding": "VINEXT_CACHE", "id": "<your-kv-namespace-id>" }
25
+ * ]
26
+ * }
27
+ */
28
+ import type { CacheHandler, CacheHandlerValue, IncrementalCacheValue } from "../shims/cache.js";
29
+ interface KVNamespace {
30
+ get(key: string, options?: {
31
+ type?: string;
32
+ }): Promise<string | null>;
33
+ get(key: string, options: {
34
+ type: "arrayBuffer";
35
+ }): Promise<ArrayBuffer | null>;
36
+ put(key: string, value: string | ArrayBuffer | ReadableStream, options?: {
37
+ expirationTtl?: number;
38
+ metadata?: Record<string, unknown>;
39
+ }): Promise<void>;
40
+ delete(key: string): Promise<void>;
41
+ list(options?: {
42
+ prefix?: string;
43
+ limit?: number;
44
+ cursor?: string;
45
+ }): Promise<{
46
+ keys: Array<{
47
+ name: string;
48
+ metadata?: Record<string, unknown>;
49
+ }>;
50
+ list_complete: boolean;
51
+ cursor?: string;
52
+ }>;
53
+ }
54
+ export declare class KVCacheHandler implements CacheHandler {
55
+ private kv;
56
+ private prefix;
57
+ constructor(kvNamespace: KVNamespace, options?: {
58
+ appPrefix?: string;
59
+ });
60
+ get(key: string, _ctx?: Record<string, unknown>): Promise<CacheHandlerValue | null>;
61
+ set(key: string, data: IncrementalCacheValue | null, ctx?: Record<string, unknown>): Promise<void>;
62
+ revalidateTag(tags: string | string[], _durations?: {
63
+ expire?: number;
64
+ }): Promise<void>;
65
+ resetRequestCache(): void;
66
+ }
67
+ export {};
68
+ //# sourceMappingURL=kv-cache-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv-cache-handler.d.ts","sourceRoot":"","sources":["../../src/cloudflare/kv-cache-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAG3B,UAAU,WAAW;IACnB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAChF,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,cAAc,EAC5C,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GACvE,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,CAAC,EAAE;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QACV,IAAI,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CAAC,CAAC;QAClE,aAAa,EAAE,OAAO,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAiCD,qBAAa,cAAe,YAAW,YAAY;IACjD,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAKhE,GAAG,CACP,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAkE9B,GAAG,CACP,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,qBAAqB,GAAG,IAAI,EAClC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;IA8DV,aAAa,CACjB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,UAAU,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/B,OAAO,CAAC,IAAI,CAAC;IAehB,iBAAiB,IAAI,IAAI;CAG1B"}
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Cloudflare KV-backed CacheHandler for vinext.
3
+ *
4
+ * Provides persistent ISR caching on Cloudflare Workers using KV as the
5
+ * storage backend. Supports time-based expiry (stale-while-revalidate)
6
+ * and tag-based invalidation.
7
+ *
8
+ * Usage in worker/index.ts:
9
+ *
10
+ * import { KVCacheHandler } from "vinext/cloudflare";
11
+ * import { setCacheHandler } from "vinext/shims/cache";
12
+ *
13
+ * export default {
14
+ * async fetch(request: Request, env: Env) {
15
+ * setCacheHandler(new KVCacheHandler(env.VINEXT_CACHE));
16
+ * // ... rest of worker handler
17
+ * }
18
+ * };
19
+ *
20
+ * Wrangler config (wrangler.jsonc):
21
+ *
22
+ * {
23
+ * "kv_namespaces": [
24
+ * { "binding": "VINEXT_CACHE", "id": "<your-kv-namespace-id>" }
25
+ * ]
26
+ * }
27
+ */
28
+ /** Key prefix for tag invalidation timestamps. */
29
+ const TAG_PREFIX = "__tag:";
30
+ /** Key prefix for cache entries. */
31
+ const ENTRY_PREFIX = "cache:";
32
+ /** Max tag length to prevent KV key abuse. */
33
+ const MAX_TAG_LENGTH = 256;
34
+ /**
35
+ * Validate a cache tag. Returns null if invalid.
36
+ * Note: `:` is rejected because TAG_PREFIX and ENTRY_PREFIX use `:` as a
37
+ * separator — allowing `:` in user tags could cause ambiguous key lookups.
38
+ */
39
+ function validateTag(tag) {
40
+ if (typeof tag !== "string" || tag.length === 0 || tag.length > MAX_TAG_LENGTH)
41
+ return null;
42
+ // Block control characters, path separators, and KV-special characters.
43
+ // eslint-disable-next-line no-control-regex -- intentional: reject control chars in tags
44
+ if (/[\x00-\x1f/\\:]/.test(tag))
45
+ return null;
46
+ return tag;
47
+ }
48
+ export class KVCacheHandler {
49
+ kv;
50
+ prefix;
51
+ constructor(kvNamespace, options) {
52
+ this.kv = kvNamespace;
53
+ this.prefix = options?.appPrefix ? `${options.appPrefix}:` : "";
54
+ }
55
+ async get(key, _ctx) {
56
+ const kvKey = this.prefix + ENTRY_PREFIX + key;
57
+ const raw = await this.kv.get(kvKey);
58
+ if (!raw)
59
+ return null;
60
+ let parsed;
61
+ try {
62
+ parsed = JSON.parse(raw);
63
+ }
64
+ catch {
65
+ // Corrupted JSON — delete and treat as miss
66
+ await this.kv.delete(kvKey);
67
+ return null;
68
+ }
69
+ // Validate deserialized shape before using
70
+ const entry = validateCacheEntry(parsed);
71
+ if (!entry) {
72
+ console.error("[vinext] Invalid cache entry shape for key:", key);
73
+ await this.kv.delete(kvKey);
74
+ return null;
75
+ }
76
+ // Restore ArrayBuffer fields that were base64-encoded for JSON storage
77
+ if (entry.value) {
78
+ const ok = restoreArrayBuffers(entry.value);
79
+ if (!ok) {
80
+ // base64 decode failed — corrupted entry, treat as miss
81
+ await this.kv.delete(kvKey);
82
+ return null;
83
+ }
84
+ }
85
+ // Check tag-based invalidation (parallel for lower latency)
86
+ if (entry.tags.length > 0) {
87
+ const tagResults = await Promise.all(entry.tags.map((tag) => this.kv.get(this.prefix + TAG_PREFIX + tag)));
88
+ for (let i = 0; i < entry.tags.length; i++) {
89
+ const tagTime = tagResults[i];
90
+ if (tagTime) {
91
+ const tagTimestamp = Number(tagTime);
92
+ if (Number.isNaN(tagTimestamp) || tagTimestamp >= entry.lastModified) {
93
+ // Tag was invalidated after this entry, or timestamp is corrupted
94
+ // — treat as miss to force re-render
95
+ await this.kv.delete(kvKey);
96
+ return null;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ // Check time-based expiry — return stale with cacheState
102
+ if (entry.revalidateAt !== null && Date.now() > entry.revalidateAt) {
103
+ return {
104
+ lastModified: entry.lastModified,
105
+ value: entry.value,
106
+ cacheState: "stale",
107
+ };
108
+ }
109
+ return {
110
+ lastModified: entry.lastModified,
111
+ value: entry.value,
112
+ };
113
+ }
114
+ async set(key, data, ctx) {
115
+ // Collect, validate, and dedupe tags from data and context
116
+ const tagSet = new Set();
117
+ if (data && "tags" in data && Array.isArray(data.tags)) {
118
+ for (const t of data.tags) {
119
+ const validated = validateTag(t);
120
+ if (validated)
121
+ tagSet.add(validated);
122
+ }
123
+ }
124
+ if (ctx && "tags" in ctx && Array.isArray(ctx.tags)) {
125
+ for (const t of ctx.tags) {
126
+ const validated = validateTag(t);
127
+ if (validated)
128
+ tagSet.add(validated);
129
+ }
130
+ }
131
+ const tags = [...tagSet];
132
+ // Determine revalidation time
133
+ let revalidateAt = null;
134
+ if (ctx) {
135
+ const revalidate = ctx.cacheControl?.revalidate ?? ctx.revalidate;
136
+ if (typeof revalidate === "number" && revalidate > 0) {
137
+ revalidateAt = Date.now() + revalidate * 1000;
138
+ }
139
+ }
140
+ if (data &&
141
+ "revalidate" in data &&
142
+ typeof data.revalidate === "number" &&
143
+ data.revalidate > 0) {
144
+ revalidateAt = Date.now() + data.revalidate * 1000;
145
+ }
146
+ // Prepare entry — convert ArrayBuffers to base64 for JSON storage
147
+ const serializable = data ? serializeForJSON(data) : null;
148
+ const entry = {
149
+ value: serializable,
150
+ tags,
151
+ lastModified: Date.now(),
152
+ revalidateAt,
153
+ };
154
+ // Calculate KV TTL — keep entries well beyond their revalidate window
155
+ // (10x revalidate period, clamped to 60s–30d) so stale-while-revalidate
156
+ // can serve stale content while background regeneration happens.
157
+ let expirationTtl;
158
+ if (revalidateAt !== null) {
159
+ const revalidateSeconds = Math.ceil((revalidateAt - Date.now()) / 1000);
160
+ // Keep in KV for 10x the revalidation period, up to 30 days
161
+ expirationTtl = Math.min(revalidateSeconds * 10, 30 * 24 * 3600);
162
+ // KV minimum TTL is 60 seconds
163
+ expirationTtl = Math.max(expirationTtl, 60);
164
+ }
165
+ await this.kv.put(this.prefix + ENTRY_PREFIX + key, JSON.stringify(entry), {
166
+ expirationTtl,
167
+ });
168
+ }
169
+ async revalidateTag(tags, _durations) {
170
+ const tagList = Array.isArray(tags) ? tags : [tags];
171
+ const now = Date.now();
172
+ const validTags = tagList.filter((t) => validateTag(t) !== null);
173
+ // Store invalidation timestamp for each tag
174
+ // Use a long TTL (30 days) so recent invalidations are always found
175
+ await Promise.all(validTags.map((tag) => this.kv.put(this.prefix + TAG_PREFIX + tag, String(now), {
176
+ expirationTtl: 30 * 24 * 3600,
177
+ })));
178
+ }
179
+ resetRequestCache() {
180
+ // No-op — KV is stateless per request
181
+ }
182
+ }
183
+ // ---------------------------------------------------------------------------
184
+ // Validation helpers
185
+ // ---------------------------------------------------------------------------
186
+ const VALID_KINDS = new Set([
187
+ "FETCH",
188
+ "APP_PAGE",
189
+ "PAGES",
190
+ "APP_ROUTE",
191
+ "REDIRECT",
192
+ "IMAGE",
193
+ ]);
194
+ /**
195
+ * Validate that a parsed JSON value has the expected KVCacheEntry shape.
196
+ * Returns the validated entry or null if the shape is invalid.
197
+ */
198
+ function validateCacheEntry(raw) {
199
+ if (!raw || typeof raw !== "object")
200
+ return null;
201
+ const obj = raw;
202
+ // Required fields
203
+ if (typeof obj.lastModified !== "number")
204
+ return null;
205
+ if (!Array.isArray(obj.tags))
206
+ return null;
207
+ if (obj.revalidateAt !== null &&
208
+ typeof obj.revalidateAt !== "number")
209
+ return null;
210
+ // value must be null or a valid cache value object with a known kind
211
+ if (obj.value !== null) {
212
+ if (!obj.value || typeof obj.value !== "object")
213
+ return null;
214
+ const value = obj.value;
215
+ if (typeof value.kind !== "string" || !VALID_KINDS.has(value.kind))
216
+ return null;
217
+ }
218
+ return raw;
219
+ }
220
+ // ---------------------------------------------------------------------------
221
+ // ArrayBuffer serialization helpers
222
+ // ---------------------------------------------------------------------------
223
+ /**
224
+ * Deep-clone a cache value, converting ArrayBuffer fields to base64 strings
225
+ * so the entire structure can be JSON.stringify'd for KV storage.
226
+ */
227
+ function serializeForJSON(value) {
228
+ if (value.kind === "APP_PAGE") {
229
+ return {
230
+ ...value,
231
+ rscData: value.rscData
232
+ ? arrayBufferToBase64(value.rscData)
233
+ : undefined,
234
+ };
235
+ }
236
+ if (value.kind === "APP_ROUTE") {
237
+ return {
238
+ ...value,
239
+ body: arrayBufferToBase64(value.body),
240
+ };
241
+ }
242
+ if (value.kind === "IMAGE") {
243
+ return {
244
+ ...value,
245
+ buffer: arrayBufferToBase64(value.buffer),
246
+ };
247
+ }
248
+ return value;
249
+ }
250
+ /**
251
+ * Restore base64 strings back to ArrayBuffers after JSON.parse.
252
+ * Returns false if any base64 decode fails (corrupted entry).
253
+ */
254
+ function restoreArrayBuffers(value) {
255
+ if (value.kind === "APP_PAGE" && typeof value.rscData === "string") {
256
+ const decoded = safeBase64ToArrayBuffer(value.rscData);
257
+ if (!decoded)
258
+ return false;
259
+ value.rscData = decoded;
260
+ }
261
+ if (value.kind === "APP_ROUTE" && typeof value.body === "string") {
262
+ const decoded = safeBase64ToArrayBuffer(value.body);
263
+ if (!decoded)
264
+ return false;
265
+ value.body = decoded;
266
+ }
267
+ if (value.kind === "IMAGE" && typeof value.buffer === "string") {
268
+ const decoded = safeBase64ToArrayBuffer(value.buffer);
269
+ if (!decoded)
270
+ return false;
271
+ value.buffer = decoded;
272
+ }
273
+ return true;
274
+ }
275
+ function arrayBufferToBase64(buffer) {
276
+ const bytes = new Uint8Array(buffer);
277
+ let binary = "";
278
+ for (let i = 0; i < bytes.length; i++) {
279
+ binary += String.fromCharCode(bytes[i]);
280
+ }
281
+ return btoa(binary);
282
+ }
283
+ function base64ToArrayBuffer(base64) {
284
+ const binary = atob(base64);
285
+ const bytes = new Uint8Array(binary.length);
286
+ for (let i = 0; i < binary.length; i++) {
287
+ bytes[i] = binary.charCodeAt(i);
288
+ }
289
+ return bytes.buffer;
290
+ }
291
+ /**
292
+ * Safely decode base64 to ArrayBuffer. Returns null on invalid input
293
+ * instead of throwing a DOMException.
294
+ */
295
+ function safeBase64ToArrayBuffer(base64) {
296
+ try {
297
+ return base64ToArrayBuffer(base64);
298
+ }
299
+ catch {
300
+ console.error("[vinext] Invalid base64 in cache entry");
301
+ return null;
302
+ }
303
+ }
304
+ //# sourceMappingURL=kv-cache-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv-cache-handler.js","sourceRoot":"","sources":["../../src/cloudflare/kv-cache-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * TPR: Traffic-aware Pre-Rendering
3
+ *
4
+ * Uses Cloudflare zone analytics to determine which pages actually get
5
+ * traffic, and pre-renders only those during deploy. The pre-rendered
6
+ * HTML is uploaded to KV in the same format ISR uses at runtime — no
7
+ * runtime changes needed.
8
+ *
9
+ * Flow:
10
+ * 1. Parse wrangler config to find custom domain and KV namespace
11
+ * 2. Resolve the Cloudflare zone for the custom domain
12
+ * 3. Query zone analytics (GraphQL) for top pages by request count
13
+ * 4. Walk ranked list until coverage threshold is met
14
+ * 5. Start the built production server locally
15
+ * 6. Fetch each hot route to produce HTML
16
+ * 7. Upload pre-rendered HTML to KV (same KVCacheEntry format ISR reads)
17
+ *
18
+ * TPR is an experimental feature enabled via --experimental-tpr. It
19
+ * gracefully skips when no custom domain, no API token, no traffic data,
20
+ * or no KV namespace is configured.
21
+ */
22
+ export interface TPROptions {
23
+ /** Project root directory. */
24
+ root: string;
25
+ /** Traffic coverage percentage (0–100). Default: 90. */
26
+ coverage: number;
27
+ /** Hard cap on number of pages to pre-render. Default: 1000. */
28
+ limit: number;
29
+ /** Analytics lookback window in hours. Default: 24. */
30
+ window: number;
31
+ }
32
+ export interface TPRResult {
33
+ /** Total unique page paths found in analytics. */
34
+ totalPaths: number;
35
+ /** Number of pages successfully pre-rendered and uploaded. */
36
+ prerenderedCount: number;
37
+ /** Actual traffic coverage achieved (percentage). */
38
+ coverageAchieved: number;
39
+ /** Wall-clock duration of the TPR step in milliseconds. */
40
+ durationMs: number;
41
+ /** If TPR was skipped, the reason. */
42
+ skipped?: string;
43
+ }
44
+ interface TrafficEntry {
45
+ path: string;
46
+ requests: number;
47
+ }
48
+ interface SelectedRoutes {
49
+ routes: TrafficEntry[];
50
+ totalRequests: number;
51
+ coveredRequests: number;
52
+ coveragePercent: number;
53
+ }
54
+ interface WranglerConfig {
55
+ accountId?: string;
56
+ kvNamespaceId?: string;
57
+ customDomain?: string;
58
+ }
59
+ /**
60
+ * Parse wrangler config (JSONC or TOML) to extract the fields TPR needs:
61
+ * account_id, VINEXT_CACHE KV namespace ID, and custom domain.
62
+ */
63
+ export declare function parseWranglerConfig(root: string): WranglerConfig | null;
64
+ /**
65
+ * Walk the ranked traffic list, accumulating request counts until the
66
+ * coverage target is met or the hard cap is reached.
67
+ */
68
+ export declare function selectRoutes(traffic: TrafficEntry[], coverageTarget: number, limit: number): SelectedRoutes;
69
+ /**
70
+ * Run the TPR pipeline: query traffic, select routes, pre-render, upload.
71
+ *
72
+ * Designed to be called between the build step and wrangler deploy in
73
+ * the `vinext deploy` pipeline. Gracefully skips (never errors) when
74
+ * the prerequisites aren't met.
75
+ */
76
+ export declare function runTPR(options: TPROptions): Promise<TPRResult>;
77
+ export {};
78
+ //# sourceMappingURL=tpr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tpr.d.ts","sourceRoot":"","sources":["../../src/cloudflare/tpr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AASH,MAAM,WAAW,UAAU;IACzB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAQD,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAuBvE;AAkXD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EAAE,EACvB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,GACZ,cAAc,CAuBhB;AAyPD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAmIpE"}