@farm.js/core 0.1.60 → 0.1.62

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 (265) hide show
  1. package/dist/{agent-mcp.d-C-2S9bnP.d.mts → agent-mcp.d-BKZ3UNbt.d.mts} +1 -1
  2. package/dist/{agent-mcp.d-SIoCUP1I.d.ts → agent-mcp.d-C1zr_nGS.d.ts} +1 -1
  3. package/dist/agent-runtime.cjs +3 -3
  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 -2
  7. package/dist/analyzer-2AHWJJR7.cjs +15 -0
  8. package/dist/analyzer-YESYU3GK.mjs +15 -0
  9. package/dist/api/route-manager.cjs +4 -4
  10. package/dist/api/route-manager.d.mts +4 -4
  11. package/dist/api/route-manager.d.ts +4 -4
  12. package/dist/api/route-manager.mjs +3 -3
  13. package/dist/api/runtime.cjs +3 -3
  14. package/dist/api/runtime.d.mts +3 -3
  15. package/dist/api/runtime.d.ts +3 -3
  16. package/dist/api/runtime.mjs +2 -2
  17. package/dist/api.cjs +5 -5
  18. package/dist/api.d.mts +4 -4
  19. package/dist/api.d.ts +4 -4
  20. package/dist/api.mjs +4 -4
  21. package/dist/{app-manifest.d-DrSAHskY.d.mts → app-manifest.d-BpvhfKRH.d.mts} +1 -1
  22. package/dist/{app-manifest.d-Tb3CJpL4.d.ts → app-manifest.d-ntch_bvA.d.ts} +1 -1
  23. package/dist/app-markdown.d.mts +3 -3
  24. package/dist/app-markdown.d.ts +3 -3
  25. package/dist/{app.d-CmWlYpZJ.d.ts → app.d-AE8_v3Db.d.ts} +4 -10
  26. package/dist/{app.d-D6QQM_kk.d.mts → app.d-CysWA_8v.d.mts} +4 -10
  27. package/dist/{chunk-FORSVMEJ.mjs → chunk-2CNKQC3G.mjs} +1 -1
  28. package/dist/{chunk-ZFUKPWFC.mjs → chunk-2JYBLE63.mjs} +416 -208
  29. package/dist/{chunk-QRX4JRBO.cjs → chunk-3CCAICF7.cjs} +5 -5
  30. package/dist/{chunk-ANHZ6SUL.mjs → chunk-3TXKFRSO.mjs} +1 -1
  31. package/dist/{chunk-BHJAYPYU.mjs → chunk-3UZVPO72.mjs} +1 -1
  32. package/dist/{chunk-6UUH4N4J.mjs → chunk-43V3ANPQ.mjs} +1 -1
  33. package/dist/chunk-4EBC7EMW.cjs +8 -0
  34. package/dist/{chunk-VZY7MAVS.cjs → chunk-4IHMHFQB.cjs} +27 -1
  35. package/dist/{chunk-FK25QSVC.cjs → chunk-4P5634G6.cjs} +2 -2
  36. package/dist/{chunk-4JTQPOKO.cjs → chunk-53ZCZ46B.cjs} +2 -2
  37. package/dist/{chunk-NQJDO7K7.cjs → chunk-545WJ5UG.cjs} +321 -37
  38. package/dist/{chunk-VU3MYZPO.mjs → chunk-5FE5YT2N.mjs} +26 -0
  39. package/dist/{chunk-A5BJKSZE.cjs → chunk-5IQ2ERQA.cjs} +2 -2
  40. package/dist/{chunk-SJRCWF4Z.mjs → chunk-5Y22WNTO.mjs} +2 -2
  41. package/dist/{chunk-U4BJKNIR.cjs → chunk-752XUZIM.cjs} +11 -6
  42. package/dist/{chunk-JBK7UJOI.cjs → chunk-AJB3DHN6.cjs} +2 -2
  43. package/dist/{chunk-YB44NKC2.cjs → chunk-AXVRUDMB.cjs} +2 -2
  44. package/dist/{chunk-LJVNMGE3.mjs → chunk-BM2LH2JM.mjs} +8 -3
  45. package/dist/{chunk-YI6FKTTN.cjs → chunk-BT4SEFLC.cjs} +261 -38
  46. package/dist/{chunk-LIFUPCXW.cjs → chunk-CFG4QERR.cjs} +13 -2
  47. package/dist/{chunk-3OWVWZ6R.cjs → chunk-CLFEQGET.cjs} +6 -6
  48. package/dist/{chunk-OZK2DS44.mjs → chunk-CROAFCMW.mjs} +1 -1
  49. package/dist/{chunk-2KTYMMWT.mjs → chunk-DPE53XWL.mjs} +1 -1
  50. package/dist/{chunk-3PX4AIXO.mjs → chunk-DQF3QLOH.mjs} +258 -35
  51. package/dist/{chunk-FSQMN2MQ.mjs → chunk-E46NXBNJ.mjs} +1 -1
  52. package/dist/{chunk-EGVC4LIG.mjs → chunk-E4RDMG3K.mjs} +1 -1
  53. package/dist/{chunk-X2CZTWQA.mjs → chunk-ECKQFEX2.mjs} +1 -1
  54. package/dist/{chunk-MTWXOEI4.cjs → chunk-EXXFSZOC.cjs} +246 -193
  55. package/dist/{chunk-UYSTTPYJ.cjs → chunk-GGNJAGGE.cjs} +643 -435
  56. package/dist/{chunk-XTG73QZA.cjs → chunk-GVOMPU3Y.cjs} +12 -8
  57. package/dist/{chunk-ZP32GNJQ.cjs → chunk-I32V5CZL.cjs} +14 -13
  58. package/dist/{chunk-37PYUEK5.mjs → chunk-IOF4KXMP.mjs} +7 -3
  59. package/dist/{chunk-ILMTRGBG.mjs → chunk-IQIKPKFP.mjs} +157 -45
  60. package/dist/{chunk-5JNUYGNF.cjs → chunk-IWRLV46X.cjs} +2 -2
  61. package/dist/{chunk-KPOMS5RO.cjs → chunk-J3GFOQOL.cjs} +3 -3
  62. package/dist/{chunk-NHD7BAKD.mjs → chunk-JCEFKP5M.mjs} +41 -25
  63. package/dist/{analyzer-LCSI3NSH.cjs → chunk-JEJQGZI7.cjs} +16 -13
  64. package/dist/{chunk-LB3DPQP6.cjs → chunk-JLDNXURZ.cjs} +23 -23
  65. package/dist/{chunk-VGG74PSU.cjs → chunk-L2JG337G.cjs} +2 -2
  66. package/dist/chunk-L4RTTTVE.mjs +8 -0
  67. package/dist/chunk-LEJDW34D.cjs +115 -0
  68. package/dist/{analyzer-22BEYV7S.mjs → chunk-LVWGURLD.mjs} +6 -3
  69. package/dist/{chunk-Z5A6CNV2.mjs → chunk-MK5E44WP.mjs} +1 -1
  70. package/dist/{chunk-T4EW7AAD.mjs → chunk-NKRZLQUK.mjs} +2 -2
  71. package/dist/{chunk-HPWB57PZ.mjs → chunk-NT3QDN2E.mjs} +1 -1
  72. package/dist/{chunk-T7I62A4C.mjs → chunk-OUWRNHTV.mjs} +81 -28
  73. package/dist/{chunk-GFT5AHAT.mjs → chunk-QDWMCFTH.mjs} +12 -1
  74. package/dist/{chunk-AER5I65K.mjs → chunk-QTD6EMN2.mjs} +1 -1
  75. package/dist/{chunk-UDJY2ZGY.cjs → chunk-RMUD75WT.cjs} +413 -301
  76. package/dist/chunk-RZNCMRD3.mjs +141 -0
  77. package/dist/{chunk-D7LTCK3U.mjs → chunk-SA7MLSP4.mjs} +11 -6
  78. package/dist/{chunk-2FRLSDBT.cjs → chunk-SM25ZC4S.cjs} +1 -1
  79. package/dist/{chunk-3YMLUNL2.cjs → chunk-SVXOCTQ2.cjs} +1 -1
  80. package/dist/{chunk-W2RZ73IU.cjs → chunk-SYXPWJ7N.cjs} +8 -8
  81. package/dist/{chunk-F6Y7ZAPQ.mjs → chunk-T46NNU4D.mjs} +6 -3
  82. package/dist/{chunk-IFHPDLIS.mjs → chunk-TGULJSHD.mjs} +5 -4
  83. package/dist/{chunk-JPIUGDK4.mjs → chunk-TZVUF5JJ.mjs} +1 -1
  84. package/dist/chunk-UWI3SJAK.cjs +141 -0
  85. package/dist/{chunk-JI5D7MXY.mjs → chunk-UYRI6U3P.mjs} +1 -1
  86. package/dist/{chunk-D2X5MUF5.cjs → chunk-V727H3RI.cjs} +47 -31
  87. package/dist/{chunk-ZMHAFH4R.mjs → chunk-VM7X5CKC.mjs} +2 -2
  88. package/dist/{chunk-VPTWKOCY.mjs → chunk-VWW4Q3BJ.mjs} +287 -6
  89. package/dist/{chunk-4P23B7DU.cjs → chunk-WKJQ2FJA.cjs} +3 -3
  90. package/dist/{chunk-HASX6DC7.cjs → chunk-WKPBIT5Q.cjs} +8 -8
  91. package/dist/{chunk-RAWWCDCT.cjs → chunk-WYAXRIYP.cjs} +3 -3
  92. package/dist/{chunk-3TL3AH25.cjs → chunk-X4K7TYN6.cjs} +12 -7
  93. package/dist/chunk-XCXHQBMM.mjs +115 -0
  94. package/dist/{chunk-DPJ66FSI.cjs → chunk-XX32BOMM.cjs} +7 -7
  95. package/dist/{chunk-2IAPKPEB.cjs → chunk-YN6BHOYY.cjs} +6 -6
  96. package/dist/{chunk-CBKRS3M4.cjs → chunk-Z7P2BTZ3.cjs} +7 -6
  97. package/dist/{chunk-SX7EECTS.mjs → chunk-ZBUAOGMY.mjs} +1 -1
  98. package/dist/{chunk-RPUJHJHE.mjs → chunk-ZFWYCVKS.mjs} +4 -3
  99. package/dist/{chunk-IFXSBJPN.cjs → chunk-ZVIEFTUA.cjs} +20 -17
  100. package/dist/{chunk-EXUONJYV.mjs → chunk-ZZI56IUY.mjs} +3 -3
  101. package/dist/{programmatic-routes-client.d-CLG2N1yH.d.ts → client-component.d-Bgt3x5Fu.d.ts} +18 -3
  102. package/dist/{programmatic-routes-client.d-CPbNqtIi.d.mts → client-component.d-BoqC2MLC.d.mts} +18 -3
  103. package/dist/{client-plugins.d-vXrbcfJ1.d.ts → client-plugins.d-BcqIy4au.d.ts} +1 -1
  104. package/dist/{client-plugins.d-CgQQ-EAv.d.mts → client-plugins.d-CWyYBxXf.d.mts} +1 -1
  105. package/dist/client-plugins.d.mts +2 -2
  106. package/dist/client-plugins.d.ts +2 -2
  107. package/dist/client.d.mts +7 -7
  108. package/dist/client.d.ts +7 -7
  109. package/dist/{config.d-DqZkLwef.d.ts → config.d-qt-mE8O5.d.mts} +6 -2
  110. package/dist/{config.d-DqZkLwef.d.mts → config.d-qt-mE8O5.d.ts} +6 -2
  111. package/dist/config.d.mts +2 -2
  112. package/dist/config.d.ts +2 -2
  113. package/dist/cron.cjs +12 -2
  114. package/dist/cron.d.mts +101 -3
  115. package/dist/cron.d.ts +101 -3
  116. package/dist/cron.mjs +11 -1
  117. package/dist/desktop.d.mts +3 -3
  118. package/dist/desktop.d.ts +3 -3
  119. package/dist/{devtools-KQZ6SRCJ.mjs → devtools-NUVXYG7I.mjs} +6 -6
  120. package/dist/{devtools-UF6JYHUN.cjs → devtools-SVRSGPNC.cjs} +8 -8
  121. package/dist/docs.cjs +9 -9
  122. package/dist/docs.d.mts +3 -3
  123. package/dist/docs.d.ts +3 -3
  124. package/dist/docs.mjs +8 -8
  125. package/dist/image/server.cjs +3 -3
  126. package/dist/image/server.mjs +2 -2
  127. package/dist/image/sharp.cjs +10 -10
  128. package/dist/image/sharp.mjs +2 -2
  129. package/dist/index.cjs +42 -27
  130. package/dist/{index.d-Dmfb7Kb_.d.mts → index.d-BDaiu2i5.d.mts} +1 -1
  131. package/dist/{index.d-DlCELfhf.d.ts → index.d-nAncqTXz.d.ts} +1 -1
  132. package/dist/index.d.mts +18 -18
  133. package/dist/index.d.ts +18 -18
  134. package/dist/index.mjs +42 -27
  135. package/dist/integrations.cjs +3 -3
  136. package/dist/integrations.d.mts +2 -2
  137. package/dist/integrations.d.ts +2 -2
  138. package/dist/integrations.mjs +2 -2
  139. package/dist/internal/app-markdown-runtime.d.mts +3 -3
  140. package/dist/internal/app-markdown-runtime.d.ts +3 -3
  141. package/dist/internal/build-runtime.cjs +27 -22
  142. package/dist/internal/build-runtime.d.mts +4 -4
  143. package/dist/internal/build-runtime.d.ts +4 -4
  144. package/dist/internal/build-runtime.mjs +26 -21
  145. package/dist/internal/cli-runtime.cjs +12 -11
  146. package/dist/internal/cli-runtime.mjs +11 -10
  147. package/dist/internal/client-error-overlay.cjs +4 -4
  148. package/dist/internal/client-error-overlay.mjs +1 -1
  149. package/dist/internal/client-runtime.d.mts +5 -5
  150. package/dist/internal/client-runtime.d.ts +5 -5
  151. package/dist/internal/compression-runtime.d.mts +2 -2
  152. package/dist/internal/compression-runtime.d.ts +2 -2
  153. package/dist/internal/config-runtime.cjs +8 -8
  154. package/dist/internal/config-runtime.d.mts +5 -5
  155. package/dist/internal/config-runtime.d.ts +5 -5
  156. package/dist/internal/config-runtime.mjs +7 -7
  157. package/dist/internal/form-actions.cjs +4 -4
  158. package/dist/internal/form-actions.mjs +3 -3
  159. package/dist/internal/infra-analytics-runtime.cjs +6 -6
  160. package/dist/internal/infra-analytics-runtime.mjs +4 -4
  161. package/dist/internal/metadata-image-runtime.cjs +3 -3
  162. package/dist/internal/metadata-image-runtime.mjs +2 -2
  163. package/dist/internal/native-server-fns.cjs +25 -0
  164. package/dist/internal/native-server-fns.d.mts +42 -0
  165. package/dist/internal/native-server-fns.d.ts +42 -0
  166. package/dist/internal/native-server-fns.mjs +25 -0
  167. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  168. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  169. package/dist/internal/production-node-env.cjs +2 -2
  170. package/dist/internal/production-node-env.mjs +1 -1
  171. package/dist/internal/production-runtime.cjs +16 -10
  172. package/dist/internal/production-runtime.d.mts +39 -12
  173. package/dist/internal/production-runtime.d.ts +39 -12
  174. package/dist/internal/production-runtime.mjs +15 -9
  175. package/dist/internal/react-cache.cjs +51 -0
  176. package/dist/internal/react-cache.d.mts +3 -0
  177. package/dist/internal/react-cache.d.ts +3 -0
  178. package/dist/internal/react-cache.mjs +51 -0
  179. package/dist/markdown.d.mts +2 -2
  180. package/dist/markdown.d.ts +2 -2
  181. package/dist/middleware.cjs +3 -3
  182. package/dist/middleware.d.mts +4 -4
  183. package/dist/middleware.d.ts +4 -4
  184. package/dist/middleware.mjs +2 -2
  185. package/dist/mobile.d.mts +10 -4
  186. package/dist/mobile.d.ts +10 -4
  187. package/dist/{modules-VHD7BELU.mjs → modules-KOKD4XS6.mjs} +2 -2
  188. package/dist/modules-QTP7WJPD.cjs +13 -0
  189. package/dist/native-server-fn-handler-GLRHAYWV.mjs +28 -0
  190. package/dist/native-server-fn-handler-J5MYRXN6.cjs +28 -0
  191. package/dist/native-specs-5OLED4MM.cjs +15 -0
  192. package/dist/{native-specs-BD7HOTMJ.mjs → native-specs-LDV6IZ4N.mjs} +1 -1
  193. package/dist/{native-tree-VWNW2MQ2.mjs → native-tree-AS5L3ID3.mjs} +2 -2
  194. package/dist/{native-tree-6G5O53O3.cjs → native-tree-Z2WYUJEV.cjs} +3 -3
  195. package/dist/native.cjs +1 -1
  196. package/dist/native.d.mts +5 -5
  197. package/dist/native.d.ts +5 -5
  198. package/dist/native.mjs +1 -1
  199. package/dist/{navigation-delegate.d-JXx40JzR.d.ts → navigation-delegate.d-BbUHRXxG.d.ts} +1 -1
  200. package/dist/{navigation-delegate.d-CnOTWOyi.d.mts → navigation-delegate.d-CSCm8ZxL.d.mts} +1 -1
  201. package/dist/navigation.d.mts +5 -5
  202. package/dist/navigation.d.ts +5 -5
  203. package/dist/{nitro-FLN6DRGJ.mjs → nitro-DD4QCA66.mjs} +5 -5
  204. package/dist/{nitro-HXAZZQKY.cjs → nitro-VRDX2H4M.cjs} +8 -8
  205. package/dist/plugin.cjs +19 -18
  206. package/dist/plugin.d.mts +5 -5
  207. package/dist/plugin.d.ts +5 -5
  208. package/dist/plugin.mjs +18 -17
  209. package/dist/{port-WOOQ3V56.mjs → port-UFUZL6RI.mjs} +2 -2
  210. package/dist/{port-C6GBH4C6.cjs → port-VTLHPZOI.cjs} +10 -10
  211. package/dist/{production-runtime.d-CP5s6RuY.d.mts → production-runtime.d-CcQiDko5.d.mts} +1 -1
  212. package/dist/{production-runtime.d-N-cE3pmy.d.ts → production-runtime.d-DgT24A0f.d.ts} +1 -1
  213. package/dist/{render-plan.d-DZ-qjjdG.d.mts → render-plan.d-BH9WF-JZ.d.mts} +1 -1
  214. package/dist/{render-plan.d-B9lAP3uX.d.ts → render-plan.d-CyrX6MDs.d.ts} +1 -1
  215. package/dist/renderer-client.d.mts +5 -5
  216. package/dist/renderer-client.d.ts +5 -5
  217. package/dist/{request.d-BiicaNxb.d.ts → request.d-BB8M8bcD.d.ts} +1 -1
  218. package/dist/{request.d-DV0oeUit.d.mts → request.d-CUrPnCW7.d.mts} +1 -1
  219. package/dist/request.d.mts +3 -3
  220. package/dist/request.d.ts +3 -3
  221. package/dist/{route-rendering.d-BrIKA51A.d.mts → route-rendering.d-CYxlzaFm.d.mts} +1 -1
  222. package/dist/{route-rendering.d-Iss0C7GR.d.ts → route-rendering.d-DYqZMIf4.d.ts} +1 -1
  223. package/dist/{router.d-mNTbOGV_.d.mts → router.d-7o24CD8u.d.mts} +1 -1
  224. package/dist/{router.d-DjGn_al7.d.ts → router.d-DaKo507j.d.ts} +1 -1
  225. package/dist/{routes.d-BKSjHuH9.d.ts → routes.d-BknKQcTu.d.ts} +7 -1
  226. package/dist/{routes.d-qd8Qf4LG.d.mts → routes.d-D1IrO9KK.d.mts} +7 -1
  227. package/dist/routes.d.mts +2 -2
  228. package/dist/routes.d.ts +2 -2
  229. package/dist/{rsc-pipeline-SVLBTY7H.cjs → rsc-pipeline-OF2I7PCX.cjs} +8 -8
  230. package/dist/{rsc-pipeline-WBLBDQXA.mjs → rsc-pipeline-RFLHDAKD.mjs} +7 -7
  231. package/dist/{runtime-DGUOWSMF.cjs → runtime-LBTK62AD.cjs} +70 -47
  232. package/dist/{runtime-HFZTVNFF.mjs → runtime-M6UJCSLA.mjs} +38 -15
  233. package/dist/{runtime.d-Bm_4hP5T.d.ts → runtime.d-CN73a-IL.d.ts} +1 -1
  234. package/dist/{runtime.d-BNVbojF1.d.mts → runtime.d-CcNuzhX6.d.mts} +1 -1
  235. package/dist/server-action-security.cjs +3 -3
  236. package/dist/server-action-security.mjs +2 -2
  237. package/dist/server-fn.cjs +4 -4
  238. package/dist/server-fn.mjs +3 -3
  239. package/dist/server-plugins.d.mts +3 -3
  240. package/dist/server-plugins.d.ts +3 -3
  241. package/dist/server-query.cjs +5 -5
  242. package/dist/server-query.mjs +4 -4
  243. package/dist/server.cjs +38 -37
  244. package/dist/server.d.mts +10 -10
  245. package/dist/server.d.ts +10 -10
  246. package/dist/server.mjs +23 -22
  247. package/dist/{spa-router.d-DHDoXxDE.d.mts → spa-router.d-CNi77LZm.d.mts} +2 -2
  248. package/dist/{spa-router.d-DAtnNoBe.d.ts → spa-router.d-Cvgf5QP4.d.ts} +2 -2
  249. package/dist/testing.cjs +6 -6
  250. package/dist/testing.d.mts +2 -2
  251. package/dist/testing.d.ts +2 -2
  252. package/dist/testing.mjs +4 -4
  253. package/dist/{utils.d-DwZ-KLSB.d.ts → utils.d-C3H-14_Y.d.ts} +1 -1
  254. package/dist/{utils.d-uKZcKJk4.d.mts → utils.d-D8VfzZYn.d.mts} +1 -1
  255. package/dist/version.cjs +2 -2
  256. package/dist/version.mjs +1 -1
  257. package/dist/vite.cjs +21 -18
  258. package/dist/vite.d.mts +5 -5
  259. package/dist/vite.d.ts +5 -5
  260. package/dist/vite.mjs +20 -17
  261. package/dist/workflows.cjs +3 -3
  262. package/dist/workflows.mjs +2 -2
  263. package/package.json +12 -2
  264. package/dist/modules-WT5D3AWY.cjs +0 -13
  265. package/dist/native-specs-IQQRJOOW.cjs +0 -15
