@farm.js/core 0.1.0-beta.97 → 0.1.0-beta.99

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 (269) hide show
  1. package/dist/after.cjs.map +1 -0
  2. package/dist/agent-runtime.cjs +7 -3
  3. package/dist/agent-runtime.cjs.map +1 -0
  4. package/dist/agent-runtime.d.mts +2 -2
  5. package/dist/agent-runtime.d.ts +2 -2
  6. package/dist/agent-runtime.mjs +2 -1
  7. package/dist/agent-runtime.mjs.map +1 -1
  8. package/dist/api/route-manager.cjs.map +1 -0
  9. package/dist/api/route-manager.d.mts +2 -2
  10. package/dist/api/route-manager.d.ts +2 -2
  11. package/dist/api/runtime.cjs.map +1 -0
  12. package/dist/api.cjs +26 -1
  13. package/dist/api.cjs.map +1 -0
  14. package/dist/api.d.mts +3 -3
  15. package/dist/api.d.ts +3 -3
  16. package/dist/api.mjs +2 -2
  17. package/dist/{app-CIOx3LvY.d.ts → app-CGjrKNoN.d.ts} +4 -4
  18. package/dist/{app-DBd6437H.d.mts → app-DOcLs_iq.d.mts} +4 -4
  19. package/dist/app-markdown.cjs +21 -0
  20. package/dist/app-markdown.cjs.map +1 -0
  21. package/dist/app-markdown.d.mts +19 -4
  22. package/dist/app-markdown.d.ts +19 -4
  23. package/dist/app-markdown.mjs +7 -1
  24. package/dist/cache.cjs.map +1 -0
  25. package/dist/{chunk-VMCHLH3Y.mjs → chunk-26BCDVJS.mjs} +19 -1
  26. package/dist/chunk-26BCDVJS.mjs.map +1 -0
  27. package/dist/{chunk-FP5Q67FO.mjs → chunk-2HYYZCCI.mjs} +308 -19
  28. package/dist/chunk-2HYYZCCI.mjs.map +1 -0
  29. package/dist/{chunk-WKDAA6V2.mjs → chunk-3BTAMIQE.mjs} +100 -41
  30. package/dist/chunk-3BTAMIQE.mjs.map +1 -0
  31. package/dist/{chunk-WD2EBM3I.mjs → chunk-3CQJV3NC.mjs} +2 -2
  32. package/dist/{chunk-I3OOUWO5.mjs → chunk-3GDRV7SG.mjs} +2 -2
  33. package/dist/{chunk-YIBV77KZ.mjs → chunk-4WLAVHCY.mjs} +2 -2
  34. package/dist/{chunk-KDP5ZSWP.mjs → chunk-7PS5NKOM.mjs} +26 -11
  35. package/dist/chunk-7PS5NKOM.mjs.map +1 -0
  36. package/dist/{chunk-X4SFHKFH.mjs → chunk-BU65A3LZ.mjs} +10 -6
  37. package/dist/chunk-BU65A3LZ.mjs.map +1 -0
  38. package/dist/{chunk-WMJGA32P.mjs → chunk-BXVOHG6B.mjs} +27 -2
  39. package/dist/{chunk-WMJGA32P.mjs.map → chunk-BXVOHG6B.mjs.map} +1 -1
  40. package/dist/{chunk-BZAIS65C.mjs → chunk-DIHNOVZZ.mjs} +40 -13
  41. package/dist/chunk-DIHNOVZZ.mjs.map +1 -0
  42. package/dist/{chunk-ISSFLGJ5.mjs → chunk-FDWECN3W.mjs} +8 -4
  43. package/dist/chunk-FDWECN3W.mjs.map +1 -0
  44. package/dist/chunk-FDWXXTWR.mjs +114 -0
  45. package/dist/chunk-FDWXXTWR.mjs.map +1 -0
  46. package/dist/{chunk-FSIXEIOB.mjs → chunk-L7FSTPGS.mjs} +2 -2
  47. package/dist/{chunk-J3MPQ4MQ.mjs → chunk-LG4XB6RN.mjs} +2 -2
  48. package/dist/{chunk-J3MPQ4MQ.mjs.map → chunk-LG4XB6RN.mjs.map} +1 -1
  49. package/dist/{chunk-AAC66ILR.mjs → chunk-LXXG3K2Y.mjs} +61 -2
  50. package/dist/chunk-LXXG3K2Y.mjs.map +1 -0
  51. package/dist/{chunk-GJ7W6LNK.mjs → chunk-N5RK4LK6.mjs} +3 -3
  52. package/dist/{chunk-D7F7YZ7L.mjs → chunk-NCVFPT67.mjs} +100 -40
  53. package/dist/{chunk-D7F7YZ7L.mjs.map → chunk-NCVFPT67.mjs.map} +1 -1
  54. package/dist/{chunk-UMUWR5XA.mjs → chunk-PURU7FXR.mjs} +2 -2
  55. package/dist/{chunk-2SKCXYLB.mjs → chunk-QQCCBMTH.mjs} +60 -6
  56. package/dist/chunk-QQCCBMTH.mjs.map +1 -0
  57. package/dist/chunk-RKUPOYQV.mjs +28 -0
  58. package/dist/chunk-RKUPOYQV.mjs.map +1 -0
  59. package/dist/{chunk-52BR7LTX.mjs → chunk-STSPSJUI.mjs} +3 -3
  60. package/dist/{chunk-EPDIF432.mjs → chunk-UOGX6UNO.mjs} +37 -17
  61. package/dist/chunk-UOGX6UNO.mjs.map +1 -0
  62. package/dist/{chunk-IZBX2TEU.mjs → chunk-VQG3QWWK.mjs} +2 -2
  63. package/dist/{chunk-35NPLKQJ.mjs → chunk-XWM2C267.mjs} +21 -105
  64. package/dist/chunk-XWM2C267.mjs.map +1 -0
  65. package/dist/{chunk-7ZVN3YZI.mjs → chunk-Z5ARESQG.mjs} +43 -1
  66. package/dist/chunk-Z5ARESQG.mjs.map +1 -0
  67. package/dist/client/lifecycle.cjs.map +1 -0
  68. package/dist/client/lifecycle.mjs +2 -2
  69. package/dist/{client-plugins-B6-07YmP.d.mts → client-plugins-BqtHoJ9C.d.mts} +91 -3
  70. package/dist/{client-plugins-By6MVUX-.d.ts → client-plugins-DYprkCKN.d.ts} +91 -3
  71. package/dist/client-plugins.cjs +1 -1
  72. package/dist/client-plugins.cjs.map +1 -0
  73. package/dist/client-plugins.d.mts +2 -2
  74. package/dist/client-plugins.d.ts +2 -2
  75. package/dist/client-plugins.mjs +2 -2
  76. package/dist/client.cjs +61 -16
  77. package/dist/client.cjs.map +1 -0
  78. package/dist/client.d.mts +5 -5
  79. package/dist/client.d.ts +5 -5
  80. package/dist/client.mjs +7 -7
  81. package/dist/config.cjs.map +1 -0
  82. package/dist/config.d.mts +2 -2
  83. package/dist/config.d.ts +2 -2
  84. package/dist/cron.cjs +48 -12
  85. package/dist/cron.cjs.map +1 -0
  86. package/dist/cron.mjs +2 -1
  87. package/dist/deferred.cjs.map +1 -0
  88. package/dist/deployment.cjs.map +1 -0
  89. package/dist/{devtools-XWZX6CCL.mjs → devtools-24N3U5IG.mjs} +9 -7
  90. package/dist/{devtools-XWZX6CCL.mjs.map → devtools-24N3U5IG.mjs.map} +1 -1
  91. package/dist/docs.cjs +7 -3
  92. package/dist/docs.cjs.map +1 -0
  93. package/dist/docs.mjs +9 -7
  94. package/dist/env-types.cjs.map +1 -0
  95. package/dist/env.cjs.map +1 -0
  96. package/dist/environment/vite.cjs.map +1 -0
  97. package/dist/environment.cjs.map +1 -0
  98. package/dist/font.cjs.map +1 -0
  99. package/dist/headers.cjs.map +1 -0
  100. package/dist/i18n/client.cjs.map +1 -0
  101. package/dist/i18n/index.cjs.map +1 -0
  102. package/dist/i18n/server.cjs.map +1 -0
  103. package/dist/image/server.cjs +99 -40
  104. package/dist/image/server.cjs.map +1 -0
  105. package/dist/image/server.d.mts +6 -0
  106. package/dist/image/server.d.ts +6 -0
  107. package/dist/image/server.mjs +1 -1
  108. package/dist/image/sharp.cjs +1 -0
  109. package/dist/image/sharp.cjs.map +1 -0
  110. package/dist/image/sharp.d.mts +1 -1
  111. package/dist/image/sharp.d.ts +1 -1
  112. package/dist/image/sharp.mjs +1 -1
  113. package/dist/image/sharp.mjs.map +1 -1
  114. package/dist/image.cjs.map +1 -0
  115. package/dist/index.cjs +943 -231
  116. package/dist/index.cjs.map +1 -0
  117. package/dist/index.d.mts +11 -11
  118. package/dist/index.d.ts +11 -11
  119. package/dist/index.mjs +38 -24
  120. package/dist/index.mjs.map +1 -1
  121. package/dist/instrumentation.cjs.map +1 -0
  122. package/dist/{integration-orm-LLW6WZNK.mjs → integration-orm-G5BPBT5X.mjs} +3 -3
  123. package/dist/integrations.cjs +168 -5
  124. package/dist/integrations.cjs.map +1 -0
  125. package/dist/integrations.d.mts +2 -2
  126. package/dist/integrations.d.ts +2 -2
  127. package/dist/integrations.mjs +10 -3
  128. package/dist/internal/build-runtime.cjs +745 -139
  129. package/dist/internal/build-runtime.cjs.map +1 -0
  130. package/dist/internal/build-runtime.d.mts +4 -4
  131. package/dist/internal/build-runtime.d.ts +4 -4
  132. package/dist/internal/build-runtime.mjs +16 -14
  133. package/dist/internal/client-runtime.cjs +7 -2
  134. package/dist/internal/client-runtime.cjs.map +1 -0
  135. package/dist/internal/client-runtime.mjs +8 -3
  136. package/dist/internal/client-runtime.mjs.map +1 -1
  137. package/dist/internal/config-runtime.cjs +59 -42
  138. package/dist/internal/config-runtime.cjs.map +1 -0
  139. package/dist/internal/config-runtime.d.mts +3 -3
  140. package/dist/internal/config-runtime.d.ts +3 -3
  141. package/dist/internal/config-runtime.mjs +8 -6
  142. package/dist/internal/isolated-boundary.cjs.map +1 -0
  143. package/dist/internal/metadata-image-runtime.cjs.map +1 -0
  144. package/dist/internal/product-telemetry-runtime.cjs +52 -5
  145. package/dist/internal/product-telemetry-runtime.cjs.map +1 -0
  146. package/dist/internal/product-telemetry-runtime.d.mts +12 -1
  147. package/dist/internal/product-telemetry-runtime.d.ts +12 -1
  148. package/dist/internal/product-telemetry-runtime.mjs +50 -5
  149. package/dist/internal/product-telemetry-runtime.mjs.map +1 -1
  150. package/dist/internal/production-node-env.cjs.map +1 -0
  151. package/dist/internal/production-runtime.cjs +56 -10
  152. package/dist/internal/production-runtime.cjs.map +1 -0
  153. package/dist/internal/production-runtime.d.mts +8 -8
  154. package/dist/internal/production-runtime.d.ts +8 -8
  155. package/dist/internal/production-runtime.mjs +2 -2
  156. package/dist/markdown.cjs.map +1 -0
  157. package/dist/{metadata-route-8_V3UonT.d.ts → metadata-route-D2be_0kC.d.ts} +17 -2
  158. package/dist/{metadata-route-CWP_HjGU.d.mts → metadata-route-Dw5CrDIZ.d.mts} +17 -2
  159. package/dist/middleware.cjs.map +1 -0
  160. package/dist/middleware.d.mts +4 -4
  161. package/dist/middleware.d.ts +4 -4
  162. package/dist/navigation.cjs.map +1 -0
  163. package/dist/{nitro-EGRNOB5P.mjs → nitro-YJEP3FWM.mjs} +4 -3
  164. package/dist/{nitro-EGRNOB5P.mjs.map → nitro-YJEP3FWM.mjs.map} +1 -1
  165. package/dist/observability.cjs.map +1 -0
  166. package/dist/plugin.cjs +599 -104
  167. package/dist/plugin.cjs.map +1 -0
  168. package/dist/plugin.d.mts +2 -2
  169. package/dist/plugin.d.ts +2 -2
  170. package/dist/plugin.mjs +13 -11
  171. package/dist/{production-runtime-CdmzsDax.d.ts → production-runtime-CTqpD1C8.d.ts} +2 -2
  172. package/dist/{production-runtime-BGRH1dKG.d.mts → production-runtime-HNqNZd4D.d.mts} +2 -2
  173. package/dist/query/client.cjs.map +1 -0
  174. package/dist/query/index.cjs.map +1 -0
  175. package/dist/query/parsers.cjs.map +1 -0
  176. package/dist/query/server.cjs.map +1 -0
  177. package/dist/{render-plan-DLxJYAA5.d.mts → render-plan-COscpW-i.d.mts} +1 -1
  178. package/dist/{render-plan-0GeHiGVZ.d.ts → render-plan-Z4kSxaT_.d.ts} +1 -1
  179. package/dist/renderer/react/client.cjs.map +1 -0
  180. package/dist/renderer/react/server.cjs.map +1 -0
  181. package/dist/renderer/react/vite.cjs.map +1 -0
  182. package/dist/renderer-client.cjs +26 -1
  183. package/dist/renderer-client.cjs.map +1 -0
  184. package/dist/renderer-client.d.mts +4 -4
  185. package/dist/renderer-client.d.ts +4 -4
  186. package/dist/renderer-client.mjs +2 -2
  187. package/dist/renderer.cjs.map +1 -0
  188. package/dist/{request-BstWbZ6O.d.ts → request-BEDb2jE9.d.ts} +1 -1
  189. package/dist/{request-BCNXSXLh.d.mts → request-CbIAqJY9.d.mts} +1 -1
  190. package/dist/request.cjs.map +1 -0
  191. package/dist/request.d.mts +3 -3
  192. package/dist/request.d.ts +3 -3
  193. package/dist/router.cjs.map +1 -0
  194. package/dist/routes.cjs.map +1 -0
  195. package/dist/routes.d.mts +2 -2
  196. package/dist/routes.d.ts +2 -2
  197. package/dist/server-action-security.cjs +117 -104
  198. package/dist/server-action-security.cjs.map +1 -0
  199. package/dist/server-action-security.mjs +2 -1
  200. package/dist/server-fn-client.cjs.map +1 -0
  201. package/dist/server-fn.cjs.map +1 -0
  202. package/dist/server-fn.mjs +3 -2
  203. package/dist/server-plugins.cjs.map +1 -0
  204. package/dist/server-plugins.d.mts +3 -3
  205. package/dist/server-plugins.d.ts +3 -3
  206. package/dist/server-query-client.cjs +26 -1
  207. package/dist/server-query-client.cjs.map +1 -0
  208. package/dist/server-query-client.mjs +3 -3
  209. package/dist/server-query.cjs.map +1 -0
  210. package/dist/server-query.mjs +4 -3
  211. package/dist/server.cjs +686 -170
  212. package/dist/server.cjs.map +1 -0
  213. package/dist/server.d.mts +8 -8
  214. package/dist/server.d.ts +8 -8
  215. package/dist/server.mjs +16 -14
  216. package/dist/server.mjs.map +1 -1
  217. package/dist/{spa-router-COgu4txb.d.ts → spa-router-CjeQites.d.ts} +1 -1
  218. package/dist/{spa-router-BeyAVSc6.d.mts → spa-router-FJbNou1a.d.mts} +1 -1
  219. package/dist/storage.cjs +7 -3
  220. package/dist/storage.cjs.map +1 -0
  221. package/dist/storage.mjs +1 -1
  222. package/dist/testing.cjs.map +1 -0
  223. package/dist/testing.d.mts +2 -2
  224. package/dist/testing.d.ts +2 -2
  225. package/dist/testing.mjs +2 -1
  226. package/dist/testing.mjs.map +1 -1
  227. package/dist/theme/client.cjs.map +1 -0
  228. package/dist/theme/index.cjs.map +1 -0
  229. package/dist/theme/runtime.cjs.map +1 -0
  230. package/dist/theme/server.cjs.map +1 -0
  231. package/dist/{utils-DL2VwDQl.d.mts → utils-BiMJv9Ys.d.mts} +1 -1
  232. package/dist/{utils-DkU2c_1B.d.ts → utils-BpnKRFv9.d.ts} +1 -1
  233. package/dist/version.cjs +1 -1
  234. package/dist/version.cjs.map +1 -0
  235. package/dist/version.mjs +1 -1
  236. package/dist/vite.cjs +599 -104
  237. package/dist/vite.cjs.map +1 -0
  238. package/dist/vite.d.mts +2 -2
  239. package/dist/vite.d.ts +2 -2
  240. package/dist/vite.mjs +13 -11
  241. package/dist/{workflows-ChyK_oTu.d.mts → workflows-BantWytQ.d.mts} +7 -0
  242. package/dist/{workflows-ChyK_oTu.d.ts → workflows-BantWytQ.d.ts} +7 -0
  243. package/dist/workflows.cjs +73 -5
  244. package/dist/workflows.cjs.map +1 -0
  245. package/dist/workflows.d.mts +1 -1
  246. package/dist/workflows.d.ts +1 -1
  247. package/dist/workflows.mjs +2 -1
  248. package/package.json +17 -17
  249. package/dist/chunk-2SKCXYLB.mjs.map +0 -1
  250. package/dist/chunk-35NPLKQJ.mjs.map +0 -1
  251. package/dist/chunk-7ZVN3YZI.mjs.map +0 -1
  252. package/dist/chunk-AAC66ILR.mjs.map +0 -1
  253. package/dist/chunk-BZAIS65C.mjs.map +0 -1
  254. package/dist/chunk-EPDIF432.mjs.map +0 -1
  255. package/dist/chunk-FP5Q67FO.mjs.map +0 -1
  256. package/dist/chunk-ISSFLGJ5.mjs.map +0 -1
  257. package/dist/chunk-KDP5ZSWP.mjs.map +0 -1
  258. package/dist/chunk-VMCHLH3Y.mjs.map +0 -1
  259. package/dist/chunk-WKDAA6V2.mjs.map +0 -1
  260. package/dist/chunk-X4SFHKFH.mjs.map +0 -1
  261. /package/dist/{chunk-WD2EBM3I.mjs.map → chunk-3CQJV3NC.mjs.map} +0 -0
  262. /package/dist/{chunk-I3OOUWO5.mjs.map → chunk-3GDRV7SG.mjs.map} +0 -0
  263. /package/dist/{chunk-YIBV77KZ.mjs.map → chunk-4WLAVHCY.mjs.map} +0 -0
  264. /package/dist/{chunk-FSIXEIOB.mjs.map → chunk-L7FSTPGS.mjs.map} +0 -0
  265. /package/dist/{chunk-GJ7W6LNK.mjs.map → chunk-N5RK4LK6.mjs.map} +0 -0
  266. /package/dist/{chunk-UMUWR5XA.mjs.map → chunk-PURU7FXR.mjs.map} +0 -0
  267. /package/dist/{chunk-52BR7LTX.mjs.map → chunk-STSPSJUI.mjs.map} +0 -0
  268. /package/dist/{chunk-IZBX2TEU.mjs.map → chunk-VQG3QWWK.mjs.map} +0 -0
  269. /package/dist/{integration-orm-LLW6WZNK.mjs.map → integration-orm-G5BPBT5X.mjs.map} +0 -0
