@farm.js/core 0.1.0-beta.48 → 0.1.0-beta.49

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 (92) hide show
  1. package/dist/api/route-manager.cjs.map +1 -1
  2. package/dist/api/route-manager.mjs +2 -2
  3. package/dist/api.cjs.map +1 -1
  4. package/dist/api.mjs +3 -3
  5. package/dist/{chunk-TIESOJ7Z.mjs → chunk-BOSVED4K.mjs} +2 -2
  6. package/dist/{chunk-XR7M5VXU.mjs → chunk-DF6GAB63.mjs} +2 -2
  7. package/dist/{chunk-3P63LWDM.mjs → chunk-DWG3W2FN.mjs} +2 -2
  8. package/dist/{chunk-3UUEBVR3.mjs → chunk-ECGXDMBF.mjs} +3 -3
  9. package/dist/{chunk-MP2SDRRB.mjs → chunk-HB3XKQ5X.mjs} +2 -2
  10. package/dist/{chunk-EHUGMAWL.mjs → chunk-LIBL3V6K.mjs} +3 -3
  11. package/dist/{chunk-ECLWCE4H.mjs → chunk-MHE2AMUC.mjs} +2 -2
  12. package/dist/{chunk-GXASWWJU.mjs → chunk-RS5Z5M26.mjs} +5 -2
  13. package/dist/chunk-RS5Z5M26.mjs.map +1 -0
  14. package/dist/{chunk-HEZHCCMF.mjs → chunk-UQ3PDDAK.mjs} +65 -29
  15. package/dist/chunk-UQ3PDDAK.mjs.map +1 -0
  16. package/dist/{chunk-VZKOMD6C.mjs → chunk-VVVDVGAS.mjs} +8 -8
  17. package/dist/{chunk-NKIHYEWC.mjs → chunk-X3JR4G7L.mjs} +2 -2
  18. package/dist/{chunk-NKIHYEWC.mjs.map → chunk-X3JR4G7L.mjs.map} +1 -1
  19. package/dist/{chunk-4E6VRJ6P.mjs → chunk-XY3B4K5E.mjs} +6 -3
  20. package/dist/chunk-XY3B4K5E.mjs.map +1 -0
  21. package/dist/{chunk-U5SPS2HR.mjs → chunk-YB7QPRM4.mjs} +6 -1
  22. package/dist/chunk-YB7QPRM4.mjs.map +1 -0
  23. package/dist/client/lifecycle.mjs +2 -2
  24. package/dist/client-plugins.cjs +1 -1
  25. package/dist/client-plugins.cjs.map +1 -1
  26. package/dist/client-plugins.mjs +2 -2
  27. package/dist/client.cjs +1 -1
  28. package/dist/client.cjs.map +1 -1
  29. package/dist/client.mjs +2 -2
  30. package/dist/cron.cjs +9 -1
  31. package/dist/cron.cjs.map +1 -1
  32. package/dist/cron.mjs +2 -1
  33. package/dist/{devtools-BUFIHBX3.mjs → devtools-S7KR2MMF.mjs} +5 -4
  34. package/dist/{devtools-BUFIHBX3.mjs.map → devtools-S7KR2MMF.mjs.map} +1 -1
  35. package/dist/docs.mjs +5 -4
  36. package/dist/index.cjs +66 -23
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.mts +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.mjs +15 -13
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/internal/build-runtime.cjs +230 -189
  43. package/dist/internal/build-runtime.cjs.map +1 -1
  44. package/dist/internal/build-runtime.d.mts +1 -1
  45. package/dist/internal/build-runtime.d.ts +1 -1
  46. package/dist/internal/build-runtime.mjs +10 -10
  47. package/dist/internal/client-runtime.cjs +1 -1
  48. package/dist/internal/client-runtime.cjs.map +1 -1
  49. package/dist/internal/client-runtime.mjs +2 -2
  50. package/dist/internal/config-runtime.cjs +10 -10
  51. package/dist/internal/config-runtime.cjs.map +1 -1
  52. package/dist/internal/config-runtime.d.mts +1 -1
  53. package/dist/internal/config-runtime.d.ts +1 -1
  54. package/dist/internal/config-runtime.mjs +4 -4
  55. package/dist/middleware.cjs.map +1 -1
  56. package/dist/middleware.mjs +3 -3
  57. package/dist/{nitro-G3BP7E7F.mjs → nitro-VXD26VW2.mjs} +4 -3
  58. package/dist/{nitro-G3BP7E7F.mjs.map → nitro-VXD26VW2.mjs.map} +1 -1
  59. package/dist/plugin.cjs +171 -149
  60. package/dist/plugin.cjs.map +1 -1
  61. package/dist/plugin.mjs +7 -7
  62. package/dist/server.cjs +203 -177
  63. package/dist/server.cjs.map +1 -1
  64. package/dist/server.d.mts +1 -1
  65. package/dist/server.d.ts +1 -1
  66. package/dist/server.mjs +10 -8
  67. package/dist/server.mjs.map +1 -1
  68. package/dist/testing.mjs +2 -2
  69. package/dist/{utils-9OPxcT1T.d.mts → utils--3v-RtD3.d.mts} +7 -1
  70. package/dist/{utils-CIIoLfn9.d.ts → utils-J3ipMElz.d.ts} +7 -1
  71. package/dist/version.cjs +1 -1
  72. package/dist/version.cjs.map +1 -1
  73. package/dist/version.mjs +1 -1
  74. package/dist/vite.cjs +171 -149
  75. package/dist/vite.cjs.map +1 -1
  76. package/dist/vite.mjs +7 -7
  77. package/dist/workflows.cjs +8 -2
  78. package/dist/workflows.cjs.map +1 -1
  79. package/dist/workflows.mjs +2 -1
  80. package/package.json +1 -1
  81. package/dist/chunk-4E6VRJ6P.mjs.map +0 -1
  82. package/dist/chunk-GXASWWJU.mjs.map +0 -1
  83. package/dist/chunk-HEZHCCMF.mjs.map +0 -1
  84. package/dist/chunk-U5SPS2HR.mjs.map +0 -1
  85. /package/dist/{chunk-TIESOJ7Z.mjs.map → chunk-BOSVED4K.mjs.map} +0 -0
  86. /package/dist/{chunk-XR7M5VXU.mjs.map → chunk-DF6GAB63.mjs.map} +0 -0
  87. /package/dist/{chunk-3P63LWDM.mjs.map → chunk-DWG3W2FN.mjs.map} +0 -0
  88. /package/dist/{chunk-3UUEBVR3.mjs.map → chunk-ECGXDMBF.mjs.map} +0 -0
  89. /package/dist/{chunk-MP2SDRRB.mjs.map → chunk-HB3XKQ5X.mjs.map} +0 -0
  90. /package/dist/{chunk-EHUGMAWL.mjs.map → chunk-LIBL3V6K.mjs.map} +0 -0
  91. /package/dist/{chunk-ECLWCE4H.mjs.map → chunk-MHE2AMUC.mjs.map} +0 -0
  92. /package/dist/{chunk-VZKOMD6C.mjs.map → chunk-VVVDVGAS.mjs.map} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  memoryRateLimitStorage,