@@ -28,8 +28,31 @@ function resolveCronConfig(cron) {
28
28
  jobs: []
29
29
  };
30
30
  }
31
+ if (typeof cron !== "object" || Array.isArray(cron)) {
32
+ throw new TypeError("`cron` must be a job map, { provider, jobs }, or false.");
33
+ }
34
+ let provider;
35
+ let entries;
36
+ if ("provider" in cron && (typeof cron.provider !== "object" || cron.provider === null)) {
37
+ if (cron.provider !== "host" && cron.provider !== "farmjs") {
38
+ throw new TypeError(
39
+ `\`cron.provider\` must be "host" (the deploy platform's scheduler) or "farmjs" (Farm.js Infra), received ${JSON.stringify(cron.provider)}.`
40
+ );
41
+ }
42
+ provider = cron.provider;
43
+ if (Object.keys(cron).some((key) => key !== "provider" && key !== "jobs")) {
44
+ throw new TypeError("When `cron.provider` is set, place named jobs inside `cron.jobs`.");
45
+ }
46
+ const configured = cron.jobs === void 0 ? {} : cron.jobs;
47
+ if (!configured || typeof configured !== "object" || Array.isArray(configured)) {
48
+ throw new TypeError("`cron.jobs` must be a map of job names to configurations.");
49
+ }
50
+ entries = configured;
51
+ } else {
52
+ entries = cron;
53
+ }
31
54
  const jobs = [];