@@ -19,6 +19,7 @@ var FarmImageRequestError = _FarmImageRequestError;
19
19
  function createFarmImageHandler(config, options) {
20
20
  const fetcher = options.fetch ?? globalThis.fetch;
21
21
  const cache = new FarmImageMemoryCache(options.cacheEntries ?? 100);
22
+ const inflight = /* @__PURE__ */ new Map();
22
23
  const allowedWidths = /* @__PURE__ */ new Set([...config.deviceSizes, ...config.imageSizes]);
23
24
  const allowedQualities = new Set(config.qualities);
24
25
  return /* @__PURE__ */ __name(async function handleFarmImage(request) {
@@ -47,50 +48,55 @@ function createFarmImageHandler(config, options) {
47
48
  "quality"
48
49
  );
49
50
  const accept = request.headers.get("accept") ?? "";
51
+ const negotiatedFormat = selectOutputFormat(accept, config.formats) ?? "";
50
52
  const cacheKey = `${sourceUrl.href}
51
53
  ${width}
52
54
  ${quality}
53
- ${accept}`;
55
+ ${negotiatedFormat}`;
54
56
  let optimized = cache.get(cacheKey);
55
57
  if (!optimized) {
56
- const fetchedSource = await fetchImageSource(
57
- sourceUrl,
58
- requestUrl.origin,
59
- config,
60
- fetcher,
61
- options.fetchRemote,
62
- options.validateRemoteUrl,
63
- request.signal
64
- );
65
- const source = await readResponseWithLimit(
66
- fetchedSource.response,
67
- config.maximumResponseBody
68
- );
69
- const sourceType = detectImageContentType(source);
70
- validateSourceType(sourceType, config);
71
- throwIfAborted(request.signal);
72
- const result = await options.transform({
73
- source,
74
- sourceUrl: fetchedSource.url,
75
- sourceType,
76
- width,
77
- quality,
78
- accept,
79
- formats: config.formats,
80
- signal: request.signal
58
+ optimized = await runCoalesced(inflight, cacheKey, request.signal, async (signal) => {
59
+ const fetchedSource = await fetchImageSource(
60
+ sourceUrl,
61
+ requestUrl.origin,
62
+ config,
63
+ fetcher,
64
+ options.fetchRemote,
65
+ options.validateRemoteUrl,
66
+ signal
67
+ );
68
+ const source = await readResponseWithLimit(
69
+ fetchedSource.response,
70
+ config.maximumResponseBody
71
+ );
72
+ const sourceType = detectImageContentType(source);
73
+ validateSourceType(sourceType, config);
74
+ throwIfAborted(signal);
75
+ const result = await options.transform({
76
+ source,
77
+ sourceUrl: fetchedSource.url,
78
+ sourceType,
79
+ width,
80
+ quality,
81
+ accept,
82
+ formats: config.formats,
83
+ signal,
84
+ maximumResponseBody: config.maximumResponseBody
85
+ });
86
+ throwIfAborted(signal);
87
+ validateTransformedResult(result, config);
88
+ const entry = {
89
+ ...result,
90
+ etag: createImageEtag(result.body),
91
+ cacheControl: `public, max-age=${config.minimumCacheTTL}, stale-while-revalidate=${Math.max(
92
+ config.minimumCacheTTL,
93
+ 60
94
+ )}`,
95
+ expiresAt: Date.now() + config.minimumCacheTTL * 1e3
96
+ };
97
+ cache.set(cacheKey, entry);
98
+ return entry;
81
99
  });
82
- throwIfAborted(request.signal);
83
- validateTransformedResult(result, config);
84
- optimized = {
85
- ...result,
86
- etag: createImageEtag(result.body),
87
- cacheControl: `public, max-age=${config.minimumCacheTTL}, stale-while-revalidate=${Math.max(
88
- config.minimumCacheTTL,
89
- 60
90
- )}`,
91
- expiresAt: Date.now() + config.minimumCacheTTL * 1e3
92
- };
93
- cache.set(cacheKey, optimized);
94
100
  }
95
101
  return createOptimizedImageResponse(request, optimized, config);
96
102
  } catch (error) {
@@ -105,11 +111,13 @@ ${accept}`;
105
111
  }, "handleFarmImage");
106
112
  }
107
113
  __name(createFarmImageHandler, "createFarmImageHandler");