8
8
  middleware,
9
9
  unwrapMiddleware
10
- } from "./chunk-ECLWCE4H.mjs";
10
+ } from "./chunk-MHE2AMUC.mjs";
11
11
  import {
12
12
  applyProductionMiddlewareHeaders,
13
13
  createProductionMiddlewareRunner
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  MiddlewareManager,
17
17
  createContext
18
- } from "./chunk-TIESOJ7Z.mjs";
18
+ } from "./chunk-BOSVED4K.mjs";
19
19
  import {
20
20
  _runWithMiddlewareContext,
21
21
  _runWithMiddlewareData,
@@ -24,7 +24,7 @@ import {
24
24
  getMiddlewareValue
25
25
  } from "./chunk-P7QDS5AT.mjs";
26
26
  import "./chunk-GIELMNBG.mjs";
27
- import "./chunk-U5SPS2HR.mjs";
27
+ import "./chunk-YB7QPRM4.mjs";
28
28
  import "./chunk-QGOHVJ6J.mjs";
29
29
  import "./chunk-RHIFZZUI.mjs";
30
30
  import "./chunk-LM2YNO4U.mjs";
@@ -3,13 +3,14 @@ import {
3
3
  } from "./chunk-H3A35IQ2.mjs";
4
4
  import {
5
5
  prepareFarmWorkflowsForNitro
6
- } from "./chunk-4E6VRJ6P.mjs";
6
+ } from "./chunk-XY3B4K5E.mjs";
7
7
  import {
8
8
  createFarmCronCloudflareConfig,
9
9
  mergeScheduledTasks,
10
10
  prepareFarmCronForNitro
11
- } from "./chunk-GXASWWJU.mjs";
11
+ } from "./chunk-RS5Z5M26.mjs";
12
12
  import "./chunk-SXWF4QRU.mjs";
