@farm.js/core 0.1.0-beta.1 → 0.1.0-beta.3

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 (230) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-runtime.d.mts +1 -1
  3. package/dist/agent-runtime.d.ts +1 -1
  4. package/dist/api/route-manager.cjs +97 -5
  5. package/dist/api/route-manager.cjs.map +1 -1
  6. package/dist/api/route-manager.d.mts +3 -2
  7. package/dist/api/route-manager.d.ts +3 -2
  8. package/dist/api/route-manager.mjs +8 -8
  9. package/dist/api/runtime.cjs +441 -5
  10. package/dist/api/runtime.cjs.map +1 -1
  11. package/dist/api/runtime.d.mts +2 -16
  12. package/dist/api/runtime.d.ts +2 -16
  13. package/dist/api/runtime.mjs +7 -1
  14. package/dist/api.cjs +579 -263
  15. package/dist/api.cjs.map +1 -1
  16. package/dist/api.d.mts +4 -147
  17. package/dist/api.d.ts +4 -147
  18. package/dist/api.mjs +30 -20
  19. package/dist/{app-BiX4qb-d.d.mts → app-BB3Iu3xh.d.mts} +2 -2
  20. package/dist/{app-CFRNJXP1.d.ts → app-DOKxo-LH.d.ts} +2 -2
  21. package/dist/app-markdown.cjs +1 -1
  22. package/dist/app-markdown.cjs.map +1 -1
  23. package/dist/app-markdown.d.mts +1 -1
  24. package/dist/app-markdown.d.ts +1 -1
  25. package/dist/app-markdown.mjs +1 -1
  26. package/dist/cache.cjs +19 -0
  27. package/dist/cache.cjs.map +1 -1
  28. package/dist/cache.d.mts +21 -1
  29. package/dist/cache.d.ts +21 -1
  30. package/dist/cache.mjs +5 -3
  31. package/dist/{chunk-QF4PHCMA.mjs → chunk-2ED5Q2GH.mjs} +3 -3
  32. package/dist/chunk-2ED5Q2GH.mjs.map +1 -0
  33. package/dist/{chunk-GZP5W4K3.mjs → chunk-32W4QEJP.mjs} +1 -1
  34. package/dist/chunk-32W4QEJP.mjs.map +1 -0
  35. package/dist/{chunk-AGS7UJ52.mjs → chunk-45LKHSHJ.mjs} +2 -2
  36. package/dist/{chunk-TU4YJICB.mjs → chunk-5FW6PQ3J.mjs} +1 -1
  37. package/dist/{chunk-TU4YJICB.mjs.map → chunk-5FW6PQ3J.mjs.map} +1 -1
  38. package/dist/{chunk-TRORP7E4.mjs → chunk-5QH4IKY3.mjs} +2 -2
  39. package/dist/{chunk-RKI6TN3A.mjs → chunk-6VS6CKAV.mjs} +2 -2
  40. package/dist/chunk-6VS6CKAV.mjs.map +1 -0
  41. package/dist/{chunk-25D7G34K.mjs → chunk-6WXJ54TC.mjs} +4 -4
  42. package/dist/{chunk-3QJO55ZF.mjs → chunk-BIOIOWXZ.mjs} +5 -3
  43. package/dist/{chunk-3QJO55ZF.mjs.map → chunk-BIOIOWXZ.mjs.map} +1 -1
  44. package/dist/{chunk-QFQRHRZS.mjs → chunk-C33RALN7.mjs} +75 -11
  45. package/dist/chunk-C33RALN7.mjs.map +1 -0
  46. package/dist/{chunk-B6N4ZB2H.mjs → chunk-CSU4KJJF.mjs} +3 -3
  47. package/dist/{chunk-JN3UU635.mjs → chunk-EJ7T4TPB.mjs} +2 -2
  48. package/dist/chunk-EJ7T4TPB.mjs.map +1 -0
  49. package/dist/{chunk-ZJQNATYV.mjs → chunk-FRPWCMMG.mjs} +3 -3
  50. package/dist/chunk-FRPWCMMG.mjs.map +1 -0
  51. package/dist/{chunk-PRNYWD7K.mjs → chunk-G5I34UA6.mjs} +67 -239
  52. package/dist/chunk-G5I34UA6.mjs.map +1 -0
  53. package/dist/{chunk-QM6VV26B.mjs → chunk-GQVGIUSN.mjs} +3 -3
  54. package/dist/{chunk-QM6VV26B.mjs.map → chunk-GQVGIUSN.mjs.map} +1 -1
  55. package/dist/{chunk-UREJA4GZ.mjs → chunk-GXASWWJU.mjs} +1 -1
  56. package/dist/{chunk-UREJA4GZ.mjs.map → chunk-GXASWWJU.mjs.map} +1 -1
  57. package/dist/{chunk-4PTK6KT4.mjs → chunk-GZWT6VI5.mjs} +22 -4
  58. package/dist/chunk-GZWT6VI5.mjs.map +1 -0
  59. package/dist/{chunk-JLWMCADZ.mjs → chunk-HZYXGV4K.mjs} +2 -2
  60. package/dist/chunk-JNYVN7YP.mjs +10 -0
  61. package/dist/chunk-JNYVN7YP.mjs.map +1 -0
  62. package/dist/{chunk-YHU7SS6L.mjs → chunk-LG3YINQN.mjs} +11 -11
  63. package/dist/chunk-LWMGIEJA.mjs +593 -0
  64. package/dist/chunk-LWMGIEJA.mjs.map +1 -0
  65. package/dist/{chunk-HXP3ZSPC.mjs → chunk-MH6FKW2I.mjs} +3 -3
  66. package/dist/{chunk-O3HADRW6.mjs → chunk-MIUW47JX.mjs} +2 -2
  67. package/dist/{chunk-O3HADRW6.mjs.map → chunk-MIUW47JX.mjs.map} +1 -1
  68. package/dist/{chunk-6XDUHOEM.mjs → chunk-NRRFGX45.mjs} +3 -3
  69. package/dist/{chunk-G3B5BRDY.mjs → chunk-OHC6VCDI.mjs} +24 -25
  70. package/dist/{chunk-G3B5BRDY.mjs.map → chunk-OHC6VCDI.mjs.map} +1 -1
  71. package/dist/{chunk-S2XHZS7W.mjs → chunk-QGQX7SFC.mjs} +2 -2
  72. package/dist/chunk-QGQX7SFC.mjs.map +1 -0
  73. package/dist/{chunk-TXCFGOHW.mjs → chunk-SHRJG6OG.mjs} +25 -1
  74. package/dist/chunk-SHRJG6OG.mjs.map +1 -0
  75. package/dist/{chunk-UHE2TTLK.mjs → chunk-T543TMFY.mjs} +8 -8
  76. package/dist/chunk-T543TMFY.mjs.map +1 -0
  77. package/dist/{chunk-SXZTEK3V.mjs → chunk-UXUAWNO5.mjs} +2 -2
  78. package/dist/{chunk-Y2OJJD7R.mjs → chunk-XIVV5IWN.mjs} +7 -9
  79. package/dist/chunk-XIVV5IWN.mjs.map +1 -0
  80. package/dist/{chunk-CHFHNEMO.mjs → chunk-XJSHJN4M.mjs} +41 -42
  81. package/dist/chunk-XJSHJN4M.mjs.map +1 -0
  82. package/dist/{chunk-Y7A27276.mjs → chunk-XUBZ7JI4.mjs} +178 -15
  83. package/dist/chunk-XUBZ7JI4.mjs.map +1 -0
  84. package/dist/{chunk-OYXO65LI.mjs → chunk-YW7OBE6Q.mjs} +4 -4
  85. package/dist/chunk-YW7OBE6Q.mjs.map +1 -0
  86. package/dist/{chunk-SOU3Q3ZA.mjs → chunk-ZZ57EH5Z.mjs} +1 -1
  87. package/dist/chunk-ZZ57EH5Z.mjs.map +1 -0
  88. package/dist/{client-D_yUjVhe.d.mts → client-DiViK9yK.d.mts} +33 -7
  89. package/dist/{client-Dkc03WP8.d.ts → client-DpEBJbts.d.ts} +33 -7
  90. package/dist/{client-plugins-BZnpeTGA.d.ts → client-plugins-CTnsZz_A.d.ts} +1 -0
  91. package/dist/{client-plugins-g4bzuCmo.d.mts → client-plugins-Cnr0D3kk.d.mts} +1 -0
  92. package/dist/client-plugins.d.mts +1 -1
  93. package/dist/client-plugins.d.ts +1 -1
  94. package/dist/client.cjs +302 -54
  95. package/dist/client.cjs.map +1 -1
  96. package/dist/client.d.mts +54 -2
  97. package/dist/client.d.ts +54 -2
  98. package/dist/client.mjs +20 -16
  99. package/dist/config.d.mts +1 -1
  100. package/dist/config.d.ts +1 -1
  101. package/dist/cron.cjs.map +1 -1
  102. package/dist/cron.mjs +1 -1
  103. package/dist/{devtools-AE4RVXCM.mjs → devtools-HE4FTUDN.mjs} +10 -10
  104. package/dist/{devtools-client-6WPY2AQU.mjs → devtools-client-3XRTBND5.mjs} +2 -11
  105. package/dist/devtools-client-3XRTBND5.mjs.map +1 -0
  106. package/dist/docs.cjs +3 -1
  107. package/dist/docs.cjs.map +1 -1
  108. package/dist/docs.mjs +10 -10
  109. package/dist/i18n/server.cjs +2 -2
  110. package/dist/i18n/server.cjs.map +1 -1
  111. package/dist/i18n/server.mjs +1 -1
  112. package/dist/index.cjs +791 -317
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.d.mts +11 -11
  115. package/dist/index.d.ts +11 -11
  116. package/dist/index.mjs +125 -110
  117. package/dist/index.mjs.map +1 -1
  118. package/dist/integrations.d.mts +1 -1
  119. package/dist/integrations.d.ts +1 -1
  120. package/dist/internal/build-runtime.cjs +162 -60
  121. package/dist/internal/build-runtime.cjs.map +1 -1
  122. package/dist/internal/build-runtime.d.mts +3 -3
  123. package/dist/internal/build-runtime.d.ts +3 -3
  124. package/dist/internal/build-runtime.mjs +26 -25
  125. package/dist/internal/client-runtime.cjs.map +1 -1
  126. package/dist/internal/client-runtime.mjs +1 -1
  127. package/dist/internal/config-runtime.cjs +1 -1
  128. package/dist/internal/config-runtime.cjs.map +1 -1
  129. package/dist/internal/config-runtime.d.mts +2 -2
  130. package/dist/internal/config-runtime.d.ts +2 -2
  131. package/dist/internal/config-runtime.mjs +9 -9
  132. package/dist/internal/production-runtime.cjs +3 -3
  133. package/dist/internal/production-runtime.cjs.map +1 -1
  134. package/dist/internal/production-runtime.d.mts +3 -3
  135. package/dist/internal/production-runtime.d.ts +3 -3
  136. package/dist/internal/production-runtime.mjs +8 -8
  137. package/dist/{metadata-C9NZxMDW.d.mts → metadata-Dp8AdvsB.d.mts} +1 -1
  138. package/dist/{metadata-DAXRaOHx.d.ts → metadata-eoVmHoyv.d.ts} +1 -1
  139. package/dist/middleware.cjs +2 -2
  140. package/dist/middleware.cjs.map +1 -1
  141. package/dist/middleware.d.mts +3 -3
  142. package/dist/middleware.d.ts +3 -3
  143. package/dist/middleware.mjs +3 -3
  144. package/dist/navigation.cjs.map +1 -1
  145. package/dist/navigation.mjs +3 -3
  146. package/dist/{nitro-KME62MWG.mjs → nitro-QO5LV6QK.mjs} +11 -13
  147. package/dist/{nitro-KME62MWG.mjs.map → nitro-QO5LV6QK.mjs.map} +1 -1
  148. package/dist/plugin.cjs +119 -39
  149. package/dist/plugin.cjs.map +1 -1
  150. package/dist/plugin.d.mts +1 -1
  151. package/dist/plugin.d.ts +1 -1
  152. package/dist/plugin.mjs +22 -21
  153. package/dist/{production-runtime-DRkCHUvJ.d.ts → production-runtime-BqTnUTai.d.ts} +1 -1
  154. package/dist/{production-runtime-flrjp_nC.d.mts → production-runtime-DtDdG9fc.d.mts} +1 -1
  155. package/dist/routes.cjs.map +1 -1
  156. package/dist/routes.d.mts +1 -1
  157. package/dist/routes.d.ts +1 -1
  158. package/dist/routes.mjs +4 -4
  159. package/dist/runtime-C1B7pSGT.d.mts +207 -0
  160. package/dist/runtime-CdPHt0bv.d.ts +207 -0
  161. package/dist/server-action-security.cjs.map +1 -1
  162. package/dist/server-action-security.mjs +2 -2
  163. package/dist/server-fn-client.cjs.map +1 -1
  164. package/dist/server-fn-client.mjs +1 -1
  165. package/dist/server-fn.cjs.map +1 -1
  166. package/dist/server-fn.mjs +3 -3
  167. package/dist/server-plugins.d.mts +2 -2
  168. package/dist/server-plugins.d.ts +2 -2
  169. package/dist/server-query-client.cjs.map +1 -1
  170. package/dist/server-query-client.mjs +4 -4
  171. package/dist/server-query.cjs.map +1 -1
  172. package/dist/server-query.mjs +5 -5
  173. package/dist/server.cjs +148 -43
  174. package/dist/server.cjs.map +1 -1
  175. package/dist/server.d.mts +6 -6
  176. package/dist/server.d.ts +6 -6
  177. package/dist/server.mjs +36 -31
  178. package/dist/server.mjs.map +1 -1
  179. package/dist/testing.cjs +95 -5
  180. package/dist/testing.cjs.map +1 -1
  181. package/dist/testing.d.mts +3 -3
  182. package/dist/testing.d.ts +3 -3
  183. package/dist/testing.mjs +18 -18
  184. package/dist/{utils-DOXXivjL.d.mts → utils-8USa5BiY.d.mts} +1 -1
  185. package/dist/{utils-DA1yo54_.d.ts → utils-DKJb6K6G.d.ts} +1 -1
  186. package/dist/version.cjs +36 -0
  187. package/dist/version.cjs.map +1 -0
  188. package/dist/version.d.mts +3 -0
  189. package/dist/version.d.ts +3 -0
  190. package/dist/version.mjs +8 -0
  191. package/dist/version.mjs.map +1 -0
  192. package/dist/vite.cjs +126 -40
  193. package/dist/vite.cjs.map +1 -1
  194. package/dist/vite.d.mts +1 -1
  195. package/dist/vite.d.ts +1 -1
  196. package/dist/vite.mjs +22 -21
  197. package/dist/workflows.cjs +6 -8
  198. package/dist/workflows.cjs.map +1 -1
  199. package/dist/workflows.mjs +1 -1
  200. package/package.json +12 -5
  201. package/types/client.d.ts +136 -13
  202. package/dist/chunk-4PTK6KT4.mjs.map +0 -1
  203. package/dist/chunk-CHFHNEMO.mjs.map +0 -1
  204. package/dist/chunk-EVGBEZDF.mjs +0 -215
  205. package/dist/chunk-EVGBEZDF.mjs.map +0 -1
  206. package/dist/chunk-GZP5W4K3.mjs.map +0 -1
  207. package/dist/chunk-JN3UU635.mjs.map +0 -1
  208. package/dist/chunk-OYXO65LI.mjs.map +0 -1
  209. package/dist/chunk-PRNYWD7K.mjs.map +0 -1
  210. package/dist/chunk-QF4PHCMA.mjs.map +0 -1
  211. package/dist/chunk-QFQRHRZS.mjs.map +0 -1
  212. package/dist/chunk-RKI6TN3A.mjs.map +0 -1
  213. package/dist/chunk-S2XHZS7W.mjs.map +0 -1
  214. package/dist/chunk-SOU3Q3ZA.mjs.map +0 -1
  215. package/dist/chunk-TXCFGOHW.mjs.map +0 -1
  216. package/dist/chunk-UHE2TTLK.mjs.map +0 -1
  217. package/dist/chunk-Y2OJJD7R.mjs.map +0 -1
  218. package/dist/chunk-Y7A27276.mjs.map +0 -1
  219. package/dist/chunk-ZJQNATYV.mjs.map +0 -1
  220. package/dist/devtools-client-6WPY2AQU.mjs.map +0 -1
  221. /package/dist/{chunk-AGS7UJ52.mjs.map → chunk-45LKHSHJ.mjs.map} +0 -0
  222. /package/dist/{chunk-TRORP7E4.mjs.map → chunk-5QH4IKY3.mjs.map} +0 -0
  223. /package/dist/{chunk-25D7G34K.mjs.map → chunk-6WXJ54TC.mjs.map} +0 -0
  224. /package/dist/{chunk-B6N4ZB2H.mjs.map → chunk-CSU4KJJF.mjs.map} +0 -0
  225. /package/dist/{chunk-JLWMCADZ.mjs.map → chunk-HZYXGV4K.mjs.map} +0 -0
  226. /package/dist/{chunk-YHU7SS6L.mjs.map → chunk-LG3YINQN.mjs.map} +0 -0
  227. /package/dist/{chunk-HXP3ZSPC.mjs.map → chunk-MH6FKW2I.mjs.map} +0 -0
  228. /package/dist/{chunk-6XDUHOEM.mjs.map → chunk-NRRFGX45.mjs.map} +0 -0
  229. /package/dist/{chunk-SXZTEK3V.mjs.map → chunk-UXUAWNO5.mjs.map} +0 -0
  230. /package/dist/{devtools-AE4RVXCM.mjs.map → devtools-HE4FTUDN.mjs.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/nitro/index.ts"],"sourcesContent":["import type { NitroConfig } from \"nitro/config\";\nimport type { ResolvedFarmConfig } from \"../config\";\nimport type { RouteManager } from \"../routing/route-manager\";\nimport type { APIRouteManager } from \"../api/route-manager\";\nimport type { ServerRenderer } from \"../server/renderer\";\nimport { createNitroAPIHandler } from \"./api-handler\";\nimport { createNitroSSRHandler } from \"./ssr-handler\";\nimport path from \"path\";\nimport { prepareFarmWorkflowsForNitro } from \"../workflows\";\nimport {\n createFarmCronCloudflareConfig,\n mergeScheduledTasks,\n prepareFarmCronForNitro,\n} from \"../cron\";\nimport { routeRulesToNitroRouteRules } from \"../route-rules\";\n\n/**\n * Create Nitro configuration for Farm.js\n * Based on https://nitro.build/config\n */\nexport async function createNitroConfig(\n config: ResolvedFarmConfig,\n routeManager: RouteManager,\n apiRouteManager: APIRouteManager,\n serverRenderer: ServerRenderer,\n preset = \"node-server\",\n): Promise<NitroConfig> {\n const root = config.root || process.cwd();\n const srcDir = config.srcDir || \"src\";\n const distDir = \".farm\";\n // Nitro build directory - where Nitro does its work (temporary)\n // We use .nitro as a working directory, but ensure output goes to .farm/.output\n const nitroBuildDir = path.join(root, distDir, \".nitro\");\n // Final output directory - where the deployable output goes\n // This MUST be .farm/.output (not .nitro/.output) for consistency\n const outputDir = path.join(root, distDir, \".output\");\n // Server directory for handlers (inside build dir, will be copied to output)\n const serverDir = path.join(nitroBuildDir, \"server\");\n\n // Ensure Nitro doesn't create its own .output inside .nitro\n // By explicitly setting output.dir, Nitro will use our specified directory\n\n // Create server directory structure for Nitro to discover routes\n // According to Nitro docs: https://nitro.build/deploy/providers/vercel\n // Routes should be in server/api/[...].ts and server/routes/[...].ts\n const { mkdir, writeFile } = await import(\"fs/promises\");\n await mkdir(serverDir, { recursive: true });\n await mkdir(path.join(serverDir, \"api\"), { recursive: true });\n await mkdir(path.join(serverDir, \"routes\"), { recursive: true });\n const farmWorkflows = await prepareFarmWorkflowsForNitro({\n ...config,\n distDir,\n });\n const farmCron = await prepareFarmCronForNitro({\n ...config,\n distDir,\n });\n const scheduledTasks = mergeScheduledTasks(farmWorkflows.scheduledTasks, farmCron.scheduledTasks);\n const cloudflareCronConfig = createFarmCronCloudflareConfig(farmCron.jobs);\n\n // Create a runtime registry file to store route managers\n // This will be populated at runtime through Nitro hooks\n const registryFile = path.join(serverDir, \"farm-registry.ts\");\n\n // Serialize route paths for SSR module loading\n const routePaths: Record<string, string> = {};\n for (const [pattern, entry] of routeManager.getRoutes()) {\n const bundledPath = entry.modulePath\n .replace(/.*\\/src\\/app\\//, \"\")\n .replace(/\\.(tsx?|jsx?)$/, \".js\");\n routePaths[pattern] = bundledPath;\n }\n\n // Load client manifest path for reference\n const clientManifestPath = path.join(root, distDir, \"client\", \"farm-client-manifest.json\");\n\n await writeFile(\n registryFile,\n `\n// Auto-generated by Farm.js\n// Runtime registry for route managers and renderers\nexport const farmRegistry: {\n apiRouteManager?: any;\n routeManager?: any;\n serverRenderer?: any;\n env?: any;\n deploymentId?: string;\n basePath?: string;\n clientManifest?: any;\n routePaths?: Record<string, string>;\n} = {\n env: ${JSON.stringify(config.env || { server: {}, public: {} }, null, 2)},\n deploymentId: ${JSON.stringify(config.deploymentId)},\n basePath: ${JSON.stringify(config.basePath)},\n routePaths: ${JSON.stringify(routePaths, null, 2)},\n};\n`,\n \"utf-8\",\n );\n\n // Create API route handler file\n // For Vercel, Nitro expects routes in server/api/[...].ts format\n // This catch-all will handle all /api/* requests\n const apiHandlerFile = path.join(serverDir, \"api\", \"[...].ts\");\n await mkdir(path.dirname(apiHandlerFile), { recursive: true });\n await writeFile(\n apiHandlerFile,\n `\n// Auto-generated by Farm.js\n// This handler intercepts all /api/* requests\nimport { defineEventHandler, getHeaders, readBody, sendWebResponse, setResponseStatus, getRequestURL } from 'h3';\nimport type { H3Event } from 'h3';\nimport { farmRegistry } from '../farm-registry';\n\nexport default defineEventHandler(async (event: H3Event) => {\n // Get URL using H3's abstraction (works in all environments)\n const url = getRequestURL(event);\n const urlPath = url.pathname;\n \n // Only handle API routes - for Vercel, Nitro routes /api/* to this handler\n // According to https://nitro.build/deploy/providers/vercel\n // This handler should process all /api/* routes\n if (!urlPath.startsWith('/api/')) {\n // Return undefined to let Nitro's routing system handle non-API routes\n return undefined;\n }\n \n // Ensure registry is populated (lazy initialization)\n // In serverless environments, the registry needs to be initialized at runtime\n if (!farmRegistry.apiRouteManager) {\n // Try to initialize from global if available (set during build)\n if (typeof globalThis !== 'undefined' && (globalThis as any).__FARM_REGISTRY__) {\n Object.assign(farmRegistry, (globalThis as any).__FARM_REGISTRY__);\n }\n // If still not available, try the init function (if it exists)\n if (!farmRegistry.apiRouteManager && (farmRegistry as any).__INIT__) {\n (farmRegistry as any).__INIT__();\n }\n }\n \n const apiRouteManager = farmRegistry.apiRouteManager;\n if (!apiRouteManager) {\n console.error('API route manager not initialized. Registry keys:', Object.keys(farmRegistry));\n setResponseStatus(event, 500);\n return { error: 'API route manager not initialized. Please check server logs.' };\n }\n \n const startTime = Date.now();\n const method = event.method || 'GET';\n const host = url.host || 'localhost';\n \n // Log API request (only in development)\n if (process.env.NODE_ENV === 'development' || !process.env.NODE_ENV) {\n try {\n const pc = await import('picocolors');\n const log = [\n pc.default.dim('[') + pc.default.bold(pc.default.blue('FARM')) + pc.default.dim(']'),\n pc.default.dim('[') + pc.default.bold(pc.default.white(method.padEnd(3))) + pc.default.dim(']'),\n pc.default.cyan('[API]'),\n pc.default.gray(\\`\\${url.protocol}//\\${host}\\${urlPath}\\`),\n ].join(' ');\n console.log(log);\n } catch {\n // picocolors not available, use simple log\n console.log(\\`[FARM] [\\${method}] [API] \\${urlPath}\\`);\n }\n }\n \n try {\n // Convert H3 event to Web Request using H3 abstractions\n const protocol = url.protocol.replace(':', '') || 'http';\n const host = url.host || 'localhost';\n const fullUrl = url.toString();\n \n const headers = new Headers();\n const h3Headers = getHeaders(event);\n \n for (const [key, value] of Object.entries(h3Headers)) {\n if (value) {\n headers.set(key, Array.isArray(value) ? value.join(', ') : String(value));\n }\n }\n \n // Get body\n let body: string | undefined;\n const method = event.method || 'GET';\n if (method !== 'GET' && method !== 'HEAD') {\n const bodyData = await readBody(event).catch(() => undefined);\n if (bodyData) {\n body = typeof bodyData === 'string' ? bodyData : JSON.stringify(bodyData);\n }\n }\n \n // Create Web Request\n const request = new Request(fullUrl, {\n method,\n headers,\n body: body || undefined,\n });\n \n // Call better-call handler\n const betterCallHandler = apiRouteManager.getHandler();\n if (!betterCallHandler) {\n setResponseStatus(event, 404);\n return { error: 'API handler not found' };\n }\n \n const response = await betterCallHandler(request);\n \n // Log API response (only in development)\n if (process.env.NODE_ENV === 'development' || !process.env.NODE_ENV) {\n const duration = Date.now() - startTime;\n const status = response.status;\n try {\n const pc = await import('picocolors');\n let statusColor = pc.default.green;\n if (status >= 500) statusColor = pc.default.red;\n else if (status >= 400) statusColor = pc.default.yellow;\n else if (status >= 300) statusColor = pc.default.cyan;\n\n const log = [\n pc.default.dim('[') + pc.default.bold(pc.default.blue('FARM')) + pc.default.dim(']'),\n status >= 400 ? pc.default.red('✗') : pc.default.green('✓'),\n pc.default.cyan('[API]'),\n pc.default.gray(urlPath),\n pc.default.dim('-'),\n statusColor(status.toString()),\n pc.default.dim(\\`(\\${duration}ms)\\`),\n ].join(' ');\n console.log(log);\n } catch {\n // picocolors not available, use simple log\n console.log(\\`[FARM] [\\${method}] [API] \\${urlPath} - \\${response.status} (\\${duration}ms)\\`);\n }\n }\n \n return sendWebResponse(response);\n } catch (error: any) {\n console.error('API handler error:', error);\n setResponseStatus(event, 500);\n return {\n error: error.message || 'Internal Server Error',\n };\n }\n});\n`,\n \"utf-8\",\n );\n\n // Create SSR catch-all route handler\n // For Vercel, Nitro expects routes in server/routes/[...].ts format\n const ssrHandlerFile = path.join(serverDir, \"routes\", \"[...].ts\");\n await mkdir(path.dirname(ssrHandlerFile), { recursive: true });\n await writeFile(\n ssrHandlerFile,\n `\n// Auto-generated by Farm.js\n// This handler handles all page routes (SSR)\nimport { defineEventHandler, setResponseStatus, getRequestURL, setHeader, getHeaders, readBody, sendWebResponse, setCookie } from 'h3';\nimport type { H3Event } from 'h3';\nimport { farmRegistry } from '../farm-registry';\nimport React from 'react';\nimport { renderToString } from 'react-dom/server';\n\nexport default defineEventHandler(async (event: H3Event) => {\n try {\n // Ensure registry is populated (lazy initialization)\n // In serverless environments, the registry needs to be initialized at runtime\n if (!farmRegistry.routeManager || !farmRegistry.serverRenderer) {\n // Try to initialize from global if available (set during build)\n if (typeof globalThis !== 'undefined' && (globalThis as any).__FARM_REGISTRY__) {\n Object.assign(farmRegistry, (globalThis as any).__FARM_REGISTRY__);\n }\n // If still not available, try the init function (if it exists)\n if ((!farmRegistry.routeManager || !farmRegistry.serverRenderer) && (farmRegistry as any).__INIT__) {\n (farmRegistry as any).__INIT__();\n }\n }\n \n const routeManager = farmRegistry.routeManager;\n const serverRenderer = farmRegistry.serverRenderer;\n \n if (!routeManager || !serverRenderer) {\n console.error('Route manager or renderer not initialized. Registry keys:', Object.keys(farmRegistry));\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return '<!DOCTYPE html><html><head><title>Error</title></head><body><h1>500 Internal Server Error</h1><p>Route manager or renderer not initialized. Please check server logs.</p></body></html>';\n }\n \n // Get URL from H3 event\n const url = getRequestURL(event);\n const pathname = url.pathname;\n const redirectMatch = routeManager.matchRedirect(pathname);\n if (redirectMatch) {\n setResponseStatus(event, redirectMatch.statusCode);\n setHeader(event, 'Location', redirectMatch.destination);\n return \\`Redirecting to \\${redirectMatch.destination}\\`;\n }\n const apiRouteManager = farmRegistry.apiRouteManager;\n\n if (apiRouteManager?.matchRoute(pathname)) {\n const handler = apiRouteManager.getHandler();\n if (!handler) {\n setResponseStatus(event, 404);\n return { error: 'API handler not found' };\n }\n\n const headers = new Headers();\n const h3Headers = getHeaders(event);\n for (const [key, value] of Object.entries(h3Headers)) {\n if (value) {\n headers.set(key, Array.isArray(value) ? value.join(', ') : String(value));\n }\n }\n\n let body: string | undefined;\n const method = event.method || 'GET';\n if (method !== 'GET' && method !== 'HEAD') {\n const bodyData = await readBody(event).catch(() => undefined);\n if (bodyData) {\n body = typeof bodyData === 'string' ? bodyData : JSON.stringify(bodyData);\n }\n }\n\n const response = await handler(new Request(url.toString(), {\n method,\n headers,\n body: body || undefined,\n }));\n\n return sendWebResponse(response);\n }\n\n // Skip API routes - let the API handler process them\n if (pathname.startsWith('/api/')) {\n // Return undefined to let Nitro's API handler process\n return undefined;\n }\n \n // Skip static assets - let Nitro serve them\n // Only skip if it's clearly a static file (has extension and not in root)\n if (pathname.startsWith('/assets/') || (pathname.includes('.') && !pathname.startsWith('/api/'))) {\n // Check if it's a static file by extension\n const staticExtensions = ['.js', '.css', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf', '.eot'];\n const hasStaticExtension = staticExtensions.some(ext => pathname.toLowerCase().endsWith(ext));\n if (hasStaticExtension) {\n return; // Let Nitro's static file handler process\n }\n }\n \n // Try to use Node.js req/res if available (for node-server preset)\n if (event.node && event.node.req && event.node.res) {\n await serverRenderer.renderPage(event.node.req as any, event.node.res as any);\n return undefined; // Response already sent\n }\n\n if (farmRegistry.deploymentId) {\n setHeader(event, 'x-farm-deployment-id', farmRegistry.deploymentId);\n setCookie(event, '__farm_deployment', farmRegistry.deploymentId, {\n httpOnly: true,\n sameSite: 'lax',\n secure: url.protocol === 'https:',\n path: farmRegistry.basePath || '/',\n });\n }\n \n // For serverless (Vercel), render to string and send HTML\n try {\n // Match route\n const { route, params, layouts } = routeManager.matchRoute(pathname);\n \n if (!route) {\n setResponseStatus(event, 404);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1></body></html>';\n }\n \n // Get search params\n const searchParamsObject: Record<string, string | string[] | undefined> = {};\n url.searchParams.forEach((value, key) => {\n const existing = searchParamsObject[key];\n if (existing) {\n if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n searchParamsObject[key] = [existing, value];\n }\n } else {\n searchParamsObject[key] = value;\n }\n });\n \n // Load route module - in production, use bundled SSR output\n // Get bundled path from registry or construct it\n let routeModule;\n const routePaths = farmRegistry.routePaths || {};\n const bundledPath = routePaths[pathname] || route.modulePath\n .replace(/.*\\\\/src\\\\/app\\\\//, '')\n .replace(/\\\\.(tsx?|jsx?)$/, '.js');\n \n try {\n // Try to load from bundled SSR output (copied to Nitro's server/farm directory)\n // Nitro bundles everything, so we need to use the correct import path\n routeModule = await import('./farm/' + bundledPath);\n } catch (importError) {\n // Fallback: try route manager's load method (for node-server preset)\n try {\n routeModule = await routeManager.loadRouteModule(route.modulePath);\n } catch (loadError) {\n // Last resort: try just the filename\n const bundledName = bundledPath.split('/').pop() || 'page.js';\n try {\n routeModule = await import('./farm/' + bundledName);\n } catch {\n throw new Error(\\`Failed to load route module: \\${route.modulePath}. Tried: ./farm/\\${bundledPath}, ./farm/\\${bundledName}\\`);\n }\n }\n }\n \n if (!routeModule.default) {\n throw new Error(\\`Route module \\${route.modulePath} does not export a default component\\`);\n }\n \n // Load layout modules\n const layoutModules = await Promise.all(\n layouts.map(async (layout) => {\n const bundledPath = layout.modulePath\n .replace(/.*\\\\/src\\\\/app\\\\//, '')\n .replace(/\\\\.(tsx?|jsx?)$/, '.js');\n \n try {\n // Try to load from bundled SSR output\n return await import('./farm/' + bundledPath);\n } catch {\n // Fallback to route manager's load method\n try {\n return await routeManager.loadLayoutModule(layout.modulePath);\n } catch {\n // Last resort: try just the filename\n const bundledName = bundledPath.split('/').pop() || 'layout.js';\n try {\n return await import('./farm/' + bundledName);\n } catch {\n // Return a dummy layout if all fails\n return { default: ({ children }: any) => children };\n }\n }\n }\n })\n );\n \n // Create page props\n const rawPageProps = {\n params,\n searchParams: Promise.resolve(searchParamsObject),\n path: pathname,\n };\n const pageProps = routeModule.__farmResolveRouteProps\n ? await routeModule.__farmResolveRouteProps(rawPageProps)\n : (() => {\n const routeSchemas = routeModule.__farmRouteParsesProps\n ? {}\n : routeModule.__farmRouteSchemas || {};\n const parsedParams = routeSchemas.params?.parse\n ? routeSchemas.params.parse(params)\n : params;\n const parsedSearch = routeSchemas.search?.parse\n ? routeSchemas.search.parse(searchParamsObject)\n : searchParamsObject;\n return {\n ...rawPageProps,\n params: parsedParams,\n search: parsedSearch,\n searchParams: Promise.resolve(parsedSearch),\n };\n })();\n \n // Create page element\n const PageComponent = routeModule.default;\n let pageElement;\n if (PageComponent.constructor.name === \"AsyncFunction\" || PageComponent.toString().includes(\"async\")) {\n pageElement = await PageComponent(pageProps);\n } else {\n pageElement = React.createElement(PageComponent, pageProps);\n }\n \n // Wrap with layouts\n for (let i = layoutModules.length - 1; i >= 0; i--) {\n const layoutModule = layoutModules[i];\n const LayoutComponent = layoutModule.default;\n pageElement = React.createElement(LayoutComponent, {\n children: pageElement,\n params,\n } as any);\n }\n \n // Render to string\n const html = renderToString(pageElement);\n \n // Get client script path from manifest\n const clientManifest = farmRegistry.clientManifest || {};\n // Find the client script for this route - check manifest structure\n let clientScript = '/assets/page-wbYjx1yQ.js'; // Default fallback\n if (clientManifest && typeof clientManifest === 'object') {\n // Manifest structure: { \"assets/page-xxx.js\": { ... } }\n const manifestEntry = Object.values(clientManifest).find((entry: any) => \n entry && entry.name === 'page'\n ) as any;\n if (manifestEntry && manifestEntry.chunks && manifestEntry.chunks[0]) {\n clientScript = '/' + manifestEntry.chunks[0];\n } else if (Object.keys(clientManifest).length > 0) {\n // Fallback to first asset in manifest\n clientScript = '/' + Object.keys(clientManifest)[0];\n }\n }\n \n // Build full HTML\n const serializedDeploymentId = JSON.stringify(farmRegistry.deploymentId || '').replace(/</g, '\\\\u003c');\n const fullHtml = \\`<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link rel=\"icon\" href=\"data:,\">\n <title>Farm.js App</title>\n <script>\n window.__FARM_DEPLOYMENT_ID__ = \\${serializedDeploymentId};\n window.__FARM_PROPS__ = \\${JSON.stringify(pageProps)};\n window.__FARM_PATH__ = \\${JSON.stringify(pathname)};\n </script>\n</head>\n<body>\n <div id=\"root\">\\${html}</div>\n <script type=\"module\" src=\"\\${clientScript}\"></script>\n</body>\n</html>\\`;\n \n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return fullHtml;\n \n } catch (renderError: any) {\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return \\`<!DOCTYPE html><html><head><title>Error</title></head><body><h1>Error</h1><p>\\${renderError.message || 'Internal Server Error'}</p></body></html>\\`;\n }\n } catch (error: any) {\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return \\`<!DOCTYPE html><html><head><title>Error</title></head><body><h1>Error</h1><p>\\${error.message || 'Internal Server Error'}</p></body></html>\\`;\n }\n});\n`,\n \"utf-8\",\n );\n\n // Create Nitro config according to https://nitro.build/config\n // Compatibility date is required in Nitro v3\n const nitroConfig: NitroConfig = {\n preset,\n // rootDir must be the project root for Nitro to correctly resolve paths\n rootDir: root,\n // srcDir should point to where source files are (for scanning)\n // But we're using scanDirs to point to our server directory\n srcDir: root,\n // buildDir is where Nitro builds (temporary working directory)\n buildDir: nitroBuildDir,\n // output.dir is where the final deployable output goes\n // This ensures everything ends up in .farm/.output\n compatibilityDate: \"2024-12-01\",\n // Vercel-specific configuration\n ...(preset === \"vercel\"\n ? {\n vercel: {\n // Ensure proper function configuration\n config: {},\n },\n }\n : {}),\n // Tell Nitro to scan the server directory we created\n // This ensures our handlers are discovered by Nitro\n scanDirs: [serverDir],\n tasks: {\n ...farmWorkflows.tasks,\n ...farmCron.tasks,\n },\n scheduledTasks,\n ...(preset === \"cloudflare-module\" && cloudflareCronConfig\n ? {\n cloudflare: cloudflareCronConfig,\n }\n : {}),\n handlers: [\n ...(farmWorkflows.handlerPath\n ? [\n {\n route: `${config.workflows.route}/**`,\n handler: farmWorkflows.handlerPath,\n },\n ]\n : []),\n ],\n // Route rules for Vercel\n routeRules: {\n \"/api/**\": {\n cors: true,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"*\",\n \"Access-Control-Allow-Headers\": \"*\",\n },\n },\n \"/**\": {\n prerender: false,\n },\n ...routeRulesToNitroRouteRules(config.routeRules),\n },\n\n // // Exclude certain directories from scanning\n // scanDirsExclude: [\n // '**/node_modules/**',\n // '**/.git/**',\n // '**/.output/**',\n // '**/.nitro/**',\n // ],\n output: {\n // CRITICAL: All output MUST go to .farm/.output (NOT .nitro/.output)\n // This ensures consistency and that deployment always uses .farm/.output\n // By explicitly setting dir, serverDir, and publicDir, we prevent Nitro\n // from creating its own .output directory inside .nitro\n dir: outputDir, // .farm/.output\n serverDir: path.join(outputDir, \"server\"), // .farm/.output/server\n publicDir: path.join(outputDir, \"public\"), // .farm/.output/public\n },\n // Use Nitro hooks to populate the runtime registry\n // This allows us to pass complex objects (route managers, renderers) at runtime\n hooks: {\n \"build:before\": async (nitro: any) => {\n // Import and populate the registry at build time\n const registryPath = path.join(serverDir, \"farm-registry.ts\");\n const { farmRegistry } = await import(/* @vite-ignore */ registryPath);\n\n // Store route paths (serializable)\n const routePaths: Record<string, string> = {};\n for (const [pattern, entry] of routeManager.getRoutes()) {\n const bundledPath = entry.modulePath\n .replace(/.*\\/src\\/app\\//, \"\")\n .replace(/\\.(tsx?|jsx?)$/, \".js\");\n routePaths[pattern] = bundledPath;\n }\n farmRegistry.routePaths = routePaths;\n\n // Load and store client manifest for SSR\n try {\n const clientManifestPath = path.join(\n root,\n distDir,\n \"client\",\n \"farm-client-manifest.json\",\n );\n const { readFile } = await import(\"fs/promises\");\n const manifestContent = await readFile(clientManifestPath, \"utf-8\");\n farmRegistry.clientManifest = JSON.parse(manifestContent);\n } catch (error) {\n // Manifest not critical, continue without it\n farmRegistry.clientManifest = {};\n }\n\n // CRITICAL: Store managers in a way that persists to runtime\n // In serverless, we can't serialize complex objects, so we store them\n // in a module-level variable that will be available at runtime\n // The handlers will access them through the registry\n // We use a closure to capture the managers\n (farmRegistry as any).__INIT__ = () => {\n farmRegistry.apiRouteManager = apiRouteManager;\n farmRegistry.routeManager = routeManager;\n farmRegistry.serverRenderer = serverRenderer;\n farmRegistry.env = config.env || { server: {}, public: {} };\n farmRegistry.deploymentId = config.deploymentId;\n farmRegistry.basePath = config.basePath;\n };\n\n // Also store in global for runtime access (works in serverless)\n // This ensures they're available even if module state is reset\n if (typeof globalThis !== \"undefined\") {\n (globalThis as any).__FARM_REGISTRY__ = {\n apiRouteManager,\n routeManager,\n serverRenderer,\n env: farmRegistry.env,\n deploymentId: farmRegistry.deploymentId,\n basePath: farmRegistry.basePath,\n clientManifest: farmRegistry.clientManifest,\n routePaths: farmRegistry.routePaths,\n };\n }\n },\n },\n // API base URL (default is /api)\n apiBaseURL: \"/api\",\n // Include public directory and client build\n publicAssets: [\n {\n baseURL: \"/\",\n dir: path.join(root, \"public\"),\n },\n // Include client build assets\n {\n baseURL: \"/\",\n dir: path.join(root, distDir, \"client\"),\n },\n ],\n // Build configuration\n minify: process.env.NODE_ENV === \"production\",\n sourceMap: true,\n // Bundle all dependencies to avoid workspace issues on Vercel\n // This ensures all farm package code is bundled into the serverless function\n // so it doesn't need to resolve workspace dependencies at runtime\n // This is similar to how Next.js and Nuxt bundle their core packages\n // bundle: true,\n // External dependencies that should NOT be bundled (provided by runtime)\n // We exclude React/ReactDOM to reduce bundle size (they're in node_modules)\n externals: {\n external: [\"react\", \"react-dom\"],\n // Keep React external - it's in the serverless function's node_modules\n // This reduces bundle size significantly\n },\n // Runtime config\n runtimeConfig: {\n public: {},\n },\n // Experimental features\n experimental: {\n tasks: farmWorkflows.workflows.length > 0 || farmCron.jobs.length > 0,\n wasm: false, // Disable for now to avoid issues\n },\n };\n\n return nitroConfig;\n}\n\n/**\n * Get Nitro preset from config\n */\nexport function getNitroPreset(preset?: string): string {\n return preset || \"node-server\";\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["routePaths","clientManifestPath"]}
1
+ {"version":3,"sources":["../src/nitro/index.ts"],"sourcesContent":["import type { NitroConfig } from \"nitro/config\";\nimport type { ResolvedFarmConfig } from \"../config\";\nimport type { RouteManager } from \"../routing/route-manager\";\nimport type { APIRouteManager } from \"../api/route-manager\";\nimport type { ServerRenderer } from \"../server/renderer\";\nimport { createNitroAPIHandler } from \"./api-handler\";\nimport { createNitroSSRHandler } from \"./ssr-handler\";\nimport path from \"path\";\nimport { prepareFarmWorkflowsForNitro } from \"../workflows\";\nimport {\n createFarmCronCloudflareConfig,\n mergeScheduledTasks,\n prepareFarmCronForNitro,\n} from \"../cron\";\nimport { routeRulesToNitroRouteRules } from \"../route-rules\";\n\n/**\n * Create Nitro configuration for Farm.js\n * Based on https://nitro.build/config\n */\nexport async function createNitroConfig(\n config: ResolvedFarmConfig,\n routeManager: RouteManager,\n apiRouteManager: APIRouteManager,\n serverRenderer: ServerRenderer,\n preset = \"node-server\",\n): Promise<NitroConfig> {\n const root = config.root || process.cwd();\n const srcDir = config.srcDir || \"src\";\n const distDir = \".farm\";\n // Nitro build directory - where Nitro does its work (temporary)\n // We use .nitro as a working directory, but ensure output goes to .farm/.output\n const nitroBuildDir = path.join(root, distDir, \".nitro\");\n // Final output directory - where the deployable output goes\n // This MUST be .farm/.output (not .nitro/.output) for consistency\n const outputDir = path.join(root, distDir, \".output\");\n // Server directory for handlers (inside build dir, will be copied to output)\n const serverDir = path.join(nitroBuildDir, \"server\");\n\n // Ensure Nitro doesn't create its own .output inside .nitro\n // By explicitly setting output.dir, Nitro will use our specified directory\n\n // Create server directory structure for Nitro to discover routes\n // According to Nitro docs: https://nitro.build/deploy/providers/vercel\n // Routes should be in server/api/[...].ts and server/routes/[...].ts\n const { mkdir, writeFile } = await import(\"fs/promises\");\n await mkdir(serverDir, { recursive: true });\n await mkdir(path.join(serverDir, \"api\"), { recursive: true });\n await mkdir(path.join(serverDir, \"routes\"), { recursive: true });\n const farmWorkflows = await prepareFarmWorkflowsForNitro({\n ...config,\n distDir,\n });\n const farmCron = await prepareFarmCronForNitro({\n ...config,\n distDir,\n });\n const scheduledTasks = mergeScheduledTasks(farmWorkflows.scheduledTasks, farmCron.scheduledTasks);\n const cloudflareCronConfig = createFarmCronCloudflareConfig(farmCron.jobs);\n\n // Create a runtime registry file to store route managers\n // This will be populated at runtime through Nitro hooks\n const registryFile = path.join(serverDir, \"farm-registry.ts\");\n\n // Serialize route paths for SSR module loading\n const routePaths: Record<string, string> = {};\n for (const [pattern, entry] of routeManager.getRoutes()) {\n const bundledPath = entry.modulePath\n .replace(/.*\\/src\\/app\\//, \"\")\n .replace(/\\.(tsx?|jsx?)$/, \".js\");\n routePaths[pattern] = bundledPath;\n }\n\n // Load client manifest path for reference\n const clientManifestPath = path.join(root, distDir, \"client\", \"farm-client-manifest.json\");\n\n await writeFile(\n registryFile,\n `\n// Auto-generated by Farm.js\n// Runtime registry for route managers and renderers\nexport const farmRegistry: {\n apiRouteManager?: any;\n routeManager?: any;\n serverRenderer?: any;\n env?: any;\n deploymentId?: string;\n basePath?: string;\n clientManifest?: any;\n routePaths?: Record<string, string>;\n} = {\n env: ${JSON.stringify(config.env || { server: {}, public: {} }, null, 2)},\n deploymentId: ${JSON.stringify(config.deploymentId)},\n basePath: ${JSON.stringify(config.basePath)},\n routePaths: ${JSON.stringify(routePaths, null, 2)},\n};\n`,\n \"utf-8\",\n );\n\n // Create API route handler file\n // For Vercel, Nitro expects routes in server/api/[...].ts format\n // This catch-all will handle all /api/* requests\n const apiHandlerFile = path.join(serverDir, \"api\", \"[...].ts\");\n await mkdir(path.dirname(apiHandlerFile), { recursive: true });\n await writeFile(\n apiHandlerFile,\n `\n// Auto-generated by Farm.js\n// This handler intercepts all /api/* requests\nimport { defineEventHandler, getHeaders, readBody, sendWebResponse, setResponseStatus, getRequestURL } from 'h3';\nimport type { H3Event } from 'h3';\nimport { farmRegistry } from '../farm-registry';\n\nexport default defineEventHandler(async (event: H3Event) => {\n // Get URL using H3's abstraction (works in all environments)\n const url = getRequestURL(event);\n const urlPath = url.pathname;\n \n // Only handle API routes - for Vercel, Nitro routes /api/* to this handler\n // According to https://nitro.build/deploy/providers/vercel\n // This handler should process all /api/* routes\n if (!urlPath.startsWith('/api/')) {\n // Return undefined to let Nitro's routing system handle non-API routes\n return undefined;\n }\n \n // Ensure registry is populated (lazy initialization)\n // In serverless environments, the registry needs to be initialized at runtime\n if (!farmRegistry.apiRouteManager) {\n // Try to initialize from global if available (set during build)\n if (typeof globalThis !== 'undefined' && (globalThis as any).__FARM_REGISTRY__) {\n Object.assign(farmRegistry, (globalThis as any).__FARM_REGISTRY__);\n }\n // If still not available, try the init function (if it exists)\n if (!farmRegistry.apiRouteManager && (farmRegistry as any).__INIT__) {\n (farmRegistry as any).__INIT__();\n }\n }\n \n const apiRouteManager = farmRegistry.apiRouteManager;\n if (!apiRouteManager) {\n console.error('API route manager not initialized. Registry keys:', Object.keys(farmRegistry));\n setResponseStatus(event, 500);\n return { error: 'API route manager not initialized. Please check server logs.' };\n }\n \n const startTime = Date.now();\n const method = event.method || 'GET';\n const host = url.host || 'localhost';\n \n // Log API request (only in development)\n if (process.env.NODE_ENV === 'development' || !process.env.NODE_ENV) {\n try {\n const pc = await import('picocolors');\n const log = [\n pc.default.dim('[') + pc.default.bold(pc.default.blue('FARM')) + pc.default.dim(']'),\n pc.default.dim('[') + pc.default.bold(pc.default.white(method.padEnd(3))) + pc.default.dim(']'),\n pc.default.cyan('[API]'),\n pc.default.gray(\\`\\${url.protocol}//\\${host}\\${urlPath}\\`),\n ].join(' ');\n console.log(log);\n } catch {\n // picocolors not available, use simple log\n console.log(\\`[FARM] [\\${method}] [API] \\${urlPath}\\`);\n }\n }\n \n try {\n // Convert H3 event to Web Request using H3 abstractions\n const protocol = url.protocol.replace(':', '') || 'http';\n const host = url.host || 'localhost';\n const fullUrl = url.toString();\n \n const headers = new Headers();\n const h3Headers = getHeaders(event);\n \n for (const [key, value] of Object.entries(h3Headers)) {\n if (value) {\n headers.set(key, Array.isArray(value) ? value.join(', ') : String(value));\n }\n }\n \n // Get body\n let body: string | undefined;\n const method = event.method || 'GET';\n if (method !== 'GET' && method !== 'HEAD') {\n const bodyData = await readBody(event).catch(() => undefined);\n if (bodyData) {\n body = typeof bodyData === 'string' ? bodyData : JSON.stringify(bodyData);\n }\n }\n \n // Create Web Request\n const request = new Request(fullUrl, {\n method,\n headers,\n body: body || undefined,\n });\n \n // Call better-call handler\n const betterCallHandler = apiRouteManager.getHandler();\n if (!betterCallHandler) {\n setResponseStatus(event, 404);\n return { error: 'API handler not found' };\n }\n \n const response = await betterCallHandler(request);\n \n // Log API response (only in development)\n if (process.env.NODE_ENV === 'development' || !process.env.NODE_ENV) {\n const duration = Date.now() - startTime;\n const status = response.status;\n try {\n const pc = await import('picocolors');\n let statusColor = pc.default.green;\n if (status >= 500) statusColor = pc.default.red;\n else if (status >= 400) statusColor = pc.default.yellow;\n else if (status >= 300) statusColor = pc.default.cyan;\n\n const log = [\n pc.default.dim('[') + pc.default.bold(pc.default.blue('FARM')) + pc.default.dim(']'),\n status >= 400 ? pc.default.red('✗') : pc.default.green('✓'),\n pc.default.cyan('[API]'),\n pc.default.gray(urlPath),\n pc.default.dim('-'),\n statusColor(status.toString()),\n pc.default.dim(\\`(\\${duration}ms)\\`),\n ].join(' ');\n console.log(log);\n } catch {\n // picocolors not available, use simple log\n console.log(\\`[FARM] [\\${method}] [API] \\${urlPath} - \\${response.status} (\\${duration}ms)\\`);\n }\n }\n \n return sendWebResponse(response);\n } catch (error: any) {\n console.error('API handler error:', error);\n setResponseStatus(event, 500);\n return {\n error: error.message || 'Internal Server Error',\n };\n }\n});\n`,\n \"utf-8\",\n );\n\n // Create SSR catch-all route handler\n // For Vercel, Nitro expects routes in server/routes/[...].ts format\n const ssrHandlerFile = path.join(serverDir, \"routes\", \"[...].ts\");\n await mkdir(path.dirname(ssrHandlerFile), { recursive: true });\n await writeFile(\n ssrHandlerFile,\n `\n// Auto-generated by Farm.js\n// This handler handles all page routes (SSR)\nimport { defineEventHandler, setResponseStatus, getRequestURL, setHeader, getHeaders, readBody, sendWebResponse, setCookie } from 'h3';\nimport type { H3Event } from 'h3';\nimport { farmRegistry } from '../farm-registry';\nimport React from 'react';\nimport { renderToString } from 'react-dom/server';\n\nexport default defineEventHandler(async (event: H3Event) => {\n try {\n // Ensure registry is populated (lazy initialization)\n // In serverless environments, the registry needs to be initialized at runtime\n if (!farmRegistry.routeManager || !farmRegistry.serverRenderer) {\n // Try to initialize from global if available (set during build)\n if (typeof globalThis !== 'undefined' && (globalThis as any).__FARM_REGISTRY__) {\n Object.assign(farmRegistry, (globalThis as any).__FARM_REGISTRY__);\n }\n // If still not available, try the init function (if it exists)\n if ((!farmRegistry.routeManager || !farmRegistry.serverRenderer) && (farmRegistry as any).__INIT__) {\n (farmRegistry as any).__INIT__();\n }\n }\n \n const routeManager = farmRegistry.routeManager;\n const serverRenderer = farmRegistry.serverRenderer;\n \n if (!routeManager || !serverRenderer) {\n console.error('Route manager or renderer not initialized. Registry keys:', Object.keys(farmRegistry));\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return '<!DOCTYPE html><html><head><title>Error</title></head><body><h1>500 Internal Server Error</h1><p>Route manager or renderer not initialized. Please check server logs.</p></body></html>';\n }\n \n // Get URL from H3 event\n const url = getRequestURL(event);\n const pathname = url.pathname;\n const redirectMatch = routeManager.matchRedirect(pathname);\n if (redirectMatch) {\n setResponseStatus(event, redirectMatch.statusCode);\n setHeader(event, 'Location', redirectMatch.destination);\n return \\`Redirecting to \\${redirectMatch.destination}\\`;\n }\n const apiRouteManager = farmRegistry.apiRouteManager;\n\n if (apiRouteManager?.matchRoute(pathname)) {\n const handler = apiRouteManager.getHandler();\n if (!handler) {\n setResponseStatus(event, 404);\n return { error: 'API handler not found' };\n }\n\n const headers = new Headers();\n const h3Headers = getHeaders(event);\n for (const [key, value] of Object.entries(h3Headers)) {\n if (value) {\n headers.set(key, Array.isArray(value) ? value.join(', ') : String(value));\n }\n }\n\n let body: string | undefined;\n const method = event.method || 'GET';\n if (method !== 'GET' && method !== 'HEAD') {\n const bodyData = await readBody(event).catch(() => undefined);\n if (bodyData) {\n body = typeof bodyData === 'string' ? bodyData : JSON.stringify(bodyData);\n }\n }\n\n const response = await handler(new Request(url.toString(), {\n method,\n headers,\n body: body || undefined,\n }));\n\n return sendWebResponse(response);\n }\n\n // Skip API routes - let the API handler process them\n if (pathname.startsWith('/api/')) {\n // Return undefined to let Nitro's API handler process\n return undefined;\n }\n \n // Skip static assets - let Nitro serve them\n // Only skip if it's clearly a static file (has extension and not in root)\n if (pathname.startsWith('/assets/') || (pathname.includes('.') && !pathname.startsWith('/api/'))) {\n // Check if it's a static file by extension\n const staticExtensions = ['.js', '.css', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf', '.eot'];\n const hasStaticExtension = staticExtensions.some(ext => pathname.toLowerCase().endsWith(ext));\n if (hasStaticExtension) {\n return; // Let Nitro's static file handler process\n }\n }\n \n // Try to use Node.js req/res if available (for node-server preset)\n if (event.node && event.node.req && event.node.res) {\n await serverRenderer.renderPage(event.node.req as any, event.node.res as any);\n return undefined; // Response already sent\n }\n\n if (farmRegistry.deploymentId) {\n setHeader(event, 'x-farm-deployment-id', farmRegistry.deploymentId);\n setCookie(event, '__farm_deployment', farmRegistry.deploymentId, {\n httpOnly: true,\n sameSite: 'lax',\n secure: url.protocol === 'https:',\n path: farmRegistry.basePath || '/',\n });\n }\n \n // For serverless (Vercel), render to string and send HTML\n try {\n // Match route\n const { route, params, layouts } = routeManager.matchRoute(pathname);\n \n if (!route) {\n setResponseStatus(event, 404);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1></body></html>';\n }\n \n // Get search params\n const searchParamsObject: Record<string, string | string[] | undefined> = {};\n url.searchParams.forEach((value, key) => {\n const existing = searchParamsObject[key];\n if (existing) {\n if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n searchParamsObject[key] = [existing, value];\n }\n } else {\n searchParamsObject[key] = value;\n }\n });\n \n // Load route module - in production, use bundled SSR output\n // Get bundled path from registry or construct it\n let routeModule;\n const routePaths = farmRegistry.routePaths || {};\n const bundledPath = routePaths[pathname] || route.modulePath\n .replace(/.*\\\\/src\\\\/app\\\\//, '')\n .replace(/\\\\.(tsx?|jsx?)$/, '.js');\n \n try {\n // Try to load from bundled SSR output (copied to Nitro's server/farm directory)\n // Nitro bundles everything, so we need to use the correct import path\n routeModule = await import('./farm/' + bundledPath);\n } catch (importError) {\n // Fallback: try route manager's load method (for node-server preset)\n try {\n routeModule = await routeManager.loadRouteModule(route.modulePath);\n } catch (loadError) {\n // Last resort: try just the filename\n const bundledName = bundledPath.split('/').pop() || 'page.js';\n try {\n routeModule = await import('./farm/' + bundledName);\n } catch {\n throw new Error(\\`Failed to load route module: \\${route.modulePath}. Tried: ./farm/\\${bundledPath}, ./farm/\\${bundledName}\\`);\n }\n }\n }\n \n if (!routeModule.default) {\n throw new Error(\\`Route module \\${route.modulePath} does not export a default component\\`);\n }\n \n // Load layout modules\n const layoutModules = await Promise.all(\n layouts.map(async (layout) => {\n const bundledPath = layout.modulePath\n .replace(/.*\\\\/src\\\\/app\\\\//, '')\n .replace(/\\\\.(tsx?|jsx?)$/, '.js');\n \n try {\n // Try to load from bundled SSR output\n return await import('./farm/' + bundledPath);\n } catch {\n // Fallback to route manager's load method\n try {\n return await routeManager.loadLayoutModule(layout.modulePath);\n } catch {\n // Last resort: try just the filename\n const bundledName = bundledPath.split('/').pop() || 'layout.js';\n try {\n return await import('./farm/' + bundledName);\n } catch {\n // Return a dummy layout if all fails\n return { default: ({ children }: any) => children };\n }\n }\n }\n })\n );\n \n // Create page props\n const rawPageProps = {\n params,\n searchParams: Promise.resolve(searchParamsObject),\n path: pathname,\n };\n const pageProps = routeModule.__farmResolveRouteProps\n ? await routeModule.__farmResolveRouteProps(rawPageProps)\n : (() => {\n const routeSchemas = routeModule.__farmRouteParsesProps\n ? {}\n : routeModule.__farmRouteSchemas || {};\n const parsedParams = routeSchemas.params?.parse\n ? routeSchemas.params.parse(params)\n : params;\n const parsedSearch = routeSchemas.search?.parse\n ? routeSchemas.search.parse(searchParamsObject)\n : searchParamsObject;\n return {\n ...rawPageProps,\n params: parsedParams,\n search: parsedSearch,\n searchParams: Promise.resolve(parsedSearch),\n };\n })();\n \n // Create page element\n const PageComponent = routeModule.default;\n let pageElement;\n if (PageComponent.constructor.name === \"AsyncFunction\" || PageComponent.toString().includes(\"async\")) {\n pageElement = await PageComponent(pageProps);\n } else {\n pageElement = React.createElement(PageComponent, pageProps);\n }\n \n // Wrap with layouts\n for (let i = layoutModules.length - 1; i >= 0; i--) {\n const layoutModule = layoutModules[i];\n const LayoutComponent = layoutModule.default;\n pageElement = React.createElement(LayoutComponent, {\n children: pageElement,\n params,\n } as any);\n }\n \n // Render to string\n const html = renderToString(pageElement);\n \n // Get client script path from manifest\n const clientManifest = farmRegistry.clientManifest || {};\n // Find the client script for this route - check manifest structure\n let clientScript = '/assets/page-wbYjx1yQ.js'; // Default fallback\n if (clientManifest && typeof clientManifest === 'object') {\n // Manifest structure: { \"assets/page-xxx.js\": { ... } }\n const manifestEntry = Object.values(clientManifest).find((entry: any) => \n entry && entry.name === 'page'\n ) as any;\n if (manifestEntry && manifestEntry.chunks && manifestEntry.chunks[0]) {\n clientScript = '/' + manifestEntry.chunks[0];\n } else if (Object.keys(clientManifest).length > 0) {\n // Fallback to first asset in manifest\n clientScript = '/' + Object.keys(clientManifest)[0];\n }\n }\n \n // Build full HTML\n const serializedDeploymentId = JSON.stringify(farmRegistry.deploymentId || '').replace(/</g, '\\\\u003c');\n const fullHtml = \\`<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link rel=\"icon\" href=\"data:,\">\n <title>Farm.js App</title>\n <script>\n window.__FARM_DEPLOYMENT_ID__ = \\${serializedDeploymentId};\n window.__FARM_PROPS__ = \\${JSON.stringify(pageProps)};\n window.__FARM_PATH__ = \\${JSON.stringify(pathname)};\n </script>\n</head>\n<body>\n <div id=\"root\">\\${html}</div>\n <script type=\"module\" src=\"\\${clientScript}\"></script>\n</body>\n</html>\\`;\n \n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return fullHtml;\n \n } catch (renderError: any) {\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return \\`<!DOCTYPE html><html><head><title>Error</title></head><body><h1>Error</h1><p>\\${renderError.message || 'Internal Server Error'}</p></body></html>\\`;\n }\n } catch (error: any) {\n setResponseStatus(event, 500);\n setHeader(event, 'Content-Type', 'text/html; charset=utf-8');\n return \\`<!DOCTYPE html><html><head><title>Error</title></head><body><h1>Error</h1><p>\\${error.message || 'Internal Server Error'}</p></body></html>\\`;\n }\n});\n`,\n \"utf-8\",\n );\n\n // Create Nitro config according to https://nitro.build/config\n // Compatibility date is required in Nitro v3\n const nitroConfig: NitroConfig = {\n preset,\n // rootDir must be the project root for Nitro to correctly resolve paths\n rootDir: root,\n // srcDir should point to where source files are (for scanning)\n // But we're using scanDirs to point to our server directory\n srcDir: root,\n // buildDir is where Nitro builds (temporary working directory)\n buildDir: nitroBuildDir,\n // output.dir is where the final deployable output goes\n // This ensures everything ends up in .farm/.output\n compatibilityDate: \"2024-12-01\",\n // Vercel-specific configuration\n ...(preset === \"vercel\"\n ? {\n vercel: {\n // Ensure proper function configuration\n config: {},\n },\n }\n : {}),\n // Tell Nitro to scan the server directory we created\n // This ensures our handlers are discovered by Nitro\n scanDirs: [serverDir],\n tasks: {\n ...farmWorkflows.tasks,\n ...farmCron.tasks,\n },\n scheduledTasks,\n ...(preset === \"cloudflare-module\" && cloudflareCronConfig\n ? {\n cloudflare: cloudflareCronConfig,\n }\n : {}),\n handlers: farmWorkflows.handlerPath\n ? [\n {\n route: `${config.workflows.route}/**`,\n handler: farmWorkflows.handlerPath,\n },\n ]\n : [],\n // Route rules for Vercel\n routeRules: {\n \"/api/**\": {\n cors: true,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"*\",\n \"Access-Control-Allow-Headers\": \"*\",\n },\n },\n \"/**\": {\n prerender: false,\n },\n ...routeRulesToNitroRouteRules(config.routeRules),\n },\n\n // // Exclude certain directories from scanning\n // scanDirsExclude: [\n // '**/node_modules/**',\n // '**/.git/**',\n // '**/.output/**',\n // '**/.nitro/**',\n // ],\n output: {\n // CRITICAL: All output MUST go to .farm/.output (NOT .nitro/.output)\n // This ensures consistency and that deployment always uses .farm/.output\n // By explicitly setting dir, serverDir, and publicDir, we prevent Nitro\n // from creating its own .output directory inside .nitro\n dir: outputDir, // .farm/.output\n serverDir: path.join(outputDir, \"server\"), // .farm/.output/server\n publicDir: path.join(outputDir, \"public\"), // .farm/.output/public\n },\n // Use Nitro hooks to populate the runtime registry\n // This allows us to pass complex objects (route managers, renderers) at runtime\n hooks: {\n \"build:before\": async (nitro: any) => {\n // Import and populate the registry at build time\n const registryPath = path.join(serverDir, \"farm-registry.ts\");\n const { farmRegistry } = await import(/* @vite-ignore */ registryPath);\n\n // Store route paths (serializable)\n const routePaths: Record<string, string> = {};\n for (const [pattern, entry] of routeManager.getRoutes()) {\n const bundledPath = entry.modulePath\n .replace(/.*\\/src\\/app\\//, \"\")\n .replace(/\\.(tsx?|jsx?)$/, \".js\");\n routePaths[pattern] = bundledPath;\n }\n farmRegistry.routePaths = routePaths;\n\n // Load and store client manifest for SSR\n try {\n const clientManifestPath = path.join(\n root,\n distDir,\n \"client\",\n \"farm-client-manifest.json\",\n );\n const { readFile } = await import(\"fs/promises\");\n const manifestContent = await readFile(clientManifestPath, \"utf-8\");\n farmRegistry.clientManifest = JSON.parse(manifestContent);\n } catch (error) {\n // Manifest not critical, continue without it\n farmRegistry.clientManifest = {};\n }\n\n // CRITICAL: Store managers in a way that persists to runtime\n // In serverless, we can't serialize complex objects, so we store them\n // in a module-level variable that will be available at runtime\n // The handlers will access them through the registry\n // We use a closure to capture the managers\n (farmRegistry as any).__INIT__ = () => {\n farmRegistry.apiRouteManager = apiRouteManager;\n farmRegistry.routeManager = routeManager;\n farmRegistry.serverRenderer = serverRenderer;\n farmRegistry.env = config.env || { server: {}, public: {} };\n farmRegistry.deploymentId = config.deploymentId;\n farmRegistry.basePath = config.basePath;\n };\n\n // Also store in global for runtime access (works in serverless)\n // This ensures they're available even if module state is reset\n if (typeof globalThis !== \"undefined\") {\n (globalThis as any).__FARM_REGISTRY__ = {\n apiRouteManager,\n routeManager,\n serverRenderer,\n env: farmRegistry.env,\n deploymentId: farmRegistry.deploymentId,\n basePath: farmRegistry.basePath,\n clientManifest: farmRegistry.clientManifest,\n routePaths: farmRegistry.routePaths,\n };\n }\n },\n },\n // API base URL (default is /api)\n apiBaseURL: \"/api\",\n // Include public directory and client build\n publicAssets: [\n {\n baseURL: \"/\",\n dir: path.join(root, \"public\"),\n },\n // Include client build assets\n {\n baseURL: \"/\",\n dir: path.join(root, distDir, \"client\"),\n },\n ],\n // Build configuration\n minify: process.env.NODE_ENV === \"production\",\n sourceMap: true,\n // Bundle all dependencies to avoid workspace issues on Vercel\n // This ensures all farm package code is bundled into the serverless function\n // so it doesn't need to resolve workspace dependencies at runtime\n // This is similar to how Next.js and Nuxt bundle their core packages\n // bundle: true,\n // External dependencies that should NOT be bundled (provided by runtime)\n // We exclude React/ReactDOM to reduce bundle size (they're in node_modules)\n externals: {\n external: [\"react\", \"react-dom\"],\n // Keep React external - it's in the serverless function's node_modules\n // This reduces bundle size significantly\n },\n // Runtime config\n runtimeConfig: {\n public: {},\n },\n // Experimental features\n experimental: {\n tasks: farmWorkflows.workflows.length > 0 || farmCron.jobs.length > 0,\n wasm: false, // Disable for now to avoid issues\n },\n };\n\n return nitroConfig;\n}\n\n/**\n * Get Nitro preset from config\n */\nexport function getNitroPreset(preset?: string): string {\n return preset || \"node-server\";\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["routePaths","clientManifestPath"]}
package/dist/plugin.cjs CHANGED
@@ -309,7 +309,7 @@ function createFarmMarkdownRouteModule(input) {
309
309
  ...props,
310
310
  components: {
311
311
  ...components,
312
- ...props?.components || {}
312
+ ...props?.components
313
313
  }
314
314
  })
315
315
  );
@@ -826,7 +826,11 @@ async function prepareFarmWorkflowsForNitro(config) {
826
826
  };
827
827
  }
