@farm.js/core 0.1.0-beta.14 → 0.1.0-beta.17

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 (271) hide show
  1. package/dist/after.d.mts +25 -0
  2. package/dist/after.d.ts +25 -0
  3. package/dist/agent-runtime.d.mts +96 -0
  4. package/dist/agent-runtime.d.ts +96 -0
  5. package/dist/api/route-manager.cjs.map +1 -1
  6. package/dist/api/route-manager.d.mts +66 -0
  7. package/dist/api/route-manager.d.ts +66 -0
  8. package/dist/api/route-manager.mjs +2 -2
  9. package/dist/api/runtime.cjs.map +1 -1
  10. package/dist/api/runtime.d.mts +3 -0
  11. package/dist/api/runtime.d.ts +3 -0
  12. package/dist/api/runtime.mjs +1 -1
  13. package/dist/api.cjs +18 -10
  14. package/dist/api.cjs.map +1 -1
  15. package/dist/api.d.mts +48 -0
  16. package/dist/api.d.ts +48 -0
  17. package/dist/api.mjs +3 -3
  18. package/dist/app-B0tE1I3o.d.ts +306 -0
  19. package/dist/app-Dv2JJb7X.d.mts +306 -0
  20. package/dist/app-markdown.d.mts +24 -0
  21. package/dist/app-markdown.d.ts +24 -0
  22. package/dist/cache.d.mts +192 -0
  23. package/dist/cache.d.ts +192 -0
  24. package/dist/{chunk-VUL55IAX.mjs → chunk-2FLBZFPG.mjs} +19 -19
  25. package/dist/chunk-2FLBZFPG.mjs.map +1 -0
  26. package/dist/{chunk-B232I2GP.mjs → chunk-3HIVDX7J.mjs} +12 -1
  27. package/dist/chunk-3HIVDX7J.mjs.map +1 -0
  28. package/dist/{chunk-JDEOUK5V.mjs → chunk-6YXKHAFU.mjs} +3 -3
  29. package/dist/{chunk-Z5CQMP54.mjs → chunk-ARRYKOI5.mjs} +2 -2
  30. package/dist/{chunk-KLA67WKG.mjs → chunk-B3FFOIWS.mjs} +2 -2
  31. package/dist/chunk-E257KFBU.mjs +227 -0
  32. package/dist/chunk-E257KFBU.mjs.map +1 -0
  33. package/dist/{chunk-PFE6GMNE.mjs → chunk-HMRFYJK6.mjs} +19 -11
  34. package/dist/chunk-HMRFYJK6.mjs.map +1 -0
  35. package/dist/{chunk-OPHK6OJN.mjs → chunk-JAEAE27K.mjs} +2 -2
  36. package/dist/{chunk-32W4QEJP.mjs → chunk-KFTGPFRD.mjs} +1 -1
  37. package/dist/chunk-KFTGPFRD.mjs.map +1 -0
  38. package/dist/{chunk-L2PE36GQ.mjs → chunk-PZXBQKCH.mjs} +15 -6
  39. package/dist/chunk-PZXBQKCH.mjs.map +1 -0
  40. package/dist/{chunk-UXUAWNO5.mjs → chunk-RIXKJPGI.mjs} +117 -55
  41. package/dist/chunk-RIXKJPGI.mjs.map +1 -0
  42. package/dist/{chunk-PNFQQSRA.mjs → chunk-T2M5QANG.mjs} +143 -41
  43. package/dist/chunk-T2M5QANG.mjs.map +1 -0
  44. package/dist/{chunk-WDU6QXNK.mjs → chunk-UCYWGN2P.mjs} +1 -1
  45. package/dist/chunk-UCYWGN2P.mjs.map +1 -0
  46. package/dist/{chunk-65A7QIKI.mjs → chunk-UMVLB3PN.mjs} +3 -3
  47. package/dist/chunk-UMVLB3PN.mjs.map +1 -0
  48. package/dist/{chunk-ARCGE2VT.mjs → chunk-VFDBC3W7.mjs} +2 -2
  49. package/dist/{chunk-ARCGE2VT.mjs.map → chunk-VFDBC3W7.mjs.map} +1 -1
  50. package/dist/{chunk-VY2UYN5R.mjs → chunk-VPCFICID.mjs} +82 -3
  51. package/dist/chunk-VPCFICID.mjs.map +1 -0
  52. package/dist/{chunk-H3TE3LOV.mjs → chunk-XMFTIVJH.mjs} +2 -2
  53. package/dist/{chunk-UB5UOSHB.mjs → chunk-ZVMV3THA.mjs} +71 -2
  54. package/dist/chunk-ZVMV3THA.mjs.map +1 -0
  55. package/dist/chunk-recovery-lnQFzcQP.d.mts +26 -0
  56. package/dist/chunk-recovery-lnQFzcQP.d.ts +26 -0
  57. package/dist/client-BT1mFQas.d.mts +447 -0
  58. package/dist/client-Nn0q4eO4.d.ts +447 -0
  59. package/dist/client-cache-CIlyBlmx.d.ts +6 -0
  60. package/dist/client-cache-D-EZ7XVW.d.mts +6 -0
  61. package/dist/client-plugins-278AvYHE.d.mts +2021 -0
  62. package/dist/client-plugins-CTQAkr7R.d.ts +2021 -0
  63. package/dist/client-plugins.d.mts +24 -0
  64. package/dist/client-plugins.d.ts +24 -0
  65. package/dist/client.cjs.map +1 -1
  66. package/dist/client.d.mts +452 -0
  67. package/dist/client.d.ts +452 -0
  68. package/dist/client.mjs +3 -3
  69. package/dist/config.d.mts +31 -0
  70. package/dist/config.d.ts +31 -0
  71. package/dist/cron.d.mts +78 -0
  72. package/dist/cron.d.ts +78 -0
  73. package/dist/deferred.d.mts +42 -0
  74. package/dist/deferred.d.ts +42 -0
  75. package/dist/deployment.cjs +12 -0
  76. package/dist/deployment.cjs.map +1 -1
  77. package/dist/deployment.d.mts +36 -0
  78. package/dist/deployment.d.ts +36 -0
  79. package/dist/deployment.mjs +3 -1
  80. package/dist/{devtools-GAZ7F3KL.mjs → devtools-K2ERKGNI.mjs} +5 -5
  81. package/dist/docs.cjs.map +1 -1
  82. package/dist/docs.d.mts +80 -0
  83. package/dist/docs.d.ts +80 -0
  84. package/dist/docs.mjs +5 -5
  85. package/dist/env-types.d.mts +12 -0
  86. package/dist/env-types.d.ts +12 -0
  87. package/dist/env.d.mts +45 -0
  88. package/dist/env.d.ts +45 -0
  89. package/dist/environment/vite.d.mts +22 -0
  90. package/dist/environment/vite.d.ts +22 -0
  91. package/dist/environment.d.mts +18 -0
  92. package/dist/environment.d.ts +18 -0
  93. package/dist/font.d.mts +95 -0
  94. package/dist/font.d.ts +95 -0
  95. package/dist/headers.d.mts +22 -0
  96. package/dist/headers.d.ts +22 -0
  97. package/dist/i18n/client.d.mts +32 -0
  98. package/dist/i18n/client.d.ts +32 -0
  99. package/dist/i18n/index.d.mts +20 -0
  100. package/dist/i18n/index.d.ts +20 -0
  101. package/dist/i18n/server.d.mts +30 -0
  102. package/dist/i18n/server.d.ts +30 -0
  103. package/dist/image/server.d.mts +37 -0
  104. package/dist/image/server.d.ts +37 -0
  105. package/dist/image/sharp.d.mts +7 -0
  106. package/dist/image/sharp.d.ts +7 -0
  107. package/dist/image-config-Duob7wER.d.mts +50 -0
  108. package/dist/image-config-Duob7wER.d.ts +50 -0
  109. package/dist/image.d.mts +39 -0
  110. package/dist/image.d.ts +39 -0
  111. package/dist/index.cjs +598 -109
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.mts +477 -0
  114. package/dist/index.d.ts +477 -0
  115. package/dist/index.mjs +45 -29
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/integration-api-CHT2OKAf.d.mts +93 -0
  118. package/dist/integration-api-CHT2OKAf.d.ts +93 -0
  119. package/dist/integrations.d.mts +24 -0
  120. package/dist/integrations.d.ts +24 -0
  121. package/dist/internal/build-runtime.cjs +438 -176
  122. package/dist/internal/build-runtime.cjs.map +1 -1
  123. package/dist/internal/build-runtime.d.mts +41 -0
  124. package/dist/internal/build-runtime.d.ts +41 -0
  125. package/dist/internal/build-runtime.mjs +13 -13
  126. package/dist/internal/client-runtime.d.mts +17 -0
  127. package/dist/internal/client-runtime.d.ts +17 -0
  128. package/dist/internal/config-runtime.cjs +140 -1
  129. package/dist/internal/config-runtime.cjs.map +1 -1
  130. package/dist/internal/config-runtime.d.mts +41 -0
  131. package/dist/internal/config-runtime.d.ts +41 -0
  132. package/dist/internal/config-runtime.mjs +4 -4
  133. package/dist/internal/metadata-image-runtime.d.mts +25 -0
  134. package/dist/internal/metadata-image-runtime.d.ts +25 -0
  135. package/dist/internal/production-node-env.d.mts +12 -0
  136. package/dist/internal/production-node-env.d.ts +12 -0
  137. package/dist/internal/production-runtime.d.mts +44 -0
  138. package/dist/internal/production-runtime.d.ts +44 -0
  139. package/dist/island-CfGru1MO.d.mts +9 -0
  140. package/dist/island-CfGru1MO.d.ts +9 -0
  141. package/dist/markdown.d.mts +60 -0
  142. package/dist/markdown.d.ts +60 -0
  143. package/dist/metadata-DmCudMw_.d.mts +22 -0
  144. package/dist/metadata-xghtOlbR.d.ts +22 -0
  145. package/dist/middleware.cjs +116 -98
  146. package/dist/middleware.cjs.map +1 -1
  147. package/dist/middleware.d.mts +171 -0
  148. package/dist/middleware.d.ts +171 -0
  149. package/dist/middleware.mjs +5 -2
  150. package/dist/navigation-errors-Dvwpzaer.d.mts +13 -0
  151. package/dist/navigation-errors-Dvwpzaer.d.ts +13 -0
  152. package/dist/navigation.cjs.map +1 -1
  153. package/dist/navigation.d.mts +14 -0
  154. package/dist/navigation.d.ts +14 -0
  155. package/dist/navigation.mjs +3 -3
  156. package/dist/observability.d.mts +335 -0
  157. package/dist/observability.d.ts +335 -0
  158. package/dist/params-BALtrRim.d.ts +15 -0
  159. package/dist/params-ry-lxqmy.d.mts +15 -0
  160. package/dist/plugin-BJDf43dc.d.mts +165 -0
  161. package/dist/plugin-BJDf43dc.d.ts +165 -0
  162. package/dist/plugin.cjs +247 -28
  163. package/dist/plugin.cjs.map +1 -1
  164. package/dist/plugin.d.mts +24 -0
  165. package/dist/plugin.d.ts +24 -0
  166. package/dist/plugin.mjs +10 -10
  167. package/dist/production-runtime-BLxSv9cU.d.ts +79 -0
  168. package/dist/production-runtime-DFN2_RXq.d.mts +79 -0
  169. package/dist/query/client.d.mts +61 -0
  170. package/dist/query/client.d.ts +61 -0
  171. package/dist/query/index.d.mts +90 -0
  172. package/dist/query/index.d.ts +90 -0
  173. package/dist/query/parsers.d.mts +25 -0
  174. package/dist/query/parsers.d.ts +25 -0
  175. package/dist/query/server.d.mts +55 -0
  176. package/dist/query/server.d.ts +55 -0
  177. package/dist/request-Cq5d6qmE.d.mts +6 -0
  178. package/dist/request-LoxDW3lp.d.ts +6 -0
  179. package/dist/request.d.mts +25 -0
  180. package/dist/request.d.ts +25 -0
  181. package/dist/resolver-DJqjLMg_.d.mts +14 -0
  182. package/dist/resolver-IH4RmPEl.d.ts +14 -0
  183. package/dist/route-runtime-DoOHzCAD.d.mts +38 -0
  184. package/dist/route-runtime-DoOHzCAD.d.ts +38 -0
  185. package/dist/router.d.mts +36 -0
  186. package/dist/router.d.ts +36 -0
  187. package/dist/routes.d.mts +226 -0
  188. package/dist/routes.d.ts +226 -0
  189. package/dist/runtime-BA9TOSu1.d.mts +231 -0
  190. package/dist/runtime-Cxpq6xZN.d.mts +27 -0
  191. package/dist/runtime-DTAQ2HDv.d.ts +231 -0
  192. package/dist/runtime-bv63eUiO.d.ts +27 -0
  193. package/dist/server-action-security.cjs +23 -1
  194. package/dist/server-action-security.cjs.map +1 -1
  195. package/dist/server-action-security.d.mts +45 -0
  196. package/dist/server-action-security.d.ts +45 -0
  197. package/dist/server-action-security.mjs +1 -1
  198. package/dist/server-fn-client.cjs.map +1 -1
  199. package/dist/server-fn-client.d.mts +33 -0
  200. package/dist/server-fn-client.d.ts +33 -0
  201. package/dist/server-fn-client.mjs +1 -1
  202. package/dist/server-fn-error-DDh14a0V.d.mts +26 -0
  203. package/dist/server-fn-error-DDh14a0V.d.ts +26 -0
  204. package/dist/server-fn.cjs +140 -3
  205. package/dist/server-fn.cjs.map +1 -1
  206. package/dist/server-fn.d.mts +121 -0
  207. package/dist/server-fn.d.ts +121 -0
  208. package/dist/server-fn.mjs +14 -3
  209. package/dist/server-plugins.d.mts +57 -0
  210. package/dist/server-plugins.d.ts +57 -0
  211. package/dist/server-query-client.d.mts +51 -0
  212. package/dist/server-query-client.d.ts +51 -0
  213. package/dist/server-query.cjs +99 -1
  214. package/dist/server-query.cjs.map +1 -1
  215. package/dist/server-query.d.mts +37 -0
  216. package/dist/server-query.d.ts +37 -0
  217. package/dist/server-query.mjs +3 -3
  218. package/dist/server.cjs +403 -33
  219. package/dist/server.cjs.map +1 -1
  220. package/dist/server.d.mts +51 -0
  221. package/dist/server.d.ts +51 -0
  222. package/dist/server.mjs +14 -14
  223. package/dist/storage.d.mts +52 -0
  224. package/dist/storage.d.ts +52 -0
  225. package/dist/testing.cjs.map +1 -1
  226. package/dist/testing.d.mts +103 -0
  227. package/dist/testing.d.ts +103 -0
  228. package/dist/testing.mjs +3 -3
  229. package/dist/transport-BmbGTXA5.d.mts +49 -0
  230. package/dist/transport-BmbGTXA5.d.ts +49 -0
  231. package/dist/types-BMxWr97v.d.mts +81 -0
  232. package/dist/types-BMxWr97v.d.ts +81 -0
  233. package/dist/types-D1A6-XvH.d.mts +73 -0
  234. package/dist/types-D1A6-XvH.d.ts +73 -0
  235. package/dist/types-DTzm4TCl.d.mts +78 -0
  236. package/dist/types-DTzm4TCl.d.ts +78 -0
  237. package/dist/utils-B6GaYNJL.d.ts +23 -0
  238. package/dist/utils-CKSHiip6.d.mts +23 -0
  239. package/dist/version.cjs +1 -1
  240. package/dist/version.cjs.map +1 -1
  241. package/dist/version.d.mts +3 -0
  242. package/dist/version.d.ts +3 -0
  243. package/dist/version.mjs +1 -1
  244. package/dist/vite.cjs +255 -30
  245. package/dist/vite.cjs.map +1 -1
  246. package/dist/vite.d.mts +24 -0
  247. package/dist/vite.d.ts +24 -0
  248. package/dist/vite.mjs +10 -10
  249. package/dist/workflows.d.mts +110 -0
  250. package/dist/workflows.d.ts +110 -0
  251. package/package.json +1 -1
  252. package/types/middleware.d.ts +36 -11
  253. package/dist/chunk-32W4QEJP.mjs.map +0 -1
  254. package/dist/chunk-65A7QIKI.mjs.map +0 -1
  255. package/dist/chunk-B232I2GP.mjs.map +0 -1
  256. package/dist/chunk-I4CUBGVF.mjs +0 -93
  257. package/dist/chunk-I4CUBGVF.mjs.map +0 -1
  258. package/dist/chunk-L2PE36GQ.mjs.map +0 -1
  259. package/dist/chunk-PFE6GMNE.mjs.map +0 -1
  260. package/dist/chunk-PNFQQSRA.mjs.map +0 -1
  261. package/dist/chunk-UB5UOSHB.mjs.map +0 -1
  262. package/dist/chunk-UXUAWNO5.mjs.map +0 -1
  263. package/dist/chunk-VUL55IAX.mjs.map +0 -1
  264. package/dist/chunk-VY2UYN5R.mjs.map +0 -1
  265. package/dist/chunk-WDU6QXNK.mjs.map +0 -1
  266. /package/dist/{chunk-JDEOUK5V.mjs.map → chunk-6YXKHAFU.mjs.map} +0 -0
  267. /package/dist/{chunk-Z5CQMP54.mjs.map → chunk-ARRYKOI5.mjs.map} +0 -0
  268. /package/dist/{chunk-KLA67WKG.mjs.map → chunk-B3FFOIWS.mjs.map} +0 -0
  269. /package/dist/{chunk-OPHK6OJN.mjs.map → chunk-JAEAE27K.mjs.map} +0 -0
  270. /package/dist/{chunk-H3TE3LOV.mjs.map → chunk-XMFTIVJH.mjs.map} +0 -0
  271. /package/dist/{devtools-GAZ7F3KL.mjs.map → devtools-K2ERKGNI.mjs.map} +0 -0