13
+ import "./chunk-YB7QPRM4.mjs";
13
14
  import "./chunk-YTMDIHQN.mjs";
14
15
  import {
15
16
  __name
@@ -676,4 +677,4 @@ export {
676
677
  createNitroConfig,
677
678
  getNitroPreset
678
679
  };
679
- //# sourceMappingURL=nitro-G3BP7E7F.mjs.map
680
+ //# sourceMappingURL=nitro-VXD26VW2.mjs.map
@@ -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';\nimport { searchParamsToObject } from '@farm.js/core/internal/production-runtime';\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 = searchParamsToObject(url.searchParams);\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 (typeof PageComponent === \"function\" && PageComponent.constructor.name === \"AsyncFunction\") {\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"]}
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';\nimport { searchParamsToObject } from '@farm.js/core/internal/production-runtime';\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 = searchParamsToObject(url.searchParams);\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 (typeof PageComponent === \"function\" && PageComponent.constructor.name === \"AsyncFunction\") {\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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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["routePaths","clientManifestPath"]}
package/dist/plugin.cjs CHANGED
@@ -822,6 +822,160 @@ var init_server_http = __esm({
822
822
  }
823
823
  });
824
824
 
825
+ // src/utils.ts
826
+ function parseRoutePath(filePath) {
827
+ const segments = [];
828
+ const normalizedPath = filePath.replace(/\\/g, "/");
829
+ const pathParts = normalizedPath.split("/").filter(Boolean);
830
+ const fileName = pathParts.pop() || "";
831
+ const fileType = getRouteType(fileName);
832
+ for (const part of pathParts) {
833
+ if (part.startsWith("(") && part.endsWith(")")) continue;
834
+ if (part.startsWith("[") && part.endsWith("]")) {
835
+ let segment = part.slice(1, -1);
836
+ const isDynamic = true;
837
+ let isOptional = false;
838
+ let isCatchAll = false;
839
+ if (segment.startsWith("[") && segment.endsWith("]")) {
840
+ isOptional = true;
841
+ segment = segment.slice(1, -1);
842
+ if (segment.startsWith("...")) {
843
+ segment = segment.slice(3);
844
+ isCatchAll = true;
845
+ }
846
+ } else if (segment.startsWith("...")) {
847
+ segment = segment.slice(3);
848
+ isCatchAll = true;
849
+ }
850
+ segments.push({ segment, isDynamic, isOptional, isCatchAll });
851
+ } else {
852
+ segments.push({
853
+ segment: part,
854
+ isDynamic: false,
855
+ isOptional: false,
856
+ isCatchAll: false
857
+ });
858
+ }
859
+ }
860
+ return {
861
+ segments,
862
+ filePath: normalizedPath,
863
+ type: fileType
864
+ };
865
+ }
866
+ function getRouteType(fileName) {
867
+ const baseName = fileName.replace(/\.(tsx?|jsx?|vue|svelte|mdx?|markdown)$/, "");
868
+ switch (baseName) {
869
+ case "page":
870
+ return "page";
871
+ case "layout":
872
+ return "layout";
873
+ case "loading":
874
+ return "loading";
875
+ case "error":
876
+ return "error";
877
+ case "not-found":
878
+ return "not-found";
879
+ default:
880
+ return "page";
881
+ }
882
+ }
883
+ function matchRoute(url, segments) {
884
+ const urlParts = url.split("/").filter(Boolean);
885
+ const params = {};
886
+ if (segments.length === 0) {
887
+ return { params, matches: urlParts.length === 0 };
888
+ }
889
+ let urlIndex = 0;
890
+ let segmentIndex = 0;
891
+ while (segmentIndex < segments.length && urlIndex <= urlParts.length) {
892
+ const segment = segments[segmentIndex];
893
+ if (!segment.isDynamic) {
894
+ if (urlParts[urlIndex] !== segment.segment) {
895
+ return { params: {}, matches: false };
896
+ }
897
+ urlIndex++;
898
+ segmentIndex++;
899
+ } else if (segment.isCatchAll) {
900
+ const remainingParts = urlParts.slice(urlIndex);
901
+ if (remainingParts.length === 0 && !segment.isOptional) {
902
+ return { params: {}, matches: false };
903
+ }
904
+ params[segment.segment] = remainingParts.join("/");
905
+ urlIndex = urlParts.length;
906
+ segmentIndex++;
907
+ } else {
908
+ if (urlIndex >= urlParts.length) {
909
+ return { params: {}, matches: false };
910
+ }
911
+ params[segment.segment] = urlParts[urlIndex];
912
+ urlIndex++;
913
+ segmentIndex++;
914
+ }
915
+ }
916
+ const matches = segmentIndex === segments.length && urlIndex === urlParts.length;
917
+ return { params, matches };
918
+ }
919
+ function resolveAppPath(root, ...paths) {
920
+ return import_path.default.resolve(root, ...paths);
921
+ }
922
+ function toRootRelativeUrlPath(absolutePath, projectRoot) {
923
+ if (absolutePath === projectRoot) return "";
924
+ if (absolutePath.startsWith(`${projectRoot}/`) || absolutePath.startsWith(`${projectRoot}\\`)) {
925
+ return absolutePath.slice(projectRoot.length).replace(/\\/g, "/");
926
+ }
927
+ return void 0;
928
+ }
929
+ function toPosixPath(filePath) {
930
+ return filePath.replace(/\\/g, "/");
931
+ }
932
+ function toViteModuleId(filePath, root) {
933
+ if (!import_path.default.isAbsolute(filePath)) return filePath;
934
+ const relativePath2 = import_path.default.relative(root, filePath);
935
+ if (relativePath2 && !relativePath2.startsWith("..") && !import_path.default.isAbsolute(relativePath2)) {
936
+ return `/${relativePath2.split(import_path.default.sep).join("/")}`;
937
+ }
938
+ const normalizedPath = filePath.replace(/\\/g, "/");
939
+ return normalizedPath.startsWith("/") ? `/@fs${normalizedPath}` : `/@fs/${normalizedPath}`;
940
+ }
941
+ async function fileExists(filePath) {
942
+ try {
943
+ const fs11 = await import("fs/promises");
944
+ await fs11.access(filePath);
945
+ return true;
946
+ } catch {
947
+ return false;
948
+ }
949
+ }
950
+ async function globFiles(pattern, cwd) {
951
+ const glob = await import("fast-glob");
952
+ return glob.default(pattern, { cwd, absolute: false });
953
+ }
954
+ var import_path, logger;
955
+ var init_utils = __esm({
956
+ "src/utils.ts"() {
957
+ "use strict";
958
+ import_path = __toESM(require("path"));
959
+ __name(parseRoutePath, "parseRoutePath");
960
+ __name(getRouteType, "getRouteType");
961
+ __name(matchRoute, "matchRoute");
962
+ __name(resolveAppPath, "resolveAppPath");
963
+ __name(toRootRelativeUrlPath, "toRootRelativeUrlPath");
964
+ __name(toPosixPath, "toPosixPath");
965
+ __name(toViteModuleId, "toViteModuleId");
966
+ __name(fileExists, "fileExists");
967
+ __name(globFiles, "globFiles");
968
+ logger = {
969
+ info: /* @__PURE__ */ __name((message) => console.log(`[info] ${message}`), "info"),
970
+ success: /* @__PURE__ */ __name((message) => console.log(`[success] ${message}`), "success"),
971
+ warn: /* @__PURE__ */ __name((message) => console.warn(`\u26A0\uFE0F ${message}`), "warn"),
972
+ error: /* @__PURE__ */ __name((message) => console.error(`\u274C ${message}`), "error"),
973
+ ready: /* @__PURE__ */ __name((message) => console.log(`${message}`), "ready"),
974
+ event: /* @__PURE__ */ __name((message) => console.log(` ${message}`), "event")
975
+ };
976
+ }
977
+ });
978
+
825
979
  // src/workflows.ts