32
- for (const [name, job] of Object.entries(cron)) {
55
+ for (const [name, job] of Object.entries(entries)) {
33
56
  if (!job || typeof job !== "object" || Array.isArray(job)) {
34
57
  throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
35
58
  }
@@ -37,6 +60,7 @@ function resolveCronConfig(cron) {
37
60
  jobs.push(normalizeCronJob(name, job));
38
61
  }
39
62
  return {
63
+ ...provider ? { provider } : {},
40
64
  enabled: jobs.length > 0,
41
65
  secretEnv: DEFAULT_FARM_CRON_SECRET_ENV,
42
66
  jobs
@@ -50,18 +74,21 @@ async function prepareFarmCronForNitro(config) {
50
74
  const path = await import("path");
51
75
  const manifestPath = path.join(root, distDir, FARM_CRON_MANIFEST);
52
76
  const generatedDir = path.join(root, distDir, ".nitro", "farm-cron");
53
- if (!cron.enabled) {
54
- await Promise.all([
55
- fs.rm(manifestPath, { force: true }),
56
- fs.rm(generatedDir, { recursive: true, force: true })
57
- ]);
77
+ const provider = cron.provider ?? "host";
78
+ const manifest = createFarmCronManifest(cron, provider);
79
+ await fs.mkdir(path.dirname(manifestPath), { recursive: true });
80
+ await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
81
+ `, "utf8");
82
+ await fs.rm(generatedDir, { recursive: true, force: true });
83
+ if (!cron.enabled || provider === "farmjs") {
58
84
  return {
59
- jobs: [],
85
+ jobs: cron.enabled ? cron.jobs : [],
60
86
  tasks: {},
61
- scheduledTasks: {}
87
+ scheduledTasks: {},
88
+ manifestPath,
89
+ provider
62
90
  };
63
91
  }
64
- await fs.rm(generatedDir, { recursive: true, force: true });
65
92
  await fs.mkdir(generatedDir, { recursive: true });
66
93
  const tasks = {};
67
94
  const wrapperNames = resolveCronWrapperFileNames(cron.jobs.map((job) => job.name));
@@ -74,26 +101,26 @@ async function prepareFarmCronForNitro(config) {
74
101
  description: job.description || `Farm cron ${job.name}`
75
102
  };
76
103
  }
77
- const manifest = createFarmCronManifest(cron);
78
- await fs.mkdir(path.dirname(manifestPath), { recursive: true });
79
- await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
80
- `, "utf8");
81
104
  return {
82
105
  jobs: cron.jobs,
83
106
  tasks,
84
107
  scheduledTasks: createCronScheduledTasks(cron.jobs),
85
- manifestPath
108
+ manifestPath,
109
+ provider: "host"
86
110
  };
87
111
  }
88
- function createFarmCronManifest(cron) {
112
+ function createFarmCronManifest(cron, provider = cron.provider ?? "host") {
89
113
  return {
90
114
  schemaVersion: 1,
115
+ provider,
91
116
  secretEnv: cron.secretEnv,
92
- jobs: cron.jobs.map((job) => ({
117
+ jobs: (cron.enabled ? cron.jobs : []).map((job) => ({
93
118
  name: job.name,
94
119
  schedule: job.schedule,
95
120
  path: job.path,
96
- description: job.description || null
121
+ description: job.description || null,
122
+ ...job.timeoutMs !== void 0 ? { timeoutMs: job.timeoutMs } : {},
123
+ ...job.input !== void 0 ? { input: job.input } : {}
97
124
  }))
98
125
  };
99
126
  }
@@ -163,14 +190,161 @@ function isCronRequestAuthorized(request, options = {}) {
163
190
  const headerSecret = request.headers.get("x-farm-cron-secret") || "";
164
191
  return farmSecretsMatch(bearer, secret) || farmSecretsMatch(headerSecret, secret);
165
192
  }
193
+ var inFlightCronRuns = /* @__PURE__ */ new Set();
194
+ function resolveCronRunControls(options) {
195
+ if (options.timeoutMs !== void 0 && (typeof options.timeoutMs !== "number" || !Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)) {
196
+ throw new TypeError(
197
+ `Farm cron \`timeoutMs\` must be a positive number of milliseconds; received ${JSON.stringify(options.timeoutMs)}. Remove the option or set a positive number.`
198
+ );
199
+ }
200
+ if (options.overlap !== void 0 && options.overlap !== "skip") {
201
+ throw new TypeError(
202
+ `Farm cron \`overlap\` only supports "skip"; received ${JSON.stringify(options.overlap)}. Remove the option to allow overlapping runs.`
203
+ );
204
+ }
205
+ return {
206
+ timeoutMs: options.timeoutMs,
207
+ // A fresh object is this route's identity, so unnamed routes never skip each other.
208
+ overlapKey: options.overlap === "skip" ? options.name ?? {} : void 0
209
+ };
210
+ }
211
+ function cronSkippedResponse() {
212
+ return Response.json({ skipped: true }, { status: 409 });
213
+ }
214
+ function cronTimeoutResponse(timeoutMs) {
215
+ return Response.json(
216
+ {
217
+ error: `The cron handler did not finish within its \`timeoutMs\` of ${timeoutMs} milliseconds. Raise \`timeoutMs\` or make the handler finish sooner.`
218
+ },
219
+ { status: 504 }
220
+ );
221
+ }
222
+ function isThenable(value) {
223
+ return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
224
+ }
225
+ function runCronRouteControlled(controls, controller, run, onSkip, onTimeout) {
226
+ const { overlapKey, timeoutMs } = controls;
227
+ if (overlapKey !== void 0) {
228
+ if (inFlightCronRuns.has(overlapKey)) return onSkip();
229
+ inFlightCronRuns.add(overlapKey);
230
+ }
231
+ const release = () => {
232
+ if (overlapKey !== void 0) inFlightCronRuns.delete(overlapKey);
233
+ };
234
+ let outcome;
235
+ try {
236
+ outcome = run();
237
+ } catch (error) {
238
+ release();
239
+ throw error;
240
+ }
241
+ if (!isThenable(outcome)) {
242
+ release();
243
+ return outcome;
244
+ }
245
+ const pending = Promise.resolve(outcome);
246
+ if (timeoutMs === void 0) return pending.finally(release);
247
+ return new Promise((resolve, reject) => {
248
+ const timer = setTimeout(() => {
249
+ controller?.abort(
250
+ new Error(
251
+ `The cron handler did not finish within its \`timeoutMs\` of ${timeoutMs} milliseconds.`
252
+ )
253
+ );
254
+ resolve(onTimeout());
255
+ }, timeoutMs);
256
+ pending.then(
257
+ (value) => {
258
+ clearTimeout(timer);
259
+ release();
260
+ resolve(value);
261
+ },
262
+ (error) => {
263
+ clearTimeout(timer);
264
+ release();
265
+ reject(error);
266
+ }
267
+ );
268
+ });
269
+ }
270
+ function createFarmCronRequestContext(request, options, signal) {
271
+ const name = request.headers.get("x-farm-cron-name") || void 0;
272
+ const scheduledAtHeader = request.headers.get("x-farm-cron-scheduled-at")?.trim() || "";
273
+ const scheduledAtMs = /^\d+$/.test(scheduledAtHeader) ? Number(scheduledAtHeader) : Number.NaN;
274
+ const scheduledAt = Number.isSafeInteger(scheduledAtMs) ? new Date(scheduledAtMs) : void 0;
275
+ return {
276
+ ...name !== void 0 ? { name } : {},
277
+ ...scheduledAt !== void 0 ? { scheduledAt } : {},
278
+ input: options.input,
279
+ signal
280
+ };
281
+ }
282
+ var FARM_CRON_SIGNATURE_HEADER = "farmjs-signature";
283
+ var CRON_SIGNATURE_VERSION = "farmjs-cron-v1";
284
+ var CRON_SIGNATURE_WINDOW_SECONDS = 300;
285
+ var CRON_SIGNATURE_PATTERN = /^t=(\d{1,12}),v1=([0-9a-f]{64})$/;
286
+ function toHex(buffer) {
287
+ let hex = "";
288
+ for (const byte of new Uint8Array(buffer)) hex += byte.toString(16).padStart(2, "0");
289
+ return hex;
290
+ }
291
+ async function farmCronSignature(apiKey, t, pathname) {
292
+ const encoder = new TextEncoder();
293
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", encoder.encode(apiKey));
294
+ const key = await globalThis.crypto.subtle.importKey(
295
+ "raw",
296
+ encoder.encode(toHex(digest)),
297
+ { name: "HMAC", hash: "SHA-256" },
298
+ false,
299
+ ["sign"]
300
+ );
301
+ const mac = await globalThis.crypto.subtle.sign(
302
+ "HMAC",
303
+ key,
304
+ encoder.encode(`${CRON_SIGNATURE_VERSION}
305
+ ${t}
306
+ GET ${pathname}`)
307
+ );
308
+ return toHex(mac);
309
+ }
310
+ async function authorizeCronRequest(request, options = {}, now = Date.now()) {
311
+ if (isCronRequestAuthorized(request, options)) return true;
312
+ const header = request.headers.get(FARM_CRON_SIGNATURE_HEADER);
313
+ if (!header) return false;
314
+ if (typeof request.method !== "string" || request.method.toUpperCase() !== "GET") return false;
315
+ if (typeof request.url !== "string") return false;
316
+ const parsed = CRON_SIGNATURE_PATTERN.exec(header.trim());
317
+ if (!parsed) return false;
318
+ const t = Number(parsed[1]);
319
+ if (Math.abs(now / 1e3 - t) > CRON_SIGNATURE_WINDOW_SECONDS) return false;
320
+ const apiKey = readFarmEnvironmentValue("FARMJS_API_KEY");
321
+ if (!apiKey) return false;
322
+ let pathname;
323
+ try {
324
+ const url = new URL(request.url);
325
+ if (url.search) return false;
326
+ pathname = url.pathname;
327
+ } catch {
328
+ return false;
329
+ }
330
+ const expected = await farmCronSignature(apiKey, t, pathname);
331
+ return farmSecretsMatch(parsed[2], expected);
332
+ }
166
333
  function cronRoute(handler, options = {}) {
167
- if (isFarmEndpoint(handler)) return guardCronEndpoint(handler, options);
334
+ const controls = resolveCronRunControls(options);
335
+ if (isFarmEndpoint(handler)) return guardCronEndpoint(handler, options, controls);
168
336
  const route = handler;
169
- return (request, ...args) => {
170
- if (!isCronRequestAuthorized(request, options)) {
171
- return Promise.resolve(unauthorizedCronResponse());
337
+ return async (request, ...args) => {
338
+ if (!await authorizeCronRequest(request, options)) {
339
+ return unauthorizedCronResponse();
172
340
  }
173
- return route(request, ...args);
341
+ return runCronRouteControlled(
342
+ controls,
343
+ void 0,
344
+ () => route(request, ...args),
345
+ cronSkippedResponse,
346
+ () => cronTimeoutResponse(controls.timeoutMs)
347
+ );
174
348
  };
175
349
  }
176
350
  function unauthorizedCronResponse() {
@@ -180,32 +354,76 @@ function isFarmEndpoint(value) {
180
354
  return typeof value === "function" && typeof value.__handler === "function";
181
355
  }
182
356
  var FUNCTION_OWN_KEYS = /* @__PURE__ */ new Set(["length", "name", "prototype", "arguments", "caller"]);
183
- function guardCronEndpoint(endpoint, options) {
184
- const allowed = (context) => {
357
+ function guardCronEndpoint(endpoint, options, controls) {
358
+ const allowed = async (context) => {
185
359
  const request = context?.request;
186
- return typeof request?.headers?.get === "function" && isCronRequestAuthorized(request, options);
360
+ if (typeof request?.headers?.get !== "function") return false;
361
+ return authorizeCronRequest(request, options);
187
362
  };
188
- const guarded = function(context) {
189
- return allowed(context) ? endpoint.call(this, context) : Promise.resolve(unauthorizedCronResponse());
363
+ const withCron = (context) => {
364
+ const controller = new AbortController();
365
+ const cron = createFarmCronRequestContext(
366
+ context.request,
367
+ options,
368
+ controller.signal
369
+ );
370
+ const invocation = {
371
+ ...context,
372
+ context: { ...context.context, cron }
373
+ };
374
+ return { controller, invocation };
375
+ };
376
+ const guarded = async function(context) {
377
+ if (!await allowed(context)) return unauthorizedCronResponse();
378
+ const { controller, invocation } = withCron(context);
379
+ return runCronRouteControlled(
380
+ controls,
381
+ controller,
382
+ () => endpoint.call(this, invocation),
383
+ cronSkippedResponse,
384
+ () => cronTimeoutResponse(controls.timeoutMs)
385
+ );
190
386
  };
191
387
  for (const key of Reflect.ownKeys(endpoint)) {
192
388
  if (typeof key === "string" && FUNCTION_OWN_KEYS.has(key)) continue;
193
389
  Object.defineProperty(guarded, key, Object.getOwnPropertyDescriptor(endpoint, key));
194
390
  }
195
- guarded.__handler = (context) => allowed(context) ? endpoint.__handler(context) : unauthorizedCronResponse();
391
+ guarded.__handler = async (context) => {
392
+ if (!await allowed(context)) return unauthorizedCronResponse();
393
+ const { controller, invocation } = withCron(context);
394
+ return runCronRouteControlled(
395
+ controls,
396
+ controller,
397
+ () => endpoint.__handler(invocation),
398
+ cronSkippedResponse,
399
+ () => cronTimeoutResponse(controls.timeoutMs)
400
+ );
401
+ };
196
402
  const invoke = endpoint.__farmInvoke;
197
403
  if (invoke) {
198
- guarded.__farmInvoke = (context) => allowed(context) ? invoke(context) : {
199
- result: unauthorizedCronResponse(),
200
- context: context.context,
201
- handlerExecuted: false,
202
- invalidations: []
404
+ guarded.__farmInvoke = async (context) => {
405
+ const denied = (result) => ({
406
+ result,
407
+ context: context.context,
408
+ handlerExecuted: false,
409
+ invalidations: []
410
+ });
411
+ if (!await allowed(context)) return denied(unauthorizedCronResponse());
412
+ const { controller, invocation } = withCron(context);
413
+ return runCronRouteControlled(
414
+ controls,
415
+ controller,
416
+ () => invoke(invocation),
417
+ () => denied(cronSkippedResponse()),
418
+ () => denied(cronTimeoutResponse(controls.timeoutMs))
419
+ );
203
420
  };
204
421
  }
205
422
  return guarded;
206
423
  }
424
+ var FARM_CRON_NAME_SEGMENT_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
207
425
  function normalizeCronJob(name, job) {
208
- if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name)) {
426
+ if (!FARM_CRON_NAME_SEGMENT_PATTERN.test(name)) {
209
427
  throw new TypeError(
210
428
  `Farm cron name ${JSON.stringify(name)} must start with a letter or number and contain only letters, numbers, dots, underscores, or hyphens.`
211
429
  );
@@ -433,5 +651,10 @@ export {
433
651
  createFarmCronCloudflareConfig,
434
652
  mergeScheduledTasks,
435
653
  isCronRequestAuthorized,
436
- cronRoute
654
+ FARM_CRON_SIGNATURE_HEADER,
655
+ farmCronSignature,
656
+ authorizeCronRequest,
657
+ cronRoute,
658
+ FARM_CRON_NAME_SEGMENT_PATTERN,
659
+ normalizeCronExpression
437
660
  };
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-QSTRBKHZ.mjs";
7
7
  import {
8
8
  parseBodySizeLimit
9
- } from "./chunk-GFT5AHAT.mjs";
9
+ } from "./chunk-QDWMCFTH.mjs";
10
10
  import {
11
11
  subscribeFarmCacheInvalidation,
12
12
  subscribeFarmCacheTask
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-2I6PUKWJ.mjs";
21
21
  import {
22
22
  withFarmRequestClientAddress
23
- } from "./chunk-GFT5AHAT.mjs";
23
+ } from "./chunk-QDWMCFTH.mjs";
24
24
  import {
25
25
  _withFarmResponseHeaders
26
26
  } from "./chunk-LM55GS4R.mjs";
@@ -29,7 +29,7 @@ import {
29
29
  } from "./chunk-F3N52U7S.mjs";
30
30
  import {
31
31
  getIntegrationSchemas
32
- } from "./chunk-IFHPDLIS.mjs";
32
+ } from "./chunk-TGULJSHD.mjs";
33
33
 
34
34
  // src/schema-dependencies.ts
35
35
  function collectSchemaDependencies(owners) {