package/dist/index.cjs CHANGED
@@ -4842,6 +4842,72 @@ var init_cache_invalidation = __esm({
4842
4842
  }
4843
4843
  });
4844
4844
 
4845
+ // src/server-fn-error.ts
4846
+ function isServerFnFailure(value) {
4847
+ if (!value || typeof value !== "object") return false;
4848
+ const candidate = value;
4849
+ return candidate[FARM_SERVER_FN_FAILURE_SYMBOL] === true && candidate.name === "ServerFnFailure" && typeof candidate.code === "string" && Number.isInteger(candidate.status) && (candidate.status ?? 0) >= 400 && (candidate.status ?? 0) <= 599;
4850
+ }
4851
+ function serializeServerFnFailure(value) {
4852
+ if (!isServerFnFailure(value)) return null;
4853
+ return {
4854
+ name: "ServerFnFailure",
4855
+ message: value.message,
4856
+ code: value.code,
4857
+ status: value.status,
4858
+ data: value.data
4859
+ };
4860
+ }
4861
+ function createServerFnTransportError(value) {
4862
+ if (isSerializedServerFnFailure(value)) {
4863
+ return new ServerFnFailure(value.code, value.data, {
4864
+ status: value.status,
4865
+ message: value.message
4866
+ });
4867
+ }
4868
+ const message = value && typeof value === "object" && "message" in value && typeof value.message === "string" ? value.message : "Server function failed";
4869
+ return new ServerActionError(message);
4870
+ }
4871
+ function isSerializedServerFnFailure(value) {
4872
+ if (!value || typeof value !== "object") return false;
4873
+ const candidate = value;
4874
+ return candidate.name === "ServerFnFailure" && typeof candidate.message === "string" && typeof candidate.code === "string" && Number.isInteger(candidate.status) && (candidate.status ?? 0) >= 400 && (candidate.status ?? 0) <= 599 && "data" in candidate;
4875
+ }
4876
+ var FARM_SERVER_FN_FAILURE_SYMBOL, _ServerFnFailure, ServerFnFailure, _ServerActionError, ServerActionError;
4877
+ var init_server_fn_error = __esm({
4878
+ "src/server-fn-error.ts"() {
4879
+ "use strict";
4880
+ FARM_SERVER_FN_FAILURE_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn.failure");
4881
+ _ServerFnFailure = class _ServerFnFailure extends Error {
4882
+ constructor(code, data, options) {
4883
+ super(options.message);
4884
+ this.name = "ServerFnFailure";
4885
+ this.code = code;
4886
+ this.data = data;
4887
+ this.status = options.status;
4888
+ Object.defineProperty(this, FARM_SERVER_FN_FAILURE_SYMBOL, {
4889
+ value: true,
4890
+ enumerable: false
4891
+ });
4892
+ }
4893
+ };
4894
+ __name(_ServerFnFailure, "ServerFnFailure");
4895
+ ServerFnFailure = _ServerFnFailure;
4896
+ _ServerActionError = class _ServerActionError extends Error {
4897
+ constructor(message = "Server function failed") {
4898
+ super(message);
4899
+ this.name = "ServerActionError";
4900
+ }
4901
+ };
4902
+ __name(_ServerActionError, "ServerActionError");
4903
+ ServerActionError = _ServerActionError;
4904
+ __name(isServerFnFailure, "isServerFnFailure");
4905
+ __name(serializeServerFnFailure, "serializeServerFnFailure");
4906
+ __name(createServerFnTransportError, "createServerFnTransportError");
4907
+ __name(isSerializedServerFnFailure, "isSerializedServerFnFailure");
4908
+ }
4909
+ });
4910
+
4845
4911
  // src/server-action-security.ts