114
+ var DEFAULT_IMAGE_TRANSFORM_BODY_LIMIT = 10 * 1024 * 1024;
108
115
  function createCloudflareImageTransformer(fetcher = globalThis.fetch) {
109
- return async ({ sourceUrl, width, quality, accept, formats, signal }) => {
116
+ return async ({ sourceUrl, width, quality, accept, formats, signal, maximumResponseBody }) => {
110
117
  const format = selectOutputFormat(accept, formats);
111
118
  const response = await fetcher(sourceUrl, {
112
119
  signal,
120
+ redirect: "manual",
113
121
  headers: { accept: "image/*" },
114
122
  cf: {
115
123
  image: {
@@ -120,6 +128,14 @@ function createCloudflareImageTransformer(fetcher = globalThis.fetch) {
120
128
  }
121
129
  }
122
130
  });
131
+ if (response.status >= 300 && response.status < 400) {
132
+ void cancelResponseBody(response);
133
+ throw new FarmImageRequestError(
134
+ "UNSUPPORTED_IMAGE",
135
+ 502,
136
+ "Source image redirected after validation"
137
+ );
138
+ }
123
139
  if (!response.ok) {
124
140
  throw new FarmImageRequestError(
125
141
  "UNSUPPORTED_IMAGE",
@@ -127,7 +143,10 @@ function createCloudflareImageTransformer(fetcher = globalThis.fetch) {
127
143
  "Cloudflare could not transform the source image"
128
144
  );
129
145
  }
130
- const body = new Uint8Array(await response.arrayBuffer());
146
+ const body = await readResponseWithLimit(
147
+ response,
148
+ maximumResponseBody ?? DEFAULT_IMAGE_TRANSFORM_BODY_LIMIT
149
+ );
131
150
  return {
132
151
  body,
133
152
  contentType: normalizeImageContentType(response.headers.get("content-type")) || detectImageContentType(body)
@@ -278,6 +297,46 @@ async function fetchImageSource(initialUrl, requestOrigin, config, fetcher, fetc
278
297
  }
279
298
  }
280
299
  __name(fetchImageSource, "fetchImageSource");
300
+ async function runCoalesced(inflight, key, requestSignal, run) {
301
+ let entry = inflight.get(key);
302
+ if (!entry) {
303
+ const controller = new AbortController();
304
+ const created = {
305
+ controller,
306
+ waiters: 0,
307
+ promise: void 0
308
+ };
309
+ created.promise = run(controller.signal).finally(() => {
310
+ if (inflight.get(key) === created) inflight.delete(key);
311
+ });
312
+ created.promise.catch(() => {
313
+ });
314
+ inflight.set(key, created);
315
+ entry = created;
316
+ }
317
+ const pending = entry;
318
+ pending.waiters += 1;
319
+ try {
320
+ return await raceRequestAbort(pending.promise, requestSignal);
321
+ } finally {
322
+ pending.waiters -= 1;
323
+ if (pending.waiters === 0 && inflight.get(key) === pending) {
324
+ inflight.delete(key);
325
+ pending.controller.abort();
326
+ }
327
+ }
328
+ }
329
+ __name(runCoalesced, "runCoalesced");
330
+ function raceRequestAbort(promise, signal) {
331
+ if (!signal) return promise;
332
+ if (signal.aborted) return Promise.reject(signal.reason ?? new Error("Aborted"));
333
+ return new Promise((resolve, reject) => {
334
+ const onAbort = /* @__PURE__ */ __name(() => reject(signal.reason ?? new Error("Aborted")), "onAbort");
335
+ signal.addEventListener("abort", onAbort, { once: true });
336
+ promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
337
+ });
338
+ }
339
+ __name(raceRequestAbort, "raceRequestAbort");
281
340
  async function readResponseWithLimit(response, limit) {
282
341
  const contentLength = response.headers.get("content-length");
283
342
  if (contentLength && Number(contentLength) > limit) {
@@ -498,4 +557,4 @@ export {
498
557
  selectOutputFormat,
499
558
  isPrivateImageAddress
500
559
  };
501
- //# sourceMappingURL=chunk-WKDAA6V2.mjs.map
560
+ //# sourceMappingURL=chunk-3BTAMIQE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/image-server.ts"],"sourcesContent":["import type {\n FarmImageFormat,\n FarmImageLocalPattern,\n FarmImageRemotePattern,\n ResolvedFarmImageConfig,\n} from \"./image-config\";\nimport { matchesFarmIfNoneMatch } from \"./server-http\";\n\nexport interface FarmImageTransformInput {\n source: Uint8Array;\n sourceUrl: URL;\n sourceType: string;\n width: number;\n quality: number;\n accept: string;\n formats: readonly FarmImageFormat[];\n signal: AbortSignal;\n /**\n * Byte ceiling for any source the transformer fetches itself. Supplied by the\n * image handler; transformers that re-fetch the origin (Cloudflare) must\n * enforce it, since they bypass the handler's bounded read.\n */\n maximumResponseBody?: number;\n}\n\nexport interface FarmImageTransformResult {\n body: Uint8Array;\n contentType: string;\n}\n\nexport type FarmImageTransformer = (\n input: FarmImageTransformInput,\n) => Promise<FarmImageTransformResult>;\n\nexport interface CreateFarmImageHandlerOptions {\n fetch?: typeof globalThis.fetch;\n /** Node-only fetcher that validates the DNS result used for remote connections. @internal */\n fetchRemote?: typeof globalThis.fetch;\n transform: FarmImageTransformer;\n validateRemoteUrl?: (url: URL) => void | Promise<void>;\n onError?: (error: unknown, request: Request) => void;\n cacheEntries?: number;\n}\n\nexport type FarmImageHandler = (request: Request) => Promise<Response | null>;\n\ntype OptimizedImage = FarmImageTransformResult & {\n etag: string;\n cacheControl: string;\n expiresAt: number;\n};\n\ntype FarmImageRequestErrorCode =\n | \"BODY_TOO_LARGE\"\n | \"DISALLOWED_SOURCE\"\n | \"INVALID_METHOD\"\n | \"INVALID_PARAMETER\"\n | \"PRIVATE_SOURCE\"\n | \"TOO_MANY_REDIRECTS\"\n | \"UNSUPPORTED_IMAGE\";\n\nexport class FarmImageRequestError extends Error {\n readonly code: FarmImageRequestErrorCode;\n readonly status: number;\n\n constructor(code: FarmImageRequestErrorCode, status: number, message: string) {\n super(message);\n this.name = \"FarmImageRequestError\";\n this.code = code;\n this.status = status;\n }\n}\n\nexport function createFarmImageHandler(\n config: ResolvedFarmImageConfig,\n options: CreateFarmImageHandlerOptions,\n): FarmImageHandler {\n const fetcher = options.fetch ?? globalThis.fetch;\n const cache = new FarmImageMemoryCache(options.cacheEntries ?? 100);\n // Identical concurrent misses share one fetch + transform. Without this a\n // burst for an uncached image (a new page going live, a CDN cold start)\n // fetches the origin and runs the codec once per request.\n const inflight = new Map<string, InflightOptimization>();\n const allowedWidths = new Set([...config.deviceSizes, ...config.imageSizes]);\n const allowedQualities = new Set(config.qualities);\n\n return async function handleFarmImage(request): Promise<Response | null> {\n const requestUrl = new URL(request.url);\n if (requestUrl.pathname !== config.path) return null;\n\n try {\n if (config.provider === \"none\") {\n throw new FarmImageRequestError(\n \"DISALLOWED_SOURCE\",\n 404,\n \"The Farm image optimizer is disabled\",\n );\n }\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n throw new FarmImageRequestError(\n \"INVALID_METHOD\",\n 405,\n \"The Farm image optimizer only accepts GET and HEAD\",\n );\n }\n\n const sourceUrl = await resolveImageSourceUrl(requestUrl, config, options.validateRemoteUrl);\n const width = parseAllowedInteger(requestUrl.searchParams.get(\"w\"), allowedWidths, \"width\");\n const quality = parseAllowedInteger(\n requestUrl.searchParams.get(\"q\"),\n allowedQualities,\n \"quality\",\n );\n const accept = request.headers.get(\"accept\") ?? \"\";\n // Key on the format the Accept header negotiates to, not the header text.\n // Both transformers derive their output from `selectOutputFormat(accept,\n // formats)` alone, so every header that negotiates to the same format\n // produces byte-identical output. Keying on the raw header let a caller\n // vary it freely (`image/webp,*/*;q=0.8`, reordered lists, extra params)\n // and force an uncached fetch and transform each time.\n const negotiatedFormat = selectOutputFormat(accept, config.formats) ?? \"\";\n const cacheKey = `${sourceUrl.href}\\n${width}\\n${quality}\\n${negotiatedFormat}`;\n let optimized = cache.get(cacheKey);\n\n if (!optimized) {\n optimized = await runCoalesced(inflight, cacheKey, request.signal, async (signal) => {\n const fetchedSource = await fetchImageSource(\n sourceUrl,\n requestUrl.origin,\n config,\n fetcher,\n options.fetchRemote,\n options.validateRemoteUrl,\n signal,\n );\n const source = await readResponseWithLimit(\n fetchedSource.response,\n config.maximumResponseBody,\n );\n const sourceType = detectImageContentType(source);\n validateSourceType(sourceType, config);\n throwIfAborted(signal);\n\n const result = await options.transform({\n source,\n sourceUrl: fetchedSource.url,\n sourceType,\n width,\n quality,\n accept,\n formats: config.formats,\n signal,\n maximumResponseBody: config.maximumResponseBody,\n });\n throwIfAborted(signal);\n validateTransformedResult(result, config);\n\n const entry = {\n ...result,\n etag: createImageEtag(result.body),\n cacheControl: `public, max-age=${config.minimumCacheTTL}, stale-while-revalidate=${Math.max(\n config.minimumCacheTTL,\n 60,\n )}`,\n expiresAt: Date.now() + config.minimumCacheTTL * 1_000,\n };\n cache.set(cacheKey, entry);\n return entry;\n });\n }\n\n return createOptimizedImageResponse(request, optimized, config);\n } catch (error) {\n if (!(error instanceof FarmImageRequestError) && !isAbortError(error)) {\n try {\n options.onError?.(error, request);\n } catch {\n // Error reporting must not replace the optimizer's sanitized response.\n }\n }\n return createFarmImageErrorResponse(error);\n }\n };\n}\n\n/** Mirrors the `images.maximumResponseBody` default (\"10mb\"). */\nconst DEFAULT_IMAGE_TRANSFORM_BODY_LIMIT = 10 * 1024 * 1024;\n\nexport function createCloudflareImageTransformer(\n fetcher: typeof globalThis.fetch = globalThis.fetch,\n): FarmImageTransformer {\n return async ({ sourceUrl, width, quality, accept, formats, signal, maximumResponseBody }) => {\n const format = selectOutputFormat(accept, formats);\n // Cloudflare resizing works by letting the edge fetch the origin, so this\n // request cannot reuse the bytes the handler already read. It still must not\n // be a weaker fetch than the validated one: `redirect: \"manual\"` keeps it\n // from silently following a hop the handler never validated, and the body is\n // read under the same ceiling as the handler's own read.\n const response = await fetcher(sourceUrl, {\n signal,\n redirect: \"manual\",\n headers: { accept: \"image/*\" },\n cf: {\n image: {\n fit: \"scale-down\",\n width,\n quality,\n ...(format ? { format: format === \"image/avif\" ? \"avif\" : \"webp\" } : {}),\n },\n },\n } as RequestInit);\n\n if (response.status >= 300 && response.status < 400) {\n void cancelResponseBody(response);\n throw new FarmImageRequestError(\n \"UNSUPPORTED_IMAGE\",\n 502,\n \"Source image redirected after validation\",\n );\n }\n\n if (!response.ok) {\n throw new FarmImageRequestError(\n \"UNSUPPORTED_IMAGE\",\n response.status === 404 ? 404 : 502,\n \"Cloudflare could not transform the source image\",\n );\n }\n\n const body = await readResponseWithLimit(\n response,\n maximumResponseBody ?? DEFAULT_IMAGE_TRANSFORM_BODY_LIMIT,\n );\n return {\n body,\n contentType:\n normalizeImageContentType(response.headers.get(\"content-type\")) ||\n detectImageContentType(body),\n };\n };\n}\n\nexport function selectOutputFormat(\n accept: string,\n formats: readonly FarmImageFormat[],\n): FarmImageFormat | undefined {\n const qualityByFormat = new Map<string, number>();\n\n for (const range of accept.split(\",\")) {\n const [rawType, ...parameters] = range.split(\";\");\n const type = rawType.trim().toLowerCase();\n if (!type) continue;\n\n let quality = 1;\n for (const parameter of parameters) {\n const [rawName, rawValue] = parameter.split(\"=\", 2);\n if (rawName.trim().toLowerCase() !== \"q\") continue;\n const parsed = Number(rawValue?.trim());\n quality = Number.isFinite(parsed) && parsed >= 0 && parsed <= 1 ? parsed : 0;\n break;\n }\n\n qualityByFormat.set(type, Math.max(qualityByFormat.get(type) ?? 0, quality));\n }\n\n let selected: FarmImageFormat | undefined;\n let selectedQuality = 0;\n for (const format of formats) {\n const quality = qualityByFormat.get(format) ?? 0;\n if (quality > selectedQuality) {\n selected = format;\n selectedQuality = quality;\n }\n }\n return selected;\n}\n\nexport function isPrivateImageAddress(address: string): boolean {\n const value = address.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n if (value === \"::\" || value === \"::1\") return true;\n if (/^(?:fc|fd)[0-9a-f]{2}:/.test(value) || /^fe[89ab][0-9a-f]:/.test(value)) return true;\n if (value.startsWith(\"::ffff:\")) return isPrivateImageAddress(value.slice(7));\n\n const parts = value.split(\".\");\n if (parts.length !== 4 || parts.some((part) => !/^\\d{1,3}$/.test(part))) return false;\n const octets = parts.map(Number);\n if (octets.some((part) => part > 255)) return false;\n\n const [a, b] = octets;\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && (b === 0 || b === 168)) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\nfunction parseAllowedInteger(\n raw: string | null,\n allowed: ReadonlySet<number>,\n name: string,\n): number {\n if (!raw || !/^\\d+$/.test(raw)) {\n throw new FarmImageRequestError(\n \"INVALID_PARAMETER\",\n 400,\n `Image ${name} must be an allowed integer`,\n );\n }\n const value = Number(raw);\n if (!allowed.has(value)) {\n throw new FarmImageRequestError(\"INVALID_PARAMETER\", 400, `Image ${name} is not configured`);\n }\n return value;\n}\n\nasync function resolveImageSourceUrl(\n requestUrl: URL,\n config: ResolvedFarmImageConfig,\n validateRemoteUrl: CreateFarmImageHandlerOptions[\"validateRemoteUrl\"],\n): Promise<URL> {\n const raw = requestUrl.searchParams.get(\"url\");\n if (!raw || raw.length > 4096 || raw.startsWith(\"//\")) {\n throw new FarmImageRequestError(\"INVALID_PARAMETER\", 400, \"Invalid image source URL\");\n }\n\n let sourceUrl: URL;\n try {\n sourceUrl = raw.startsWith(\"/\") ? new URL(raw, requestUrl.origin) : new URL(raw);\n } catch {\n throw new FarmImageRequestError(\"INVALID_PARAMETER\", 400, \"Invalid image source URL\");\n }\n\n await validateImageSourceUrl(sourceUrl, requestUrl.origin, config, validateRemoteUrl);\n return sourceUrl;\n}\n\nasync function validateImageSourceUrl(\n sourceUrl: URL,\n requestOrigin: string,\n config: ResolvedFarmImageConfig,\n validateRemoteUrl: CreateFarmImageHandlerOptions[\"validateRemoteUrl\"],\n): Promise<void> {\n if (sourceUrl.protocol !== \"http:\" && sourceUrl.protocol !== \"https:\") {\n throw new FarmImageRequestError(\"DISALLOWED_SOURCE\", 400, \"Unsupported image protocol\");\n }\n if (sourceUrl.username || sourceUrl.password || sourceUrl.hash) {\n throw new FarmImageRequestError(\"DISALLOWED_SOURCE\", 400, \"Unsafe image source URL\");\n }\n\n if (sourceUrl.origin === requestOrigin) {\n if (\n sourceUrl.pathname === config.path ||\n !matchesLocalPatterns(sourceUrl, config.localPatterns)\n ) {\n throw new FarmImageRequestError(\n \"DISALLOWED_SOURCE\",\n 400,\n \"Local image source is not allowed\",\n );\n }\n return;\n }\n\n if (!matchesRemoteSource(sourceUrl, config)) {\n throw new FarmImageRequestError(\"DISALLOWED_SOURCE\", 400, \"Remote image source is not allowed\");\n }\n if (!config.dangerouslyAllowLocalIP && isPrivateImageAddress(sourceUrl.hostname)) {\n throw new FarmImageRequestError(\"PRIVATE_SOURCE\", 400, \"Private image source is not allowed\");\n }\n if (!config.dangerouslyAllowLocalIP) {\n await validateRemoteUrl?.(sourceUrl);\n }\n}\n\nasync function fetchImageSource(\n initialUrl: URL,\n requestOrigin: string,\n config: ResolvedFarmImageConfig,\n fetcher: typeof globalThis.fetch,\n fetchRemote: typeof globalThis.fetch | undefined,\n validateRemoteUrl: CreateFarmImageHandlerOptions[\"validateRemoteUrl\"],\n signal: AbortSignal,\n): Promise<{ response: Response; url: URL }> {\n let currentUrl = initialUrl;\n\n for (let redirectCount = 0; ; redirectCount += 1) {\n throwIfAborted(signal);\n const sourceFetcher = currentUrl.origin === requestOrigin ? fetcher : (fetchRemote ?? fetcher);\n const response = await sourceFetcher(currentUrl, {\n method: \"GET\",\n redirect: \"manual\",\n signal,\n headers: {\n accept: \"image/avif,image/webp,image/*,*/*;q=0.8\",\n \"user-agent\": \"Farm.js Image Optimizer\",\n },\n });\n\n if (![301, 302, 303, 307, 308].includes(response.status)) {\n if (!response.ok) {\n await cancelResponseBody(response);\n throw new FarmImageRequestError(\n \"UNSUPPORTED_IMAGE\",\n response.status === 404 ? 404 : 502,\n \"Could not fetch source image\",\n );\n }\n return { response, url: currentUrl };\n }\n\n if (redirectCount >= config.maximumRedirects) {\n await cancelResponseBody(response);\n throw new FarmImageRequestError(\n \"TOO_MANY_REDIRECTS\",\n 400,\n \"Source image exceeded the redirect limit\",\n );\n }\n const location = response.headers.get(\"location\");\n if (!location) {\n await cancelResponseBody(response);\n throw new FarmImageRequestError(\"UNSUPPORTED_IMAGE\", 502, \"Invalid image redirect\");\n }\n await cancelResponseBody(response);\n currentUrl = new URL(location, currentUrl);\n await validateImageSourceUrl(currentUrl, requestOrigin, config, validateRemoteUrl);\n }\n}\n\ntype InflightOptimization = {\n promise: Promise<OptimizedImage>;\n controller: AbortController;\n waiters: number;\n};\n\n/**\n * Share one in-flight optimization between identical concurrent requests.\n *\n * The shared work runs under its own AbortController rather than any single\n * request's signal, so one caller going away cannot cancel the image everyone\n * else is waiting for. The controller is aborted only when the last waiter\n * leaves, so an abandoned burst still stops promptly.\n */\nasync function runCoalesced(\n inflight: Map<string, InflightOptimization>,\n key: string,\n requestSignal: AbortSignal,\n run: (signal: AbortSignal) => Promise<OptimizedImage>,\n): Promise<OptimizedImage> {\n let entry = inflight.get(key);\n if (!entry) {\n const controller = new AbortController();\n const created: InflightOptimization = {\n controller,\n waiters: 0,\n promise: undefined as unknown as Promise<OptimizedImage>,\n };\n created.promise = run(controller.signal).finally(() => {\n if (inflight.get(key) === created) inflight.delete(key);\n });\n // Every waiter can detach before the shared work settles: an already\n // aborted request returns early without ever attaching to this promise,\n // and the last waiter leaving aborts the controller. Keep one no-op\n // handler so that rejection is never reported as unhandled. Waiters still\n // observe it, because this does not replace the promise they await.\n created.promise.catch(() => {});\n inflight.set(key, created);\n entry = created;\n }\n\n const pending = entry;\n pending.waiters += 1;\n try {\n return await raceRequestAbort(pending.promise, requestSignal);\n } finally {\n pending.waiters -= 1;\n if (pending.waiters === 0 && inflight.get(key) === pending) {\n inflight.delete(key);\n pending.controller.abort();\n }\n }\n}\n\nfunction raceRequestAbort(\n promise: Promise<OptimizedImage>,\n signal: AbortSignal,\n): Promise<OptimizedImage> {\n if (!signal) return promise;\n if (signal.aborted) return Promise.reject(signal.reason ?? new Error(\"Aborted\"));\n\n return new Promise<OptimizedImage>((resolve, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error(\"Aborted\"));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n promise.then(resolve, reject).finally(() => signal.removeEventListener(\"abort\", onAbort));\n });\n}\n\nasync function readResponseWithLimit(response: Response, limit: number): Promise<Uint8Array> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && Number(contentLength) > limit) {\n // Cleanup (including an unread tee branch) must not delay the size rejection.\n void cancelResponseBody(response);\n throw new FarmImageRequestError(\"BODY_TOO_LARGE\", 413, \"Source image is too large\");\n }\n\n if (!response.body) return new Uint8Array();\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let byteLength = 0;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n byteLength += value.byteLength;\n if (byteLength > limit) {\n const error = new FarmImageRequestError(\"BODY_TOO_LARGE\", 413, \"Source image is too large\");\n void reader.cancel(error).catch(() => {});\n throw error;\n }\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n const result = new Uint8Array(byteLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return result;\n}\n\nasync function cancelResponseBody(response: Response): Promise<void> {\n try {\n await response.body?.cancel();\n } catch {\n // Cleanup must not replace the request error or redirect result.\n }\n}\n\nfunction detectImageContentType(bytes: Uint8Array): string {\n if (\n bytes.length >= 8 &&\n bytes[0] === 0x89 &&\n bytes[1] === 0x50 &&\n bytes[2] === 0x4e &&\n bytes[3] === 0x47\n ) {\n return \"image/png\";\n }\n if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n return \"image/jpeg\";\n }\n if (bytes.length >= 6) {\n const signature = new TextDecoder().decode(bytes.slice(0, 6));\n if (signature === \"GIF87a\" || signature === \"GIF89a\") return \"image/gif\";\n }\n if (bytes.length >= 12) {\n const riff = new TextDecoder().decode(bytes.slice(0, 4));\n const webp = new TextDecoder().decode(bytes.slice(8, 12));\n if (riff === \"RIFF\" && webp === \"WEBP\") return \"image/webp\";\n const box = new TextDecoder().decode(bytes.slice(4, 12));\n if (box.startsWith(\"ftypavif\") || box.startsWith(\"ftypavis\")) return \"image/avif\";\n }\n\n const prefix = new TextDecoder().decode(bytes.slice(0, 512)).trimStart().toLowerCase();\n if (prefix.startsWith(\"<svg\") || (prefix.startsWith(\"<?xml\") && prefix.includes(\"<svg\"))) {\n return \"image/svg+xml\";\n }\n return \"\";\n}\n\nfunction validateSourceType(type: string, config: ResolvedFarmImageConfig): void {\n if (!type || (type === \"image/svg+xml\" && !config.dangerouslyAllowSVG)) {\n throw new FarmImageRequestError(\"UNSUPPORTED_IMAGE\", 415, \"Unsupported source image\");\n }\n}\n\nfunction validateTransformedResult(\n result: FarmImageTransformResult,\n config: ResolvedFarmImageConfig,\n): void {\n if (!(result.body instanceof Uint8Array) || result.body.byteLength === 0) {\n throw new Error(\"The image transformer returned an empty response\");\n }\n if (result.body.byteLength > config.maximumResponseBody) {\n throw new FarmImageRequestError(\"BODY_TOO_LARGE\", 413, \"Optimized image is too large\");\n }\n const contentType = normalizeImageContentType(result.contentType);\n if (!contentType || (contentType === \"image/svg+xml\" && !config.dangerouslyAllowSVG)) {\n throw new Error(\"The image transformer returned an unsupported content type\");\n }\n result.contentType = contentType;\n}\n\nfunction normalizeImageContentType(value: string | null): string {\n const type = value?.split(\";\", 1)[0].trim().toLowerCase() ?? \"\";\n return type.startsWith(\"image/\") ? type : \"\";\n}\n\nfunction matchesRemoteSource(url: URL, config: ResolvedFarmImageConfig): boolean {\n if (config.domains.includes(url.hostname.toLowerCase())) return true;\n return config.remotePatterns.some((pattern) => matchesRemotePattern(url, pattern));\n}\n\nfunction matchesRemotePattern(url: URL, pattern: FarmImageRemotePattern): boolean {\n return (\n (!pattern.protocol || url.protocol === `${pattern.protocol}:`) &&\n matchesHostname(url.hostname, pattern.hostname) &&\n (pattern.port === undefined || url.port === pattern.port) &&\n matchesGlob(url.pathname, pattern.pathname ?? \"/**\") &&\n (pattern.search === undefined || url.search === pattern.search)\n );\n}\n\nfunction matchesLocalPatterns(url: URL, patterns: readonly FarmImageLocalPattern[]): boolean {\n return patterns.some(\n (pattern) =>\n matchesGlob(url.pathname, pattern.pathname) &&\n (pattern.search === undefined || url.search === pattern.search),\n );\n}\n\nfunction matchesHostname(hostname: string, pattern: string): boolean {\n const normalizedHostname = hostname.toLowerCase();\n const normalizedPattern = pattern.toLowerCase();\n if (normalizedPattern.startsWith(\"**.\")) {\n const suffix = normalizedPattern.slice(3);\n return normalizedHostname === suffix || normalizedHostname.endsWith(`.${suffix}`);\n }\n if (normalizedPattern.startsWith(\"*.\")) {\n const suffix = normalizedPattern.slice(2);\n const prefix = normalizedHostname.slice(0, -(suffix.length + 1));\n return normalizedHostname.endsWith(`.${suffix}`) && !!prefix && !prefix.includes(\".\");\n }\n return normalizedHostname === normalizedPattern;\n}\n\nfunction matchesGlob(value: string, pattern: string): boolean {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const source = escaped.replace(/\\*\\*/g, \"\\0\").replace(/\\*/g, \"[^/]*\").replace(/\\0/g, \".*\");\n return new RegExp(`^${source}$`).test(value);\n}\n\nfunction createOptimizedImageResponse(\n request: Request,\n image: OptimizedImage,\n config: ResolvedFarmImageConfig,\n): Response {\n const headers = new Headers({\n \"cache-control\": image.cacheControl,\n \"content-type\": image.contentType,\n \"content-length\": String(image.body.byteLength),\n \"content-disposition\": \"inline\",\n etag: image.etag,\n vary: \"Accept\",\n \"x-content-type-options\": \"nosniff\",\n });\n if (image.contentType === \"image/svg+xml\" && config.dangerouslyAllowSVG) {\n headers.set(\"content-security-policy\", \"default-src 'none'; sandbox\");\n }\n if (matchesFarmIfNoneMatch(request.headers.get(\"if-none-match\"), image.etag)) {\n headers.delete(\"content-length\");\n return new Response(null, { status: 304, headers });\n }\n const body =\n request.method === \"HEAD\"\n ? null\n : image.body.buffer.slice(\n image.body.byteOffset,\n image.body.byteOffset + image.body.byteLength,\n );\n return new Response(body as ArrayBuffer | null, { status: 200, headers });\n}\n\nfunction createFarmImageErrorResponse(error: unknown): Response {\n const status =\n error instanceof FarmImageRequestError ? error.status : isAbortError(error) ? 499 : 500;\n const headers = new Headers({\n \"cache-control\": \"no-store\",\n \"content-type\": \"text/plain; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n });\n if (status === 405) headers.set(\"allow\", \"GET, HEAD\");\n\n const message =\n status === 400\n ? \"Invalid image request\"\n : status === 404\n ? \"Image not found\"\n : status === 405\n ? \"Method not allowed\"\n : status === 413\n ? \"Image is too large\"\n : status === 415\n ? \"Unsupported image\"\n : status === 499\n ? \"Image request cancelled\"\n : \"Image optimization failed\";\n return new Response(message, { status, headers });\n}\n\nfunction createImageEtag(bytes: Uint8Array): string {\n let hash = 0x811c9dc5;\n for (const byte of bytes) {\n hash ^= byte;\n hash = Math.imul(hash, 0x01000193);\n }\n return `W/\"farm-${bytes.byteLength.toString(16)}-${(hash >>> 0).toString(16)}\"`;\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n throw signal.reason instanceof Error\n ? signal.reason\n : new DOMException(\"The image request was aborted\", \"AbortError\");\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && error.name === \"AbortError\";\n}\n\nclass FarmImageMemoryCache {\n private readonly entries = new Map<string, OptimizedImage>();\n\n constructor(private readonly capacity: number) {}\n\n get(key: string): OptimizedImage | undefined {\n const value = this.entries.get(key);\n if (!value) return undefined;\n if (value.expiresAt <= Date.now()) {\n this.entries.delete(key);\n return undefined;\n }\n this.entries.delete(key);\n this.entries.set(key, value);\n return value;\n }\n\n set(key: string, value: OptimizedImage): void {\n if (this.capacity <= 0) return;\n this.entries.delete(key);\n this.entries.set(key, value);\n while (this.entries.size > this.capacity) {\n const oldestKey = this.entries.keys().next().value as string | undefined;\n if (oldestKey === undefined) break;\n this.entries.delete(oldestKey);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getFarmClientDataCache,
3
3
  trackFarmClientCacheInvalidations
4
- } from "./chunk-WMJGA32P.mjs";
4
+ } from "./chunk-BXVOHG6B.mjs";
5
5
  import {
6
6
  isFarmServerQueryResult
7
7
  } from "./chunk-EHTUKVSW.mjs";
@@ -248,4 +248,4 @@ export {
248
248
  fetchServerQuery,
249
249
  prefetchServerQuery
250
250
  };
251
- //# sourceMappingURL=chunk-WD2EBM3I.mjs.map
251
+ //# sourceMappingURL=chunk-3CQJV3NC.mjs.map
@@ -2,7 +2,7 @@ import {
2
2
  ServerFnFailure,
3
3
  getServerActionExecutionContext,
4
4
  getServerActionSignal
5
- } from "./chunk-35NPLKQJ.mjs";
5
+ } from "./chunk-XWM2C267.mjs";
6
6
  import {
7
7
  applyFarmCacheInvalidationTargets
8
8
  } from "./chunk-2HDOV47R.mjs";
@@ -300,4 +300,4 @@ export {
300
300
  createServerFn,
301
301
  _parseServerFnSchema
302
302
  };
303
- //# sourceMappingURL=chunk-I3OOUWO5.mjs.map
303
+ //# sourceMappingURL=chunk-3GDRV7SG.mjs.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-GTU5AB4E.mjs";
8
8
  import {
9
9
  resolveDocsConfig
10
- } from "./chunk-X4SFHKFH.mjs";
10
+ } from "./chunk-BU65A3LZ.mjs";
11
11
  import {
12
12
  resolveFarmDocsFontAssets,
13
13
  toFarmDocsPublicFontAssets
@@ -2621,4 +2621,4 @@ export {
2621
2621
  createDocsAPI,
2622
2622
  createFarmDocsAPIHandler
2623
2623
  };
2624
- //# sourceMappingURL=chunk-YIBV77KZ.mjs.map
2624
+ //# sourceMappingURL=chunk-4WLAVHCY.mjs.map
@@ -1,3 +1,6 @@
1
+ import {
2
+ renderFarmAgentJsonLd
3
+ } from "./chunk-Z5ARESQG.mjs";
1
4
  import {
2
5
  resolveFarmThemeConfig
3
6
  } from "./chunk-H53KVQUU.mjs";
@@ -74,7 +77,7 @@ function addMetadataImageReference(metadata, reference) {
74
77
  };
75
78
  }
76
79
  __name(addMetadataImageReference, "addMetadataImageReference");
77
- function renderMetadataHead(metadata) {
80
+ function renderMetadataHead(metadata, options = {}) {
78
81
  const resolvedMetadata = metadata || {};
79
82
  const metadataBase = resolveMetadataBase(resolvedMetadata);
80
83
  const explicitTitle = resolveMetadataTitle(resolvedMetadata.title);
@@ -95,14 +98,16 @@ function renderMetadataHead(metadata) {
95
98
  appendMetaName(tags, "publisher", resolvedMetadata.publisher);
96
99
  appendMetaName(tags, "robots", normalizeRobots(resolvedMetadata.robots));
97
100
  const alternates = resolvedMetadata.alternates;
98
- if (isRecord(alternates)) {
99
- appendLink(tags, "canonical", resolveMetadataUrl(alternates.canonical, metadataBase));
100
- if (isRecord(alternates.languages)) {
101
- for (const [language, href] of Object.entries(alternates.languages)) {
102
- appendLink(tags, "alternate", resolveMetadataUrl(href, metadataBase), {
103
- hreflang: language
104
- });
105
- }
101
+ const explicitCanonical = isRecord(alternates) ? alternates.canonical : void 0;
102
+ const canonicalHref = explicitCanonical != null ? resolveMetadataUrl(explicitCanonical, metadataBase) : options.pathname ? resolveMetadataUrl(options.pathname, metadataBase) : void 0;
103
+ if (canonicalHref) {
104
+ appendLink(tags, "canonical", canonicalHref);
105
+ }
106
+ if (isRecord(alternates) && isRecord(alternates.languages)) {
107
+ for (const [language, href] of Object.entries(alternates.languages)) {
108
+ appendLink(tags, "alternate", resolveMetadataUrl(href, metadataBase), {
109
+ hreflang: language
110
+ });
106
111
  }
107
112
  }
108
113
  const hasFavicon = appendIcons(tags, resolvedMetadata.icons, metadataBase);
@@ -115,6 +120,16 @@ function renderMetadataHead(metadata) {
115
120
  }
116
121
  appendOpenGraph(tags, resolvedMetadata.openGraph, metadataBase);
117
122
  appendTwitter(tags, resolvedMetadata.twitter, metadataBase);
123
+ if (options.jsonLd) {
124
+ const jsonLdConfig = options.jsonLd === true ? {} : options.jsonLd;
125
+ const jsonLdScript = renderFarmAgentJsonLd(jsonLdConfig, {
126
+ metadataBase,
127
+ siteName: isRecord(resolvedMetadata.openGraph) ? normalizeContent(resolvedMetadata.openGraph.siteName) : void 0,
128
+ title: explicitTitle,
129
+ description: normalizeContent(resolvedMetadata.description)
130
+ });
131
+ if (jsonLdScript) tags.push(jsonLdScript);
132
+ }
118
133
  return {
119
134
  title: escapeText(title),
120
135
  tags: tags.length > 0 ? `
@@ -140,7 +155,7 @@ function appendOpenGraph(tags, openGraph, metadataBase) {
140
155
  appendMetaProperty(tags, "og:description", openGraph.description);
141
156
  appendMetaProperty(tags, "og:url", resolveMetadataUrl(openGraph.url, metadataBase));
142
157
  appendMetaProperty(tags, "og:site_name", openGraph.siteName);
143
- appendMetaProperty(tags, "og:type", openGraph.type);
158
+ appendMetaProperty(tags, "og:type", openGraph.type ?? "website");
144
159
  appendMetaProperty(tags, "og:locale", openGraph.locale);
145
160
  const images = normalizeMetadataImages(
146
161
  openGraph.images ?? openGraph.image,
@@ -692,4 +707,4 @@ export {
692
707
  createFarmThemeDocumentParts,
693
708
  applyFarmThemeDocument
694
709
  };
695
- //# sourceMappingURL=chunk-KDP5ZSWP.mjs.map
710
+ //# sourceMappingURL=chunk-7PS5NKOM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/metadata.ts","../src/metadata-route.ts","../src/components/error-page.ts","../src/theme/server-runtime.ts"],"sourcesContent":["import type { Metadata } from \"./types\";\nimport { renderFarmAgentJsonLd, type FarmAgentJsonLd } from \"./agent-config\";\n\nexport type MetadataImageKind = \"opengraph\" | \"twitter\";\n\nexport interface FarmMetadataImageReference {\n kind: MetadataImageKind;\n href: string;\n alt?: string;\n width?: number;\n height?: number;\n contentType?: string;\n}\n\nexport interface RenderedMetadataHead {\n title: string;\n tags: string;\n hasFavicon: boolean;\n /** False when the title is the framework fallback rather than configured. */\n hasExplicitTitle: boolean;\n}\n\ntype MetadataRecord = Metadata & Record<string, any>;\n\nexport function mergeMetadata(\n base: MetadataRecord | undefined,\n next: MetadataRecord | undefined,\n): MetadataRecord {\n if (!base) return next ? { ...next } : {};\n if (!next) return { ...base };\n\n return {\n ...base,\n ...next,\n title: mergeMetadataTitle(base.title, next.title),\n openGraph: mergeNestedMetadata(base.openGraph, next.openGraph),\n twitter: mergeNestedMetadata(base.twitter, next.twitter),\n alternates: mergeNestedMetadata((base as any).alternates, (next as any).alternates),\n icons: mergeNestedMetadata((base as any).icons, (next as any).icons),\n };\n}\n\nfunction mergeMetadataTitle(base: Metadata[\"title\"], next: Metadata[\"title\"]): Metadata[\"title\"] {\n if (next === undefined) return base;\n\n const parentTemplate = isRecord(base) ? normalizeContent(base.template) : undefined;\n if (typeof next === \"string\") {\n return parentTemplate ? applyTitleTemplate(parentTemplate, next) : next;\n }\n\n if (!isRecord(next)) return next;\n\n const defaultTitle = normalizeContent(next.default) ?? resolveMetadataTitle(base);\n return {\n ...next,\n default:\n defaultTitle && parentTemplate\n ? applyTitleTemplate(parentTemplate, defaultTitle)\n : defaultTitle,\n };\n}\n\nfunction applyTitleTemplate(template: string, title: string): string {\n return template.split(\"%s\").join(title);\n}\n\nexport function addMetadataImageReference(\n metadata: MetadataRecord,\n reference: FarmMetadataImageReference,\n): MetadataRecord {\n if (reference.kind === \"opengraph\") {\n const openGraph = { ...metadata.openGraph };\n if (!hasMetadataImages(openGraph.images) && !hasMetadataImages((openGraph as any).image)) {\n openGraph.images = [\n {\n url: reference.href,\n width: reference.width,\n height: reference.height,\n alt: reference.alt,\n type: reference.contentType,\n },\n ];\n }\n\n return {\n ...metadata,\n openGraph,\n };\n }\n\n const twitter = { ...metadata.twitter };\n if (!hasMetadataImages(twitter.images)) {\n twitter.images = [reference.href];\n twitter.card = twitter.card || \"summary_large_image\";\n }\n\n return {\n ...metadata,\n twitter,\n };\n}\n\nexport interface RenderMetadataHeadOptions {\n /**\n * Current request pathname. Used to emit a default `<link rel=\"canonical\">`\n * when the route does not set one, so agents and crawlers can resolve the\n * page's identity. Combined with `metadataBase` into an absolute URL when a\n * base is configured; otherwise emitted as a self-referential path.\n */\n pathname?: string;\n /**\n * Agent JSON-LD config. When truthy, a schema.org JSON-LD script is emitted in\n * the head, built from this config and the page/site metadata. `true` uses the\n * defaults; `false`/omitted (the default) emits nothing.\n */\n jsonLd?: FarmAgentJsonLd | boolean;\n}\n\nexport function renderMetadataHead(\n metadata: MetadataRecord | undefined,\n options: RenderMetadataHeadOptions = {},\n): RenderedMetadataHead {\n const resolvedMetadata = metadata || {};\n const metadataBase = resolveMetadataBase(resolvedMetadata);\n const explicitTitle = resolveMetadataTitle(resolvedMetadata.title);\n const title = explicitTitle || \"Farm.js App\";\n const tags: string[] = [];\n\n appendMetaName(tags, \"description\", resolvedMetadata.description);\n appendMetaName(tags, \"keywords\", normalizeKeywords(resolvedMetadata.keywords));\n appendMetaName(tags, \"author\", (resolvedMetadata as any).author);\n\n if (Array.isArray(resolvedMetadata.authors)) {\n for (const author of resolvedMetadata.authors) {\n appendMetaName(tags, \"author\", author?.name);\n if (author?.url) {\n appendLink(tags, \"author\", resolveMetadataUrl(author.url, metadataBase));\n }\n }\n }\n\n appendMetaName(tags, \"creator\", resolvedMetadata.creator);\n appendMetaName(tags, \"publisher\", resolvedMetadata.publisher);\n appendMetaName(tags, \"robots\", normalizeRobots(resolvedMetadata.robots));\n\n const alternates = (resolvedMetadata as any).alternates;\n const explicitCanonical = isRecord(alternates) ? alternates.canonical : undefined;\n // Default the canonical link to the current path when the route does not set\n // one. This is a self-referential canonical (absolute when `metadataBase` is\n // configured), which is safe for every page and gives agents/crawlers a\n // stable identity for the URL.\n const canonicalHref =\n explicitCanonical != null\n ? resolveMetadataUrl(explicitCanonical, metadataBase)\n : options.pathname\n ? resolveMetadataUrl(options.pathname, metadataBase)\n : undefined;\n if (canonicalHref) {\n appendLink(tags, \"canonical\", canonicalHref);\n }\n\n if (isRecord(alternates) && isRecord(alternates.languages)) {\n for (const [language, href] of Object.entries(alternates.languages)) {\n appendLink(tags, \"alternate\", resolveMetadataUrl(href, metadataBase), {\n hreflang: language,\n });\n }\n }\n\n const hasFavicon = appendIcons(tags, (resolvedMetadata as any).icons, metadataBase);\n\n if ((resolvedMetadata as any).manifest) {\n appendLink(\n tags,\n \"manifest\",\n resolveMetadataUrl((resolvedMetadata as any).manifest, metadataBase),\n );\n }\n\n appendOpenGraph(tags, resolvedMetadata.openGraph, metadataBase);\n appendTwitter(tags, resolvedMetadata.twitter, metadataBase);\n\n if (options.jsonLd) {\n const jsonLdConfig = options.jsonLd === true ? {} : options.jsonLd;\n const jsonLdScript = renderFarmAgentJsonLd(jsonLdConfig, {\n metadataBase,\n siteName: isRecord(resolvedMetadata.openGraph)\n ? normalizeContent(resolvedMetadata.openGraph.siteName)\n : undefined,\n title: explicitTitle,\n description: normalizeContent(resolvedMetadata.description),\n });\n if (jsonLdScript) tags.push(jsonLdScript);\n }\n\n return {\n title: escapeText(title),\n tags: tags.length > 0 ? `\\n ${tags.join(\"\\n \")}` : \"\",\n hasFavicon,\n hasExplicitTitle: Boolean(explicitTitle),\n };\n}\n\nfunction mergeNestedMetadata(base: unknown, next: unknown): any {\n if (isRecord(base) && isRecord(next)) {\n return {\n ...base,\n ...next,\n };\n }\n\n return next ?? base;\n}\n\nfunction appendOpenGraph(tags: string[], openGraph: Metadata[\"openGraph\"], metadataBase?: string) {\n if (!isRecord(openGraph)) return;\n\n appendMetaProperty(tags, \"og:title\", openGraph.title);\n appendMetaProperty(tags, \"og:description\", openGraph.description);\n appendMetaProperty(tags, \"og:url\", resolveMetadataUrl(openGraph.url, metadataBase));\n appendMetaProperty(tags, \"og:site_name\", openGraph.siteName);\n // Default og:type so a route that sets Open Graph data without a type still\n // emits a valid entity type for agents and social crawlers.\n appendMetaProperty(tags, \"og:type\", openGraph.type ?? \"website\");\n appendMetaProperty(tags, \"og:locale\", (openGraph as any).locale);\n\n const images = normalizeMetadataImages(\n openGraph.images ?? (openGraph as any).image,\n metadataBase,\n );\n for (const image of images) {\n appendMetaProperty(tags, \"og:image\", image.url);\n appendMetaProperty(tags, \"og:image:width\", image.width);\n appendMetaProperty(tags, \"og:image:height\", image.height);\n appendMetaProperty(tags, \"og:image:alt\", image.alt);\n appendMetaProperty(tags, \"og:image:type\", image.type);\n }\n}\n\nfunction appendTwitter(tags: string[], twitter: Metadata[\"twitter\"], metadataBase?: string) {\n if (!isRecord(twitter)) return;\n\n appendMetaName(tags, \"twitter:card\", twitter.card);\n appendMetaName(tags, \"twitter:site\", twitter.site);\n appendMetaName(tags, \"twitter:creator\", twitter.creator);\n appendMetaName(tags, \"twitter:title\", twitter.title);\n appendMetaName(tags, \"twitter:description\", twitter.description);\n\n for (const image of normalizeMetadataImages(twitter.images, metadataBase)) {\n appendMetaName(tags, \"twitter:image\", image.url);\n appendMetaName(tags, \"twitter:image:alt\", image.alt);\n }\n}\n\nfunction appendIcons(tags: string[], icons: unknown, metadataBase?: string): boolean {\n if (!icons) return false;\n\n if (typeof icons === \"string\") {\n const initialTagCount = tags.length;\n appendLink(tags, \"icon\", resolveMetadataUrl(icons, metadataBase));\n return tags.length > initialTagCount;\n }\n\n if (!isRecord(icons)) return false;\n\n const initialTagCount = tags.length;\n appendIconList(tags, \"icon\", icons.icon, metadataBase);\n appendIconList(tags, \"shortcut icon\", icons.shortcut, metadataBase);\n const hasFavicon = tags.length > initialTagCount;\n appendIconList(tags, \"apple-touch-icon\", icons.apple, metadataBase);\n return hasFavicon;\n}\n\nfunction appendIconList(tags: string[], rel: string, value: unknown, metadataBase?: string) {\n for (const icon of normalizeArray(value)) {\n if (typeof icon === \"string\") {\n appendLink(tags, rel, resolveMetadataUrl(icon, metadataBase));\n continue;\n }\n\n if (!isRecord(icon)) continue;\n appendLink(tags, rel, resolveMetadataUrl(icon.url, metadataBase), {\n sizes: icon.sizes,\n type: icon.type,\n });\n }\n}\n\nfunction appendMetaName(tags: string[], name: string, content: unknown) {\n const normalized = normalizeContent(content);\n if (!normalized) return;\n tags.push(`<meta name=\"${escapeAttribute(name)}\" content=\"${escapeAttribute(normalized)}\">`);\n}\n\nfunction appendMetaProperty(tags: string[], property: string, content: unknown) {\n const normalized = normalizeContent(content);\n if (!normalized) return;\n tags.push(\n `<meta property=\"${escapeAttribute(property)}\" content=\"${escapeAttribute(normalized)}\">`,\n );\n}\n\nfunction appendLink(\n tags: string[],\n rel: string,\n href: unknown,\n attrs: Record<string, unknown> = {},\n) {\n const normalizedHref = normalizeContent(href);\n if (!normalizedHref) return;\n\n const attrText = Object.entries(attrs)\n .map(([key, value]) => {\n const normalized = normalizeContent(value);\n return normalized ? ` ${key}=\"${escapeAttribute(normalized)}\"` : \"\";\n })\n .join(\"\");\n\n tags.push(\n `<link rel=\"${escapeAttribute(rel)}\" href=\"${escapeAttribute(normalizedHref)}\"${attrText}>`,\n );\n}\n\nfunction normalizeMetadataImages(\n value: unknown,\n metadataBase?: string,\n): Array<{\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n type?: string;\n}> {\n return normalizeArray(value)\n .map((item) => {\n if (typeof item === \"string\") {\n return { url: resolveMetadataUrl(item, metadataBase) || item };\n }\n\n if (!isRecord(item)) return null;\n const rawUrl = item.url || item.src;\n const url = resolveMetadataUrl(rawUrl, metadataBase);\n if (!url) return null;\n\n return {\n url,\n width: normalizeNumber(item.width),\n height: normalizeNumber(item.height),\n alt: typeof item.alt === \"string\" ? item.alt : undefined,\n type: typeof item.type === \"string\" ? item.type : undefined,\n };\n })\n .filter((item): item is NonNullable<typeof item> => item !== null);\n}\n\nfunction normalizeArray(value: unknown): unknown[] {\n if (value == null) return [];\n return Array.isArray(value) ? value : [value];\n}\n\nfunction hasMetadataImages(value: unknown): boolean {\n return normalizeMetadataImages(value).length > 0;\n}\n\nfunction resolveMetadataTitle(title: Metadata[\"title\"]): string | undefined {\n if (typeof title === \"string\") return title;\n if (isRecord(title)) {\n return normalizeContent(title.default);\n }\n return undefined;\n}\n\nfunction normalizeKeywords(keywords: Metadata[\"keywords\"]): string | undefined {\n if (Array.isArray(keywords)) return keywords.filter(Boolean).join(\", \");\n return keywords;\n}\n\nfunction normalizeRobots(robots: Metadata[\"robots\"]): string | undefined {\n if (typeof robots === \"string\") return robots;\n if (!isRecord(robots)) return undefined;\n\n const values: string[] = [];\n if (typeof robots.index === \"boolean\") values.push(robots.index ? \"index\" : \"noindex\");\n if (typeof robots.follow === \"boolean\") values.push(robots.follow ? \"follow\" : \"nofollow\");\n return values.join(\", \") || undefined;\n}\n\nfunction resolveMetadataBase(metadata: MetadataRecord): string | undefined {\n const base = metadata.metadataBase;\n if (!base) return undefined;\n return String(base);\n}\n\nfunction resolveMetadataUrl(value: unknown, metadataBase?: string): string | undefined {\n const normalized = normalizeContent(value);\n if (!normalized) return undefined;\n if (!metadataBase) return normalized;\n\n try {\n return new URL(normalized, metadataBase).toString();\n } catch {\n return normalized;\n }\n}\n\nfunction normalizeNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\nfunction normalizeContent(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n if (value instanceof URL) return value.toString();\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction escapeText(value: string): string {\n return value.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeText(value).replace(/\"/g, \"&quot;\");\n}\n","import { omitFarmResponseBody } from \"./response-body\";\n\nexport type ApplicationMetadataRouteKind = \"sitemap\" | \"robots\" | \"manifest\";\n\nexport namespace MetadataRoute {\n export type SitemapChangeFrequency =\n | \"always\"\n | \"hourly\"\n | \"daily\"\n | \"weekly\"\n | \"monthly\"\n | \"yearly\"\n | \"never\";\n\n export interface SitemapEntry {\n url: string;\n lastModified?: string | Date;\n changeFrequency?: SitemapChangeFrequency;\n priority?: number;\n alternates?: {\n languages?: Record<string, string>;\n };\n }\n\n export type Sitemap = SitemapEntry[];\n\n export interface RobotsRule {\n userAgent: string | string[];\n allow?: string | string[];\n disallow?: string | string[];\n crawlDelay?: number;\n }\n\n export interface Robots {\n rules: RobotsRule | RobotsRule[];\n sitemap?: string | string[];\n host?: string;\n }\n\n export interface ManifestIcon {\n src: string;\n sizes?: string;\n type?: string;\n purpose?: string;\n }\n\n export interface Manifest {\n name?: string;\n short_name?: string;\n description?: string;\n id?: string;\n start_url?: string;\n scope?: string;\n display?: \"fullscreen\" | \"standalone\" | \"minimal-ui\" | \"browser\" | string;\n orientation?: string;\n background_color?: string;\n theme_color?: string;\n lang?: string;\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n categories?: string[];\n icons?: ManifestIcon[];\n [key: string]: unknown;\n }\n}\n\nexport interface MetadataRouteContext {\n request: Request;\n params: Record<string, string>;\n searchParams: URLSearchParams;\n /** The concrete route-segment path that owns the metadata file. */\n path: string;\n}\n\nexport interface FarmMetadataRouteModule {\n revalidate?: number | false;\n}\n\nexport interface FarmMetadataRouteResponseOptions {\n method?: string;\n}\n\nfunction isResponse(value: unknown): value is Response {\n return (\n typeof Response !== \"undefined\" &&\n (value instanceof Response ||\n Boolean(\n value &&\n typeof value === \"object\" &&\n typeof (value as Response).arrayBuffer === \"function\" &&\n (value as Response).headers,\n ))\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nfunction resolveCacheControl(revalidate: number | false | undefined): string {\n if (revalidate === false) {\n return \"public, max-age=31536000, immutable\";\n }\n if (typeof revalidate === \"number\" && Number.isFinite(revalidate) && revalidate > 0) {\n return `public, s-maxage=${Math.floor(revalidate)}, stale-while-revalidate=300`;\n }\n return \"public, max-age=0, must-revalidate\";\n}\n\nfunction escapeXml(value: unknown): string {\n return String(value)\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n\nfunction serializeSitemap(value: unknown): string {\n if (!Array.isArray(value)) {\n throw new TypeError(\"sitemap.ts must return an array or a Response\");\n }\n\n const entries = value.map((candidate, index) => {\n if (!isRecord(candidate) || typeof candidate.url !== \"string\" || !candidate.url) {\n throw new TypeError(`sitemap.ts entry ${index} must include a non-empty url`);\n }\n return candidate as unknown as MetadataRoute.SitemapEntry;\n });\n const hasLanguageAlternates = entries.some(\n (entry) => entry.alternates?.languages && Object.keys(entry.alternates.languages).length > 0,\n );\n const namespace = hasLanguageAlternates ? ' xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"' : \"\";\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"${namespace}>`,\n ];\n\n for (const entry of entries) {\n lines.push(\" <url>\", ` <loc>${escapeXml(entry.url)}</loc>`);\n if (entry.lastModified !== undefined) {\n const lastModified =\n entry.lastModified instanceof Date ? entry.lastModified.toISOString() : entry.lastModified;\n lines.push(` <lastmod>${escapeXml(lastModified)}</lastmod>`);\n }\n if (entry.changeFrequency) {\n lines.push(` <changefreq>${escapeXml(entry.changeFrequency)}</changefreq>`);\n }\n if (entry.priority !== undefined) {\n lines.push(` <priority>${escapeXml(entry.priority)}</priority>`);\n }\n for (const [language, href] of Object.entries(entry.alternates?.languages || {})) {\n lines.push(\n ` <xhtml:link rel=\"alternate\" hreflang=\"${escapeXml(language)}\" href=\"${escapeXml(href)}\" />`,\n );\n }\n lines.push(\" </url>\");\n }\n\n lines.push(\"</urlset>\");\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction toArray<T>(value: T | T[] | undefined): T[] {\n return value === undefined ? [] : Array.isArray(value) ? value : [value];\n}\n\nfunction serializeRobots(value: unknown): string {\n if (!isRecord(value)) {\n throw new TypeError(\"robots.ts must return a robots object or a Response\");\n }\n\n const robots = value as unknown as MetadataRoute.Robots;\n const rules = toArray(robots.rules);\n if (rules.length === 0) {\n throw new TypeError(\"robots.ts must return at least one rule\");\n }\n\n const sections = rules.map((rule, index) => {\n if (!isRecord(rule)) {\n throw new TypeError(`robots.ts rule ${index} must be an object`);\n }\n const userAgents = toArray(rule.userAgent).filter(\n (userAgent): userAgent is string => typeof userAgent === \"string\" && Boolean(userAgent),\n );\n if (userAgents.length === 0) {\n throw new TypeError(`robots.ts rule ${index} must include a userAgent`);\n }\n\n const lines = userAgents.map((userAgent) => `User-agent: ${userAgent}`);\n for (const allow of toArray(rule.allow)) lines.push(`Allow: ${allow}`);\n for (const disallow of toArray(rule.disallow)) lines.push(`Disallow: ${disallow}`);\n if (rule.crawlDelay !== undefined) lines.push(`Crawl-delay: ${rule.crawlDelay}`);\n return lines.join(\"\\n\");\n });\n\n const globalLines = [\n ...toArray(robots.sitemap).map((sitemap) => `Sitemap: ${sitemap}`),\n ...(robots.host ? [`Host: ${robots.host}`] : []),\n ];\n return `${[...sections, ...(globalLines.length ? [globalLines.join(\"\\n\")] : [])].join(\"\\n\\n\")}\\n`;\n}\n\nfunction serializeManifest(value: unknown): string {\n if (!isRecord(value)) {\n throw new TypeError(\"manifest.ts must return a manifest object or a Response\");\n }\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\n/** @internal */\nexport function createFarmMetadataRouteResponse(\n kind: ApplicationMetadataRouteKind,\n value: unknown,\n routeModule: FarmMetadataRouteModule = {},\n options: FarmMetadataRouteResponseOptions = {},\n): Response {\n const method = (options.method || \"GET\").toUpperCase();\n if (method !== \"GET\" && method !== \"HEAD\") {\n return new Response(null, { status: 405, headers: { Allow: \"GET, HEAD\" } });\n }\n\n if (isResponse(value)) {\n return method === \"HEAD\" ? omitFarmResponseBody(value) : value;\n }\n\n const body =\n kind === \"sitemap\"\n ? serializeSitemap(value)\n : kind === \"robots\"\n ? serializeRobots(value)\n : serializeManifest(value);\n const contentType =\n kind === \"sitemap\"\n ? \"application/xml; charset=utf-8\"\n : kind === \"robots\"\n ? \"text/plain; charset=utf-8\"\n : \"application/manifest+json; charset=utf-8\";\n\n return new Response(method === \"HEAD\" ? null : body, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": resolveCacheControl(routeModule.revalidate),\n \"X-Content-Type-Options\": \"nosniff\",\n },\n });\n}\n","import { DEFAULT_ERROR_STYLES } from \"./error-styles\";\n\nexport { DEFAULT_ERROR_STYLES } from \"./error-styles\";\n\nconst ERROR_STATUS_TEXT: Record<number, string> = {\n 400: \"Bad Request\",\n 401: \"Unauthorized\",\n 402: \"Payment Required\",\n 403: \"Forbidden\",\n 404: \"Not Found\",\n 405: \"Method Not Allowed\",\n 406: \"Not Acceptable\",\n 408: \"Request Timeout\",\n 409: \"Conflict\",\n 410: \"Gone\",\n 411: \"Length Required\",\n 412: \"Precondition Failed\",\n 413: \"Content Too Large\",\n 414: \"URI Too Long\",\n 415: \"Unsupported Media Type\",\n 416: \"Range Not Satisfiable\",\n 418: \"I'm a Teapot\",\n 422: \"Unprocessable Content\",\n 423: \"Locked\",\n 424: \"Failed Dependency\",\n 425: \"Too Early\",\n 426: \"Upgrade Required\",\n 428: \"Precondition Required\",\n 429: \"Too Many Requests\",\n 431: \"Request Header Fields Too Large\",\n 451: \"Unavailable For Legal Reasons\",\n 500: \"Internal Server Error\",\n 501: \"Not Implemented\",\n 502: \"Bad Gateway\",\n 503: \"Service Unavailable\",\n 504: \"Gateway Timeout\",\n 505: \"HTTP Version Not Supported\",\n 506: \"Variant Also Negotiates\",\n 507: \"Insufficient Storage\",\n 508: \"Loop Detected\",\n 510: \"Not Extended\",\n 511: \"Network Authentication Required\",\n};\n\nconst ERROR_TITLES: Record<number, string> = {\n 400: \"The request could not be understood\",\n 401: \"Authentication is required\",\n 403: \"You do not have access to this page\",\n 404: \"The requested page could not be found\",\n 405: \"This request method is not supported\",\n 408: \"The request took too long\",\n 409: \"The request conflicts with the current state\",\n 410: \"This resource is no longer available\",\n 413: \"The request is too large\",\n 422: \"The request could not be processed\",\n 429: \"Too many requests were sent\",\n 500: \"Application failed during server rendering\",\n 501: \"This operation is not implemented\",\n 502: \"An upstream service returned an invalid response\",\n 503: \"The service is temporarily unavailable\",\n 504: \"An upstream service took too long to respond\",\n};\n\nconst ERROR_PUBLIC_MESSAGES: Record<number, string> = {\n 400: \"Check the request and try again.\",\n 401: \"Sign in and try this request again.\",\n 403: \"Use an account with the required permissions or return home.\",\n 404: \"Check the address or return to the home page.\",\n 405: \"Use a supported request method and try again.\",\n 408: \"Try the request again in a moment.\",\n 409: \"Refresh the page, review the latest state, and try again.\",\n 410: \"Return home to continue browsing.\",\n 413: \"Reduce the request size and try again.\",\n 422: \"Review the request data and try again.\",\n 429: \"Wait a moment before trying again.\",\n 500: \"An unexpected error prevented this page from rendering.\",\n 501: \"This operation is not available yet.\",\n 502: \"Try again after the upstream service recovers.\",\n 503: \"Try again in a moment.\",\n 504: \"Try again after the upstream service recovers.\",\n};\n\nexport interface DefaultErrorSourceLine {\n number: number;\n content: string;\n highlight?: boolean;\n}\n\nexport interface DefaultErrorSourceFrame {\n file: string;\n line: number;\n column: number;\n lines: DefaultErrorSourceLine[];\n}\n\nexport interface DefaultErrorPageOptions {\n statusCode?: number;\n statusText?: string;\n requestPath?: string;\n method?: string;\n message?: string;\n errorName?: string;\n stack?: string;\n sourceFrame?: DefaultErrorSourceFrame;\n development?: boolean;\n farmVersion?: string;\n nodeVersion?: string;\n mode?: string;\n}\n\nfunction escapeHtml(value: unknown): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\nfunction serializeJsonForHtml(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\nfunction normalizeErrorStatus(status: unknown): number | undefined {\n const value = typeof status === \"string\" && status.trim() ? Number(status) : status;\n return typeof value === \"number\" && Number.isInteger(value) && value >= 400 && value <= 599\n ? value\n : undefined;\n}\n\nexport function resolveDefaultErrorStatus(error: unknown): number {\n if (error && typeof error === \"object\") {\n const candidate = error as { status?: unknown; statusCode?: unknown };\n return (\n normalizeErrorStatus(candidate.status) ?? normalizeErrorStatus(candidate.statusCode) ?? 500\n );\n }\n return 500;\n}\n\nexport function getDefaultErrorStatusText(statusCode: number): string {\n return ERROR_STATUS_TEXT[statusCode] || (statusCode >= 500 ? \"Server Error\" : \"Request Error\");\n}\n\nexport function getDefaultErrorTitle(statusCode: number): string {\n return (\n ERROR_TITLES[statusCode] ||\n (statusCode >= 500\n ? \"The server could not complete the request\"\n : \"The request could not be completed\")\n );\n}\n\nfunction getDefaultErrorPublicMessage(statusCode: number): string {\n return ERROR_PUBLIC_MESSAGES[statusCode] || \"Try again or return to the home page.\";\n}\n\nfunction createSourceFrameMarkup(sourceFrame?: DefaultErrorSourceFrame): string {\n if (!sourceFrame) {\n return `<p class=\"farm-default-error__details-empty\">Source location is unavailable. Copy the debug report to inspect the filtered stack trace.</p>`;\n }\n\n const lines = sourceFrame.lines\n .map(\n (line) =>\n `<span class=\"farm-default-error__source-line${line.highlight ? \" farm-default-error__source-line--active\" : \"\"}\"><span class=\"farm-default-error__source-gutter\">${line.highlight ? \"&gt;\" : \"&nbsp;\"} ${line.number}</span><span class=\"farm-default-error__source-text\">${escapeHtml(line.content || \" \")}</span></span>`,\n )\n .join(\"\\n\");\n\n return `<div class=\"farm-default-error__source\"><p class=\"farm-default-error__source-path\">${escapeHtml(sourceFrame.file)}:${sourceFrame.line}:${sourceFrame.column}</p><pre class=\"farm-default-error__source-code\" tabindex=\"0\"><code>${lines}</code></pre></div>`;\n}\n\nfunction createDebugReport(\n options: Required<Pick<DefaultErrorPageOptions, \"statusCode\">> & DefaultErrorPageOptions,\n): string {\n const statusText = options.statusText || getDefaultErrorStatusText(options.statusCode);\n const sourceFrame = options.sourceFrame;\n const source = sourceFrame\n ? [\n `\\`${sourceFrame.file}:${sourceFrame.line}:${sourceFrame.column}\\``,\n \"\",\n \"```text\",\n ...sourceFrame.lines.map(\n (line) =>\n `${line.highlight ? \">\" : \" \"} ${String(line.number).padStart(4, \" \")} | ${line.content}`,\n ),\n \"```\",\n ].join(\"\\n\")\n : \"Source frame unavailable.\";\n\n return [\n \"# Farm.js debug report\",\n \"\",\n \"## Error\",\n `- Status: ${options.statusCode} ${statusText}`,\n `- Name: ${options.errorName || \"Error\"}`,\n `- Message: ${options.message || getDefaultErrorPublicMessage(options.statusCode)}`,\n `- Request: ${(options.method || \"GET\").toUpperCase()} ${options.requestPath || \"/\"}`,\n \"\",\n \"## Runtime\",\n `- Farm.js: ${options.farmVersion || \"unknown\"}`,\n `- Node.js: ${options.nodeVersion || \"unknown\"}`,\n `- Mode: ${options.mode || \"development\"}`,\n \"\",\n \"## Source\",\n source,\n \"\",\n \"## Filtered stack\",\n \"```text\",\n options.stack || \"Stack trace unavailable.\",\n \"```\",\n ].join(\"\\n\");\n}\n\nconst ERROR_PAGE_SCRIPT = `<script>(function(){var root=document.querySelector(\"[data-farm-default-error]\");if(!root)return;var retry=root.querySelector(\"[data-farm-error-retry]\");if(retry)retry.addEventListener(\"click\",function(){window.location.reload()})})();</script>`;\nconst ERROR_COPY_SCRIPT = `<script>(function(){var root=document.querySelector(\"[data-farm-default-error]\");var copy=root&&root.querySelector(\"[data-farm-error-copy]\");var report=document.getElementById(\"farm-default-error-report\");if(!copy||!report)return;copy.addEventListener(\"click\",async function(){var value=\"\";try{value=JSON.parse(report.textContent||'\"\"')}catch(_error){value=report.textContent||\"\"}try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(value)}else{var area=document.createElement(\"textarea\");area.value=value;area.setAttribute(\"readonly\",\"\");area.style.position=\"fixed\";area.style.opacity=\"0\";document.body.appendChild(area);area.select();document.execCommand(\"copy\");area.remove()}var label=copy.querySelector(\"[data-farm-error-copy-label]\");var status=copy.querySelector(\"[data-farm-error-copy-status]\");if(label)label.textContent=\"COPIED\";if(status)status.textContent=\"Debug report copied\";window.setTimeout(function(){if(label)label.textContent=\"COPY DEBUG REPORT\";if(status)status.textContent=\"\"},1800)}catch(_error){var status=copy.querySelector(\"[data-farm-error-copy-status]\");if(status)status.textContent=\"Unable to copy the debug report\"}})})();</script>`;\n\nexport function createDefaultErrorMarkup(options: DefaultErrorPageOptions = {}): string {\n const statusCode = normalizeErrorStatus(options.statusCode) ?? 500;\n const statusText = options.statusText || getDefaultErrorStatusText(statusCode);\n const development = options.development === true;\n const title = getDefaultErrorTitle(statusCode);\n const message =\n development && options.message ? options.message : getDefaultErrorPublicMessage(statusCode);\n const requestPath = options.requestPath || \"/\";\n const method = (options.method || \"GET\").toUpperCase();\n const eyebrow = statusCode >= 500 ? \"Runtime error\" : \"Request error\";\n const details = development\n ? `<section class=\"farm-default-error__details\" aria-labelledby=\"farm-default-error-details-title\"><div class=\"farm-default-error__details-header\"><h2 id=\"farm-default-error-details-title\" class=\"farm-default-error__details-title\">Details</h2><button class=\"farm-default-error__copy\" type=\"button\" data-farm-error-copy><span data-farm-error-copy-label>COPY DEBUG REPORT</span><span class=\"farm-default-error__sr-only\" aria-live=\"polite\" data-farm-error-copy-status></span></button></div>${createSourceFrameMarkup(options.sourceFrame)}<p class=\"farm-default-error__meta\">Farm.js v${escapeHtml(options.farmVersion || \"unknown\")} · ${escapeHtml(options.mode || \"development\")} · Node.js ${escapeHtml(options.nodeVersion || \"unknown\")}</p></section>`\n : \"\";\n const report = development\n ? `<script id=\"farm-default-error-report\" type=\"application/json\">${serializeJsonForHtml(createDebugReport({ ...options, statusCode, statusText, requestPath, method }))}</script>${ERROR_COPY_SCRIPT}`\n : \"\";\n\n return `<style>${DEFAULT_ERROR_STYLES}</style><main class=\"farm-default-error\" data-farm-default-error role=\"alert\" aria-labelledby=\"farm-default-error-title\" aria-describedby=\"farm-default-error-description\"><div class=\"farm-default-error__content\"><p class=\"farm-default-error__code\" aria-hidden=\"true\">${statusCode}</p><p class=\"farm-default-error__eyebrow\">${escapeHtml(eyebrow)}</p><header class=\"farm-default-error__summary\"><h1 id=\"farm-default-error-title\" class=\"farm-default-error__title\">${escapeHtml(title)}</h1><p id=\"farm-default-error-description\" class=\"farm-default-error__message\">${escapeHtml(message)}</p></header><section class=\"farm-default-error__panel\" aria-label=\"Error information\"><div class=\"farm-default-error__row\"><span class=\"farm-default-error__label\">Request</span><span class=\"farm-default-error__value\">${escapeHtml(method)} ${escapeHtml(requestPath)}</span></div><div class=\"farm-default-error__row\"><span class=\"farm-default-error__label\">Status</span><span class=\"farm-default-error__value\">${statusCode} ${escapeHtml(statusText)}</span></div>${details}</section><div class=\"farm-default-error__actions\"><button class=\"farm-default-error__action farm-default-error__action--primary\" type=\"button\" data-farm-error-retry>TRY AGAIN</button><a class=\"farm-default-error__action\" href=\"/\">RETURN HOME</a></div></div>${report}${ERROR_PAGE_SCRIPT}</main>`;\n}\n","import { resolveFarmThemeConfig } from \"./config\";\nimport type {\n FarmThemeConfig,\n FarmThemePreference,\n FarmThemeRuntime,\n ResolvedFarmThemeConfig,\n} from \"./types\";\n\nconst THEME_SCRIPT_ID = \"farm-theme-script\";\nconst THEME_STYLE_ID = \"farm-theme-style\";\n\ndeclare global {\n interface Window {\n __FARM_THEME__?: FarmThemeRuntime;\n }\n}\n\nexport interface FarmThemeDocumentParts {\n attributes: string;\n head: string;\n}\n\nexport function createFarmThemeDocumentParts(\n input: FarmThemeConfig | ResolvedFarmThemeConfig | false | undefined,\n basePath = \"/\",\n serverTheme?: FarmThemePreference,\n): FarmThemeDocumentParts {\n const config = resolveFarmThemeConfig(input, basePath);\n if (!config.enabled) return { attributes: \"\", head: \"\" };\n\n const hydrationTheme = serverTheme ?? config.default;\n const initialTheme = hydrationTheme === \"system\" ? \"light\" : hydrationTheme;\n const script = createFarmThemeBootstrapScript(config, hydrationTheme);\n\n return {\n attributes: ` data-theme=\"${initialTheme}\"`,\n head: `<style id=\"${THEME_STYLE_ID}\">:root[data-theme=\"light\"]{color-scheme:light}:root[data-theme=\"dark\"]{color-scheme:dark}</style><script id=\"${THEME_SCRIPT_ID}\">${script}</script>`,\n };\n}\n\nexport function createFarmThemeBootstrapScript(\n config: ResolvedFarmThemeConfig,\n serverTheme: FarmThemePreference = config.default,\n): string {\n return `(function(config,serverTheme){\nvar isTheme=function(value){return value===\"light\"||value===\"dark\"||value===\"system\";};\nvar decode=function(value){try{return decodeURIComponent(value);}catch(_error){return value;}};\nvar readCookie=function(){var entries=document.cookie.split(\";\");for(var index=0;index<entries.length;index++){var entry=entries[index];var separator=entry.indexOf(\"=\");if(separator<0)continue;if(decode(entry.slice(0,separator).trim())===config.storageKey)return decode(entry.slice(separator+1).trim());}};\nvar media=window.matchMedia(\"(prefers-color-scheme: dark)\");\nvar resolveTheme=function(theme){return theme===\"system\"?(media.matches?\"dark\":\"light\"):theme;};\nvar storedTheme=readCookie();\nvar preference=isTheme(storedTheme)?storedTheme:config.default;\nvar serverSnapshot={theme:serverTheme,resolvedTheme:serverTheme===\"system\"?undefined:serverTheme,mounted:false};\nvar apply=function(){var resolvedTheme=resolveTheme(preference);document.documentElement.dataset.theme=resolvedTheme;var snapshot={theme:preference,resolvedTheme:resolvedTheme,mounted:true};if(window.__FARM_THEME__)window.__FARM_THEME__.snapshot=snapshot;return snapshot;};\nvar emit=function(){var snapshot=apply();window.dispatchEvent(new CustomEvent(\"farm:themechange\",{detail:snapshot}));};\nvar persist=function(theme){var secure=window.location.protocol===\"https:\"?\"; Secure\":\"\";document.cookie=encodeURIComponent(config.storageKey)+\"=\"+encodeURIComponent(theme)+\"; Path=\"+config.cookiePath+\"; Max-Age=31536000; SameSite=Lax\"+secure;try{localStorage.setItem(config.storageKey,theme);}catch(_error){}};\nvar setTheme=function(theme){if(!isTheme(theme))throw new TypeError(\"Unknown FARMJS theme: \"+String(theme));preference=theme;persist(theme);emit();};\nvar initialSnapshot={theme:preference,resolvedTheme:resolveTheme(preference),mounted:true};\nwindow.__FARM_THEME__={config:config,serverSnapshot:serverSnapshot,snapshot:initialSnapshot,setTheme:setTheme};\ndocument.documentElement.dataset.theme=initialSnapshot.resolvedTheme;\nvar handleSystemChange=function(){if(preference===\"system\")emit();};\nif(typeof media.addEventListener===\"function\")media.addEventListener(\"change\",handleSystemChange);else if(typeof media.addListener===\"function\")media.addListener(handleSystemChange);\nwindow.addEventListener(\"storage\",function(event){if(event.key!==config.storageKey||!isTheme(event.newValue))return;preference=event.newValue;persist(preference);emit();});\n})(${serializeInlineValue(config)},${serializeInlineValue(serverTheme)});`;\n}\n\nexport function applyFarmThemeDocument(\n html: string,\n input: FarmThemeConfig | ResolvedFarmThemeConfig | false | undefined,\n basePath = \"/\",\n serverTheme?: FarmThemePreference,\n): string {\n const parts = createFarmThemeDocumentParts(input, basePath, serverTheme);\n if (!parts.head) return html;\n\n let output = html.replace(/<html([^>]*)>/i, (_match, attributes: string) => {\n const nextAttributes = attributes.replace(/\\sdata-theme=(?:\"[^\"]*\"|'[^']*'|[^\\s>]+)/i, \"\");\n return `<html${nextAttributes}${parts.attributes}>`;\n });\n\n if (!output.includes(`id=\"${THEME_SCRIPT_ID}\"`)) {\n output = output.replace(/<head([^>]*)>/i, `<head$1>${parts.head}`);\n }\n\n return output;\n}\n\nfunction serializeInlineValue(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n"],"mappings":"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","names":["initialTagCount","isRecord"]}
@@ -22,8 +22,9 @@ import {
22
22
  resolveFarmRenderer
23
23
  } from "./chunk-5EZRXIFH.mjs";
24
24
  import {
25
+ resolveFarmAgentConfig,
25
26
  resolveFarmPerformanceConfig
26
- } from "./chunk-7ZVN3YZI.mjs";
27
+ } from "./chunk-Z5ARESQG.mjs";
27
28
  import {
28
29
  resolveFarmImageConfig
29
30
  } from "./chunk-235AKA6S.mjs";
@@ -39,19 +40,19 @@ import {
39
40
  } from "./chunk-EUYRVVXL.mjs";
40
41
  import {
41
42
  resolveWorkflowsConfig
42
- } from "./chunk-2SKCXYLB.mjs";
43
+ } from "./chunk-QQCCBMTH.mjs";
43
44
  import {
44
45
  resolveCronConfig
45
- } from "./chunk-BZAIS65C.mjs";
46
+ } from "./chunk-DIHNOVZZ.mjs";
46
47
  import {
47
48
  resolveServerActionsConfig
48
- } from "./chunk-35NPLKQJ.mjs";
49
+ } from "./chunk-XWM2C267.mjs";
49
50
  import {
50
51
  resolveFarmThemeConfig
51
52
  } from "./chunk-H53KVQUU.mjs";
52
53
  import {
53
54
  resolveIntegrationPlugins
54
- } from "./chunk-AAC66ILR.mjs";
55
+ } from "./chunk-LXXG3K2Y.mjs";
55
56
  import {
56
57
  resolveFarmI18nConfig
57
58
  } from "./chunk-STV7A2LH.mjs";
@@ -600,6 +601,7 @@ async function resolveConfig(userConfig, mode) {
600
601
  const openapi = {
601
602
  enabled: false,
602
603
  route: "/docs/reference",
604
+ specRoute: "/openapi.json",
603
605
  title: "API Documentation",
604
606
  description: "Auto-generated API documentation",
605
607
  version: "1.0.0",
@@ -607,6 +609,7 @@ async function resolveConfig(userConfig, mode) {
607
609
  ...userConfig.openapi
608
610
  };
609
611
  if (openapi.route !== void 0) validateConfigRouteSource(openapi.route, "openapi.route");
612
+ if (openapi.specRoute) validateConfigRouteSource(openapi.specRoute, "openapi.specRoute");
610
613
  const resolved = {
611
614
  [FARM_RESOLVED_CUSTOM_CONTEXT]: typeof userConfig.context === "function",
612
615
  root,
@@ -639,6 +642,7 @@ async function resolveConfig(userConfig, mode) {
639
642
  ppr: false,
640
643
  ...userConfig.experimental
641
644
  },
645
+ agent: resolveFarmAgentConfig(userConfig.agent),
642
646
  plugins: [...resolveIntegrationPlugins(integrations), ...userConfig.plugins || []],
643
647
  integrations,
644
648
  trailingSlash: userConfig.trailingSlash ?? false,
@@ -735,4 +739,4 @@ export {
735
739
  resolveConfig,
736
740
  loadConfig
737
741
  };
738
- //# sourceMappingURL=chunk-X4SFHKFH.mjs.map
742
+ //# sourceMappingURL=chunk-BU65A3LZ.mjs.map