826
980
  var workflows_exports = {};
827
981
  __export(workflows_exports, {
@@ -990,14 +1144,14 @@ async function prepareFarmWorkflowsForNitro(config) {
990
1144
  const tasks = {};
991
1145
  const scheduledTasks = createScheduledTasks(workflows);
992
1146
  for (const workflow of workflows) {
993
- const wrapperPath = path30.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
1147
+ const wrapperPath = toPosixPath(path30.join(generatedDir, `${safeFileName(workflow.id)}.mjs`));
994
1148
  await fs11.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
995
1149
  tasks[workflow.id] = {
996
1150
  handler: wrapperPath,
997
1151
  description: workflow.description || `Farm workflow ${workflow.id}`
998
1152
  };
999
1153
  }
1000
- const handlerPath = path30.join(generatedDir, "http-handler.mjs");
1154
+ const handlerPath = toPosixPath(path30.join(generatedDir, "http-handler.mjs"));
1001
1155
  await fs11.writeFile(
1002
1156
  handlerPath,
1003
1157
  createNitroWorkflowHTTPHandler(
@@ -1356,6 +1510,7 @@ var init_workflows = __esm({
1356
1510
  "src/workflows.ts"() {
1357
1511
  "use strict";
1358
1512
  init_server_http();
1513
+ init_utils();
1359
1514
  DEFAULT_FARM_WORKFLOW_DIRS = ["src/jobs", "src/workflows", "src/cron"];
1360
1515
  DEFAULT_FARM_WORKFLOW_ROUTE = "/api/_farm/workflows";
1361
1516
  DEFAULT_FARM_WORKFLOW_SECRET_ENV = "CRON_SECRET";
@@ -1508,6 +1663,7 @@ var DEFAULT_FARM_CRON_SECRET_ENV, CRON_FIELD_RANGES;
1508
1663
  var init_cron = __esm({
1509
1664
  "src/cron.ts"() {
1510
1665
  "use strict";
1666
+ init_utils();
1511
1667
  DEFAULT_FARM_CRON_SECRET_ENV = "CRON_SECRET";
1512
1668
  CRON_FIELD_RANGES = [
1513
1669
  [0, 59, "minute"],
@@ -12663,152 +12819,7 @@ init_app_markdown_config();
12663
12819
  init_markdown();
12664
12820
  init_workflows();
12665
12821
  init_cron();
12666
-
12667
- // src/utils.ts
12668
- var import_path = __toESM(require("path"));
12669
- function parseRoutePath(filePath) {
12670
- const segments = [];
12671
- const normalizedPath = filePath.replace(/\\/g, "/");
12672
- const pathParts = normalizedPath.split("/").filter(Boolean);
12673
- const fileName = pathParts.pop() || "";
12674
- const fileType = getRouteType(fileName);
12675
- for (const part of pathParts) {
12676
- if (part.startsWith("(") && part.endsWith(")")) continue;
12677
- if (part.startsWith("[") && part.endsWith("]")) {
12678
- let segment = part.slice(1, -1);
12679
- const isDynamic = true;
12680
- let isOptional = false;
12681
- let isCatchAll = false;
12682
- if (segment.startsWith("[") && segment.endsWith("]")) {
12683
- isOptional = true;
12684
- segment = segment.slice(1, -1);
12685
- if (segment.startsWith("...")) {
12686
- segment = segment.slice(3);
12687
- isCatchAll = true;
12688
- }
12689
- } else if (segment.startsWith("...")) {
12690
- segment = segment.slice(3);
12691
- isCatchAll = true;
12692
- }
12693
- segments.push({ segment, isDynamic, isOptional, isCatchAll });
12694
- } else {
12695
- segments.push({
12696
- segment: part,
12697
- isDynamic: false,
12698
- isOptional: false,
12699
- isCatchAll: false
12700
- });
12701
- }
12702
- }
12703
- return {
12704
- segments,
12705
- filePath: normalizedPath,
12706
- type: fileType
12707
- };
12708
- }
12709
- __name(parseRoutePath, "parseRoutePath");
12710
- function getRouteType(fileName) {
12711
- const baseName = fileName.replace(/\.(tsx?|jsx?|vue|svelte|mdx?|markdown)$/, "");
12712
- switch (baseName) {
12713
- case "page":
12714
- return "page";
12715
- case "layout":
12716
- return "layout";
12717
- case "loading":
12718
- return "loading";
12719
- case "error":
12720
- return "error";
12721
- case "not-found":
12722
- return "not-found";
12723
- default:
12724
- return "page";
12725
- }
12726
- }
12727
- __name(getRouteType, "getRouteType");
12728
- function matchRoute(url, segments) {
12729
- const urlParts = url.split("/").filter(Boolean);
12730
- const params = {};
12731
- if (segments.length === 0) {
12732
- return { params, matches: urlParts.length === 0 };
12733
- }
12734
- let urlIndex = 0;
12735
- let segmentIndex = 0;
12736
- while (segmentIndex < segments.length && urlIndex <= urlParts.length) {
12737
- const segment = segments[segmentIndex];
12738
- if (!segment.isDynamic) {
12739
- if (urlParts[urlIndex] !== segment.segment) {
12740
- return { params: {}, matches: false };
12741
- }
12742
- urlIndex++;
12743
- segmentIndex++;
12744
- } else if (segment.isCatchAll) {
12745
- const remainingParts = urlParts.slice(urlIndex);
12746
- if (remainingParts.length === 0 && !segment.isOptional) {
12747
- return { params: {}, matches: false };
12748
- }
12749
- params[segment.segment] = remainingParts.join("/");
12750
- urlIndex = urlParts.length;
12751
- segmentIndex++;
12752
- } else {
12753
- if (urlIndex >= urlParts.length) {
12754
- return { params: {}, matches: false };
12755
- }
12756
- params[segment.segment] = urlParts[urlIndex];
12757
- urlIndex++;
12758
- segmentIndex++;
12759
- }
12760
- }
12761
- const matches = segmentIndex === segments.length && urlIndex === urlParts.length;
12762
- return { params, matches };
12763
- }
12764
- __name(matchRoute, "matchRoute");
12765
- function resolveAppPath(root, ...paths) {
12766
- return import_path.default.resolve(root, ...paths);
12767
- }
12768
- __name(resolveAppPath, "resolveAppPath");
12769
- function toRootRelativeUrlPath(absolutePath, projectRoot) {
12770
- if (absolutePath === projectRoot) return "";
12771
- if (absolutePath.startsWith(`${projectRoot}/`) || absolutePath.startsWith(`${projectRoot}\\`)) {
12772
- return absolutePath.slice(projectRoot.length).replace(/\\/g, "/");
12773
- }
12774
- return void 0;
12775
- }
12776
- __name(toRootRelativeUrlPath, "toRootRelativeUrlPath");
12777
- function toViteModuleId(filePath, root) {
12778
- if (!import_path.default.isAbsolute(filePath)) return filePath;
12779
- const relativePath2 = import_path.default.relative(root, filePath);
12780
- if (relativePath2 && !relativePath2.startsWith("..") && !import_path.default.isAbsolute(relativePath2)) {
12781
- return `/${relativePath2.split(import_path.default.sep).join("/")}`;
12782
- }
12783
- const normalizedPath = filePath.replace(/\\/g, "/");
12784
- return normalizedPath.startsWith("/") ? `/@fs${normalizedPath}` : `/@fs/${normalizedPath}`;
12785
- }
12786
- __name(toViteModuleId, "toViteModuleId");
12787
- async function fileExists(filePath) {
12788
- try {
12789
- const fs11 = await import("fs/promises");
12790
- await fs11.access(filePath);
12791
- return true;
12792
- } catch {
12793
- return false;
12794
- }
12795
- }
12796
- __name(fileExists, "fileExists");
12797
- async function globFiles(pattern, cwd) {
12798
- const glob = await import("fast-glob");
12799
- return glob.default(pattern, { cwd, absolute: false });
12800
- }
12801
- __name(globFiles, "globFiles");
12802
- var logger = {
12803
- info: /* @__PURE__ */ __name((message) => console.log(`[info] ${message}`), "info"),
12804
- success: /* @__PURE__ */ __name((message) => console.log(`[success] ${message}`), "success"),
12805
- warn: /* @__PURE__ */ __name((message) => console.warn(`\u26A0\uFE0F ${message}`), "warn"),
12806
- error: /* @__PURE__ */ __name((message) => console.error(`\u274C ${message}`), "error"),
12807
- ready: /* @__PURE__ */ __name((message) => console.log(`${message}`), "ready"),
12808
- event: /* @__PURE__ */ __name((message) => console.log(` ${message}`), "event")
12809
- };
12810
-
12811
- // src/app.ts
12822
+ init_utils();
12812
12823
  init_storage();
12813
12824
  init_observability();
12814
12825
  init_route_rules();
@@ -12817,6 +12828,9 @@ init_server_http();
12817
12828
  init_image_config();
12818
12829
  init_layers();
12819
12830
 
12831
+ // src/routing/route-manager.ts
12832
+ init_utils();
12833
+
12820
12834
  // src/ssg.ts
12821
12835
  var import_promises2 = require("fs/promises");
12822
12836
  var OPTIONAL_CATCH_ALL_SEGMENT = /^\[\[\.\.\.([^\]]+)\]\]$/;
@@ -14568,6 +14582,7 @@ function normalizePathname(pathname) {
14568
14582
  __name(normalizePathname, "normalizePathname");
14569
14583
 
14570
14584
  // src/routing/route-slots.ts
14585
+ init_utils();
14571
14586
  var SLOT_SEGMENT = /^@([A-Za-z][A-Za-z0-9_-]*)$/;
14572
14587
  function parseRouteSlotFile(filePath) {
14573
14588
  const normalized = filePath.replace(/\\/g, "/");
@@ -15620,6 +15635,7 @@ __name(safeGlobFiles, "safeGlobFiles");
15620
15635
  // src/server/renderer.ts
15621
15636
  var fs3 = __toESM(require("fs"));
15622
15637
  var path11 = __toESM(require("path"));
15638
+ init_utils();
15623
15639
 
15624
15640
  // src/server/full-document.ts
15625
15641
  function stripContentsWrappers(markup) {
@@ -19021,7 +19037,7 @@ _setFarmThemeServerSnapshotResolver(() => {
19021
19037
  });
19022
19038
 
19023
19039
  // package.json
19024
- var version = "0.1.0-beta.48";
19040
+ var version = "0.1.0-beta.49";
19025
19041
 
19026
19042
  // src/version.ts
19027
19043
  var FARM_VERSION = version;
@@ -21251,6 +21267,9 @@ function normalizeFarmAppAPIConfig(config) {
21251
21267
  }
21252
21268
  __name(normalizeFarmAppAPIConfig, "normalizeFarmAppAPIConfig");
21253
21269
 
21270
+ // src/vite.ts
21271
+ init_utils();
21272
+
21254
21273
  // src/default-styles.ts
21255
21274
  var defaultGlobalCSS = `@import "tailwindcss";
21256
21275
  `;
@@ -21528,6 +21547,7 @@ __name(isArrayIndex, "isArrayIndex");
21528
21547
  // src/api/route-manager.ts
21529
21548
  var fs5 = __toESM(require("fs"));
21530
21549
  var path15 = __toESM(require("path"));
21550
+ init_utils();
21531
21551
  init_route_runtime();
21532
21552
 
21533
21553
  // src/api/runtime.ts
@@ -22435,6 +22455,7 @@ function normalizeMiddlewareModule(middlewareModule, routePath) {
22435
22455
  __name(normalizeMiddlewareModule, "normalizeMiddlewareModule");
22436
22456
 
22437
22457
  // src/middleware/manager.ts
22458
+ init_utils();
22438
22459
  init_response();
22439
22460
  init_observability();
22440
22461
 
@@ -22881,6 +22902,7 @@ init_type_generator();
22881
22902
  // src/routing/generate-route-types.ts
22882
22903
  var path17 = __toESM(require("path"));
22883
22904
  var fs7 = __toESM(require("fs"));
22905
+ init_utils();
22884
22906
  init_write_file_if_changed();
22885
22907
  init_renderer();
22886
22908
  function routeSegmentsToTsTypeLiteral(segments) {