4846
4912
  function resolveServerActionsConfig(config) {
4847
4913
  const allowedOrigins = (config?.allowedOrigins ?? []).map(normalizeAllowedOriginPattern);
@@ -4928,7 +4994,9 @@ function createServerActionRequestErrorResponse(error) {
4928
4994
  headers: headers2
4929
4995
  });
4930
4996
  }
4931
- function sanitizeServerActionError(_error) {
4997
+ function sanitizeServerActionError(error) {
4998
+ const declaredFailure = serializeServerFnFailure(error);
4999
+ if (declaredFailure) return declaredFailure;
4932
5000
  return {
4933
5001
  name: "ServerActionError",
4934
5002
  message: "Server function failed"
@@ -5227,6 +5295,7 @@ var init_server_action_security = __esm({
5227
5295
  "use strict";
5228
5296
  import_node_async_hooks = require("async_hooks");
5229
5297
  init_cache_invalidation();
5298
+ init_server_fn_error();
5230
5299
  DEFAULT_SERVER_ACTION_BODY_SIZE_LIMIT = 1e6;
5231
5300
  _ServerActionRequestError = class _ServerActionRequestError extends Error {
5232
5301
  constructor(code, status, message) {
@@ -10252,6 +10321,15 @@ var init_deferred = __esm({
10252
10321
  });
10253
10322
 
10254
10323
  // src/deployment.ts
10324
+ function getFarmPresetRuntime(preset) {
10325
+ if (preset === "cloudflare" || preset === "cloudflare-pages" || preset === "cloudflare-module" || preset === "netlify-edge" || preset === "vercel-edge" || preset === "deno") {
10326
+ return "edge";
10327
+ }
10328
+ if (preset === "node-server" || preset === "vercel" || preset === "netlify" || preset === "aws-lambda" || preset === "azure" || preset === "firebase" || preset === "bun" || preset === "self-host" || preset === "farm") {
10329
+ return "node";
10330
+ }
10331
+ return "unknown";
10332
+ }
10255
10333
  function normalizeFarmDeploymentId(value) {
10256
10334
  if (typeof value !== "string" || value.trim() === "") {
10257
10335
  throw new TypeError("Farm deploymentId must be a non-empty string");
@@ -10370,6 +10448,7 @@ var init_deployment = __esm({
10370
10448
  FARM_DEPLOYMENT_COOKIE = "__farm_deployment";
10371
10449
  FARM_DEPLOYMENT_MISMATCH_CODE = "FARM_DEPLOYMENT_MISMATCH";
10372
10450
  FARM_DEPLOYMENT_MISMATCH_STATUS = 409;
10451
+ __name(getFarmPresetRuntime, "getFarmPresetRuntime");
10373
10452
  _FarmDeploymentMismatchError = class _FarmDeploymentMismatchError extends Error {
10374
10453
  constructor(clientDeploymentId, serverDeploymentId) {
10375
10454
  super("The application was updated while this page was open. Refresh before trying again.");
@@ -15073,6 +15152,143 @@ var init_preload = __esm({
15073
15152
  }
15074
15153
  });
15075
15154
 
15155
+ // src/security.ts
15156
+ function resolveFarmSecurityConfig(input) {
15157
+ if (input === void 0) return { csp: false };
15158
+ if (!isPlainRecord(input)) {
15159
+ throw new TypeError("security must be an object containing the csp option.");
15160
+ }
15161
+ if (Object.prototype.hasOwnProperty.call(input, "contentSecurityPolicy")) {
15162
+ throw new TypeError(
15163
+ "security.contentSecurityPolicy is not supported. Use security.csp instead."
15164
+ );
15165
+ }
15166
+ const csp = input.csp;
15167
+ if (csp === void 0 || csp === false) return { csp: false };
15168
+ if (typeof csp === "string") {
15169
+ return {
15170
+ csp: {
15171
+ value: validateSerializedCsp(csp),
15172
+ reportOnly: false
15173
+ }
15174
+ };
15175
+ }
15176
+ if (!isPlainRecord(csp)) {
15177
+ throw new TypeError("security.csp must be a policy string, false, or an options object.");
15178
+ }
15179
+ const reportOnly = validateReportOnly(csp.reportOnly);
15180
+ if (Object.prototype.hasOwnProperty.call(csp, "value")) {
15181
+ if (Object.prototype.hasOwnProperty.call(csp, "policy") || Object.prototype.hasOwnProperty.call(csp, "directives")) {
15182
+ throw new TypeError(
15183
+ "Resolved security.csp values cannot include policy or directives options."
15184
+ );
15185
+ }
15186
+ return {
15187
+ csp: {
15188
+ value: validateSerializedCsp(csp.value),
15189
+ reportOnly
15190
+ }
15191
+ };
15192
+ }
15193
+ const { policy, directives } = csp;
15194
+ if (policy !== void 0 && directives !== void 0) {
15195
+ throw new TypeError("security.csp accepts either policy or directives, not both.");
15196
+ }
15197
+ if (policy === void 0 && directives === void 0) {
15198
+ throw new TypeError("security.csp requires a policy string or directives object.");
15199
+ }
15200
+ return {
15201
+ csp: {
15202
+ value: policy !== void 0 ? validateSerializedCsp(policy) : serializeFarmCspDirectives(directives),
15203
+ reportOnly
15204
+ }
15205
+ };
15206
+ }
15207
+ function serializeFarmCspDirectives(directives) {
15208
+ if (!isPlainRecord(directives)) {
15209
+ throw new TypeError("security.csp.directives must be an object.");
15210
+ }
15211
+ const serialized = [];
15212
+ const normalizedNames = /* @__PURE__ */ new Set();
15213
+ for (const [configuredName, configuredValue] of Object.entries(directives)) {
15214
+ if (configuredValue === false || configuredValue === null || configuredValue === void 0) {
15215
+ continue;
15216
+ }
15217
+ const name = normalizeDirectiveName(configuredName);
15218
+ if (normalizedNames.has(name)) {
15219
+ throw new TypeError(`security.csp contains the duplicate directive ${JSON.stringify(name)}.`);
15220
+ }
15221
+ normalizedNames.add(name);
15222
+ const values = configuredValue === true ? [] : (Array.isArray(configuredValue) ? configuredValue : [configuredValue]).map(
15223
+ validateDirectiveValue
15224
+ );
15225
+ serialized.push(values.length > 0 ? `${name} ${values.join(" ")}` : name);
15226
+ }
15227
+ if (serialized.length === 0) {
15228
+ throw new TypeError("security.csp.directives must contain at least one enabled directive.");
15229
+ }
15230
+ return serialized.join("; ");
15231
+ }
15232
+ function getFarmSecurityHeader(security) {
15233
+ if (!security.csp) return void 0;
15234
+ return {
15235
+ key: security.csp.reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy",
15236
+ value: security.csp.value
15237
+ };
15238
+ }
15239
+ function normalizeDirectiveName(value) {
15240
+ const name = value.trim().replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
15241
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
15242
+ throw new TypeError(`Invalid security.csp directive name: ${JSON.stringify(value)}.`);
15243
+ }
15244
+ return name;
15245
+ }
15246
+ function validateDirectiveValue(value) {
15247
+ if (typeof value !== "string") {
15248
+ throw new TypeError("security.csp directive values must be strings or booleans.");
15249
+ }
15250
+ const normalized = value.trim();
15251
+ if (!normalized || /[;\r\n]/.test(normalized) || normalized.includes("\0")) {
15252
+ throw new TypeError(`Invalid security.csp directive value: ${JSON.stringify(value)}.`);
15253
+ }
15254
+ return normalized;
15255
+ }
15256
+ function validateSerializedCsp(value) {
15257
+ if (typeof value !== "string") {
15258
+ throw new TypeError("security.csp policy must be a non-empty single-line string.");
15259
+ }
15260
+ const normalized = value.trim().replace(/;+$/g, "").trim();
15261
+ if (!normalized || /[\r\n]/.test(normalized) || normalized.includes("\0")) {
15262
+ throw new TypeError("security.csp policy must be a non-empty single-line string.");
15263
+ }
15264
+ return normalized;
15265
+ }
15266
+ function validateReportOnly(value) {
15267
+ if (value === void 0) return false;
15268
+ if (typeof value !== "boolean") {
15269
+ throw new TypeError("security.csp.reportOnly must be a boolean.");
15270
+ }
15271
+ return value;
15272
+ }
15273
+ function isPlainRecord(value) {
15274
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
15275
+ const prototype = Object.getPrototypeOf(value);
15276
+ return prototype === Object.prototype || prototype === null;
15277
+ }
15278
+ var init_security = __esm({
15279
+ "src/security.ts"() {
15280
+ "use strict";
15281
+ __name(resolveFarmSecurityConfig, "resolveFarmSecurityConfig");
15282
+ __name(serializeFarmCspDirectives, "serializeFarmCspDirectives");
15283
+ __name(getFarmSecurityHeader, "getFarmSecurityHeader");
15284
+ __name(normalizeDirectiveName, "normalizeDirectiveName");
15285
+ __name(validateDirectiveValue, "validateDirectiveValue");
15286
+ __name(validateSerializedCsp, "validateSerializedCsp");
15287
+ __name(validateReportOnly, "validateReportOnly");
15288
+ __name(isPlainRecord, "isPlainRecord");
15289
+ }
15290
+ });
15291
+
15076
15292
  // src/app.ts
15077
15293
  function isResolvedDocsConfig(value) {
15078
15294
  return !!value && typeof value === "object" && "enabled" in value && "entry" in value && "config" in value;
@@ -15113,6 +15329,7 @@ var init_app = __esm({
15113
15329
  init_cache();
15114
15330
  init_auth_config();
15115
15331
  init_preload();
15332
+ init_security();
15116
15333
  defaultDocsConfig = {
15117
15334
  enabled: false,
15118
15335
  entry: "/docs",
@@ -15177,6 +15394,7 @@ var init_app = __esm({
15177
15394
  routeRules: normalizeRouteRules(config.routeRules),
15178
15395
  context: config.context || (() => void 0),
15179
15396
  serverActions: resolveServerActionsConfig(config.serverActions),
15397
+ security: resolveFarmSecurityConfig(config.security),
15180
15398
  images: resolveFarmImageConfig(config.images),
15181
15399
  performance: resolveFarmPerformanceConfig(config.performance),
15182
15400
  i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
@@ -15968,13 +16186,13 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
15968
16186
  }
15969
16187
  const middleware2 = normalizeEndpointMiddleware(options.middleware);
15970
16188
  const errors = normalizeEndpointErrors(options.errors);
15971
- const fail = createEndpointFail(errors);
16189
+ const error = createEndpointErrorHandler(errors);
15972
16190
  const wrappedHandler = /* @__PURE__ */ __name((async (ctx) => {
15973
16191
  const execution = await runEndpointMiddleware(
15974
16192
  middleware2,
15975
16193
  ctx,
15976
16194
  handler,
15977
- fail,
16195
+ error,
15978
16196
  options.invalidates
15979
16197
  );
15980
16198
  return execution.result;
@@ -15994,7 +16212,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
15994
16212
  endpoint2.__method = options.method || "GET";
15995
16213
  endpoint2.__autoPath = !path32;
15996
16214
  endpoint2.__handler = wrappedHandler;
15997
- endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, fail, options.invalidates);
16215
+ endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, error, options.invalidates);
15998
16216
  endpoint2.__middleware = middleware2;
15999
16217
  endpoint2.__sourceHandler = handler;
16000
16218
  endpoint2.__invalidates = options.invalidates;
@@ -16025,8 +16243,9 @@ function normalizeEndpointErrors(definitions) {
16025
16243
  if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
16026
16244
  throw new TypeError(`Endpoint error "${code}" status must be an integer between 400 and 599`);
16027
16245
  }
16028
- if (!definition.schema || typeof definition.schema.parse !== "function") {
16029
- throw new TypeError(`Endpoint error "${code}" requires a schema with parse()`);
16246
+ const dataSchema = resolveEndpointErrorSchema(definition);
16247
+ if (!dataSchema || typeof dataSchema.parse !== "function") {
16248
+ throw new TypeError(`Endpoint error "${code}" requires a data schema with parse()`);
16030
16249
  }
16031
16250
  if (definition.message !== void 0 && typeof definition.message !== "string") {
16032
16251
  throw new TypeError(`Endpoint error "${code}" message must be a string`);
@@ -16035,13 +16254,19 @@ function normalizeEndpointErrors(definitions) {
16035
16254
  }
16036
16255
  return Object.freeze(normalized);
16037
16256
  }
16038
- function createEndpointFail(definitions) {
16257
+ function resolveEndpointErrorSchema(definition) {
16258
+ if (definition.data && definition.schema) {
16259
+ throw new TypeError("Endpoint errors cannot define both data and schema");
16260
+ }
16261
+ return definition.data ?? definition.schema;
16262
+ }
16263
+ function createEndpointErrorHandler(definitions) {
16039
16264
  return ((code, data) => {
16040
16265
  const definition = definitions[code];
16041
16266
  if (!definition) {
16042
16267
  throw new TypeError(`Endpoint error "${code}" is not declared`);
16043
16268
  }
16044
- const parsed = definition.schema.parse(data);
16269
+ const parsed = resolveEndpointErrorSchema(definition).parse(data);
16045
16270
  throw new EndpointFailure(code, parsed, {
16046
16271
  status: definition.status,
16047
16272
  message: definition.message ?? "Request failed"
@@ -16061,7 +16286,7 @@ function normalizeEndpointMiddleware(middleware2) {
16061
16286
  }
16062
16287
  return Object.freeze(normalized);
16063
16288
  }
16064
- async function runEndpointMiddleware(middleware2, handlerContext, handler, fail, invalidations) {
16289
+ async function runEndpointMiddleware(middleware2, handlerContext, handler, error, invalidations) {
16065
16290
  let context = createInitialEndpointContext(handlerContext.context);
16066
16291
  for (let index = 0; index < middleware2.length; index++) {
16067
16292
  const result2 = await middleware2[index]({ ...handlerContext, context });
@@ -16089,7 +16314,7 @@ async function runEndpointMiddleware(middleware2, handlerContext, handler, fail,
16089
16314
  }
16090
16315
  context = mergeEndpointContext(context, result2, index);
16091
16316
  }
16092
- const result = await handler({ ...handlerContext, context, fail });
16317
+ const result = await handler({ ...handlerContext, context, error, fail: error });
16093
16318
  return {
16094
16319
  result,
16095
16320
  context,
@@ -16219,7 +16444,8 @@ var init_endpoint = __esm({
16219
16444
  EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
16220
16445
  UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
16221
16446
  __name(normalizeEndpointErrors, "normalizeEndpointErrors");
16222
- __name(createEndpointFail, "createEndpointFail");
16447
+ __name(resolveEndpointErrorSchema, "resolveEndpointErrorSchema");
16448
+ __name(createEndpointErrorHandler, "createEndpointErrorHandler");
16223
16449
  __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
16224
16450
  __name(runEndpointMiddleware, "runEndpointMiddleware");
16225
16451
  __name(applyEndpointInvalidations, "applyEndpointInvalidations");
@@ -17824,6 +18050,13 @@ function routePatternToTsTypeLiterals(pattern) {
17824
18050
  function routePatternToRouteLiteral(pattern) {
17825
18051
  return JSON.stringify(pattern);
17826
18052
  }
18053
+ function renderTypeUnion(values) {
18054
+ return values.length <= 1 ? values[0] || "never" : `
18055
+ | ${values.join("\n | ")}`;
18056
+ }
18057
+ function renderTypeAlias(name, value) {
18058
+ return `export type ${name} =${value.startsWith("\n") ? "" : " "}${value};`;
18059
+ }
17827
18060
  function createRoutePattern(route2) {
17828
18061
  if (route2.segments.length === 0) return "/";
17829
18062
  return "/" + route2.segments.map((seg) => {
@@ -17883,9 +18116,9 @@ async function createRouteTypeDeclarations(options, outPath) {
17883
18116
  const typeLiterals = Array.from(new Set(sortedPatterns.flatMap(routePatternToTsTypeLiterals)));
17884
18117
  const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
17885
18118
  const routeModulePatternLiterals = Array.from(routeModulePatterns).sort().map(routePatternToRouteLiteral);
17886
- const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
17887
- const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
17888
- const routeModulePatternType = routeModulePatternLiterals.length ? routeModulePatternLiterals.join(" | ") : "never";
18119
+ const routePathType = suppressLintOnLink ? "string" : renderTypeUnion(typeLiterals);
18120
+ const routePatternType = suppressLintOnLink ? "string" : renderTypeUnion(patternLiterals);
18121
+ const routeModulePatternType = renderTypeUnion(routeModulePatternLiterals);
17889
18122
  const routeTypesImportPath = `./${path14.basename(outPath).replace(/\.d\.ts$/, "")}`;
17890
18123
  const linkAugmentationBlock = suppressLintOnLink ? "" : `
17891
18124
  declare module "@farm.js/core/client" {
@@ -17927,9 +18160,9 @@ declare global {
17927
18160
  * Regenerated on dev start and when routes change.
17928
18161
  * Set suppressLintOnLink: true in farm.config.ts to accept any string on Link href.
17929
18162
  */
17930
- export type RoutePath = ${routePathType};
17931
- export type RoutePattern = ${routePatternType};
17932
- export type RouteModulePattern = ${routeModulePatternType};${linkAugmentationBlock}${routeModuleAugmentationBlock}
18163
+ ${renderTypeAlias("RoutePath", routePathType)}
18164
+ ${renderTypeAlias("RoutePattern", routePatternType)}
18165
+ ${renderTypeAlias("RouteModulePattern", routeModulePatternType)}${linkAugmentationBlock}${routeModuleAugmentationBlock}
17933
18166
  `;
17934
18167
  return content;
17935
18168
  }
@@ -17946,6 +18179,8 @@ var init_generate_route_types = __esm({
17946
18179
  __name(routeSegmentsToTsTypeLiteral, "routeSegmentsToTsTypeLiteral");
17947
18180
  __name(routePatternToTsTypeLiterals, "routePatternToTsTypeLiterals");
17948
18181
  __name(routePatternToRouteLiteral, "routePatternToRouteLiteral");
18182
+ __name(renderTypeUnion, "renderTypeUnion");
18183
+ __name(renderTypeAlias, "renderTypeAlias");
17949
18184
  __name(createRoutePattern, "createRoutePattern");
17950
18185
  DEFAULT_OUT_FILE = "farm-routes.d.ts";
17951
18186
  __name(generateRouteTypes, "generateRouteTypes");
@@ -18246,7 +18481,8 @@ async function generateFarmTypeArtifacts(options) {
18246
18481
  const sourceRoots = getFarmSourceRoots({ root, srcDir, layers: options.layers });
18247
18482
  const appDirs = getFarmAppDirectories({ root, srcDir, layers: options.layers });
18248
18483
  const result = {
18249
- apiRoutes: []
18484
+ apiRoutes: [],
18485
+ stalePaths: []
18250
18486
  };
18251
18487
  const unifiedTypesPath = (0, import_path8.join)(root, srcDir, "farm.d.ts");
18252
18488
  const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
@@ -18262,22 +18498,29 @@ async function generateFarmTypeArtifacts(options) {
18262
18498
  unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
18263
18499
  result.routeTypesPath = unifiedTypesPath;
18264
18500
  } else if (shouldGenerateRoutes) {
18265
- result.routeTypesPath = await generateRouteTypes({
18501
+ const routeOptions = {
18266
18502
  root,
18267
18503
  srcDir,
18268
18504
  outFile: options.routeTypesOutFile,
18269
18505
  extraRoutes: options.extraRoutes || [],
18270
18506
  suppressLintOnLink: options.suppressLintOnLink,
18271
18507
  sourceRoots
18272
- });
18508
+ };
18509
+ if (options.check) {
18510
+ const routeTypesPath = resolveGeneratedPath(root, srcDir, options.routeTypesOutFile);
18511
+ const content = await createRouteTypeDeclarations(routeOptions, routeTypesPath);
18512
+ checkGeneratedFile(routeTypesPath, content, result.stalePaths);
18513
+ result.routeTypesPath = routeTypesPath;
18514
+ } else {
18515
+ result.routeTypesPath = await generateRouteTypes(routeOptions);
18516
+ }
18273
18517
  }
18274
18518
  if (shouldGenerateApi) {
18275
18519
  const generator = new APITypeGenerator(appDirs);
18276
18520
  const apiRoutes = generator.scanAPIRoutes();
18277
18521
  const apiTypesPath = options.apiTypesOutFile ? (0, import_path8.resolve)(root, options.apiTypesOutFile) : (0, import_path8.join)(root, srcDir, "lib", "api.generated.ts");
18278
18522
  const content = generator.generateAPIRouter(apiRoutes, { outFile: apiTypesPath });
18279
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(apiTypesPath), { recursive: true });
18280
- writeFileIfChanged(apiTypesPath, content);
18523
+ writeOrCheckGeneratedFile(apiTypesPath, content, options.check, result.stalePaths);
18281
18524
  result.apiTypesPath = apiTypesPath;
18282
18525
  result.apiRoutes = apiRoutes;
18283
18526
  }
@@ -18295,36 +18538,63 @@ async function generateFarmTypeArtifacts(options) {
18295
18538
  );
18296
18539
  result.envTypesPath = unifiedTypesPath;
18297
18540
  } else if (shouldGenerateEnv) {
18298
- result.envTypesPath = await generateEnvTypes({
18541
+ const envOptions = {
18299
18542
  root,
18300
18543
  srcDir,
18301
18544
  outFile: options.envTypesOutFile,
18302
18545
  configPath: options.configPath,
18303
18546
  layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
18304
- });
18547
+ };
18548
+ if (options.check) {
18549
+ const envTypesPath = resolveGeneratedPath(root, srcDir, options.envTypesOutFile);
18550
+ checkGeneratedFile(
18551
+ envTypesPath,
18552
+ createEnvTypeDeclarations(envOptions, envTypesPath),
18553
+ result.stalePaths
18554
+ );
18555
+ result.envTypesPath = envTypesPath;
18556
+ } else {
18557
+ result.envTypesPath = await generateEnvTypes(envOptions);
18558
+ }
18305
18559
  }
18306
18560
  if (shouldGenerateImages && options.imageTypesOutFile) {
18307
- result.imageTypesPath = generateFarmImageTypes({
18308
- root,
18309
- srcDir,
18310
- outFile: options.imageTypesOutFile
18311
- });
18561
+ const imageTypesPath = resolveGeneratedPath(root, srcDir, options.imageTypesOutFile, false);
18562
+ if (options.check) {
18563
+ checkGeneratedFile(imageTypesPath, createFarmImageTypeDeclarations(), result.stalePaths);
18564
+ result.imageTypesPath = imageTypesPath;
18565
+ } else {
18566
+ result.imageTypesPath = generateFarmImageTypes({
18567
+ root,
18568
+ srcDir,
18569
+ outFile: options.imageTypesOutFile
18570
+ });
18571
+ }
18312
18572
  }
18313
18573
  if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
18314
18574
  const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
18315
18575
  unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
18316
18576
  result.i18nTypesPath = unifiedTypesPath;
18317
18577
  } else if (shouldGenerateI18n && options.i18nConfig) {
18318
- result.i18nTypesPath = await generateFarmI18nTypes({
18319
- root,
18320
- srcDir,
18321
- config: options.i18nConfig,
18322
- outFile: options.i18nTypesOutFile
18323
- });
18578
+ if (options.check) {
18579
+ const i18nTypesPath = resolveGeneratedPath(root, srcDir, options.i18nTypesOutFile, false);
18580
+ const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
18581
+ checkGeneratedFile(
18582
+ i18nTypesPath,
18583
+ renderFarmI18nTypes(options.i18nConfig.locales, signatures),
18584
+ result.stalePaths
18585
+ );
18586
+ result.i18nTypesPath = i18nTypesPath;
18587
+ } else {
18588
+ result.i18nTypesPath = await generateFarmI18nTypes({
18589
+ root,
18590
+ srcDir,
18591
+ config: options.i18nConfig,
18592
+ outFile: options.i18nTypesOutFile
18593
+ });
18594
+ }
18324
18595
  }
18325
18596
  if (shouldRefreshUnifiedTypes) {
18326
- (0, import_fs4.mkdirSync)((0, import_path8.dirname)(unifiedTypesPath), { recursive: true });
18327
- writeFileIfChanged(
18597
+ writeOrCheckGeneratedFile(
18328
18598
  unifiedTypesPath,
18329
18599
  `/**
18330
18600
  * Generated by Farm.js. Do not edit.
@@ -18333,13 +18603,37 @@ async function generateFarmTypeArtifacts(options) {
18333
18603
 
18334
18604
  import "@farm.js/core/image";
18335
18605
 
18336
- ${unifiedSections.join("\n")}`
18606
+ ${unifiedSections.map((section) => section.trimEnd()).join("\n\n")}
18607
+ `,
18608
+ options.check,
18609
+ result.stalePaths
18337
18610
  );
18338
18611
  result.typesPath = unifiedTypesPath;
18339
- removeLegacyTypeArtifacts(root, srcDir);
18612
+ if (options.check) {
18613
+ collectLegacyTypeArtifacts(root, srcDir, result.stalePaths);
18614
+ } else {
18615
+ removeLegacyTypeArtifacts(root, srcDir);
18616
+ }
18340
18617
  }
18341
18618
  return result;
18342
18619
  }
18620
+ function resolveGeneratedPath(root, srcDir, outFile, relativeToSrc = true) {
18621
+ if ((0, import_path8.isAbsolute)(outFile)) return (0, import_path8.resolve)(outFile);
18622
+ return (0, import_path8.resolve)(root, relativeToSrc ? (0, import_path8.join)(srcDir, outFile) : outFile);
18623
+ }
18624
+ function writeOrCheckGeneratedFile(filePath, content, check, stalePaths) {
18625
+ if (check) {
18626
+ checkGeneratedFile(filePath, content, stalePaths);
18627
+ return;
18628
+ }
18629
+ (0, import_fs4.mkdirSync)((0, import_path8.dirname)(filePath), { recursive: true });
18630
+ writeFileIfChanged(filePath, content);
18631
+ }
18632
+ function checkGeneratedFile(filePath, content, stalePaths) {
18633
+ if (!(0, import_fs4.existsSync)(filePath) || (0, import_fs4.readFileSync)(filePath, "utf8") !== content) {
18634
+ stalePaths.push(filePath);
18635
+ }
18636
+ }
18343
18637
  function removeLegacyTypeArtifacts(root, srcDir) {
18344
18638
  for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
18345
18639
  const filePath = (0, import_path8.join)(root, srcDir, fileName);
@@ -18350,6 +18644,13 @@ function removeLegacyTypeArtifacts(root, srcDir) {
18350
18644
  }
18351
18645
  }
18352
18646
  }
18647
+ function collectLegacyTypeArtifacts(root, srcDir, stalePaths) {
18648
+ for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
18649
+ const filePath = (0, import_path8.join)(root, srcDir, fileName);
18650
+ if (!(0, import_fs4.existsSync)(filePath)) continue;
18651
+ if ((0, import_fs4.readFileSync)(filePath, "utf8").includes(marker)) stalePaths.push(filePath);
18652
+ }
18653
+ }
18353
18654
  var import_fs4, import_path8, LEGACY_TYPE_ARTIFACTS;
18354
18655
  var init_type_artifacts = __esm({
18355
18656
  "src/type-artifacts.ts"() {
@@ -18365,6 +18666,9 @@ var init_type_artifacts = __esm({
18365
18666
  init_layers();
18366
18667
  init_write_file_if_changed();
18367
18668
  __name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
18669
+ __name(resolveGeneratedPath, "resolveGeneratedPath");
18670
+ __name(writeOrCheckGeneratedFile, "writeOrCheckGeneratedFile");
18671
+ __name(checkGeneratedFile, "checkGeneratedFile");
18368
18672
  LEGACY_TYPE_ARTIFACTS = [
18369
18673
  ["farm-routes.d.ts", "Auto-generated route types"],
18370
18674
  ["farm-env.d.ts", "Auto-generated env types"],
@@ -18372,6 +18676,7 @@ var init_type_artifacts = __esm({
18372
18676
  ["farm-i18n.d.ts", "Generated by Farm.js"]
18373
18677
  ];
18374
18678
  __name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
18679
+ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
18375
18680
  }
18376
18681
  });
18377
18682
 
@@ -18728,7 +19033,7 @@ var init_environment_vite = __esm({
18728
19033
  var version;
18729
19034
  var init_package = __esm({
18730
19035
  "package.json"() {
18731
- version = "0.1.0-beta.14";
19036
+ version = "0.1.0-beta.17";
18732
19037
  }
18733
19038
  });
18734
19039
 
@@ -19489,11 +19794,28 @@ function createFarmClientOptimizeDepsConfig(entries) {
19489
19794
  ...entries?.length ? { entries: [...entries] } : {}
19490
19795
  };
19491
19796
  }
19797
+ function createFarmSourceAlias(projectRoot, srcDir = "src") {
19798
+ return {
19799
+ "@": import_node_path9.default.resolve(projectRoot, srcDir)
19800
+ };
19801
+ }
19492
19802
  function mergeNoExternal(farmValue, userValue) {
19493
19803
  if (farmValue === true || userValue === true) return true;
19494
19804
  const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
19495
19805
  return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
19496
19806
  }
19807
+ function mergeAlias(farmValue, userValue) {
19808
+ if (!farmValue) return userValue || {};
19809
+ if (!userValue) return farmValue;
19810
+ if (!Array.isArray(farmValue) && !Array.isArray(userValue)) {
19811
+ return {
19812
+ ...farmValue,
19813
+ ...userValue
19814
+ };
19815
+ }
19816
+ const normalize = /* @__PURE__ */ __name((value) => Array.isArray(value) ? [...value] : Object.entries(value).map(([find, replacement]) => ({ find, replacement })), "normalize");
19817
+ return [...normalize(userValue), ...normalize(farmValue)];
19818
+ }
19497
19819
  function mergeFarmViteConfig(farmConfig, userConfig = {}) {
19498
19820
  const noDiscovery = userConfig.optimizeDeps?.noDiscovery ?? farmConfig.optimizeDeps?.noDiscovery;
19499
19821
  const holdUntilCrawlEnd = userConfig.optimizeDeps?.holdUntilCrawlEnd ?? (userConfig.optimizeDeps?.noDiscovery === true ? false : farmConfig.optimizeDeps?.holdUntilCrawlEnd);
@@ -19508,6 +19830,7 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
19508
19830
  resolve: {
19509
19831
  ...farmConfig.resolve,
19510
19832
  ...userConfig.resolve,
19833
+ alias: mergeAlias(farmConfig.resolve?.alias, userConfig.resolve?.alias),
19511
19834
  dedupe: Array.from(
19512
19835
  /* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
19513
19836
  )
@@ -19560,7 +19883,9 @@ var init_vite_config = __esm({
19560
19883
  ];
19561
19884
  __name(createFarmClientOptimizeDepsEntries, "createFarmClientOptimizeDepsEntries");
19562
19885
  __name(createFarmClientOptimizeDepsConfig, "createFarmClientOptimizeDepsConfig");
19886
+ __name(createFarmSourceAlias, "createFarmSourceAlias");
19563
19887
  __name(mergeNoExternal, "mergeNoExternal");
19888
+ __name(mergeAlias, "mergeAlias");
19564
19889
  __name(mergeFarmViteConfig, "mergeFarmViteConfig");
19565
19890
  }
19566
19891
  });
@@ -23520,6 +23845,8 @@ async function resolveConfig(userConfig, mode) {
23520
23845
  const routeRules = normalizeRouteRules(userConfig.routeRules);
23521
23846
  const routeRuleRedirects = routeRulesToRedirects(routeRules);
23522
23847
  const routeRuleHeaders = routeRulesToHeaders(routeRules);
23848
+ const security = resolveFarmSecurityConfig(userConfig.security);
23849
+ const securityHeader = getFarmSecurityHeader(security);
23523
23850
  const deploy = resolveDeployConfig(userConfig);
23524
23851
  const root = userConfig.root || process.cwd();
23525
23852
  const srcDir = userConfig.srcDir || "src";
@@ -23575,7 +23902,11 @@ async function resolveConfig(userConfig, mode) {
23575
23902
  trailingSlash: userConfig.trailingSlash ?? false,
23576
23903
  redirects: /* @__PURE__ */ __name(() => [...redirects, ...routeRuleRedirects], "redirects"),
23577
23904
  rewrites: /* @__PURE__ */ __name(() => rewrites, "rewrites"),
23578
- headers: /* @__PURE__ */ __name(() => [...headers2, ...routeRuleHeaders], "headers"),
23905
+ headers: /* @__PURE__ */ __name(() => [
23906
+ ...headers2,
23907
+ ...routeRuleHeaders,
23908
+ ...securityHeader ? [{ source: "/*", headers: [securityHeader] }] : []
23909
+ ], "headers"),
23579
23910
  routeRules,
23580
23911
  images: resolveFarmImageConfig(userConfig.images),
23581
23912
  performance: resolveFarmPerformanceConfig(userConfig.performance),
@@ -23594,6 +23925,7 @@ async function resolveConfig(userConfig, mode) {
23594
23925
  notFound: userConfig.notFound || {},
23595
23926
  context: userConfig.context || (() => void 0),
23596
23927
  serverActions: resolveServerActionsConfig(userConfig.serverActions),
23928
+ security,
23597
23929
  deploymentId,
23598
23930
  output: userConfig.output || "standalone",
23599
23931
  distDir: userConfig.distDir || ".farm",
@@ -23673,6 +24005,7 @@ var init_config2 = __esm({
23673
24005
  init_config();
23674
24006
  init_auth_config();
23675
24007
  init_preload();
24008
+ init_security();
23676
24009
  init_config_entry();
23677
24010
  FARM_RESOLVED_CUSTOM_CONTEXT = /* @__PURE__ */ Symbol.for("farm.resolvedCustomContext");
23678
24011
  __name(hasCustomFarmRouteContext, "hasCustomFarmRouteContext");
@@ -30507,7 +30840,7 @@ async function defineConfig2(config = {}) {
30507
30840
  // Stub out problematic server-only modules during dev mode
30508
30841
  alias: {
30509
30842
  ...getFarmLayerAliases(config.layers),
30510
- "@": path25.resolve(appRoot, "src"),
30843
+ ...createFarmSourceAlias(appRoot, config.srcDir),
30511
30844
  // Nitro internals that should not be resolved in browser
30512
30845
  "supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
30513
30846
  "@poppinss/dumper": "data:text/javascript,export default {};",
@@ -31947,6 +32280,7 @@ __export(src_exports, {
31947
32280
  FARM_DEVTOOLS_LAUNCH_PARAM: () => FARM_DEVTOOLS_LAUNCH_PARAM,
31948
32281
  FARM_DEVTOOLS_PATH: () => FARM_DEVTOOLS_PATH,
31949
32282
  FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY: () => FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY,
32283
+ FARM_SERVER_FN_FAILURE_SYMBOL: () => FARM_SERVER_FN_FAILURE_SYMBOL,
31950
32284
  FARM_SERVER_FN_SYMBOL: () => FARM_SERVER_FN_SYMBOL,
31951
32285
  FARM_SERVER_QUERY_SYMBOL: () => FARM_SERVER_QUERY_SYMBOL,
31952
32286
  FarmClientPluginManager: () => FarmClientPluginManager,
@@ -31969,7 +32303,10 @@ __export(src_exports, {
31969
32303
  PluginManager: () => PluginManager,
31970
32304
  SPARouter: () => SPARouter,
31971
32305
  ScalarAPIDocumentation: () => ScalarAPIDocumentation,
32306
+ ServerActionError: () => ServerActionError,
31972
32307
  ServerActionRequestError: () => ServerActionRequestError,
32308
+ ServerFnFailure: () => ServerFnFailure,
32309
+ UnsupportedRateLimitStorageError: () => UnsupportedRateLimitStorageError,
31973
32310
  _parseServerFnSchema: () => _parseServerFnSchema,
31974
32311
  _runWithAfterNodeResponse: () => _runWithAfterNodeResponse,
31975
32312
  _runWithAfterRequest: () => _runWithAfterRequest,
@@ -32058,6 +32395,7 @@ __export(src_exports, {
32058
32395
  createServerAPIClient: () => createServerAPIClient,
32059
32396
  createServerActionRequestErrorResponse: () => createServerActionRequestErrorResponse,
32060
32397
  createServerFn: () => createServerFn,
32398
+ createServerFnTransportError: () => createServerFnTransportError,
32061
32399
  createServerMiddleware: () => createServerMiddleware,
32062
32400
  createServerOnlyFn: () => createServerOnlyFn,
32063
32401
  createServerQuery: () => createServerQuery,
@@ -32111,6 +32449,7 @@ __export(src_exports, {
32111
32449
  getFarmDocsRouteTypeEntries: () => getFarmDocsRouteTypeEntries,
32112
32450
  getFarmIntegrationPluginServerRuntime: () => getFarmIntegrationPluginServerRuntime,
32113
32451
  getFarmLayerAliases: () => getFarmLayerAliases,
32452
+ getFarmPresetRuntime: () => getFarmPresetRuntime,
32114
32453
  getFarmRedirectError: () => getFarmRedirectError,
32115
32454
  getFarmRequestDeploymentId: () => getFarmRequestDeploymentId,
32116
32455
  getFarmResponseDeploymentId: () => getFarmResponseDeploymentId,
@@ -32174,6 +32513,7 @@ __export(src_exports, {
32174
32513
  isProgrammaticRouteManifest: () => isProgrammaticRouteManifest,
32175
32514
  isProgrammaticRoutesFileName: () => isProgrammaticRoutesFileName,
32176
32515
  isSSGModule: () => isSSGModule,
32516
+ isServerFnFailure: () => isServerFnFailure,
32177
32517
  isWebResponse: () => isWebResponse2,
32178
32518
  jsonStream: () => jsonStream,
32179
32519
  layout: () => layout,
@@ -32191,6 +32531,7 @@ __export(src_exports, {
32191
32531
  matchRegisteredIntegrationRoute: () => matchRegisteredIntegrationRoute,
32192
32532
  matchRoute: () => matchRoute,
32193
32533
  matchSSGPage: () => matchSSGPage,
32534
+ memoryRateLimitStorage: () => memoryRateLimitStorage,
32194
32535
  memoryStorage: () => memoryStorage,
32195
32536
  mergeFarmRouteRuntimeConfigs: () => mergeFarmRouteRuntimeConfigs,
32196
32537
  mergeScheduledTasks: () => mergeScheduledTasks,
@@ -34647,35 +34988,69 @@ function parseRouteParams(input, parsers, options = {}) {
34647
34988
  __name(parseRouteParams, "parseRouteParams");
34648
34989
 
34649
34990
  // src/middleware/chain.ts
34650
- init_storage();
34651
- function getRateLimitStorage() {
34652
- return getStorage("ratelimit");
34653
- }
34654
- __name(getRateLimitStorage, "getRateLimitStorage");
34655
- var defaultRateLimitStorage = {
34656
- async get(key) {
34657
- const storage = getRateLimitStorage();
34658
- const value = await storage.getItem(key);
34659
- return value ?? null;
34660
- },
34661
- async set(key, value, ttl) {
34662
- const storage = getRateLimitStorage();
34663
- await storage.setItem(key, value, ttl ? { ttl } : void 0);
34664
- },
34665
- async delete(key) {
34666
- const storage = getRateLimitStorage();
34667
- await storage.removeItem(key);
34668
- },
34669
- async ttl(key) {
34670
- const storage = getRateLimitStorage();
34671
- const record = await storage.getItem(key);
34672
- if (!record || !record.resetAt) {
34991
+ var DEFAULT_MEMORY_RATE_LIMIT_ENTRIES = 1e5;
34992
+ var _UnsupportedRateLimitStorageError = class _UnsupportedRateLimitStorageError extends TypeError {
34993
+ constructor() {
34994
+ super(
34995
+ "RateLimitStorage must implement atomic increment(key, windowMs). Legacy get/set adapters can lose increments under concurrency. Use memoryRateLimitStorage() for one process or redisRateLimitStorage() from @farm.js/cache-redis for production."
34996
+ );
34997
+ this.name = "UnsupportedRateLimitStorageError";
34998
+ }
34999
+ };
35000
+ __name(_UnsupportedRateLimitStorageError, "UnsupportedRateLimitStorageError");
35001
+ var UnsupportedRateLimitStorageError = _UnsupportedRateLimitStorageError;
35002
+ function memoryRateLimitStorage(options = {}) {
35003
+ const maxEntries = options.maxEntries ?? DEFAULT_MEMORY_RATE_LIMIT_ENTRIES;
35004
+ if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0) {
35005
+ throw new TypeError("memoryRateLimitStorage maxEntries must be a positive safe integer.");
35006
+ }
35007
+ const records = /* @__PURE__ */ new Map();
35008
+ function read(key, now2) {
35009
+ const record = records.get(key);
35010
+ if (!record) return null;
35011
+ if (record.resetAt <= now2) {
35012
+ records.delete(key);
34673
35013
  return null;
34674
35014
  }
34675
- const remainingMs = record.resetAt - Date.now();
34676
- return remainingMs > 0 ? Math.ceil(remainingMs / 1e3) : null;
35015
+ return record;
34677
35016
  }
34678
- };
35017
+ __name(read, "read");
35018
+ function pruneExpired(now2) {
35019
+ for (const [key, record] of records) {
35020
+ if (record.resetAt <= now2) records.delete(key);
35021
+ }
35022
+ }
35023
+ __name(pruneExpired, "pruneExpired");
35024
+ return {
35025
+ increment(key, windowMs) {
35026
+ if (!Number.isSafeInteger(windowMs) || windowMs <= 0) {
35027
+ throw new TypeError("Rate-limit windowMs must be a positive safe integer.");
35028
+ }
35029
+ const now2 = Date.now();
35030
+ const current = read(key, now2);
35031
+ if (current) {
35032
+ const next2 = { count: current.count + 1, resetAt: current.resetAt };
35033
+ records.set(key, next2);
35034
+ return next2;
35035
+ }
35036
+ if (records.size >= maxEntries) pruneExpired(now2);
35037
+ if (records.size >= maxEntries) {
35038
+ throw new Error(
35039
+ `Process-local rate-limit storage reached its ${maxEntries} active-key capacity. Configure a shared production adapter or increase maxEntries.`
35040
+ );
35041
+ }
35042
+ const next = { count: 1, resetAt: now2 + windowMs };
35043
+ records.set(key, next);
35044
+ return next;
35045
+ },
35046
+ get(key) {
35047
+ const record = read(key, Date.now());
35048
+ return record ? { ...record } : null;
35049
+ }
35050
+ };
35051
+ }
35052
+ __name(memoryRateLimitStorage, "memoryRateLimitStorage");
35053
+ var defaultRateLimitStorage = memoryRateLimitStorage();
34679
35054
  function parseTimeWindow(window2) {
34680
35055
  const match = window2.match(/^(\d+)(ms|s|m|h|d)$/);
34681
35056
  if (!match) throw new Error(`Invalid time window: ${window2}`);
@@ -34688,52 +35063,73 @@ function parseTimeWindow(window2) {
34688
35063
  h: 60 * 60 * 1e3,
34689
35064
  d: 24 * 60 * 60 * 1e3
34690
35065
  };
34691
- return value * multipliers[unit];
35066
+ const windowMs = value * multipliers[unit];
35067
+ if (!Number.isSafeInteger(windowMs) || windowMs <= 0) {
35068
+ throw new Error(`Invalid time window: ${window2}`);
35069
+ }
35070
+ return windowMs;
34692
35071
  }
34693
35072
  __name(parseTimeWindow, "parseTimeWindow");
34694
35073
  function createRateLimitMiddleware(config) {
35074
+ if (!Number.isSafeInteger(config.requests) || config.requests <= 0) {
35075
+ throw new TypeError("Rate limit requests must be a positive safe integer.");
35076
+ }
34695
35077
  const windowMs = parseTimeWindow(config.window);
34696
35078
  const storage = config.storage || defaultRateLimitStorage;
35079
+ assertAtomicRateLimitStorage(storage);
34697
35080
  return async (ctx, next) => {
34698
35081
  const key = config.keyGenerator ? config.keyGenerator(ctx) : `${ctx.request.socket.remoteAddress}:${ctx.pathname}`;
35082
+ const current = await storage.increment(key, windowMs);
35083
+ assertRateLimitIncrementResult(current);
34699
35084
  const now2 = Date.now();
34700
- const ttlSeconds = Math.ceil(windowMs / 1e3);
34701
- const record = await storage.get(key);
34702
- if (record && now2 > record.resetAt) {
34703
- await storage.delete(key);
34704
- }
34705
- const current = await storage.get(key);
34706
- if (!current) {
34707
- await storage.set(
34708
- key,
34709
- {
34710
- count: 1,
34711
- resetAt: now2 + windowMs
34712
- },
34713
- ttlSeconds
34714
- );
34715
- return next();
34716
- }
34717
- if (current.count >= config.requests) {
35085
+ const resetIn = Math.max(1, Math.ceil((current.resetAt - now2) / 1e3));
35086
+ const remaining = Math.max(0, config.requests - current.count);
35087
+ setRateLimitHeaders(ctx, config.requests, remaining, resetIn, Math.ceil(windowMs / 1e3));
35088
+ if (current.count > config.requests) {
35089
+ setMiddlewareResponseHeader(ctx, "Retry-After", String(resetIn));
34718
35090
  if (config.onLimit) {
34719
35091
  const result = await config.onLimit(ctx);
34720
- if (result) return;
35092
+ if (result) return result;
34721
35093
  }
34722
35094
  ctx.json(
34723
35095
  {
34724
35096
  error: "Rate limit exceeded",
34725
- retryAfter: Math.ceil((current.resetAt - now2) / 1e3)
35097
+ retryAfter: resetIn
34726
35098
  },
34727
35099
  429
34728
35100
  );
34729
35101
  return;
34730
35102
  }
34731
- current.count++;
34732
- await storage.set(key, current, ttlSeconds);
34733
35103
  return next();
34734
35104
  };
34735
35105
  }
34736
35106
  __name(createRateLimitMiddleware, "createRateLimitMiddleware");
35107
+ function assertAtomicRateLimitStorage(storage) {
35108
+ if (!storage || typeof storage.increment !== "function") {
35109
+ throw new UnsupportedRateLimitStorageError();
35110
+ }
35111
+ }
35112
+ __name(assertAtomicRateLimitStorage, "assertAtomicRateLimitStorage");
35113
+ function assertRateLimitIncrementResult(result) {
35114
+ if (!result || !Number.isSafeInteger(result.count) || result.count <= 0 || !Number.isFinite(result.resetAt) || result.resetAt <= 0) {
35115
+ throw new TypeError(
35116
+ "RateLimitStorage.increment() must return a positive integer count and a resetAt timestamp."
35117
+ );
35118
+ }
35119
+ }
35120
+ __name(assertRateLimitIncrementResult, "assertRateLimitIncrementResult");
35121
+ function setRateLimitHeaders(ctx, limit, remaining, resetIn, windowSeconds) {
35122
+ setMiddlewareResponseHeader(ctx, "RateLimit-Policy", `"farm";q=${limit};w=${windowSeconds}`);
35123
+ setMiddlewareResponseHeader(ctx, "RateLimit", `"farm";r=${remaining};t=${resetIn}`);
35124
+ }
35125
+ __name(setRateLimitHeaders, "setRateLimitHeaders");
35126
+ function setMiddlewareResponseHeader(ctx, name, value) {
35127
+ ctx.headers.set(name, value);
35128
+ if (!ctx.response.headersSent && !ctx.response.writableEnded) {
35129
+ ctx.response.setHeader(name, value);
35130
+ }
35131
+ }
35132
+ __name(setMiddlewareResponseHeader, "setMiddlewareResponseHeader");
34737
35133
  function matchPattern(pattern, pathname) {
34738
35134
  if (pattern instanceof RegExp) {
34739
35135
  return pattern.test(pathname);
@@ -34883,6 +35279,15 @@ var _MiddlewareChainImpl = class _MiddlewareChainImpl {
34883
35279
  __name(_MiddlewareChainImpl, "MiddlewareChainImpl");
34884
35280
  var MiddlewareChainImpl = _MiddlewareChainImpl;
34885
35281
  async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage) {
35282
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
35283
+ throw new TypeError("Rate limit must be a positive safe integer.");
35284
+ }
35285
+ assertAtomicRateLimitStorage(storage);
35286
+ if (typeof storage.get !== "function") {
35287
+ throw new TypeError(
35288
+ "getRateLimitStatus() requires a RateLimitStorage adapter that implements get(key)."
35289
+ );
35290
+ }
34886
35291
  const record = await storage.get(key);
34887
35292
  if (!record) {
34888
35293
  return {
@@ -34894,6 +35299,7 @@ async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage)
34894
35299
  isLimited: false
34895
35300
  };
34896
35301
  }
35302
+ assertRateLimitIncrementResult(record);
34897
35303
  const now2 = Date.now();
34898
35304
  if (record.resetAt && now2 > record.resetAt) {
34899
35305
  return {
@@ -34914,9 +35320,6 @@ async function getRateLimitStatus(key, limit, storage = defaultRateLimitStorage)
34914
35320
  const remainingMs = record.resetAt - now2;
34915
35321
  resetIn = remainingMs > 0 ? Math.ceil(remainingMs / 1e3) : null;
34916
35322
  resetAt = new Date(record.resetAt);
34917
- } else if (storage.ttl) {
34918
- resetIn = await storage.ttl(key);
34919
- resetAt = resetIn ? new Date(now2 + resetIn * 1e3) : null;
34920
35323
  }
34921
35324
  return {
34922
35325
  requests,
@@ -35722,6 +36125,8 @@ init_image_types();
35722
36125
  init_server_action_security();
35723
36126
  init_request_bridge();
35724
36127
  init_cache();
36128
+ init_server_fn_error();
36129
+ init_server_fn_error();
35725
36130
  var FARM_SERVER_FN_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn");
35726
36131
  var UNSAFE_FORM_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
35727
36132
  function createServerMiddleware(options) {
@@ -35744,6 +36149,8 @@ function createServerFn(options) {
35744
36149
  throw new TypeError("createServerFn requires a handler function");
35745
36150
  }
35746
36151
  const middleware2 = resolveServerFnMiddleware(options.middleware);
36152
+ const errors = normalizeServerFnErrors(options.errors);
36153
+ const error = createServerFnErrorHandler(errors);
35747
36154
  const serverFn = /* @__PURE__ */ __name(async (value) => {
35748
36155
  const formData = isFormData2(value) ? value : void 0;
35749
36156
  const rawInput = formData ? formDataToObject2(formData) : value;
@@ -35761,7 +36168,7 @@ function createServerFn(options) {
35761
36168
  let resolvedContext = Object.freeze(/* @__PURE__ */ Object.create(null));
35762
36169
  const result = await runServerFnMiddleware(middleware2, handlerContext, async (context) => {
35763
36170
  resolvedContext = context.context;
35764
- return options.handler(context);
36171
+ return options.handler({ ...context, error });
35765
36172
  });
35766
36173
  const parsedResult = await _parseServerFnSchema(options.output, result, "output");
35767
36174
  if (options.invalidates) {
@@ -35791,6 +36198,10 @@ function createServerFn(options) {
35791
36198
  value: options.output,
35792
36199
  enumerable: false
35793
36200
  },
36201
+ __farmServerFnError: {
36202
+ value: void 0,
36203
+ enumerable: false
36204
+ },
35794
36205
  __farmServerFnMiddleware: {
35795
36206
  value: middleware2,
35796
36207
  enumerable: false
@@ -35829,6 +36240,78 @@ async function runServerFnMiddleware(middleware2, handlerContext, handler) {
35829
36240
  return dispatch(0, Object.freeze(/* @__PURE__ */ Object.create(null)));
35830
36241
  }
35831
36242
  __name(runServerFnMiddleware, "runServerFnMiddleware");
36243
+ function normalizeServerFnErrors(definitions) {
36244
+ if (definitions === void 0) return Object.freeze({});
36245
+ if (!isPlainServerFnObject(definitions)) {
36246
+ throw new TypeError("createServerFn errors must be an object");
36247
+ }
36248
+ const normalized = /* @__PURE__ */ Object.create(null);
36249
+ for (const [code, definition] of Object.entries(definitions)) {
36250
+ if (!code.trim()) {
36251
+ throw new TypeError("Server function error codes cannot be empty");
36252
+ }
36253
+ if (!definition || typeof definition !== "object") {
36254
+ throw new TypeError(`Server function error "${code}" must be an object`);
36255
+ }
36256
+ if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
36257
+ throw new TypeError(
36258
+ `Server function error "${code}" status must be an integer between 400 and 599`
36259
+ );
36260
+ }
36261
+ if (!definition.data || typeof definition.data.parse !== "function" && typeof definition.data.safeParse !== "function") {
36262
+ throw new TypeError(
36263
+ `Server function error "${code}" data must provide synchronous parse() or safeParse()`
36264
+ );
36265
+ }
36266
+ if (definition.message !== void 0 && typeof definition.message !== "string") {
36267
+ throw new TypeError(`Server function error "${code}" message must be a string`);
36268
+ }
36269
+ normalized[code] = Object.freeze({ ...definition });
36270
+ }
36271
+ return Object.freeze(normalized);
36272
+ }
36273
+ __name(normalizeServerFnErrors, "normalizeServerFnErrors");
36274
+ function createServerFnErrorHandler(definitions) {
36275
+ return ((code, data) => {
36276
+ const definition = definitions[code];
36277
+ if (!definition) {
36278
+ throw new TypeError(`Server function error "${code}" is not declared`);
36279
+ }
36280
+ const parsed = parseServerFnFailureData(code, definition.data, data);
36281
+ throw new ServerFnFailure(code, parsed, {
36282
+ status: definition.status,
36283
+ message: definition.message ?? "Server function failed"
36284
+ });
36285
+ });
36286
+ }
36287
+ __name(createServerFnErrorHandler, "createServerFnErrorHandler");
36288
+ function parseServerFnFailureData(code, schema, value) {
36289
+ if (typeof schema.safeParse === "function") {
36290
+ const result2 = schema.safeParse(value);
36291
+ if (isPromiseLike2(result2)) {
36292
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
36293
+ }
36294
+ return unwrapSafeParseResult(result2);
36295
+ }
36296
+ const result = schema.parse(value);
36297
+ if (isPromiseLike2(result)) {
36298
+ throw new TypeError(`Server function error "${code}" data schema must parse synchronously`);
36299
+ }
36300
+ return result;
36301
+ }
36302
+ __name(parseServerFnFailureData, "parseServerFnFailureData");
36303
+ function isPlainServerFnObject(value) {
36304
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
36305
+ const prototype = Object.getPrototypeOf(value);
36306
+ return prototype === Object.prototype || prototype === null;
36307
+ }
36308
+ __name(isPlainServerFnObject, "isPlainServerFnObject");
36309
+ function isPromiseLike2(value) {
36310
+ return Boolean(
36311
+ value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function"
36312
+ );
36313
+ }
36314
+ __name(isPromiseLike2, "isPromiseLike");
35832
36315
  function resolveServerFnMiddleware(middleware2) {
35833
36316
  const resolved = [];
35834
36317
  const seen = /* @__PURE__ */ new Set();
@@ -36441,6 +36924,7 @@ init_fonts();
36441
36924
 
36442
36925
  // src/route-runtime-manifest.ts
36443
36926
  var import_path10 = __toESM(require("path"));
36927
+ init_deployment();
36444
36928
  init_route_runtime();
36445
36929
  init_ssg();
36446
36930
  var FARM_ROUTE_RUNTIME_MANIFEST = "route-runtime-manifest.json";
@@ -36501,10 +36985,15 @@ async function writeFarmRouteRuntimeManifest(directory, manifest) {
36501
36985
  }
36502
36986
  __name(writeFarmRouteRuntimeManifest, "writeFarmRouteRuntimeManifest");
36503
36987
  function validateFarmRouteRuntimeDeployment(manifest, preset) {
36504
- const runtime = getPresetRuntime(preset);
36988
+ const runtime = getFarmPresetRuntime(preset);
36505
36989
  const warnings = /* @__PURE__ */ new Set();
36506
36990
  for (const route2 of manifest.routes) {
36507
36991
  if (route2.rendering === "static") continue;
36992
+ if (runtime === "unknown" && route2.runtime !== "auto") {
36993
+ warnings.add(
36994
+ `Preset "${preset}" has an unknown runtime, so Farm could not verify routes that explicitly require node or edge.`
36995
+ );
36996
+ }
36508
36997
  if (runtime !== "unknown" && route2.runtime !== "auto" && route2.runtime !== runtime) {
36509
36998
  throw new Error(
36510
36999
  `Route "${route2.pattern}" requires the ${route2.runtime} runtime, but preset "${preset}" emits ${runtime} functions. Choose a compatible preset or change the route runtime.`
@@ -36524,16 +37013,6 @@ function validateFarmRouteRuntimeDeployment(manifest, preset) {
36524
37013
  return { runtime, warnings: Array.from(warnings) };
36525
37014
  }
36526
37015
  __name(validateFarmRouteRuntimeDeployment, "validateFarmRouteRuntimeDeployment");
36527
- function getPresetRuntime(preset) {
36528
- if (preset === "cloudflare" || preset === "cloudflare-pages" || preset === "cloudflare-module" || preset === "netlify-edge" || preset === "vercel-edge" || preset === "deno") {
36529
- return "edge";
36530
- }
36531
- if (preset === "node-server" || preset === "vercel" || preset === "netlify" || preset === "aws-lambda" || preset === "azure" || preset === "firebase" || preset === "bun") {
36532
- return "node";
36533
- }
36534
- return "unknown";
36535
- }
36536
- __name(getPresetRuntime, "getPresetRuntime");
36537
37016
  function normalizeManifestSource(root, modulePath) {
36538
37017
  const queryIndex = modulePath.indexOf("?");
36539
37018
  const filePath = queryIndex === -1 ? modulePath : modulePath.slice(0, queryIndex);
@@ -36803,6 +37282,7 @@ __name(withVite5TransformContext, "withVite5TransformContext");
36803
37282
 
36804
37283
  // src/nitro/universal-build.ts
36805
37284
  init_font_vite();
37285
+ init_vite_config();
36806
37286
  var import_meta = {};
36807
37287
  function preloadFarmNitroRuntime() {
36808
37288
  return import("nitro").then(
@@ -39196,9 +39676,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
39196
39676
  postcss: postcssConfigDir
39197
39677
  } : void 0,
39198
39678
  resolve: {
39199
- alias: {
39200
- "@": import_path12.default.resolve(root, "src")
39201
- },
39679
+ alias: createFarmSourceAlias(root, config.srcDir),
39202
39680
  // Programmatic route wrappers are created inside @farm.js/core. Resolve
39203
39681
  // their React imports from the application so React 18/19 elements and
39204
39682
  // the selected server renderer always share the same runtime instance.
@@ -42856,6 +43334,9 @@ async function createProjectModuleServer(createViteServer, config, root) {
42856
43334
  middlewareMode: true,
42857
43335
  hmr: false
42858
43336
  },
43337
+ resolve: {
43338
+ alias: createFarmSourceAlias(root, config.srcDir)
43339
+ },
42859
43340
  optimizeDeps: {
42860
43341
  noDiscovery: true
42861
43342
  },
@@ -44526,6 +45007,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44526
45007
  FARM_DEVTOOLS_LAUNCH_PARAM,
44527
45008
  FARM_DEVTOOLS_PATH,
44528
45009
  FARM_INTEGRATION_INTERNAL_DISPATCH_CONTEXT_KEY,
45010
+ FARM_SERVER_FN_FAILURE_SYMBOL,
44529
45011
  FARM_SERVER_FN_SYMBOL,
44530
45012
  FARM_SERVER_QUERY_SYMBOL,
44531
45013
  FarmClientPluginManager,
@@ -44548,7 +45030,10 @@ __name(decodeCookiePart, "decodeCookiePart");
44548
45030
  PluginManager,
44549
45031
  SPARouter,
44550
45032
  ScalarAPIDocumentation,
45033
+ ServerActionError,
44551
45034
  ServerActionRequestError,
45035
+ ServerFnFailure,
45036
+ UnsupportedRateLimitStorageError,
44552
45037
  _parseServerFnSchema,
44553
45038
  _runWithAfterNodeResponse,
44554
45039
  _runWithAfterRequest,
@@ -44637,6 +45122,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44637
45122
  createServerAPIClient,
44638
45123
  createServerActionRequestErrorResponse,
44639
45124
  createServerFn,
45125
+ createServerFnTransportError,
44640
45126
  createServerMiddleware,
44641
45127
  createServerOnlyFn,
44642
45128
  createServerQuery,
@@ -44690,6 +45176,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44690
45176
  getFarmDocsRouteTypeEntries,
44691
45177
  getFarmIntegrationPluginServerRuntime,
44692
45178
  getFarmLayerAliases,
45179
+ getFarmPresetRuntime,
44693
45180
  getFarmRedirectError,
44694
45181
  getFarmRequestDeploymentId,
44695
45182
  getFarmResponseDeploymentId,
@@ -44753,6 +45240,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44753
45240
  isProgrammaticRouteManifest,
44754
45241
  isProgrammaticRoutesFileName,
44755
45242
  isSSGModule,
45243
+ isServerFnFailure,
44756
45244
  isWebResponse,
44757
45245
  jsonStream,
44758
45246
  layout,
@@ -44770,6 +45258,7 @@ __name(decodeCookiePart, "decodeCookiePart");
44770
45258
  matchRegisteredIntegrationRoute,
44771
45259
  matchRoute,
44772
45260
  matchSSGPage,
45261
+ memoryRateLimitStorage,
44773
45262
  memoryStorage,
44774
45263
  mergeFarmRouteRuntimeConfigs,
44775
45264
  mergeScheduledTasks,