828
828
  const handlerPath = path22.join(generatedDir, "http-handler.mjs");
829
- await fs8.writeFile(handlerPath, createNitroWorkflowHTTPHandler(workflowConfig, workflows), "utf8");
829
+ await fs8.writeFile(
830
+ handlerPath,
831
+ createNitroWorkflowHTTPHandler(workflowConfig, workflows),
832
+ "utf8"
833
+ );
830
834
  const manifestPath = path22.join(generatedDir, "manifest.json");
831
835
  await fs8.writeFile(
832
836
  manifestPath,
@@ -900,13 +904,7 @@ function normalizeSchedule(schedule) {
900
904
  return (Array.isArray(schedule) ? schedule : [schedule]).map((value) => value.trim()).filter(Boolean);
901
905
  }
902
906
  function resolveWorkflowDefinition(module2) {
903
- const candidates = [
904
- module2.default,
905
- module2.workflow,
906
- module2.cron,
907
- module2.task,
908
- module2.job
909
- ];
907
+ const candidates = [module2.default, module2.workflow, module2.cron, module2.task, module2.job];
910
908
  for (const candidate of candidates) {
911
909
  if (candidate && typeof candidate === "object" && typeof candidate.run === "function") {
912
910
  return candidate;
@@ -1899,8 +1897,8 @@ function compareFarmRouteRuleSpecificity(left, right) {
1899
1897
  }
1900
1898
  function getFarmRouteRuleSpecificity(pattern) {
1901
1899
  return normalizeRoutePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
1902
- if (segment === "**" || /^\[\[\.\.\./.test(segment)) return score + 1;
1903
- if (segment === "*" || /^\[\.\.\./.test(segment)) return score + 10;
1900
+ if (segment === "**" || segment.startsWith("[[...")) return score + 1;
1901
+ if (segment === "*" || segment.startsWith("[...")) return score + 10;
1904
1902
  if (/^\[.+\]$/.test(segment) || /^:.+$/.test(segment)) return score + 50;
1905
1903
  return score + 100;
1906
1904
  }, 0);
@@ -1963,18 +1961,39 @@ function getFarmCacheInvalidationState() {
1963
1961
  listeners: /* @__PURE__ */ new Set()
1964
1962
  });
1965
1963
  }
1964
+ function encodeFarmCacheInvalidations(keys) {
1965
+ const normalized = Array.from(
1966
+ new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
1967
+ );
1968
+ if (normalized.length === 0) return null;
1969
+ return encodeURIComponent(JSON.stringify(normalized));
1970
+ }
1971
+ function decodeFarmCacheInvalidations(value) {
1972
+ if (!value) return [];
1973
+ try {
1974
+ const parsed = JSON.parse(decodeURIComponent(value));
1975
+ return Array.isArray(parsed) ? Array.from(
1976
+ new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
1977
+ ) : [];
1978
+ } catch {
1979
+ return [];
1980
+ }
1981
+ }
1966
1982
  function subscribeFarmCacheInvalidation(listener) {
1967
1983
  const state = getFarmCacheInvalidationState();
1968
1984
  state.listeners.add(listener);
1969
1985
  return () => state.listeners.delete(listener);
1970
1986
  }
1971
- var FARM_CACHE_INVALIDATION_STATE, globalState;
1987
+ var FARM_CACHE_INVALIDATION_HEADER, FARM_CACHE_INVALIDATION_STATE, globalState;
1972
1988
  var init_cache_invalidation = __esm({
1973
1989
  "src/cache-invalidation.ts"() {
1974
1990
  "use strict";
1991
+ FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
1975
1992
  FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
1976
1993
  globalState = globalThis;
1977
1994
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
1995
+ __name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
1996
+ __name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
1978
1997
  __name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
1979
1998
  }
1980
1999
  });
@@ -4534,7 +4553,9 @@ function readManifest(contentDir) {
4534
4553
  const manifestPath = import_node_path7.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
4535
4554
  if (!(0, import_node_fs5.existsSync)(manifestPath)) return null;
4536
4555
  try {
4537
- const parsed = JSON.parse((0, import_node_fs5.readFileSync)(manifestPath, "utf8"));
4556
+ const parsed = JSON.parse(
4557
+ (0, import_node_fs5.readFileSync)(manifestPath, "utf8")
4558
+ );
4538
4559
  if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
4539
4560
  const pages = Object.fromEntries(
4540
4561
  Object.entries(parsed.pages).filter(
@@ -10706,16 +10727,7 @@ __export(devtools_client_exports, {
10706
10727
  function parseShortcut(shortcut) {
10707
10728
  const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim()).filter(Boolean);
10708
10729
  const key = tokens.find(
10709
- (token) => ![
10710
- "alt",
10711
- "ctrl",
10712
- "control",
10713
- "meta",
10714
- "cmd",
10715
- "command",
10716
- "mod",
10717
- "shift"
10718
- ].includes(token)
10730
+ (token) => !["alt", "ctrl", "control", "meta", "cmd", "command", "mod", "shift"].includes(token)
10719
10731
  );
10720
10732
  if (!key) {
10721
10733
  return null;
@@ -14114,7 +14126,7 @@ function mergeMetadata(base, next) {
14114
14126
  __name(mergeMetadata, "mergeMetadata");
14115
14127
  function addMetadataImageReference(metadata, reference) {
14116
14128
  if (reference.kind === "opengraph") {
14117
- const openGraph = { ...metadata.openGraph || {} };
14129
+ const openGraph = { ...metadata.openGraph };
14118
14130
  if (!hasMetadataImages(openGraph.images) && !hasMetadataImages(openGraph.image)) {
14119
14131
  openGraph.images = [
14120
14132
  {
@@ -14131,7 +14143,7 @@ function addMetadataImageReference(metadata, reference) {
14131
14143
  openGraph
14132
14144
  };
14133
14145
  }
14134
- const twitter = { ...metadata.twitter || {} };
14146
+ const twitter = { ...metadata.twitter };
14135
14147
  if (!hasMetadataImages(twitter.images)) {
14136
14148
  twitter.images = [reference.href];
14137
14149
  twitter.card = twitter.card || "summary_large_image";
@@ -14737,8 +14749,8 @@ var _FarmI18nRuntime = class _FarmI18nRuntime {
14737
14749
  cookie: this.config.cookie,
14738
14750
  direction: getFarmLocaleDirection(resolution.locale, this.config.direction),
14739
14751
  messages: {
14740
- ...this.catalogs[this.config.fallbackLocale] || {},
14741
- ...this.catalogs[resolution.locale] || {}
14752
+ ...this.catalogs[this.config.fallbackLocale],
14753
+ ...this.catalogs[resolution.locale]
14742
14754
  }
14743
14755
  };
14744
14756
  }
@@ -16212,11 +16224,7 @@ var _FarmApp = class _FarmApp {
16212
16224
  _setDefaultFarmI18nRuntime(this.i18nRuntime);
16213
16225
  this.viteServer = viteServer;
16214
16226
  this.routeManager = new RouteManager(this.config, viteServer);
16215
- this.serverRenderer = new ServerRenderer(
16216
- this.config,
16217
- this.routeManager,
16218
- this.i18nRuntime
16219
- );
16227
+ this.serverRenderer = new ServerRenderer(this.config, this.routeManager, this.i18nRuntime);
16220
16228
  }
16221
16229
  async initialize() {
16222
16230
  if (process.env.FARM_VERBOSE) {
@@ -16661,6 +16669,29 @@ var fs3 = __toESM(require("fs"));
16661
16669
  var path10 = __toESM(require("path"));
16662
16670
  init_route_runtime();
16663
16671
 
16672
+ // src/api/runtime.ts
16673
+ init_cache_invalidation();
16674
+
16675
+ // src/api/endpoint.ts
16676
+ var import_better_call = require("better-call");
16677
+ var _EndpointFailure = class _EndpointFailure extends Error {
16678
+ constructor(code, data, options) {
16679
+ super(options.message);
16680
+ this.name = "EndpointFailure";
16681
+ this.code = code;
16682
+ this.data = data;
16683
+ this.status = options.status;
16684
+ }
16685
+ };
16686
+ __name(_EndpointFailure, "EndpointFailure");
16687
+ var EndpointFailure = _EndpointFailure;
16688
+ function isEndpointFailure(value) {
16689
+ return value instanceof EndpointFailure;
16690
+ }
16691
+ __name(isEndpointFailure, "isEndpointFailure");
16692
+ var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
16693
+ var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
16694
+
16664
16695
  // src/api/runtime.ts
16665
16696
  function matchAPIRoute(routes, pathname) {
16666
16697
  const exactRoute = routes.get(pathname);
@@ -16693,10 +16724,10 @@ __name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
16693
16724
  async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
16694
16725
  const farmHandler = endpoint.__handler || (isFarmContextHandler(endpoint) ? endpoint : null);
16695
16726
  if (!farmHandler) {
16696
- const result2 = await endpoint(request, {
16727
+ const result = await endpoint(request, {
16697
16728
  params: Promise.resolve(params)
16698
16729
  });
16699
- return normalizeRouteResponse(result2);
16730
+ return normalizeRouteResponse(result);
16700
16731
  }
16701
16732
  const url = new URL(request.url);
16702
16733
  const query = {};
@@ -16721,15 +16752,30 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
16721
16752
  if (headersValidation instanceof Response) {
16722
16753
  return headersValidation;
16723
16754
  }
16724
- const result = await farmHandler({
16755
+ const handlerContext = {
16725
16756
  query: queryValidation,
16726
16757
  body: bodyValidation,
16727
16758
  headers: headersValidation,
16728
16759
  request,
16729
16760
  context: {},
16730
16761
  params
16731
- });
16732
- return normalizeRouteResponse(result);
16762
+ };
16763
+ let execution;
16764
+ try {
16765
+ execution = typeof endpoint.__farmInvoke === "function" ? await endpoint.__farmInvoke(handlerContext) : {
16766
+ result: await farmHandler(handlerContext),
16767
+ context: handlerContext.context,
16768
+ handlerExecuted: true,
16769
+ invalidations: []
16770
+ };
16771
+ } catch (error) {
16772
+ if (isEndpointFailure(error)) {
16773
+ return createEndpointFailureResponse(error);
16774
+ }
16775
+ throw error;
16776
+ }
16777
+ const response = normalizeRouteResponse(execution.result);
16778
+ return attachEndpointInvalidations(response, execution.invalidations);
16733
16779
  }
16734
16780
  __name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
16735
16781
  function normalizeRouteResponse(result) {
@@ -16749,6 +16795,40 @@ function isWebResponse2(value) {
16749
16795
  return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
16750
16796
  }
16751
16797
  __name(isWebResponse2, "isWebResponse");
16798
+ function attachEndpointInvalidations(response, keys) {
16799
+ const existing = decodeFarmCacheInvalidations(
16800
+ response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
16801
+ );
16802
+ const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
16803
+ if (!encoded) return response;
16804
+ const headers = new Headers(response.headers);
16805
+ headers.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
16806
+ return new Response(response.body, {
16807
+ status: response.status,
16808
+ statusText: response.statusText,
16809
+ headers
16810
+ });
16811
+ }
16812
+ __name(attachEndpointInvalidations, "attachEndpointInvalidations");
16813
+ function createEndpointFailureResponse(failure) {
16814
+ return new Response(
16815
+ JSON.stringify({
16816
+ error: {
16817
+ code: failure.code,
16818
+ message: failure.message,
16819
+ data: failure.data
16820
+ }
16821
+ }),
16822
+ {
16823
+ status: failure.status,
16824
+ headers: {
16825
+ "cache-control": "no-store",
16826
+ "content-type": "application/json"
16827
+ }
16828
+ }
16829
+ );
16830
+ }
16831
+ __name(createEndpointFailureResponse, "createEndpointFailureResponse");
16752
16832
  function isFarmContextHandler(endpoint) {
16753
16833
  if (typeof endpoint !== "function") {
16754
16834
  return false;
@@ -17777,7 +17857,7 @@ var _MiddlewareManager = class _MiddlewareManager {
17777
17857
  if (!nestedMatch.matched) {
17778
17858
  return { matched: false };
17779
17859
  }
17780
- const params = { ...nestedMatch.params || {} };
17860
+ const params = { ...nestedMatch.params };
17781
17861
  delete params.__farmRest;
17782
17862
  return {
17783
17863
  matched: true,
@@ -18678,7 +18758,7 @@ function isResolvedEnvScope(value) {
18678
18758
  }
18679
18759
  __name(isResolvedEnvScope, "isResolvedEnvScope");
18680
18760
  function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
18681
- return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !/\.d\.ts$/.test(normalizedFile) && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
18761
+ return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !normalizedFile.endsWith(".d.ts") && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
18682
18762
  }
18683
18763
  __name(isPotentialProgrammaticRouteSourceFile, "isPotentialProgrammaticRouteSourceFile");
18684
18764
  function fileContainsProgrammaticPageRoute(file) {