@flight-framework/core 0.6.5 → 0.6.7

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 (161) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +541 -541
  3. package/dist/actions/index.d.ts +1 -58
  4. package/dist/actions/index.js +1 -1
  5. package/dist/adapters/index.js +1 -1
  6. package/dist/cache/index.js +1 -1
  7. package/dist/{chunk-FSJNOPYE.js → chunk-2JVEH76V.js} +3 -3
  8. package/dist/chunk-2JVEH76V.js.map +1 -0
  9. package/dist/{chunk-VPFMHGEV.js → chunk-3N5ZBVZJ.js} +2 -2
  10. package/dist/chunk-3N5ZBVZJ.js.map +1 -0
  11. package/dist/{chunk-2F2QU6RC.js → chunk-3UQJE3XZ.js} +2 -2
  12. package/dist/chunk-3UQJE3XZ.js.map +1 -0
  13. package/dist/{chunk-3KRBRSRJ.js → chunk-4U7CJVNQ.js} +2 -2
  14. package/dist/chunk-4U7CJVNQ.js.map +1 -0
  15. package/dist/{chunk-PDW5WCMW.js → chunk-5XHOLZBJ.js} +2 -2
  16. package/dist/chunk-5XHOLZBJ.js.map +1 -0
  17. package/dist/{chunk-MDQNNIHH.js → chunk-65JYF3DJ.js} +2 -2
  18. package/dist/chunk-65JYF3DJ.js.map +1 -0
  19. package/dist/{chunk-K2CQZPCG.js → chunk-6GI6HFSQ.js} +2 -2
  20. package/dist/chunk-6GI6HFSQ.js.map +1 -0
  21. package/dist/{chunk-LNV47HGV.js → chunk-6IG6XIXU.js} +2 -2
  22. package/dist/chunk-6IG6XIXU.js.map +1 -0
  23. package/dist/{chunk-PVUMB632.js → chunk-A2QRUBVE.js} +2 -2
  24. package/dist/chunk-A2QRUBVE.js.map +1 -0
  25. package/dist/{chunk-W6D62JCI.js → chunk-A4TKWQBU.js} +2 -2
  26. package/dist/chunk-A4TKWQBU.js.map +1 -0
  27. package/dist/{chunk-GCQZ4FHI.js → chunk-ARBKF6VI.js} +2 -2
  28. package/dist/{chunk-GCQZ4FHI.js.map → chunk-ARBKF6VI.js.map} +1 -1
  29. package/dist/{chunk-ZVC3ZWLM.js → chunk-B2LPSCES.js} +2 -2
  30. package/dist/chunk-B2LPSCES.js.map +1 -0
  31. package/dist/{chunk-62C7LX2E.js → chunk-CKJHJPKQ.js} +2 -2
  32. package/dist/chunk-CKJHJPKQ.js.map +1 -0
  33. package/dist/{chunk-RSVA2EYO.js → chunk-CNY3ZUVG.js} +2 -2
  34. package/dist/chunk-CNY3ZUVG.js.map +1 -0
  35. package/dist/{chunk-IXMD5QH2.js → chunk-EHVUAFNH.js} +2 -2
  36. package/dist/chunk-EHVUAFNH.js.map +1 -0
  37. package/dist/{chunk-P6WSBVDT.js → chunk-FRAH5QNY.js} +4 -4
  38. package/dist/chunk-FRAH5QNY.js.map +1 -0
  39. package/dist/{chunk-MQQLYWZZ.js → chunk-GNS2FGPC.js} +2 -2
  40. package/dist/chunk-GNS2FGPC.js.map +1 -0
  41. package/dist/{chunk-TASAT7KB.js → chunk-HNPO6LFW.js} +2 -2
  42. package/dist/chunk-HNPO6LFW.js.map +1 -0
  43. package/dist/{chunk-EGB7C73X.js → chunk-KDEA64UX.js} +5 -5
  44. package/dist/chunk-KDEA64UX.js.map +1 -0
  45. package/dist/{chunk-NWMJYTMB.js → chunk-LAKHYTHL.js} +3 -3
  46. package/dist/chunk-LAKHYTHL.js.map +1 -0
  47. package/dist/{chunk-R7SQAREQ.js → chunk-LKOPJ3GS.js} +2 -2
  48. package/dist/chunk-LKOPJ3GS.js.map +1 -0
  49. package/dist/{chunk-WOEIJWGJ.js → chunk-NZS2YJ43.js} +2 -2
  50. package/dist/chunk-NZS2YJ43.js.map +1 -0
  51. package/dist/{chunk-XGP3C2ZE.js → chunk-OZ3EXPLE.js} +4 -112
  52. package/dist/chunk-OZ3EXPLE.js.map +1 -0
  53. package/dist/{chunk-YHEVHRLH.js → chunk-OZBPR27I.js} +2 -2
  54. package/dist/chunk-OZBPR27I.js.map +1 -0
  55. package/dist/{chunk-T4Z4HM4W.js → chunk-PAVI5W6M.js} +3 -3
  56. package/dist/chunk-PAVI5W6M.js.map +1 -0
  57. package/dist/chunk-PL37KFRJ.js +3 -0
  58. package/dist/chunk-PL37KFRJ.js.map +1 -0
  59. package/dist/{chunk-XSY5AAXT.js → chunk-PO7IHPFF.js} +2 -2
  60. package/dist/chunk-PO7IHPFF.js.map +1 -0
  61. package/dist/{chunk-OYF2OAKS.js → chunk-R7MEVVA4.js} +2 -2
  62. package/dist/chunk-R7MEVVA4.js.map +1 -0
  63. package/dist/{chunk-WFAWAHJH.js → chunk-UFWGOJL7.js} +2 -2
  64. package/dist/chunk-UFWGOJL7.js.map +1 -0
  65. package/dist/{chunk-XOIYNY4I.js → chunk-VNO2YUVD.js} +2 -2
  66. package/dist/chunk-VNO2YUVD.js.map +1 -0
  67. package/dist/{chunk-ZIE56LCA.js → chunk-XU6MRYG2.js} +3 -3
  68. package/dist/chunk-XU6MRYG2.js.map +1 -0
  69. package/dist/{chunk-6BDCTUQY.js → chunk-YNTMYL36.js} +3 -3
  70. package/dist/chunk-YNTMYL36.js.map +1 -0
  71. package/dist/{chunk-77MJZCYD.js → chunk-ZQS3WBE7.js} +2 -2
  72. package/dist/chunk-ZQS3WBE7.js.map +1 -0
  73. package/dist/client.d.ts +1 -1
  74. package/dist/client.js +9 -9
  75. package/dist/client.js.map +1 -1
  76. package/dist/config/index.js +1 -1
  77. package/dist/errors/index.js +2 -2
  78. package/dist/file-router/index.js +1 -1
  79. package/dist/file-router/streaming-hints.js +1 -1
  80. package/dist/handlers/index.js +1 -1
  81. package/dist/index.d.ts +1 -3
  82. package/dist/index.js +31 -31
  83. package/dist/index.js.map +1 -1
  84. package/dist/islands/index.js +1 -1
  85. package/dist/middleware/index.js +1 -1
  86. package/dist/react/index.js +2 -2
  87. package/dist/react/index.js.map +1 -1
  88. package/dist/render/index.js +1 -1
  89. package/dist/router/index.js +1 -1
  90. package/dist/rsc/adapters/index.js +4 -4
  91. package/dist/rsc/adapters/preact.js +1 -1
  92. package/dist/rsc/adapters/react.js +1 -1
  93. package/dist/rsc/adapters/solid.js +1 -1
  94. package/dist/rsc/adapters/vue.js +1 -1
  95. package/dist/rsc/boundaries.js +1 -1
  96. package/dist/rsc/context.js +1 -1
  97. package/dist/rsc/index.js +11 -11
  98. package/dist/rsc/legacy.js +1 -1
  99. package/dist/rsc/payload.js +1 -1
  100. package/dist/rsc/plugins/esbuild.js +2 -2
  101. package/dist/rsc/plugins/index.js +4 -4
  102. package/dist/rsc/plugins/rollup.js +2 -2
  103. package/dist/rsc/renderer.js +3 -3
  104. package/dist/rsc/stream.js +1 -1
  105. package/dist/rsc/vite-plugin.js +2 -2
  106. package/dist/server/index.js +4 -4
  107. package/dist/streaming/adapters/index.js +1 -1
  108. package/dist/streaming/conditional.js +1 -1
  109. package/dist/streaming/index.js +1 -1
  110. package/dist/streaming/observability.js +2 -2
  111. package/dist/streaming/priority.js +1 -1
  112. package/dist/utils/index.d.ts +28 -83
  113. package/dist/utils/index.js +2 -2
  114. package/package.json +225 -235
  115. package/dist/chunk-2F2QU6RC.js.map +0 -1
  116. package/dist/chunk-3KRBRSRJ.js.map +0 -1
  117. package/dist/chunk-62C7LX2E.js.map +0 -1
  118. package/dist/chunk-6BDCTUQY.js.map +0 -1
  119. package/dist/chunk-77MJZCYD.js.map +0 -1
  120. package/dist/chunk-EGB7C73X.js.map +0 -1
  121. package/dist/chunk-FSJNOPYE.js.map +0 -1
  122. package/dist/chunk-IXMD5QH2.js.map +0 -1
  123. package/dist/chunk-J7WEZXWH.js +0 -14
  124. package/dist/chunk-J7WEZXWH.js.map +0 -1
  125. package/dist/chunk-K2CQZPCG.js.map +0 -1
  126. package/dist/chunk-LNV47HGV.js.map +0 -1
  127. package/dist/chunk-MDQNNIHH.js.map +0 -1
  128. package/dist/chunk-MFUJN7RV.js +0 -20
  129. package/dist/chunk-MFUJN7RV.js.map +0 -1
  130. package/dist/chunk-MQQLYWZZ.js.map +0 -1
  131. package/dist/chunk-NWMJYTMB.js.map +0 -1
  132. package/dist/chunk-OYF2OAKS.js.map +0 -1
  133. package/dist/chunk-P6WSBVDT.js.map +0 -1
  134. package/dist/chunk-PDW5WCMW.js.map +0 -1
  135. package/dist/chunk-PVUMB632.js.map +0 -1
  136. package/dist/chunk-R7SQAREQ.js.map +0 -1
  137. package/dist/chunk-RSVA2EYO.js.map +0 -1
  138. package/dist/chunk-T4Z4HM4W.js.map +0 -1
  139. package/dist/chunk-TASAT7KB.js.map +0 -1
  140. package/dist/chunk-VPFMHGEV.js.map +0 -1
  141. package/dist/chunk-W6D62JCI.js.map +0 -1
  142. package/dist/chunk-WF46NESN.js +0 -67
  143. package/dist/chunk-WF46NESN.js.map +0 -1
  144. package/dist/chunk-WFAWAHJH.js.map +0 -1
  145. package/dist/chunk-WOEIJWGJ.js.map +0 -1
  146. package/dist/chunk-XGP3C2ZE.js.map +0 -1
  147. package/dist/chunk-XOIYNY4I.js.map +0 -1
  148. package/dist/chunk-XSY5AAXT.js.map +0 -1
  149. package/dist/chunk-YHEVHRLH.js.map +0 -1
  150. package/dist/chunk-ZIE56LCA.js.map +0 -1
  151. package/dist/chunk-ZVC3ZWLM.js.map +0 -1
  152. package/dist/env-9do2c6yn.d.ts +0 -42
  153. package/dist/plugins/env-plugin.d.ts +0 -47
  154. package/dist/plugins/env-plugin.js +0 -3
  155. package/dist/plugins/env-plugin.js.map +0 -1
  156. package/dist/plugins/index.d.ts +0 -221
  157. package/dist/plugins/index.js +0 -192
  158. package/dist/plugins/index.js.map +0 -1
  159. package/dist/plugins/server-boundary-plugin.d.ts +0 -40
  160. package/dist/plugins/server-boundary-plugin.js +0 -3
  161. package/dist/plugins/server-boundary-plugin.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/file-router/index.ts"],"names":[],"mappings":"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","file":"chunk-3KRBRSRJ.js","sourcesContent":["/**\r\n * @flight-framework/core - File Router\r\n * \r\n * Auto-discovery of routes from file system.\r\n * Similar to Next.js App Router and Nuxt server/api patterns.\r\n */\r\n\r\nimport { readdir } from 'node:fs/promises';\r\nimport { join, basename, extname } from 'node:path';\r\nimport { pathToFileURL } from 'node:url';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\r\n\r\nexport type Handler = (context: unknown) => Response | Promise<Response>;\r\nexport type Middleware = (context: unknown, next: () => Promise<Response>) => Response | Promise<Response>;\r\n\r\nexport interface FileRoute {\r\n /** HTTP method (GET, POST, etc) or 'ALL' */\r\n method: HttpMethod | 'ALL';\r\n /** Route path with params (e.g., /users/:id) */\r\n path: string;\r\n /** Original file path */\r\n filePath: string;\r\n /** Handler function (for APIs) */\r\n handler?: Handler;\r\n /** Route-specific middleware */\r\n middleware?: Middleware[];\r\n /** Route type: 'page' for SSR pages, 'api' for API endpoints */\r\n type: 'page' | 'api';\r\n /** Component function (for pages) */\r\n component?: () => unknown;\r\n /** Page metadata (title, description, etc) */\r\n meta?: Record<string, unknown>;\r\n /** Parallel route slot name (for @folder convention) */\r\n slot?: string;\r\n /** Intercepting route info (for (.) (..) (...) convention) */\r\n interceptInfo?: {\r\n /** Number of levels to intercept: 1 = same, 2 = parent, 3+ = root */\r\n level: number;\r\n /** Target route segment to intercept */\r\n target: string;\r\n /** Original path that triggers interception */\r\n interceptPath: string;\r\n };\r\n}\r\n\r\nexport interface FileRouterOptions {\r\n /** Root directory to scan (default: src/routes) */\r\n directory: string;\r\n /** File extensions to consider (default: ['.ts', '.js']) */\r\n extensions?: string[];\r\n /** Whether to watch for changes (default: false in prod) */\r\n watch?: boolean;\r\n /** \r\n * Custom module loader for development with Vite.\r\n * Pass vite.ssrLoadModule to load TSX files correctly.\r\n * Falls back to native import() if not provided.\r\n */\r\n moduleLoader?: (filePath: string) => Promise<any>;\r\n}\r\n\r\nexport interface ScanResult {\r\n routes: FileRoute[];\r\n errors: string[];\r\n}\r\n\r\n// ============================================================================\r\n// File Scanner\r\n// ============================================================================\r\n\r\n/**\r\n * Scan a directory for route files\r\n */\r\nexport async function scanRoutes(options: FileRouterOptions): Promise<ScanResult> {\r\n const {\r\n directory,\r\n extensions = ['.ts', '.js'],\r\n } = options;\r\n\r\n const routes: FileRoute[] = [];\r\n const errors: string[] = [];\r\n\r\n async function scanDir(dir: string, basePath: string = ''): Promise<void> {\r\n try {\r\n const entries = await readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Skip hidden directories and node_modules\r\n if (entry.name.startsWith('.') || entry.name === 'node_modules') {\r\n continue;\r\n }\r\n\r\n // Detect parallel route slots (@folder convention)\r\n if (entry.name.startsWith('@')) {\r\n const slotName = entry.name.slice(1);\r\n // Scan slot directory and mark routes with slot name\r\n const slotRoutes = await scanSlotDir(fullPath, basePath, slotName, extensions);\r\n routes.push(...slotRoutes);\r\n continue;\r\n }\r\n\r\n // Detect intercepting routes ((.) (..) (...) convention)\r\n const interceptMatch = entry.name.match(/^\\((\\.+)\\)(.+)$/);\r\n if (interceptMatch) {\r\n const level = interceptMatch[1].length;\r\n const targetSegment = interceptMatch[2];\r\n // Scan intercept directory and mark routes with interceptInfo\r\n const interceptRoutes = await scanInterceptDir(\r\n fullPath,\r\n basePath,\r\n level,\r\n targetSegment,\r\n extensions\r\n );\r\n routes.push(...interceptRoutes);\r\n continue;\r\n }\r\n\r\n // Detect route groups ((groupName) without dots - organizational only)\r\n // Route groups allow organizing routes without affecting URL structure\r\n // Example: (marketing)/about.page.tsx -> /about (not /marketing/about)\r\n const groupMatch = entry.name.match(/^\\(([^.]+)\\)$/);\r\n if (groupMatch) {\r\n // This is a route group - scan contents but don't add group to path\r\n await scanDir(fullPath, basePath);\r\n continue;\r\n }\r\n\r\n // Recurse into subdirectory\r\n await scanDir(fullPath, `${basePath}/${entry.name}`);\r\n } else if (entry.isFile()) {\r\n const ext = extname(entry.name);\r\n\r\n if (!extensions.includes(ext)) {\r\n continue;\r\n }\r\n\r\n // Parse route from filename\r\n const routeInfo = parseRouteFile(entry.name, basePath);\r\n\r\n if (routeInfo && routeInfo.method && routeInfo.path) {\r\n routes.push({\r\n method: routeInfo.method,\r\n path: routeInfo.path,\r\n filePath: fullPath,\r\n type: routeInfo.type,\r\n });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n errors.push(`Failed to scan ${dir}: ${error}`);\r\n }\r\n }\r\n\r\n await scanDir(directory);\r\n\r\n return { routes, errors };\r\n}\r\n\r\n/**\r\n * Scan a parallel route slot directory\r\n */\r\nasync function scanSlotDir(\r\n dir: string,\r\n basePath: string,\r\n slotName: string,\r\n extensions: string[] = ['.ts', '.js', '.tsx', '.jsx']\r\n): Promise<FileRoute[]> {\r\n const routes: FileRoute[] = [];\r\n\r\n try {\r\n const entries = await readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n\r\n if (entry.isFile()) {\r\n const ext = extname(entry.name);\r\n\r\n if (!extensions.includes(ext)) {\r\n continue;\r\n }\r\n\r\n const routeInfo = parseRouteFile(entry.name, basePath);\r\n\r\n if (routeInfo && routeInfo.method && routeInfo.path) {\r\n routes.push({\r\n method: routeInfo.method,\r\n path: routeInfo.path,\r\n filePath: fullPath,\r\n type: routeInfo.type,\r\n slot: slotName,\r\n });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(`[Flight] Failed to scan slot @${slotName}:`, error);\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n/**\r\n * Scan an intercepting route directory\r\n * Uses (.) (..) (...) convention similar to Next.js\r\n * - (.)segment - intercepts from same level\r\n * - (..)segment - intercepts from parent level\r\n * - (...)segment - intercepts from root\r\n */\r\nasync function scanInterceptDir(\r\n dir: string,\r\n basePath: string,\r\n level: number,\r\n targetSegment: string,\r\n extensions: string[] = ['.ts', '.js', '.tsx', '.jsx']\r\n): Promise<FileRoute[]> {\r\n const routes: FileRoute[] = [];\r\n\r\n // Calculate the intercept path based on level\r\n const pathParts = basePath.split('/').filter(Boolean);\r\n let interceptPath: string;\r\n\r\n if (level === 1) {\r\n // (.) - Same level, intercepts sibling route\r\n interceptPath = `${basePath}/${targetSegment}`;\r\n } else if (level === 2) {\r\n // (..) - Parent level\r\n pathParts.pop();\r\n interceptPath = `/${pathParts.join('/')}/${targetSegment}`;\r\n } else {\r\n // (...) - Root level (3 or more dots)\r\n interceptPath = `/${targetSegment}`;\r\n }\r\n\r\n try {\r\n const entries = await readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name);\r\n\r\n if (entry.isFile()) {\r\n const ext = extname(entry.name);\r\n\r\n if (!extensions.includes(ext)) {\r\n continue;\r\n }\r\n\r\n const routeInfo = parseRouteFile(entry.name, basePath);\r\n\r\n if (routeInfo && routeInfo.method && routeInfo.path) {\r\n routes.push({\r\n method: routeInfo.method,\r\n path: routeInfo.path,\r\n filePath: fullPath,\r\n type: routeInfo.type,\r\n interceptInfo: {\r\n level,\r\n target: targetSegment,\r\n interceptPath: interceptPath.replace(/\\/+/g, '/') || '/',\r\n },\r\n });\r\n }\r\n } else if (entry.isDirectory()) {\r\n // Recurse into subdirectories within intercept folder\r\n const subRoutes = await scanInterceptDir(\r\n fullPath,\r\n `${basePath}/${entry.name}`,\r\n level,\r\n targetSegment,\r\n extensions\r\n );\r\n routes.push(...subRoutes);\r\n }\r\n }\r\n } catch (error) {\r\n console.error(`[Flight] Failed to scan intercept (${'.'.repeat(level)})${targetSegment}:`, error);\r\n }\r\n\r\n return routes;\r\n}\r\n\r\n// ============================================================================\r\n// Route Parser\r\n// ============================================================================\r\n\r\ninterface ParsedRoute {\r\n method: HttpMethod | 'ALL';\r\n path: string;\r\n type: 'page' | 'api';\r\n}\r\n\r\n/**\r\n * Parse route information from filename and path\r\n * \r\n * Patterns:\r\n * - index.ts → /\r\n * - users.ts → /users\r\n * - users.get.ts → GET /users (API)\r\n * - users.post.ts → POST /users (API)\r\n * - about.page.tsx → GET /about (Page)\r\n * - blog/[slug].page.tsx → GET /blog/:slug (Page)\r\n * - [id].ts → /:id\r\n * - [...slug].ts → /* (catch-all)\r\n * - [[...slug]].ts → /* (optional catch-all)\r\n */\r\nfunction parseRouteFile(filename: string, basePath: string): ParsedRoute | null {\r\n const ext = extname(filename);\r\n const nameWithoutExt = basename(filename, ext);\r\n\r\n // Skip files starting with underscore (private)\r\n if (nameWithoutExt.startsWith('_')) {\r\n return null;\r\n }\r\n\r\n // Detect route type\r\n let type: 'page' | 'api' = 'api';\r\n let routeName = nameWithoutExt;\r\n let method: HttpMethod | 'ALL' = 'ALL';\r\n\r\n // Check for page suffix (e.g., about.page.tsx, index.page.tsx)\r\n const pageMatch = nameWithoutExt.match(/^(.+)?\\.page$/i);\r\n if (pageMatch) {\r\n type = 'page';\r\n method = 'GET'; // Pages are always GET\r\n routeName = pageMatch[1] || 'index';\r\n } else {\r\n // Check for method suffix (e.g., users.get.ts)\r\n const methodMatch = nameWithoutExt.match(/^(.+)\\.(get|post|put|delete|patch|head|options)$/i);\r\n if (methodMatch) {\r\n routeName = methodMatch[1] || nameWithoutExt;\r\n method = (methodMatch[2] || 'ALL').toUpperCase() as HttpMethod;\r\n }\r\n }\r\n\r\n // Also check if file is in /api/ directory\r\n if (basePath.startsWith('/api') || basePath.includes('/api/')) {\r\n type = 'api';\r\n }\r\n\r\n // Build route path\r\n let path = basePath;\r\n\r\n if (routeName !== 'index') {\r\n path = `${basePath}/${convertToRoutePath(routeName)}`;\r\n }\r\n\r\n // Ensure path starts with /\r\n if (!path.startsWith('/')) {\r\n path = '/' + path;\r\n }\r\n\r\n // Remove trailing slash (except for root)\r\n if (path !== '/' && path.endsWith('/')) {\r\n path = path.slice(0, -1);\r\n }\r\n\r\n return { method, path, type };\r\n}\r\n\r\n/**\r\n * Convert filename segment to route path segment\r\n * \r\n * - [id] → :id\r\n * - [...slug] → *\r\n * - [[...slug]] → *?\r\n */\r\nfunction convertToRoutePath(name: string): string {\r\n // Optional catch-all: [[...slug]]\r\n if (name.startsWith('[[...') && name.endsWith(']]')) {\r\n const paramName = name.slice(5, -2);\r\n return `:${paramName}*`;\r\n }\r\n\r\n // Catch-all: [...slug]\r\n if (name.startsWith('[...') && name.endsWith(']')) {\r\n const paramName = name.slice(4, -1);\r\n return `:${paramName}+`;\r\n }\r\n\r\n // Dynamic param: [id]\r\n if (name.startsWith('[') && name.endsWith(']')) {\r\n const paramName = name.slice(1, -1);\r\n return `:${paramName}`;\r\n }\r\n\r\n return name;\r\n}\r\n\r\n// ============================================================================\r\n// Route Loader\r\n// ============================================================================\r\n\r\n/**\r\n * Load routes with their handlers or components\r\n * @param scanResult - Result from scanRoutes\r\n * @param moduleLoader - Optional custom loader (use vite.ssrLoadModule for dev)\r\n */\r\nexport async function loadRoutes(\r\n scanResult: ScanResult,\r\n moduleLoader?: (filePath: string) => Promise<any>\r\n): Promise<FileRoute[]> {\r\n const loadedRoutes: FileRoute[] = [];\r\n\r\n for (const route of scanResult.routes) {\r\n try {\r\n // Use custom loader if provided (Vite ssrLoadModule for TSX)\r\n // Otherwise fall back to native import() for production\r\n let module: any;\r\n if (moduleLoader) {\r\n module = await moduleLoader(route.filePath);\r\n } else {\r\n // Convert to file:// URL for Windows ESM compatibility\r\n const fileUrl = pathToFileURL(route.filePath).href;\r\n module = await import(fileUrl);\r\n }\r\n\r\n // Handle PAGE routes\r\n if (route.type === 'page') {\r\n // Pages export default component\r\n const component = module.default;\r\n const meta = module.meta || module.metadata || {};\r\n\r\n if (component) {\r\n loadedRoutes.push({\r\n ...route,\r\n component,\r\n meta,\r\n });\r\n }\r\n continue;\r\n }\r\n\r\n // Handle API routes\r\n if (route.method === 'ALL') {\r\n // Look for named exports: GET, POST, PUT, DELETE, etc\r\n const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];\r\n\r\n for (const method of methods) {\r\n if (typeof module[method] === 'function') {\r\n loadedRoutes.push({\r\n ...route,\r\n method,\r\n handler: module[method],\r\n });\r\n }\r\n }\r\n\r\n // Also check for default export as handler\r\n if (typeof module.default === 'function') {\r\n loadedRoutes.push({\r\n ...route,\r\n method: 'ALL',\r\n handler: module.default,\r\n });\r\n }\r\n } else {\r\n // Specific method from filename suffix\r\n const handler = module[route.method] || module.default;\r\n\r\n if (typeof handler === 'function') {\r\n loadedRoutes.push({\r\n ...route,\r\n handler,\r\n });\r\n }\r\n }\r\n } catch (error) {\r\n console.error(`[Flight] Failed to load route ${route.filePath}:`, error);\r\n }\r\n }\r\n\r\n return loadedRoutes;\r\n}\r\n\r\n// ============================================================================\r\n// File Router Factory\r\n// ============================================================================\r\n\r\nexport interface FileRouter {\r\n routes: FileRoute[];\r\n refresh: () => Promise<void>;\r\n}\r\n\r\n/**\r\n * Create a file-based router\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createFileRouter } from '@flight-framework/core/file-router';\r\n * import { createServer } from '@flight-framework/http';\r\n * \r\n * const router = await createFileRouter({ directory: './src/routes' });\r\n * const app = createServer();\r\n * \r\n * // Register all discovered routes\r\n * for (const route of router.routes) {\r\n * app[route.method.toLowerCase()](route.path, route.handler);\r\n * }\r\n * ```\r\n */\r\nexport async function createFileRouter(options: FileRouterOptions): Promise<FileRouter> {\r\n let routes: FileRoute[] = [];\r\n const { moduleLoader } = options;\r\n\r\n async function refresh(): Promise<void> {\r\n const scanResult = await scanRoutes(options);\r\n\r\n if (scanResult.errors.length > 0) {\r\n console.warn('[Flight] Route scan errors:', scanResult.errors);\r\n }\r\n\r\n routes = await loadRoutes(scanResult, moduleLoader);\r\n\r\n console.log(`[Flight] Loaded ${routes.length} routes from ${options.directory}`);\r\n }\r\n\r\n // Initial load\r\n await refresh();\r\n\r\n return {\r\n get routes() {\r\n return routes;\r\n },\r\n refresh,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Parallel Routes Resolution\r\n// ============================================================================\r\n\r\n/**\r\n * Resolved parallel route slots for a layout.\r\n * Each slot name maps to its resolved component or null if not matched.\r\n */\r\nexport interface ResolvedSlots {\r\n [slotName: string]: {\r\n /** The component to render */\r\n component: () => unknown;\r\n /** The full route information */\r\n route: FileRoute;\r\n } | null;\r\n}\r\n\r\n/**\r\n * Resolve parallel route slots for a given path.\r\n * \r\n * Parallel routes use the @folder convention to define named slots\r\n * that can render alongside the main content in a layout.\r\n * \r\n * @param routes - All loaded routes from the file router\r\n * @param currentPath - The current URL path to resolve slots for\r\n * @returns Object mapping slot names to their resolved components\r\n * \r\n * @example\r\n * ```typescript\r\n * // Given routes from @modal/ and @sidebar/ directories\r\n * const slots = resolveParallelSlots(router.routes, '/dashboard');\r\n * \r\n * // In layout:\r\n * if (slots.modal) {\r\n * renderModal(slots.modal.component);\r\n * }\r\n * ```\r\n */\r\nexport function resolveParallelSlots(\r\n routes: FileRoute[],\r\n currentPath: string\r\n): ResolvedSlots {\r\n const slots: ResolvedSlots = {};\r\n const normalizedPath = normalizePath(currentPath);\r\n\r\n // Get all unique slot names from routes\r\n const slotNames = new Set<string>();\r\n for (const route of routes) {\r\n if (route.slot) {\r\n slotNames.add(route.slot);\r\n }\r\n }\r\n\r\n // For each slot, find matching route or default\r\n for (const slotName of slotNames) {\r\n const slotRoutes = routes.filter(r => r.slot === slotName);\r\n\r\n // Find exact match for current path\r\n let matchingRoute = slotRoutes.find(r => {\r\n const routePath = normalizePath(r.path);\r\n return pathMatches(routePath, normalizedPath);\r\n });\r\n\r\n // If no match, look for default.page in the slot\r\n if (!matchingRoute) {\r\n matchingRoute = slotRoutes.find(r =>\r\n r.path.endsWith('/default') || r.filePath.includes('default.page')\r\n );\r\n }\r\n\r\n if (matchingRoute && matchingRoute.component) {\r\n slots[slotName] = {\r\n component: matchingRoute.component,\r\n route: matchingRoute,\r\n };\r\n } else {\r\n // Slot has no matching content for this path\r\n slots[slotName] = null;\r\n }\r\n }\r\n\r\n return slots;\r\n}\r\n\r\n/**\r\n * Get the default page for an unmatched slot.\r\n * \r\n * When a parallel route slot doesn't have a matching route for the current path,\r\n * it should render its default.page if one exists, or null.\r\n * \r\n * @param routes - All loaded routes\r\n * @param slotName - Name of the slot (without @)\r\n * @param basePath - Base path to search from\r\n * @returns The default route for the slot, or null\r\n */\r\nexport function getSlotDefault(\r\n routes: FileRoute[],\r\n slotName: string,\r\n basePath: string = ''\r\n): FileRoute | null {\r\n const normalizedBase = normalizePath(basePath);\r\n\r\n return routes.find(r =>\r\n r.slot === slotName &&\r\n (r.filePath.includes('default.page') || r.path === `${normalizedBase}/default`)\r\n ) || null;\r\n}\r\n\r\n/**\r\n * Get all slot names used in the routes.\r\n * \r\n * @param routes - All loaded routes\r\n * @returns Array of unique slot names\r\n */\r\nexport function getSlotNames(routes: FileRoute[]): string[] {\r\n const names = new Set<string>();\r\n for (const route of routes) {\r\n if (route.slot) {\r\n names.add(route.slot);\r\n }\r\n }\r\n return Array.from(names);\r\n}\r\n\r\n// ============================================================================\r\n// Intercepting Routes Resolution\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a navigation should be intercepted by an intercepting route.\r\n * \r\n * Intercepting routes use the (.) (..) (...) convention:\r\n * - (.)segment - intercepts from same level\r\n * - (..)segment - intercepts from parent level \r\n * - (...)segment - intercepts from root\r\n * \r\n * @param routes - All loaded routes\r\n * @param fromPath - Current path where navigation originates\r\n * @param toPath - Target path the user wants to navigate to\r\n * @returns The intercepting route if found, null otherwise\r\n * \r\n * @example\r\n * ```typescript\r\n * // User is on /feed and clicks link to /photo/123\r\n * const intercepted = findInterceptingRoute(routes, '/feed', '/photo/123');\r\n * \r\n * if (intercepted) {\r\n * // Render intercepted.component as modal instead of navigating\r\n * showModal(intercepted);\r\n * }\r\n * ```\r\n */\r\nexport function findInterceptingRoute(\r\n routes: FileRoute[],\r\n fromPath: string,\r\n toPath: string\r\n): FileRoute | null {\r\n const normalizedFrom = normalizePath(fromPath);\r\n const normalizedTo = normalizePath(toPath);\r\n\r\n // Filter to only intercepting routes\r\n const interceptingRoutes = routes.filter(r => r.interceptInfo);\r\n\r\n for (const route of interceptingRoutes) {\r\n const { interceptInfo } = route;\r\n if (!interceptInfo) continue;\r\n\r\n // Check if the interceptPath matches the target path\r\n const interceptPath = normalizePath(interceptInfo.interceptPath);\r\n\r\n if (!pathMatches(interceptPath, normalizedTo)) {\r\n continue;\r\n }\r\n\r\n // Check if we're navigating from a valid origin based on level\r\n // For level 1 (.), the intercept route is at same level as navigation origin\r\n // For level 2 (..), the intercept route is one level up from navigation origin\r\n // For level 3+ (...), intercepts from anywhere\r\n\r\n let validOrigin = false;\r\n\r\n // Find the intercept marker position in route path\r\n // Route path example: /feed/(.)photo/:id -> base is /feed\r\n const routePathStr = normalizePath(route.path);\r\n const interceptMarkerMatch = routePathStr.match(/\\/\\(\\.+\\)/);\r\n\r\n if (interceptInfo.level >= 3) {\r\n // (...) - Root level: intercepts from anywhere\r\n validOrigin = true;\r\n } else if (interceptMarkerMatch && interceptMarkerMatch.index !== undefined) {\r\n // Extract the base path before the intercept marker\r\n const routeBase = routePathStr.substring(0, interceptMarkerMatch.index);\r\n\r\n if (interceptInfo.level === 1) {\r\n // (.) - Same level: origin should be at or under the route base\r\n // Route at /feed/(.)photo, origin should be /feed or /feed/*\r\n validOrigin = normalizedFrom === routeBase ||\r\n normalizedFrom.startsWith(routeBase + '/') ||\r\n (routeBase === '' && normalizedFrom.startsWith('/'));\r\n } else if (interceptInfo.level === 2) {\r\n // (..) - Parent level: origin is one level deeper\r\n // Route at /gallery/albums/(..)photo, origin should be /gallery/albums/*\r\n validOrigin = normalizedFrom === routeBase ||\r\n normalizedFrom.startsWith(routeBase + '/');\r\n }\r\n }\r\n\r\n if (validOrigin) {\r\n return route;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Check if an intercepting route should be dismissed on this navigation.\r\n * \r\n * @param currentRoute - The currently active intercepting route\r\n * @param toPath - The path being navigated to\r\n * @returns true if the interception should be dismissed\r\n */\r\nexport function shouldDismissIntercept(\r\n currentRoute: FileRoute | null,\r\n toPath: string\r\n): boolean {\r\n if (!currentRoute || !currentRoute.interceptInfo) {\r\n return false;\r\n }\r\n\r\n const normalizedTo = normalizePath(toPath);\r\n const interceptPath = normalizePath(currentRoute.interceptInfo.interceptPath);\r\n\r\n // Dismiss if navigating away from the intercepted path\r\n return !pathMatches(interceptPath, normalizedTo);\r\n}\r\n\r\n/**\r\n * Get route params from a path match.\r\n * \r\n * @param routePath - The route pattern with params (e.g., /photo/:id)\r\n * @param actualPath - The actual URL path (e.g., /photo/123)\r\n * @returns Object with matched params, or null if no match\r\n */\r\nexport function extractRouteParams(\r\n routePath: string,\r\n actualPath: string\r\n): Record<string, string> | null {\r\n const routeParts = routePath.split('/').filter(Boolean);\r\n const actualParts = actualPath.split('/').filter(Boolean);\r\n\r\n if (routeParts.length !== actualParts.length) {\r\n // Check for catch-all\r\n const hasCatchAll = routeParts.some(p => p.endsWith('+') || p.endsWith('*'));\r\n if (!hasCatchAll) {\r\n return null;\r\n }\r\n }\r\n\r\n const params: Record<string, string> = {};\r\n\r\n for (let i = 0; i < routeParts.length; i++) {\r\n const routePart = routeParts[i];\r\n const actualPart = actualParts[i];\r\n\r\n if (!routePart) continue;\r\n\r\n if (routePart.startsWith(':')) {\r\n // Dynamic param\r\n const paramName = routePart.slice(1).replace(/[+*]$/, '');\r\n\r\n if (routePart.endsWith('+') || routePart.endsWith('*')) {\r\n // Catch-all: collect remaining parts\r\n params[paramName] = actualParts.slice(i).join('/');\r\n break;\r\n }\r\n\r\n if (!actualPart) {\r\n if (routePart.endsWith('*')) {\r\n // Optional catch-all, can be empty\r\n params[paramName] = '';\r\n break;\r\n }\r\n return null;\r\n }\r\n\r\n params[paramName] = actualPart;\r\n } else if (routePart !== actualPart) {\r\n return null;\r\n }\r\n }\r\n\r\n return params;\r\n}\r\n\r\n// ============================================================================\r\n// Path Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Normalize a path for consistent comparison.\r\n */\r\nfunction normalizePath(path: string): string {\r\n let normalized = path.trim();\r\n\r\n // Ensure starts with /\r\n if (!normalized.startsWith('/')) {\r\n normalized = '/' + normalized;\r\n }\r\n\r\n // Remove trailing slash (except for root)\r\n if (normalized !== '/' && normalized.endsWith('/')) {\r\n normalized = normalized.slice(0, -1);\r\n }\r\n\r\n // Remove duplicate slashes\r\n normalized = normalized.replace(/\\/+/g, '/');\r\n\r\n return normalized;\r\n}\r\n\r\n/**\r\n * Check if a route path matches an actual path.\r\n * Handles dynamic segments (:param) and catch-alls.\r\n */\r\nfunction pathMatches(routePath: string, actualPath: string): boolean {\r\n const routeParts = routePath.split('/').filter(Boolean);\r\n const actualParts = actualPath.split('/').filter(Boolean);\r\n\r\n for (let i = 0; i < routeParts.length; i++) {\r\n const routePart = routeParts[i];\r\n const actualPart = actualParts[i];\r\n\r\n if (!routePart) continue;\r\n\r\n // Catch-all segment\r\n if (routePart.startsWith(':') && (routePart.endsWith('+') || routePart.endsWith('*'))) {\r\n return true; // Matches rest of path\r\n }\r\n\r\n // Dynamic segment\r\n if (routePart.startsWith(':')) {\r\n if (!actualPart) return false;\r\n continue; // Any value matches\r\n }\r\n\r\n // Static segment - must match exactly\r\n if (routePart !== actualPart) {\r\n return false;\r\n }\r\n }\r\n\r\n // Check lengths match (unless catch-all was present)\r\n return routeParts.length === actualParts.length;\r\n}\r\n\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/rsc/context.ts"],"names":[],"mappings":"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","file":"chunk-62C7LX2E.js","sourcesContent":["/**\r\n * @flight-framework/core - Server Context\r\n * \r\n * API de contexto para Server Components.\r\n * Provee acceso a datos del request de forma explícita y type-safe.\r\n * \r\n * Filosofía Flight:\r\n * - Contexto EXPLÍCITO (no magia con AsyncLocalStorage)\r\n * - Pasado como argumento (testeable, predecible)\r\n * - Extensible con adapters custom\r\n * - Inmutable por defecto\r\n * \r\n * @module @flight-framework/core/rsc/context\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Contexto del servidor disponible en Server Components\r\n */\r\nexport interface ServerContext {\r\n /** Request actual (Web API Request) */\r\n readonly request: Request;\r\n\r\n /** Parámetros de ruta */\r\n readonly params: Readonly<Record<string, string>>;\r\n\r\n /** Search params de la URL */\r\n readonly searchParams: URLSearchParams;\r\n\r\n /** Headers del request */\r\n readonly headers: Headers;\r\n\r\n /** Accessor de cookies */\r\n readonly cookies: CookieAccessor;\r\n\r\n /** Headers de respuesta (mutables) */\r\n readonly responseHeaders: Headers;\r\n\r\n /** Signal para cancelación */\r\n readonly signal: AbortSignal;\r\n\r\n /** URL parseada */\r\n readonly url: URL;\r\n\r\n /** Método HTTP */\r\n readonly method: string;\r\n\r\n /** Context extensions (para adapters) */\r\n readonly extensions: ContextExtensions;\r\n}\r\n\r\n/**\r\n * Accessor para cookies con lazy parsing\r\n */\r\nexport interface CookieAccessor {\r\n /** Obtiene el valor de una cookie */\r\n get(name: string): string | undefined;\r\n\r\n /** Obtiene todas las cookies */\r\n getAll(): Readonly<Record<string, string>>;\r\n\r\n /** Verifica si existe una cookie */\r\n has(name: string): boolean;\r\n}\r\n\r\n/**\r\n * Extensiones del contexto para adapters\r\n */\r\nexport interface ContextExtensions {\r\n /** Obtiene una extensión */\r\n get<T>(key: string): T | undefined;\r\n\r\n /** Verifica si existe una extensión */\r\n has(key: string): boolean;\r\n}\r\n\r\n/**\r\n * Opciones para crear ServerContext\r\n */\r\nexport interface ServerContextOptions {\r\n /** Parámetros de ruta */\r\n params?: Record<string, string>;\r\n\r\n /** Extensiones custom */\r\n extensions?: Record<string, unknown>;\r\n\r\n /** Headers de respuesta iniciales */\r\n responseHeaders?: HeadersInit;\r\n}\r\n\r\n// ============================================================================\r\n// Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Crea un ServerContext a partir de un Request\r\n * \r\n * @example\r\n * ```typescript\r\n * const ctx = createServerContext(request, { \r\n * params: { id: '123' } \r\n * });\r\n * \r\n * // En un Server Component\r\n * async function UserPage(props, ctx: ServerContext) {\r\n * const userId = ctx.params.id;\r\n * const user = await db.users.get(userId);\r\n * return <UserProfile user={user} />;\r\n * }\r\n * ```\r\n */\r\nexport function createServerContext(\r\n request: Request,\r\n options: ServerContextOptions = {}\r\n): ServerContext {\r\n const { params = {}, extensions = {}, responseHeaders: initHeaders } = options;\r\n\r\n // Parse URL\r\n const url = new URL(request.url);\r\n\r\n // Lazy cookie parsing\r\n let parsedCookies: Record<string, string> | null = null;\r\n\r\n const parseCookies = (): Record<string, string> => {\r\n if (parsedCookies !== null) return parsedCookies;\r\n\r\n parsedCookies = {};\r\n const cookieHeader = request.headers.get('cookie');\r\n\r\n if (cookieHeader) {\r\n for (const cookie of cookieHeader.split(';')) {\r\n const trimmed = cookie.trim();\r\n const eqIndex = trimmed.indexOf('=');\r\n\r\n if (eqIndex > 0) {\r\n const key = trimmed.slice(0, eqIndex).trim();\r\n const value = trimmed.slice(eqIndex + 1).trim();\r\n\r\n // Decode URL-encoded values\r\n try {\r\n parsedCookies[key] = decodeURIComponent(value);\r\n } catch {\r\n parsedCookies[key] = value;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return parsedCookies;\r\n };\r\n\r\n // Cookie accessor\r\n const cookies: CookieAccessor = {\r\n get(name: string): string | undefined {\r\n return parseCookies()[name];\r\n },\r\n getAll(): Readonly<Record<string, string>> {\r\n return Object.freeze({ ...parseCookies() });\r\n },\r\n has(name: string): boolean {\r\n return name in parseCookies();\r\n },\r\n };\r\n\r\n // Extensions accessor\r\n const contextExtensions: ContextExtensions = {\r\n get<T>(key: string): T | undefined {\r\n return extensions[key] as T | undefined;\r\n },\r\n has(key: string): boolean {\r\n return key in extensions;\r\n },\r\n };\r\n\r\n // Response headers (mutable)\r\n const responseHeaders = new Headers(initHeaders);\r\n\r\n return Object.freeze({\r\n request,\r\n params: Object.freeze({ ...params }),\r\n searchParams: url.searchParams,\r\n headers: request.headers,\r\n cookies,\r\n responseHeaders,\r\n signal: request.signal,\r\n url,\r\n method: request.method,\r\n extensions: contextExtensions,\r\n });\r\n}\r\n\r\n// ============================================================================\r\n// Context Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Obtiene un header del request\r\n */\r\nexport function getHeader(ctx: ServerContext, name: string): string | null {\r\n return ctx.headers.get(name);\r\n}\r\n\r\n/**\r\n * Obtiene todos los headers como objeto\r\n */\r\nexport function getHeaders(ctx: ServerContext): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n ctx.headers.forEach((value, key) => {\r\n headers[key] = value;\r\n });\r\n return headers;\r\n}\r\n\r\n/**\r\n * Verifica si el request es un POST/PUT/PATCH/DELETE (mutation request)\r\n */\r\nexport function isMutationRequest(ctx: ServerContext): boolean {\r\n return ['POST', 'PUT', 'PATCH', 'DELETE'].includes(ctx.method);\r\n}\r\n\r\n/**\r\n * Verifica si el request acepta JSON\r\n */\r\nexport function acceptsJson(ctx: ServerContext): boolean {\r\n const accept = ctx.headers.get('accept') || '';\r\n return accept.includes('application/json') || accept.includes('*/*');\r\n}\r\n\r\n/**\r\n * Verifica si el request es AJAX/fetch\r\n */\r\nexport function isAjaxRequest(ctx: ServerContext): boolean {\r\n return ctx.headers.get('x-requested-with')?.toLowerCase() === 'xmlhttprequest' ||\r\n ctx.headers.has('x-flight-action');\r\n}\r\n\r\n/**\r\n * Verifica si el request viene de un bot\r\n */\r\nexport function isBotRequest(ctx: ServerContext): boolean {\r\n const ua = ctx.headers.get('user-agent')?.toLowerCase() || '';\r\n const botPatterns = [\r\n 'bot', 'crawler', 'spider', 'scraper',\r\n 'googlebot', 'bingbot', 'yandexbot', 'duckduckbot',\r\n 'slurp', 'baiduspider', 'facebookexternalhit',\r\n 'twitterbot', 'linkedinbot', 'embedly', 'quora',\r\n 'outbrain', 'pinterest', 'slack', 'vkshare',\r\n 'w3c_validator', 'lighthouse', 'pagespeed',\r\n ];\r\n return botPatterns.some(pattern => ua.includes(pattern));\r\n}\r\n\r\n/**\r\n * Verifica si el cliente soporta streaming\r\n */\r\nexport function supportsStreaming(ctx: ServerContext): boolean {\r\n // Check for no-stream preference\r\n const noStream = ctx.searchParams.get('_nostream');\r\n if (noStream === '1' || noStream === 'true') return false;\r\n\r\n // Bots typically don't support streaming well\r\n if (isBotRequest(ctx)) return false;\r\n\r\n // Check for slow connection hints\r\n const connection = ctx.headers.get('downlink') || ctx.headers.get('ect');\r\n if (connection === 'slow-2g' || connection === '2g') return false;\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Obtiene el idioma preferido del cliente\r\n */\r\nexport function getPreferredLanguage(ctx: ServerContext, available: string[]): string | undefined {\r\n const acceptLang = ctx.headers.get('accept-language');\r\n if (!acceptLang) return available[0];\r\n\r\n // Parse Accept-Language header\r\n const languages = acceptLang\r\n .split(',')\r\n .map(lang => {\r\n const [code, q = 'q=1'] = lang.trim().split(';');\r\n const quality = parseFloat(q.replace('q=', '')) || 1;\r\n return { code: code!.trim().toLowerCase(), quality };\r\n })\r\n .sort((a, b) => b.quality - a.quality);\r\n\r\n // Find best match\r\n for (const { code } of languages) {\r\n // Exact match\r\n const exact = available.find(a => a.toLowerCase() === code);\r\n if (exact) return exact;\r\n\r\n // Language-only match (e.g., 'es' matches 'es-AR')\r\n const baseCode = code.split('-')[0];\r\n const partial = available.find(a => a.toLowerCase().startsWith(baseCode!));\r\n if (partial) return partial;\r\n }\r\n\r\n return available[0];\r\n}\r\n\r\n// ============================================================================\r\n// Response Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Sets a cookie in the response\r\n */\r\nexport function setCookie(\r\n ctx: ServerContext,\r\n name: string,\r\n value: string,\r\n options: CookieOptions = {}\r\n): void {\r\n const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];\r\n\r\n if (options.maxAge !== undefined) {\r\n parts.push(`Max-Age=${options.maxAge}`);\r\n }\r\n if (options.expires) {\r\n parts.push(`Expires=${options.expires.toUTCString()}`);\r\n }\r\n if (options.path) {\r\n parts.push(`Path=${options.path}`);\r\n }\r\n if (options.domain) {\r\n parts.push(`Domain=${options.domain}`);\r\n }\r\n if (options.secure) {\r\n parts.push('Secure');\r\n }\r\n if (options.httpOnly) {\r\n parts.push('HttpOnly');\r\n }\r\n if (options.sameSite) {\r\n parts.push(`SameSite=${options.sameSite}`);\r\n }\r\n\r\n ctx.responseHeaders.append('Set-Cookie', parts.join('; '));\r\n}\r\n\r\n/**\r\n * Deletes a cookie\r\n */\r\nexport function deleteCookie(ctx: ServerContext, name: string, options: Pick<CookieOptions, 'path' | 'domain'> = {}): void {\r\n setCookie(ctx, name, '', {\r\n ...options,\r\n maxAge: 0,\r\n expires: new Date(0),\r\n });\r\n}\r\n\r\n/**\r\n * Cookie options\r\n */\r\nexport interface CookieOptions {\r\n /** Max age in seconds */\r\n maxAge?: number;\r\n /** Expiration date */\r\n expires?: Date;\r\n /** Cookie path */\r\n path?: string;\r\n /** Cookie domain */\r\n domain?: string;\r\n /** HTTPS only */\r\n secure?: boolean;\r\n /** Not accessible via JavaScript */\r\n httpOnly?: boolean;\r\n /** SameSite attribute */\r\n sameSite?: 'Strict' | 'Lax' | 'None';\r\n}\r\n\r\n/**\r\n * Sets cache control headers\r\n */\r\nexport function setCacheControl(ctx: ServerContext, options: CacheControlOptions): void {\r\n const parts: string[] = [];\r\n\r\n if (options.public) parts.push('public');\r\n if (options.private) parts.push('private');\r\n if (options.noCache) parts.push('no-cache');\r\n if (options.noStore) parts.push('no-store');\r\n if (options.maxAge !== undefined) parts.push(`max-age=${options.maxAge}`);\r\n if (options.sMaxAge !== undefined) parts.push(`s-maxage=${options.sMaxAge}`);\r\n if (options.staleWhileRevalidate !== undefined) {\r\n parts.push(`stale-while-revalidate=${options.staleWhileRevalidate}`);\r\n }\r\n if (options.staleIfError !== undefined) {\r\n parts.push(`stale-if-error=${options.staleIfError}`);\r\n }\r\n if (options.mustRevalidate) parts.push('must-revalidate');\r\n if (options.immutable) parts.push('immutable');\r\n\r\n ctx.responseHeaders.set('Cache-Control', parts.join(', '));\r\n}\r\n\r\n/**\r\n * Cache control options\r\n */\r\nexport interface CacheControlOptions {\r\n public?: boolean;\r\n private?: boolean;\r\n noCache?: boolean;\r\n noStore?: boolean;\r\n maxAge?: number;\r\n sMaxAge?: number;\r\n staleWhileRevalidate?: number;\r\n staleIfError?: number;\r\n mustRevalidate?: boolean;\r\n immutable?: boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Error Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Not found error - triggers 404 handling\r\n */\r\nexport function notFound(message = 'Not Found'): never {\r\n const error = new Error(message) as Error & { __flight_not_found: true };\r\n error.__flight_not_found = true;\r\n throw error;\r\n}\r\n\r\n/**\r\n * Check if error is a not found error\r\n */\r\nexport function isNotFoundError(error: unknown): boolean {\r\n return error instanceof Error && '__flight_not_found' in error;\r\n}\r\n\r\n/**\r\n * Redirect error - triggers redirect handling\r\n */\r\nexport function redirect(url: string, status: 301 | 302 | 303 | 307 | 308 = 307): never {\r\n const error = new Error(`Redirect: ${url}`) as Error & {\r\n __flight_redirect: { url: string; status: number }\r\n };\r\n error.__flight_redirect = { url, status };\r\n throw error;\r\n}\r\n\r\n/**\r\n * Check if error is a redirect error\r\n */\r\nexport function isRedirectError(error: unknown): error is Error & {\r\n __flight_redirect: { url: string; status: number }\r\n} {\r\n return error instanceof Error && '__flight_redirect' in error;\r\n}\r\n\r\n/**\r\n * Get redirect info from error\r\n */\r\nexport function getRedirectInfo(error: Error & { __flight_redirect: { url: string; status: number } }): { url: string; status: number } {\r\n return error.__flight_redirect;\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/streaming/observability.ts"],"names":[],"mappings":"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","file":"chunk-6BDCTUQY.js","sourcesContent":["/**\r\n * @flight-framework/core - Streaming Observability\r\n * \r\n * Zero-telemetry metrics and instrumentation for streaming SSR.\r\n * All data stays on YOUR infrastructure - never sent anywhere.\r\n * \r\n * Best Practices 2026:\r\n * - Comprehensive timing metrics for each boundary\r\n * - Hook-based observability for custom integrations\r\n * - Performance insights without vendor lock-in\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createInstrumentedStream } from '@flight-framework/core/streaming';\r\n * \r\n * const { stream, metrics } = await createInstrumentedStream({\r\n * shell: '<html>...',\r\n * boundaries: [...],\r\n * onMetrics: (m) => myAnalytics.track(m), // YOUR system\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { StreamingRenderOptions, SuspenseBoundaryConfig } from './index.js';\r\nimport { createStreamingSSR } from './index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Timing information for a single boundary\r\n */\r\nexport interface BoundaryTiming {\r\n /** Boundary identifier */\r\n id: string;\r\n /** When the boundary started resolving (ms since stream start) */\r\n startTime: number;\r\n /** When the boundary finished resolving */\r\n endTime: number;\r\n /** Total duration in milliseconds */\r\n duration: number;\r\n /** Whether it resolved successfully */\r\n success: boolean;\r\n /** Size of content in bytes (if successful) */\r\n contentSize?: number;\r\n /** Error message if failed */\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Overall streaming metrics\r\n */\r\nexport interface StreamingMetrics {\r\n /** Unique ID for this stream session */\r\n streamId: string;\r\n /** When streaming started */\r\n startTime: number;\r\n /** Time to shell ready (TTFB improvement) */\r\n shellTime: number;\r\n /** Time until all boundaries resolved */\r\n totalStreamTime: number;\r\n /** Individual boundary timings */\r\n boundaries: BoundaryTiming[];\r\n /** Number of boundaries that resolved successfully */\r\n successCount: number;\r\n /** Number of boundaries that failed */\r\n errorCount: number;\r\n /** Total bytes streamed */\r\n totalBytes: number;\r\n /** Strategy used (if priority streaming) */\r\n strategy?: string;\r\n /** Custom metadata you can add */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Observability hooks for streaming events\r\n */\r\nexport interface StreamingObserver {\r\n /** Called when streaming starts */\r\n onStreamStart?: (streamId: string) => void;\r\n /** Called when shell is sent */\r\n onShellReady?: (timing: { streamId: string; duration: number }) => void;\r\n /** Called when a boundary starts resolving */\r\n onBoundaryStart?: (info: { streamId: string; boundaryId: string; startTime: number }) => void;\r\n /** Called when a boundary finishes */\r\n onBoundaryEnd?: (timing: BoundaryTiming & { streamId: string }) => void;\r\n /** Called when streaming completes */\r\n onStreamEnd?: (metrics: StreamingMetrics) => void;\r\n /** Called on any error */\r\n onError?: (error: { streamId: string; boundaryId?: string; error: Error }) => void;\r\n}\r\n\r\n/**\r\n * Configuration for instrumented streaming\r\n */\r\nexport interface InstrumentedStreamConfig {\r\n /** Initial HTML shell */\r\n shell: string;\r\n /** Closing HTML */\r\n shellEnd: string;\r\n /** Suspense boundaries */\r\n suspenseBoundaries: SuspenseBoundaryConfig[];\r\n /** Streaming options */\r\n options?: StreamingRenderOptions;\r\n /** Observer hooks */\r\n observer?: StreamingObserver;\r\n /** Callback when all metrics are ready */\r\n onMetrics?: (metrics: StreamingMetrics) => void;\r\n /** Custom metadata to include in metrics */\r\n meta?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Result of instrumented streaming\r\n */\r\nexport interface InstrumentedStreamResult {\r\n /** The readable stream */\r\n stream: ReadableStream<Uint8Array>;\r\n /** Abort the stream */\r\n abort: () => void;\r\n /** Shell ready promise */\r\n shellReady: Promise<void>;\r\n /** All content ready promise */\r\n allReady: Promise<void>;\r\n /** Final metrics (resolves when stream completes) */\r\n metrics: Promise<StreamingMetrics>;\r\n /** Stream ID for correlation */\r\n streamId: string;\r\n}\r\n\r\n// ============================================================================\r\n// Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Generate a unique stream ID\r\n */\r\nfunction generateStreamId(): string {\r\n return `stream_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Create an instrumented streaming SSR response with full observability\r\n */\r\nexport async function createInstrumentedStream(\r\n config: InstrumentedStreamConfig\r\n): Promise<InstrumentedStreamResult> {\r\n const {\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries,\r\n options = {},\r\n observer,\r\n onMetrics,\r\n meta,\r\n } = config;\r\n\r\n const streamId = generateStreamId();\r\n const startTime = Date.now();\r\n const boundaryTimings: BoundaryTiming[] = [];\r\n const boundaryStarts = new Map<string, number>();\r\n let shellTime = 0;\r\n let totalBytes = 0;\r\n\r\n // Metrics promise\r\n let resolveMetrics: (m: StreamingMetrics) => void;\r\n const metricsPromise = new Promise<StreamingMetrics>((r) => { resolveMetrics = r; });\r\n\r\n // Notify stream start\r\n observer?.onStreamStart?.(streamId);\r\n\r\n // Wrap boundaries with instrumentation\r\n const instrumentedBoundaries: SuspenseBoundaryConfig[] = suspenseBoundaries.map(boundary => {\r\n const boundaryStart = Date.now();\r\n boundaryStarts.set(boundary.id, boundaryStart);\r\n\r\n observer?.onBoundaryStart?.({\r\n streamId,\r\n boundaryId: boundary.id,\r\n startTime: boundaryStart - startTime,\r\n });\r\n\r\n return {\r\n ...boundary,\r\n contentPromise: boundary.contentPromise.then(\r\n (content) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: true,\r\n contentSize: new TextEncoder().encode(content).length,\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n return content;\r\n },\r\n (error) => {\r\n const endTime = Date.now();\r\n const timing: BoundaryTiming = {\r\n id: boundary.id,\r\n startTime: boundaryStarts.get(boundary.id)! - startTime,\r\n endTime: endTime - startTime,\r\n duration: endTime - boundaryStarts.get(boundary.id)!,\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error),\r\n };\r\n boundaryTimings.push(timing);\r\n observer?.onBoundaryEnd?.({ ...timing, streamId });\r\n observer?.onError?.({ streamId, boundaryId: boundary.id, error: error as Error });\r\n throw error;\r\n }\r\n ),\r\n };\r\n });\r\n\r\n // Create the underlying stream with instrumented callbacks\r\n const result = await createStreamingSSR({\r\n shell,\r\n shellEnd,\r\n suspenseBoundaries: instrumentedBoundaries,\r\n options: {\r\n ...options,\r\n onShellReady: () => {\r\n shellTime = Date.now() - startTime;\r\n observer?.onShellReady?.({ streamId, duration: shellTime });\r\n options.onShellReady?.();\r\n },\r\n onAllReady: () => {\r\n const totalStreamTime = Date.now() - startTime;\r\n\r\n const metrics: StreamingMetrics = {\r\n streamId,\r\n startTime,\r\n shellTime,\r\n totalStreamTime,\r\n boundaries: boundaryTimings,\r\n successCount: boundaryTimings.filter(b => b.success).length,\r\n errorCount: boundaryTimings.filter(b => !b.success).length,\r\n totalBytes,\r\n meta,\r\n };\r\n\r\n observer?.onStreamEnd?.(metrics);\r\n onMetrics?.(metrics);\r\n resolveMetrics!(metrics);\r\n options.onAllReady?.();\r\n },\r\n onError: (error) => {\r\n observer?.onError?.({ streamId, error });\r\n options.onError?.(error);\r\n },\r\n },\r\n });\r\n\r\n // Wrap stream to count bytes\r\n const countingStream = result.stream.pipeThrough(\r\n new TransformStream<Uint8Array, Uint8Array>({\r\n transform(chunk, controller) {\r\n totalBytes += chunk.length;\r\n controller.enqueue(chunk);\r\n },\r\n })\r\n );\r\n\r\n return {\r\n stream: countingStream,\r\n abort: result.abort,\r\n shellReady: result.shellReady,\r\n allReady: result.allReady,\r\n metrics: metricsPromise,\r\n streamId,\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Metrics Aggregator\r\n// ============================================================================\r\n\r\n/**\r\n * Aggregate metrics from multiple streams for analysis\r\n */\r\nexport class MetricsAggregator {\r\n private metrics: StreamingMetrics[] = [];\r\n private maxSamples: number;\r\n\r\n constructor(maxSamples = 1000) {\r\n this.maxSamples = maxSamples;\r\n }\r\n\r\n /**\r\n * Add metrics from a stream\r\n */\r\n add(metrics: StreamingMetrics): void {\r\n this.metrics.push(metrics);\r\n if (this.metrics.length > this.maxSamples) {\r\n this.metrics.shift();\r\n }\r\n }\r\n\r\n /**\r\n * Get average shell time\r\n */\r\n getAverageShellTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.shellTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get average total stream time\r\n */\r\n getAverageTotalTime(): number {\r\n if (this.metrics.length === 0) return 0;\r\n return this.metrics.reduce((sum, m) => sum + m.totalStreamTime, 0) / this.metrics.length;\r\n }\r\n\r\n /**\r\n * Get slowest boundaries (by average duration)\r\n */\r\n getSlowestBoundaries(limit = 5): { id: string; avgDuration: number; errorRate: number }[] {\r\n const boundaryStats = new Map<string, { totalDuration: number; count: number; errors: number }>();\r\n\r\n for (const m of this.metrics) {\r\n for (const b of m.boundaries) {\r\n const stats = boundaryStats.get(b.id) || { totalDuration: 0, count: 0, errors: 0 };\r\n stats.totalDuration += b.duration;\r\n stats.count++;\r\n if (!b.success) stats.errors++;\r\n boundaryStats.set(b.id, stats);\r\n }\r\n }\r\n\r\n return [...boundaryStats.entries()]\r\n .map(([id, stats]) => ({\r\n id,\r\n avgDuration: stats.totalDuration / stats.count,\r\n errorRate: stats.errors / stats.count,\r\n }))\r\n .sort((a, b) => b.avgDuration - a.avgDuration)\r\n .slice(0, limit);\r\n }\r\n\r\n /**\r\n * Get overall error rate\r\n */\r\n getErrorRate(): number {\r\n const total = this.metrics.reduce((sum, m) => sum + m.boundaries.length, 0);\r\n const errors = this.metrics.reduce((sum, m) => sum + m.errorCount, 0);\r\n return total > 0 ? errors / total : 0;\r\n }\r\n\r\n /**\r\n * Get percentiles for shell time\r\n */\r\n getShellTimePercentiles(): { p50: number; p90: number; p99: number } {\r\n const sorted = [...this.metrics].map(m => m.shellTime).sort((a, b) => a - b);\r\n const len = sorted.length;\r\n if (len === 0) return { p50: 0, p90: 0, p99: 0 };\r\n\r\n return {\r\n p50: sorted[Math.floor(len * 0.5)] ?? 0,\r\n p90: sorted[Math.floor(len * 0.9)] ?? 0,\r\n p99: sorted[Math.floor(len * 0.99)] ?? 0,\r\n };\r\n }\r\n\r\n /**\r\n * Export all metrics for external analysis\r\n */\r\n export(): StreamingMetrics[] {\r\n return [...this.metrics];\r\n }\r\n\r\n /**\r\n * Clear all metrics\r\n */\r\n clear(): void {\r\n this.metrics = [];\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Utility: Create Observer from Logger\r\n// ============================================================================\r\n\r\n/**\r\n * Create a streaming observer from a simple logger function\r\n */\r\nexport function createLoggerObserver(\r\n log: (message: string, data?: Record<string, unknown>) => void\r\n): StreamingObserver {\r\n return {\r\n onStreamStart: (streamId) => {\r\n log('[Flight] Stream started', { streamId });\r\n },\r\n onShellReady: ({ streamId, duration }) => {\r\n log('[Flight] Shell ready', { streamId, duration: `${duration}ms` });\r\n },\r\n onBoundaryStart: ({ streamId, boundaryId, startTime }) => {\r\n log('[Flight] Boundary started', { streamId, boundaryId, startTime: `${startTime}ms` });\r\n },\r\n onBoundaryEnd: (timing) => {\r\n log('[Flight] Boundary completed', {\r\n streamId: (timing as any).streamId,\r\n boundaryId: timing.id,\r\n duration: `${timing.duration}ms`,\r\n success: timing.success,\r\n size: timing.contentSize ? `${timing.contentSize}b` : undefined,\r\n });\r\n },\r\n onStreamEnd: (metrics) => {\r\n log('[Flight] Stream completed', {\r\n streamId: metrics.streamId,\r\n totalTime: `${metrics.totalStreamTime}ms`,\r\n shellTime: `${metrics.shellTime}ms`,\r\n boundaries: metrics.boundaries.length,\r\n errors: metrics.errorCount,\r\n });\r\n },\r\n onError: ({ streamId, boundaryId, error }) => {\r\n log('[Flight] Stream error', { streamId, boundaryId, error: error.message });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Create observer that sends metrics to a custom endpoint (YOUR infrastructure)\r\n */\r\nexport function createHttpObserver(endpoint: string, options?: {\r\n headers?: Record<string, string>;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n}): StreamingObserver {\r\n const { headers = {}, batchSize = 10, flushInterval = 5000 } = options || {};\r\n const buffer: StreamingMetrics[] = [];\r\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const flush = async () => {\r\n if (buffer.length === 0) return;\r\n const batch = buffer.splice(0, buffer.length);\r\n\r\n try {\r\n await fetch(endpoint, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...headers,\r\n },\r\n body: JSON.stringify({ metrics: batch, timestamp: Date.now() }),\r\n });\r\n } catch (error) {\r\n console.error('[Flight] Failed to send metrics:', error);\r\n // Re-add to buffer for retry\r\n buffer.unshift(...batch);\r\n }\r\n };\r\n\r\n const scheduleFlush = () => {\r\n if (flushTimer) return;\r\n flushTimer = setTimeout(() => {\r\n flushTimer = null;\r\n flush();\r\n }, flushInterval);\r\n };\r\n\r\n return {\r\n onStreamEnd: (metrics) => {\r\n buffer.push(metrics);\r\n if (buffer.length >= batchSize) {\r\n flush();\r\n } else {\r\n scheduleFlush();\r\n }\r\n },\r\n };\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/handler.ts","../src/adapters/validation.ts","../src/adapters/index.ts"],"names":[],"mappings":"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","file":"chunk-77MJZCYD.js","sourcesContent":["/**\r\n * Flight Universal Handler - Platform-agnostic request handler\r\n * \r\n * This is the core abstraction that allows Flight applications to run anywhere.\r\n * Adapters can use this handler, or implement their own - zero lock-in.\r\n * \r\n * @module @flight-framework/core/adapters/handler\r\n */\r\n\r\nimport type { RenderContext, RenderResult, UIFrameworkAdapter } from '../render/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Route rules for per-path configuration\r\n * Similar to Nitro's routeRules - completely optional to use\r\n */\r\nexport interface RouteRules {\r\n [pattern: string]: RouteRuleConfig;\r\n}\r\n\r\nexport interface RouteRuleConfig {\r\n /** Cache configuration */\r\n cache?: {\r\n /** Max age in seconds */\r\n maxAge?: number;\r\n /** Stale-while-revalidate in seconds */\r\n swr?: number;\r\n /** Vary headers */\r\n vary?: string[];\r\n };\r\n\r\n /** CORS configuration */\r\n cors?: boolean | CorsOptions;\r\n\r\n /** Headers to add to response */\r\n headers?: Record<string, string>;\r\n\r\n /** Redirect configuration */\r\n redirect?: string | {\r\n to: string;\r\n statusCode?: 301 | 302 | 303 | 307 | 308;\r\n };\r\n\r\n /** Proxy to another URL */\r\n proxy?: string;\r\n\r\n /** Render mode override */\r\n render?: 'ssr' | 'ssg' | 'csr' | 'isr';\r\n\r\n /** ISR revalidation time in seconds */\r\n isr?: number;\r\n\r\n /** Prerender at build time */\r\n prerender?: boolean;\r\n}\r\n\r\nexport interface CorsOptions {\r\n origin?: string | string[] | boolean;\r\n methods?: string[];\r\n allowedHeaders?: string[];\r\n exposedHeaders?: string[];\r\n credentials?: boolean;\r\n maxAge?: number;\r\n}\r\n\r\n/**\r\n * Handler options - all optional, user configures what they need\r\n */\r\nexport interface UniversalHandlerOptions {\r\n /** Route manifest from build */\r\n manifest?: RouteManifest;\r\n\r\n /** UI framework adapter (optional - for SSR) */\r\n framework?: UIFrameworkAdapter;\r\n\r\n /** Route rules (optional) */\r\n routeRules?: RouteRules;\r\n\r\n /** Static files directory (optional) */\r\n staticDir?: string;\r\n\r\n /** Base path (optional) */\r\n basePath?: string;\r\n\r\n /** Custom error handler (optional) */\r\n onError?: (error: Error, request: Request) => Response | Promise<Response>;\r\n\r\n /** Custom not found handler (optional) */\r\n onNotFound?: (request: Request) => Response | Promise<Response>;\r\n\r\n /** Hooks for extensibility (optional) */\r\n hooks?: HandlerHooks;\r\n}\r\n\r\n/**\r\n * Handler hooks for extensibility - all optional\r\n */\r\nexport interface HandlerHooks {\r\n /** Before handling request */\r\n beforeHandle?: (request: Request) => Request | Promise<Request> | void;\r\n\r\n /** After getting response, before sending */\r\n afterHandle?: (request: Request, response: Response) => Response | Promise<Response> | void;\r\n\r\n /** Before SSR render */\r\n beforeRender?: (context: RenderContext) => void | Promise<void>;\r\n\r\n /** After SSR render */\r\n afterRender?: (result: RenderResult) => RenderResult | Promise<RenderResult>;\r\n}\r\n\r\n/**\r\n * Route manifest from build\r\n */\r\nexport interface RouteManifest {\r\n routes: Array<{\r\n path: string;\r\n component: string;\r\n mode: 'ssr' | 'ssg' | 'csr' | 'isr';\r\n handler?: string;\r\n }>;\r\n staticFiles?: string[];\r\n}\r\n\r\n/**\r\n * Universal handler interface\r\n */\r\nexport interface UniversalHandler {\r\n /** Handle a fetch request */\r\n fetch(request: Request, env?: unknown, ctx?: unknown): Promise<Response>;\r\n\r\n /** Check if this handler can handle the request */\r\n canHandle(request: Request): boolean;\r\n}\r\n\r\n// ============================================================================\r\n// Handler Factory\r\n// ============================================================================\r\n\r\n/**\r\n * Create a universal request handler\r\n * \r\n * This is the main abstraction for handling requests.\r\n * Adapters can use this, extend it, or ignore it completely.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Using the handler (optional)\r\n * import { createUniversalHandler } from '@flight-framework/core/adapters';\r\n * \r\n * const handler = createUniversalHandler({\r\n * manifest: await import('./manifest.json'),\r\n * routeRules: {\r\n * '/api/**': { cors: true },\r\n * '/blog/**': { cache: { maxAge: 3600 } },\r\n * },\r\n * });\r\n * \r\n * // In your adapter\r\n * export default {\r\n * fetch: handler.fetch,\r\n * };\r\n * ```\r\n */\r\nexport function createUniversalHandler(options: UniversalHandlerOptions = {}): UniversalHandler {\r\n const {\r\n manifest,\r\n routeRules = {},\r\n basePath = '',\r\n onError = defaultErrorHandler,\r\n onNotFound = defaultNotFoundHandler,\r\n hooks = {},\r\n } = options;\r\n\r\n return {\r\n /**\r\n * Handle incoming request\r\n */\r\n async fetch(request: Request, env?: unknown, ctx?: unknown): Promise<Response> {\r\n try {\r\n // Run beforeHandle hook\r\n if (hooks.beforeHandle) {\r\n const modifiedRequest = await hooks.beforeHandle(request);\r\n if (modifiedRequest) request = modifiedRequest;\r\n }\r\n\r\n const url = new URL(request.url);\r\n let pathname = url.pathname;\r\n\r\n // Strip base path if present\r\n if (basePath && pathname.startsWith(basePath)) {\r\n pathname = pathname.slice(basePath.length) || '/';\r\n }\r\n\r\n // Apply route rules\r\n const rules = matchRouteRules(pathname, routeRules);\r\n\r\n // Handle redirect rules\r\n if (rules?.redirect) {\r\n return handleRedirect(rules.redirect);\r\n }\r\n\r\n // Handle proxy rules\r\n if (rules?.proxy) {\r\n return handleProxy(request, rules.proxy);\r\n }\r\n\r\n // Handle CORS preflight\r\n if (request.method === 'OPTIONS' && rules?.cors) {\r\n return handleCorsPreFlight(rules.cors);\r\n }\r\n\r\n // Find matching route from manifest\r\n const route = manifest?.routes?.find(r => matchPath(pathname, r.path));\r\n\r\n // No matching route - try static or return 404\r\n if (!route) {\r\n return await onNotFound(request);\r\n }\r\n\r\n // Build render context\r\n const context: RenderContext = {\r\n url,\r\n params: extractParams(pathname, route.path),\r\n headers: request.headers,\r\n method: request.method,\r\n };\r\n\r\n // Run beforeRender hook\r\n if (hooks.beforeRender) {\r\n await hooks.beforeRender(context);\r\n }\r\n\r\n // Generate response based on route mode\r\n let response: Response;\r\n\r\n switch (route.mode) {\r\n case 'ssr':\r\n case 'isr':\r\n response = await handleSSR(context, options);\r\n break;\r\n case 'ssg':\r\n response = await handleSSG(context, options);\r\n break;\r\n case 'csr':\r\n response = handleCSR(options);\r\n break;\r\n default:\r\n response = await handleSSR(context, options);\r\n }\r\n\r\n // Apply cache headers from route rules\r\n if (rules?.cache) {\r\n response = applyCacheHeaders(response, rules.cache);\r\n }\r\n\r\n // Apply CORS headers\r\n if (rules?.cors) {\r\n response = applyCorsHeaders(response, rules.cors, request);\r\n }\r\n\r\n // Apply custom headers\r\n if (rules?.headers) {\r\n response = applyCustomHeaders(response, rules.headers);\r\n }\r\n\r\n // Run afterHandle hook\r\n if (hooks.afterHandle) {\r\n const modifiedResponse = await hooks.afterHandle(request, response);\r\n if (modifiedResponse) response = modifiedResponse;\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n return onError(error as Error, request);\r\n }\r\n },\r\n\r\n /**\r\n * Check if this handler can handle the request\r\n */\r\n canHandle(request: Request): boolean {\r\n const url = new URL(request.url);\r\n let pathname = url.pathname;\r\n\r\n if (basePath && pathname.startsWith(basePath)) {\r\n pathname = pathname.slice(basePath.length) || '/';\r\n }\r\n\r\n // Check manifest routes\r\n if (manifest?.routes) {\r\n return manifest.routes.some(r => matchPath(pathname, r.path));\r\n }\r\n\r\n // Check route rules\r\n return Object.keys(routeRules).some(pattern =>\r\n matchPath(pathname, pattern)\r\n );\r\n },\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Internal Helpers\r\n// ============================================================================\r\n\r\nfunction defaultErrorHandler(error: Error, _request: Request): Response {\r\n console.error('[Flight] Request error:', error);\r\n\r\n return new Response(\r\n JSON.stringify({\r\n error: 'Internal Server Error',\r\n message: process.env.NODE_ENV === 'development' ? error.message : undefined,\r\n }),\r\n {\r\n status: 500,\r\n headers: { 'Content-Type': 'application/json' },\r\n }\r\n );\r\n}\r\n\r\nfunction defaultNotFoundHandler(_request: Request): Response {\r\n return new Response('Not Found', { status: 404 });\r\n}\r\n\r\nfunction matchRouteRules(pathname: string, rules: RouteRules): RouteRuleConfig | null {\r\n for (const [pattern, config] of Object.entries(rules)) {\r\n if (matchPath(pathname, pattern)) {\r\n return config;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nfunction matchPath(pathname: string, pattern: string): boolean {\r\n // Handle exact match\r\n if (pattern === pathname) return true;\r\n\r\n // Handle wildcard patterns\r\n if (pattern.endsWith('/**')) {\r\n const prefix = pattern.slice(0, -3);\r\n return pathname.startsWith(prefix);\r\n }\r\n\r\n if (pattern.endsWith('/*')) {\r\n const prefix = pattern.slice(0, -2);\r\n const rest = pathname.slice(prefix.length);\r\n return pathname.startsWith(prefix) && !rest.includes('/');\r\n }\r\n\r\n // Handle dynamic params\r\n const patternParts = pattern.split('/');\r\n const pathParts = pathname.split('/');\r\n\r\n if (patternParts.length !== pathParts.length) return false;\r\n\r\n return patternParts.every((part, i) => {\r\n if (part.startsWith('[') && part.endsWith(']')) return true;\r\n if (part.startsWith(':')) return true;\r\n return part === pathParts[i];\r\n });\r\n}\r\n\r\nfunction extractParams(pathname: string, pattern: string): Record<string, string> {\r\n const params: Record<string, string> = {};\r\n const patternParts = pattern.split('/');\r\n const pathParts = pathname.split('/');\r\n\r\n patternParts.forEach((part, i) => {\r\n if (part.startsWith('[') && part.endsWith(']')) {\r\n const key = part.slice(1, -1).replace('...', '');\r\n params[key] = pathParts[i] ?? '';\r\n } else if (part.startsWith(':')) {\r\n params[part.slice(1)] = pathParts[i] ?? '';\r\n }\r\n });\r\n\r\n return params;\r\n}\r\n\r\nfunction handleRedirect(redirect: string | { to: string; statusCode?: number }): Response {\r\n const to = typeof redirect === 'string' ? redirect : redirect.to;\r\n const status = typeof redirect === 'string' ? 302 : (redirect.statusCode ?? 302);\r\n\r\n return new Response(null, {\r\n status,\r\n headers: { Location: to },\r\n });\r\n}\r\n\r\nasync function handleProxy(request: Request, target: string): Promise<Response> {\r\n const url = new URL(request.url);\r\n const targetUrl = new URL(target);\r\n targetUrl.pathname = url.pathname;\r\n targetUrl.search = url.search;\r\n\r\n const proxyRequest = new Request(targetUrl.toString(), {\r\n method: request.method,\r\n headers: request.headers,\r\n body: request.body,\r\n });\r\n\r\n return fetch(proxyRequest);\r\n}\r\n\r\nfunction handleCorsPreFlight(cors: boolean | CorsOptions): Response {\r\n // Normalize CORS options - true means default options, object means custom\r\n const options: CorsOptions = cors === true ? {} : (cors || {});\r\n\r\n return new Response(null, {\r\n status: 204,\r\n headers: {\r\n 'Access-Control-Allow-Origin': resolveOrigin(options.origin),\r\n 'Access-Control-Allow-Methods': (options.methods ?? ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).join(', '),\r\n 'Access-Control-Allow-Headers': (options.allowedHeaders ?? ['Content-Type', 'Authorization']).join(', '),\r\n 'Access-Control-Max-Age': String(options.maxAge ?? 86400),\r\n ...(options.credentials && { 'Access-Control-Allow-Credentials': 'true' }),\r\n },\r\n });\r\n}\r\n\r\nfunction resolveOrigin(origin?: string | string[] | boolean): string {\r\n if (origin === true || origin === undefined) return '*';\r\n if (origin === false) return '*';\r\n if (Array.isArray(origin)) return origin[0] ?? '*';\r\n return origin;\r\n}\r\n\r\nfunction applyCacheHeaders(response: Response, cache: { maxAge?: number; swr?: number }): Response {\r\n const headers = new Headers(response.headers);\r\n\r\n let cacheControl = `public, max-age=${cache.maxAge ?? 0}`;\r\n if (cache.swr) {\r\n cacheControl += `, stale-while-revalidate=${cache.swr}`;\r\n }\r\n\r\n headers.set('Cache-Control', cacheControl);\r\n\r\n return new Response(response.body, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers,\r\n });\r\n}\r\n\r\nfunction applyCorsHeaders(response: Response, cors: boolean | CorsOptions, _request: Request): Response {\r\n // Normalize CORS options\r\n const options: CorsOptions = cors === true ? {} : (cors || {});\r\n const headers = new Headers(response.headers);\r\n\r\n headers.set('Access-Control-Allow-Origin', resolveOrigin(options.origin));\r\n\r\n if (options.credentials) {\r\n headers.set('Access-Control-Allow-Credentials', 'true');\r\n }\r\n\r\n if (options.exposedHeaders) {\r\n headers.set('Access-Control-Expose-Headers', options.exposedHeaders.join(', '));\r\n }\r\n\r\n return new Response(response.body, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers,\r\n });\r\n}\r\n\r\nfunction applyCustomHeaders(response: Response, customHeaders: Record<string, string>): Response {\r\n const headers = new Headers(response.headers);\r\n\r\n for (const [key, value] of Object.entries(customHeaders)) {\r\n headers.set(key, value);\r\n }\r\n\r\n return new Response(response.body, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers,\r\n });\r\n}\r\n\r\nasync function handleSSR(context: RenderContext, options: UniversalHandlerOptions): Promise<Response> {\r\n const { framework, hooks } = options;\r\n\r\n // If no framework adapter, return placeholder\r\n if (!framework) {\r\n return new Response(createPlaceholderHTML(context.url.pathname), {\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\r\n });\r\n }\r\n\r\n // Render with framework adapter\r\n let result = await framework.renderToString({} as never, context);\r\n\r\n // Run afterRender hook\r\n if (hooks?.afterRender) {\r\n const modifiedResult = await hooks.afterRender(result);\r\n if (modifiedResult) result = modifiedResult;\r\n }\r\n\r\n return new Response(result.html, {\r\n status: result.status,\r\n headers: result.headers,\r\n });\r\n}\r\n\r\nasync function handleSSG(context: RenderContext, options: UniversalHandlerOptions): Promise<Response> {\r\n // For SSG, typically serve pre-rendered HTML\r\n // Fall back to SSR if not found\r\n return handleSSR(context, options);\r\n}\r\n\r\nfunction handleCSR(options: UniversalHandlerOptions): Response {\r\n const html = `<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>Flight App</title>\r\n </head>\r\n <body>\r\n <div id=\"app\"></div>\r\n <script type=\"module\" src=\"/assets/client.js\"></script>\r\n </body>\r\n</html>`;\r\n\r\n return new Response(html, {\r\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\r\n });\r\n}\r\n\r\nfunction createPlaceholderHTML(pathname: string): string {\r\n return `<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>Flight</title>\r\n <style>\r\n body { font-family: system-ui, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #0a0a0a; color: #fafafa; }\r\n .container { text-align: center; }\r\n h1 { font-size: 3rem; margin-bottom: 0.5rem; }\r\n p { color: #888; }\r\n code { background: #1a1a1a; padding: 0.25rem 0.5rem; border-radius: 4px; font-size: 0.875rem; }\r\n </style>\r\n </head>\r\n <body>\r\n <div class=\"container\">\r\n <h1>Flight</h1>\r\n <p>Path: <code>${pathname}</code></p>\r\n <p>Configure a UI framework adapter to enable SSR.</p>\r\n </div>\r\n </body>\r\n</html>`;\r\n}\r\n\r\n// Note: All exports are at the point of definition (export interface, export function)\r\n","/**\r\n * Flight Adapters - Optional Validation Helpers\r\n * \r\n * This module provides optional validation utilities for adapter options.\r\n * Zod is NOT required - these are only used if the developer chooses to\r\n * add runtime validation to their adapter.\r\n * \r\n * @example Without validation (default - no Zod needed)\r\n * ```typescript\r\n * import { createAdapter } from '@flight-framework/core/adapters';\r\n * \r\n * export default function myAdapter(options = {}) {\r\n * return createAdapter({\r\n * name: 'my-adapter',\r\n * adapt: async (builder) => { ... }\r\n * });\r\n * }\r\n * ```\r\n * \r\n * @example With optional Zod validation (if developer wants it)\r\n * ```typescript\r\n * import { createValidatedAdapter } from '@flight-framework/core/adapters';\r\n * import { z } from 'zod';\r\n * \r\n * const optionsSchema = z.object({\r\n * port: z.number().default(3000),\r\n * healthCheck: z.boolean().default(true),\r\n * });\r\n * \r\n * export default createValidatedAdapter(\r\n * 'my-adapter',\r\n * optionsSchema,\r\n * (options) => ({\r\n * adapt: async (builder) => { ... }\r\n * })\r\n * );\r\n * ```\r\n * \r\n * @module @flight-framework/core/adapters/validation\r\n */\r\n\r\nimport type { FlightAdapter, AdapterBuilder } from './index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Minimal Zod-like schema interface\r\n * This allows the validation helper to work with Zod or any compatible library\r\n * without requiring Zod as a direct dependency\r\n */\r\nexport interface ZodLikeSchema<T = unknown> {\r\n parse(data: unknown): T;\r\n safeParse(data: unknown): { success: true; data: T } | { success: false; error: unknown };\r\n}\r\n\r\n/**\r\n * Options for validated adapter factory\r\n */\r\nexport interface ValidatedAdapterOptions<T> {\r\n /** Parsed and validated options */\r\n adapt: (builder: AdapterBuilder) => Promise<void>;\r\n /** Optional emulate function */\r\n emulate?: FlightAdapter['emulate'];\r\n /** Optional supports declaration */\r\n supports?: FlightAdapter['supports'];\r\n}\r\n\r\n// ============================================================================\r\n// Validation Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create a validated adapter factory\r\n * \r\n * This helper validates adapter options at runtime using a Zod-like schema.\r\n * The developer chooses whether to use this - it's completely optional.\r\n * \r\n * @param name - Adapter name\r\n * @param schema - Zod-like schema for options validation\r\n * @param factory - Factory function that receives validated options\r\n * @returns Adapter factory function\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createValidatedAdapter } from '@flight-framework/core/adapters';\r\n * import { z } from 'zod';\r\n * \r\n * const schema = z.object({\r\n * port: z.number().default(3000),\r\n * region: z.string().optional(),\r\n * });\r\n * \r\n * export default createValidatedAdapter('my-adapter', schema, (options) => ({\r\n * adapt: async (builder) => {\r\n * // options is fully typed: { port: number; region?: string }\r\n * console.log(`Using port ${options.port}`);\r\n * }\r\n * }));\r\n * ```\r\n */\r\nexport function createValidatedAdapter<TSchema extends ZodLikeSchema>(\r\n name: string,\r\n schema: TSchema,\r\n factory: (options: ReturnType<TSchema['parse']>) => ValidatedAdapterOptions<ReturnType<TSchema['parse']>>\r\n): (options?: unknown) => FlightAdapter {\r\n return (rawOptions: unknown = {}): FlightAdapter => {\r\n // Validate options using the provided schema\r\n const parseResult = schema.safeParse(rawOptions);\r\n\r\n if (!parseResult.success) {\r\n const errorMessage = formatValidationError(name, parseResult.error);\r\n throw new Error(errorMessage);\r\n }\r\n\r\n const validatedOptions = parseResult.data as ReturnType<TSchema['parse']>;\r\n const adapterConfig = factory(validatedOptions);\r\n\r\n return {\r\n name,\r\n adapt: adapterConfig.adapt,\r\n emulate: adapterConfig.emulate,\r\n supports: adapterConfig.supports,\r\n };\r\n };\r\n}\r\n\r\n/**\r\n * Validate adapter options without throwing\r\n * Returns null if validation fails, useful for optional validation\r\n * \r\n * @param schema - Zod-like schema\r\n * @param options - Options to validate\r\n * @returns Validated options or null\r\n */\r\nexport function validateAdapterOptions<TSchema extends ZodLikeSchema>(\r\n schema: TSchema,\r\n options: unknown\r\n): ReturnType<TSchema['parse']> | null {\r\n const result = schema.safeParse(options);\r\n return result.success ? (result.data as ReturnType<TSchema['parse']>) : null;\r\n}\r\n\r\n/**\r\n * Assert adapter options are valid, throwing detailed error if not\r\n * \r\n * @param name - Adapter name for error messages\r\n * @param schema - Zod-like schema\r\n * @param options - Options to validate\r\n * @returns Validated options\r\n * @throws Error with detailed message if validation fails\r\n */\r\nexport function assertValidOptions<TSchema extends ZodLikeSchema>(\r\n name: string,\r\n schema: TSchema,\r\n options: unknown\r\n): ReturnType<TSchema['parse']> {\r\n const result = schema.safeParse(options);\r\n\r\n if (!result.success) {\r\n throw new Error(formatValidationError(name, result.error));\r\n }\r\n\r\n return result.data as ReturnType<TSchema['parse']>;\r\n}\r\n\r\n// ============================================================================\r\n// Error Formatting\r\n// ============================================================================\r\n\r\n/**\r\n * Format a validation error into a readable message\r\n */\r\nfunction formatValidationError(adapterName: string, error: unknown): string {\r\n const prefix = `[${adapterName}] Invalid adapter options`;\r\n\r\n // Handle Zod errors\r\n if (error && typeof error === 'object' && 'issues' in error) {\r\n const zodError = error as { issues: Array<{ path: (string | number)[]; message: string }> };\r\n const issues = zodError.issues\r\n .map(issue => ` - ${issue.path.join('.')}: ${issue.message}`)\r\n .join('\\n');\r\n return `${prefix}:\\n${issues}`;\r\n }\r\n\r\n // Fallback for other error types\r\n if (error instanceof Error) {\r\n return `${prefix}: ${error.message}`;\r\n }\r\n\r\n return `${prefix}: Unknown validation error`;\r\n}\r\n\r\n// ============================================================================\r\n// Type Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Extract the inferred type from a Zod-like schema\r\n * Useful for typing adapter options in TypeScript\r\n */\r\nexport type InferSchema<T extends ZodLikeSchema> = ReturnType<T['parse']>;\r\n","/**\r\n * Flight Adapters - Universal deployment adapters\r\n * \r\n * Adapters transform Flight's output for different deployment targets.\r\n * The user chooses where to deploy - Flight provides the adapters.\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/** Build manifest containing all generated assets */\r\nexport interface BuildManifest {\r\n /** Entry points by name */\r\n entries: Record<string, string>;\r\n /** All generated files */\r\n files: string[];\r\n /** Route information */\r\n routes: RouteManifestEntry[];\r\n /** Server entry point (if applicable) */\r\n serverEntry?: string;\r\n /** Client entry point */\r\n clientEntry?: string;\r\n}\r\n\r\n/** Route information in manifest */\r\nexport interface RouteManifestEntry {\r\n /** Route path pattern */\r\n path: string;\r\n /** Render mode for this route */\r\n mode: 'ssr' | 'ssg' | 'csr' | 'isr';\r\n /** Component/handler file path */\r\n component: string;\r\n /** Pre-rendered paths (for SSG/ISR) */\r\n prerendered?: string[];\r\n}\r\n\r\n/** Builder utilities passed to adapters */\r\nexport interface AdapterBuilder {\r\n /** Build manifest */\r\n manifest: BuildManifest;\r\n /** Project root directory */\r\n root: string;\r\n /** Build output directory */\r\n outDir: string;\r\n\r\n /** Read a file from the build output */\r\n readFile(path: string): Promise<string>;\r\n /** Write a file to the adapter output */\r\n writeFile(path: string, content: string): Promise<void>;\r\n /** Copy files from build to adapter output */\r\n copy(from: string, to: string): Promise<void>;\r\n /** Get all files matching a pattern */\r\n glob(pattern: string): Promise<string[]>;\r\n /** Compress files for production */\r\n compress?(files: string[]): Promise<void>;\r\n\r\n /** Log info message */\r\n log: {\r\n info(message: string): void;\r\n warn(message: string): void;\r\n error(message: string): void;\r\n };\r\n}\r\n\r\n/** Flight adapter interface */\r\nexport interface FlightAdapter {\r\n /** Adapter name */\r\n name: string;\r\n\r\n /** \r\n * Transform the build output for the target platform\r\n * This is called after Flight's build process completes\r\n */\r\n adapt(builder: AdapterBuilder): Promise<void>;\r\n\r\n /**\r\n * Optional: Start listening for requests (for Node.js/Bun adapters)\r\n */\r\n listen?(server: unknown, port: number): Promise<void>;\r\n\r\n /**\r\n * Optional: Emulate the platform during development\r\n * Useful for testing platform-specific behavior locally\r\n */\r\n emulate?(): {\r\n /** Platform-specific env vars */\r\n env?: Record<string, string>;\r\n /** Custom middleware for dev server */\r\n middleware?: unknown[];\r\n };\r\n\r\n /**\r\n * Optional: Declare what this adapter supports\r\n * Flight uses this to warn about incompatible features\r\n */\r\n supports?: {\r\n /** Can read files at runtime (for dynamic content) */\r\n read?: () => boolean;\r\n /** Supports streaming responses */\r\n streaming?: () => boolean;\r\n /** Supports WebSockets */\r\n websockets?: () => boolean;\r\n /** Supports edge runtime */\r\n edge?: () => boolean;\r\n /** Supports Node.js runtime */\r\n node?: () => boolean;\r\n };\r\n}\r\n\r\n\r\n// ============================================================================\r\n// Adapter Factory Helper\r\n// ============================================================================\r\n\r\nexport interface AdapterOptions {\r\n name: string;\r\n adapt: (builder: AdapterBuilder) => Promise<void>;\r\n emulate?: FlightAdapter['emulate'];\r\n supports?: FlightAdapter['supports'];\r\n}\r\n\r\n/**\r\n * Create a Flight adapter\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createAdapter } from '@flight-framework/core/adapters';\r\n * \r\n * export default function myAdapter(options = {}) {\r\n * return createAdapter({\r\n * name: 'my-adapter',\r\n * async adapt(builder) {\r\n * // Transform build output for your platform\r\n * },\r\n * });\r\n * }\r\n * ```\r\n */\r\nexport function createAdapter(options: AdapterOptions): FlightAdapter {\r\n return {\r\n name: options.name,\r\n adapt: options.adapt,\r\n emulate: options.emulate,\r\n supports: options.supports,\r\n };\r\n}\r\n\r\n// Re-export universal handler for adapters to use (optional)\r\nexport * from './handler.js';\r\n\r\n// Re-export optional validation helpers (Zod not required)\r\nexport * from './validation.js';\r\n\r\n// ============================================================================\r\n// Agnostic Service Adapters (Interfaces)\r\n// ============================================================================\r\n\r\n/**\r\n * Storage Adapter Interface\r\n * \r\n * Implement this to use any storage provider:\r\n * S3, Supabase Storage, Cloudflare R2, local filesystem, etc.\r\n */\r\nexport interface StorageAdapter {\r\n name: string;\r\n\r\n /** Upload a file */\r\n upload(path: string, data: Buffer | Uint8Array | string, options?: {\r\n contentType?: string;\r\n metadata?: Record<string, string>;\r\n }): Promise<{ url: string; path: string }>;\r\n\r\n /** Download a file */\r\n download(path: string): Promise<Buffer>;\r\n\r\n /** Delete a file */\r\n delete(path: string): Promise<void>;\r\n\r\n /** List files with optional prefix */\r\n list(prefix?: string): Promise<string[]>;\r\n\r\n /** Get a signed URL for direct access */\r\n getSignedUrl?(path: string, options?: {\r\n expiresIn?: number;\r\n operation?: 'read' | 'write';\r\n }): Promise<string>;\r\n}\r\n\r\n/**\r\n * Auth Adapter Interface\r\n * \r\n * Implement this to use any auth provider:\r\n * Better Auth, Supabase Auth, Lucia, Auth.js, etc.\r\n */\r\nexport interface AuthAdapter {\r\n name: string;\r\n\r\n /** Get the current user from a request */\r\n getUser(request: Request): Promise<AuthUser | null>;\r\n\r\n /** Verify a session token */\r\n verifySession(token: string): Promise<AuthSession | null>;\r\n\r\n /** Optional middleware for handling auth-specific routes (e.g., /api/auth/*) */\r\n middleware?: (req: Request) => Promise<Response | null>;\r\n}\r\n\r\nexport interface AuthUser {\r\n id: string;\r\n email?: string;\r\n name?: string;\r\n avatar?: string;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\nexport interface AuthSession {\r\n user: AuthUser;\r\n expiresAt: Date;\r\n token: string;\r\n}\r\n\r\n/**\r\n * Email Adapter Interface\r\n * \r\n * Implement this to use any email provider:\r\n * Resend, SendGrid, Postmark, SMTP, etc.\r\n */\r\nexport interface EmailAdapter {\r\n name: string;\r\n\r\n /** Send an email */\r\n send(options: {\r\n to: string | string[];\r\n subject: string;\r\n html?: string;\r\n text?: string;\r\n from?: string;\r\n replyTo?: string;\r\n attachments?: Array<{\r\n filename: string;\r\n content: Buffer | string;\r\n contentType?: string;\r\n }>;\r\n }): Promise<{ id: string; success: boolean }>;\r\n}\r\n\r\n/**\r\n * Queue/Jobs Adapter Interface\r\n * \r\n * Implement this to use any job queue:\r\n * BullMQ, Quirrel, Inngest, custom, etc.\r\n */\r\nexport interface JobsAdapter {\r\n name: string;\r\n\r\n /** Add a job to the queue */\r\n enqueue<T>(jobName: string, data: T, options?: {\r\n delay?: number;\r\n priority?: number;\r\n retries?: number;\r\n }): Promise<{ id: string }>;\r\n\r\n /** Schedule a recurring job */\r\n schedule?(jobName: string, cron: string, data?: unknown): Promise<{ id: string }>;\r\n\r\n /** Cancel a job */\r\n cancel?(jobId: string): Promise<void>;\r\n}\r\n\r\n/**\r\n * Database Adapter Interface\r\n * \r\n * Note: This is intentionally minimal. \r\n * For databases, use your preferred ORM/query builder directly.\r\n * This interface is for Flight's internal use (sessions, cache, etc.)\r\n */\r\nexport interface DatabaseAdapter {\r\n name: string;\r\n\r\n /** Raw query execution */\r\n query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;\r\n\r\n /** Execute a mutation */\r\n execute(sql: string, params?: unknown[]): Promise<{ rowsAffected: number }>;\r\n\r\n /** Transaction support */\r\n transaction?<T>(fn: (tx: DatabaseAdapter) => Promise<T>): Promise<T>;\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/index.ts"],"names":[],"mappings":"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","file":"chunk-EGB7C73X.js","sourcesContent":["/**\r\n * Flight Server - Main server factory\r\n * \r\n * Creates a Flight server instance that handles routing, middleware, and rendering.\r\n * This is the primary entry point for Flight applications.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createServer } from '@flight-framework/core';\r\n * \r\n * const server = createServer();\r\n * \r\n * server.get('/api/health', () => Response.json({ status: 'ok' }));\r\n * \r\n * // Just works! Auto-detects Node.js, Bun, or Deno\r\n * server.listen(3000);\r\n * ```\r\n */\r\n\r\nimport { createRouter, type Router } from '../router/index.js';\r\nimport {\r\n createMiddlewareChain,\r\n createContextFromRequest,\r\n createResponseFromContext,\r\n type MiddlewareChain,\r\n type Middleware,\r\n} from '../middleware/index.js';\r\nimport { type FlightConfig, type FlightUserConfig, resolveConfig } from '../config/index.js';\r\nimport type { FlightAdapter } from '../adapters/index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/** Route handler function signature */\r\nexport type RouteHandler = (context: RouteHandlerContext) => Promise<Response> | Response;\r\n\r\n/** Context passed to route handlers */\r\nexport interface RouteHandlerContext {\r\n /** The incoming request */\r\n request: Request;\r\n /** URL parameters from routing */\r\n params: Record<string, string | string[]>;\r\n /** Query parameters */\r\n query: URLSearchParams;\r\n /** Parsed URL */\r\n url: URL;\r\n /** Local data from middleware */\r\n locals: Record<string, unknown>;\r\n /** Database instance (if configured) */\r\n db?: unknown;\r\n /** Auth instance (if configured) */\r\n auth?: unknown;\r\n /** Email instance (if configured) */\r\n email?: unknown;\r\n}\r\n\r\n/** Server options */\r\nexport interface ServerOptions {\r\n /** Server configuration */\r\n config?: FlightUserConfig;\r\n /** Deployment adapter */\r\n adapter?: FlightAdapter;\r\n /** Database instance */\r\n db?: unknown;\r\n /** Auth instance */\r\n auth?: unknown;\r\n /** Email instance */\r\n email?: unknown;\r\n}\r\n\r\n/** Route definition for the server */\r\nexport interface ServerRoute {\r\n /** HTTP method (GET, POST, etc.) */\r\n method: string | string[];\r\n /** Route path pattern */\r\n path: string;\r\n /** Route handler */\r\n handler: RouteHandler;\r\n}\r\n\r\n/** Listen options */\r\nexport interface ListenOptions {\r\n /** Port to listen on (default: 3000) */\r\n port?: number;\r\n /** Hostname to bind to (default: 'localhost') */\r\n hostname?: string;\r\n /** Callback when server starts */\r\n onListen?: (info: { port: number; hostname: string }) => void;\r\n}\r\n\r\n/** Flight Server instance */\r\nexport interface FlightServer {\r\n /** Add a route */\r\n route(method: string | string[], path: string, handler: RouteHandler): FlightServer;\r\n\r\n /** Convenience methods for common HTTP methods */\r\n get(path: string, handler: RouteHandler): FlightServer;\r\n post(path: string, handler: RouteHandler): FlightServer;\r\n put(path: string, handler: RouteHandler): FlightServer;\r\n delete(path: string, handler: RouteHandler): FlightServer;\r\n patch(path: string, handler: RouteHandler): FlightServer;\r\n\r\n /** Add middleware */\r\n use(middleware: Middleware): FlightServer;\r\n use(path: string, middleware: Middleware): FlightServer;\r\n\r\n /** Handle incoming request (Web standard Request/Response) */\r\n handle(request: Request): Promise<Response>;\r\n\r\n /** \r\n * Start the HTTP server\r\n * Auto-detects runtime: Node.js, Bun, or Deno\r\n */\r\n listen(port?: number | ListenOptions): Promise<void>;\r\n\r\n /** Fetch handler for Bun.serve() and Deno.serve() */\r\n fetch(request: Request): Promise<Response>;\r\n\r\n /** Get the resolved configuration */\r\n readonly config: FlightConfig;\r\n\r\n /** Get the router instance */\r\n readonly router: Router<RouteHandler>;\r\n\r\n /** Get the middleware chain */\r\n readonly middleware: MiddlewareChain;\r\n}\r\n\r\n// ============================================================================\r\n// Runtime Detection\r\n// ============================================================================\r\n\r\ntype Runtime = 'node' | 'bun' | 'deno' | 'unknown';\r\n\r\nfunction detectRuntime(): Runtime {\r\n // @ts-expect-error - Bun global\r\n if (typeof Bun !== 'undefined') return 'bun';\r\n // @ts-expect-error - Deno global \r\n if (typeof Deno !== 'undefined') return 'deno';\r\n if (typeof process !== 'undefined' && process.versions?.node) return 'node';\r\n return 'unknown';\r\n}\r\n\r\n// ============================================================================\r\n// Server Implementation\r\n// ============================================================================\r\n\r\ninterface RouteEntry {\r\n methods: Set<string>;\r\n handler: RouteHandler;\r\n}\r\n\r\n/**\r\n * Create a new Flight server instance\r\n * \r\n * @example\r\n * ```typescript\r\n * import { createServer } from '@flight-framework/core';\r\n * \r\n * const server = createServer();\r\n * \r\n * server.get('/api/users', async ({ db }) => {\r\n * const users = await db.query('SELECT * FROM users');\r\n * return Response.json(users);\r\n * });\r\n * \r\n * // Works on Node.js, Bun, and Deno!\r\n * server.listen(3000);\r\n * ```\r\n */\r\nexport function createServer(options: ServerOptions = {}): FlightServer {\r\n const config = resolveConfig(options.config ?? {});\r\n const router = createRouter<RouteEntry>();\r\n const middlewareChain = createMiddlewareChain();\r\n\r\n // Store dependencies\r\n const deps = {\r\n db: options.db,\r\n auth: options.auth,\r\n email: options.email,\r\n };\r\n\r\n function addRoute(method: string | string[], path: string, handler: RouteHandler): FlightServer {\r\n const methods = Array.isArray(method) ? method : [method];\r\n const methodSet = new Set(methods.map(m => m.toUpperCase()));\r\n\r\n // Check if route already exists\r\n const existingMatch = router.match(path);\r\n if (existingMatch && existingMatch.route.path === path) {\r\n // Merge methods\r\n for (const m of methodSet) {\r\n existingMatch.route.handler.methods.add(m);\r\n }\r\n existingMatch.route.handler.handler = handler;\r\n } else {\r\n router.add({\r\n path,\r\n handler: { methods: methodSet, handler },\r\n });\r\n }\r\n\r\n return server;\r\n }\r\n\r\n function useMiddleware(\r\n pathOrMiddleware: string | Middleware,\r\n maybeMiddleware?: Middleware\r\n ): FlightServer {\r\n if (typeof pathOrMiddleware === 'string' && maybeMiddleware) {\r\n middlewareChain.use(pathOrMiddleware, maybeMiddleware);\r\n } else if (typeof pathOrMiddleware === 'function') {\r\n middlewareChain.use(pathOrMiddleware);\r\n }\r\n return server;\r\n }\r\n\r\n async function handle(request: Request): Promise<Response> {\r\n const url = new URL(request.url);\r\n const method = request.method.toUpperCase();\r\n\r\n // Run middleware\r\n const ctx = createContextFromRequest(request);\r\n await middlewareChain.execute(ctx);\r\n\r\n // If middleware already set a response, return it\r\n if (ctx.responseBody !== undefined) {\r\n return createResponseFromContext(ctx);\r\n }\r\n\r\n // Match route\r\n const match = router.match(url.pathname);\r\n if (!match) {\r\n return new Response('Not Found', { status: 404 });\r\n }\r\n\r\n // Check method\r\n if (!match.route.handler.methods.has(method) && !match.route.handler.methods.has('*')) {\r\n return new Response('Method Not Allowed', { status: 405 });\r\n }\r\n\r\n // Build handler context\r\n const handlerContext: RouteHandlerContext = {\r\n request,\r\n params: match.params,\r\n query: url.searchParams,\r\n url,\r\n locals: ctx.locals,\r\n ...deps,\r\n };\r\n\r\n try {\r\n return await match.route.handler.handler(handlerContext);\r\n } catch (error) {\r\n console.error('Route handler error:', error);\r\n return new Response('Internal Server Error', { status: 500 });\r\n }\r\n }\r\n\r\n /**\r\n * Start the HTTP server\r\n * Auto-detects the runtime and uses the appropriate server\r\n */\r\n async function listen(portOrOptions?: number | ListenOptions): Promise<void> {\r\n const opts: ListenOptions = typeof portOrOptions === 'number'\r\n ? { port: portOrOptions }\r\n : portOrOptions ?? {};\r\n\r\n const port = opts.port ?? config.dev.port ?? 3000;\r\n const hostname = opts.hostname ?? 'localhost';\r\n\r\n // Check for custom adapter first\r\n const adapter = options.adapter ?? config.adapter;\r\n if (adapter?.listen) {\r\n await adapter.listen(server, port);\r\n return;\r\n }\r\n\r\n const runtime = detectRuntime();\r\n\r\n switch (runtime) {\r\n case 'bun':\r\n await startBunServer(port, hostname, opts.onListen);\r\n break;\r\n case 'deno':\r\n await startDenoServer(port, hostname, opts.onListen);\r\n break;\r\n case 'node':\r\n default:\r\n await startNodeServer(port, hostname, opts.onListen);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Start Node.js HTTP server\r\n */\r\n async function startNodeServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n const { createServer: createHttpServer } = await import('node:http');\r\n\r\n const httpServer = createHttpServer(async (req, res) => {\r\n const url = new URL(req.url || '/', `http://${hostname}:${port}`);\r\n\r\n // Build headers\r\n const headers = new Headers();\r\n for (const [key, value] of Object.entries(req.headers)) {\r\n if (value) {\r\n const headerValue = Array.isArray(value) ? value[0] : value;\r\n if (headerValue) headers.set(key, headerValue);\r\n }\r\n }\r\n\r\n // Read body for POST/PUT/PATCH\r\n let body: string | undefined;\r\n if (['POST', 'PUT', 'PATCH'].includes(req.method || '')) {\r\n body = await new Promise<string>((resolve) => {\r\n let data = '';\r\n req.on('data', chunk => data += chunk);\r\n req.on('end', () => resolve(data));\r\n });\r\n }\r\n\r\n const request = new Request(url.toString(), {\r\n method: req.method,\r\n headers,\r\n body: body || undefined,\r\n });\r\n\r\n try {\r\n const response = await handle(request);\r\n\r\n res.statusCode = response.status;\r\n response.headers.forEach((value, key) => {\r\n res.setHeader(key, value);\r\n });\r\n\r\n const responseBody = await response.text();\r\n res.end(responseBody);\r\n } catch (error) {\r\n console.error('Server error:', error);\r\n res.statusCode = 500;\r\n res.setHeader('Content-Type', 'application/json');\r\n res.end(JSON.stringify({ error: 'Internal Server Error' }));\r\n }\r\n });\r\n\r\n return new Promise((resolve) => {\r\n httpServer.listen(port, hostname, () => {\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Node.js) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n resolve();\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Start Bun server\r\n */\r\n async function startBunServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n // @ts-expect-error - Bun types\r\n Bun.serve({\r\n port,\r\n hostname,\r\n fetch: handle,\r\n });\r\n\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Bun) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n }\r\n\r\n /**\r\n * Start Deno server\r\n */\r\n async function startDenoServer(port: number, hostname: string, onListen?: ListenOptions['onListen']): Promise<void> {\r\n // @ts-expect-error - Deno types\r\n Deno.serve({ port, hostname }, handle);\r\n\r\n const info = { port, hostname };\r\n if (onListen) {\r\n onListen(info);\r\n } else {\r\n console.log(`\r\n╔═══════════════════════════════════════════════════════════╗\r\n║ Flight Server (Deno) ║\r\n╠═══════════════════════════════════════════════════════════╣\r\n║ Server: http://${hostname}:${port.toString().padEnd(37)}║\r\n╚═══════════════════════════════════════════════════════════╝\r\n`);\r\n }\r\n }\r\n\r\n const server: FlightServer = {\r\n route: addRoute,\r\n get: (path, handler) => addRoute('GET', path, handler),\r\n post: (path, handler) => addRoute('POST', path, handler),\r\n put: (path, handler) => addRoute('PUT', path, handler),\r\n delete: (path, handler) => addRoute('DELETE', path, handler),\r\n patch: (path, handler) => addRoute('PATCH', path, handler),\r\n use: useMiddleware as FlightServer['use'],\r\n handle,\r\n listen,\r\n fetch: handle, // Alias for Bun/Deno compatibility\r\n get config() { return config; },\r\n get router() { return router as unknown as Router<RouteHandler>; },\r\n get middleware() { return middlewareChain; },\r\n };\r\n\r\n return server;\r\n}\r\n\r\n// ============================================================================\r\n// Helper Exports\r\n// ============================================================================\r\n\r\n/** Type guard to check if an object is a FlightServer */\r\nexport function isFlightServer(obj: unknown): obj is FlightServer {\r\n return (\r\n typeof obj === 'object' &&\r\n obj !== null &&\r\n 'handle' in obj &&\r\n 'route' in obj &&\r\n typeof (obj as FlightServer).handle === 'function'\r\n );\r\n}\r\n\r\n/** Get current runtime */\r\nexport function getRuntime(): Runtime {\r\n return detectRuntime();\r\n}\r\n\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors/index.ts"],"names":[],"mappings":"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","file":"chunk-FSJNOPYE.js","sourcesContent":["/**\r\n * @flight-framework/core - Error Handling\r\n * \r\n * Comprehensive error handling utilities for Flight applications.\r\n * All utilities are OPTIONAL - developers can use their own error handling.\r\n * \r\n * Philosophy: Flight OFFERS these utilities, but never IMPOSES them.\r\n * Using throw new Error() works perfectly fine - this is your choice.\r\n */\r\n\r\nimport { isProduction, isDevelopment } from '../utils/env.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for creating a Flight error\r\n */\r\nexport interface FlightErrorOptions {\r\n /** HTTP status code */\r\n statusCode: number;\r\n /** Short status message (e.g., \"Not Found\") */\r\n statusMessage?: string;\r\n /** Detailed error message */\r\n message?: string;\r\n /** Additional data to include with the error */\r\n data?: Record<string, unknown>;\r\n /** If true, shows full-screen error page instead of error boundary */\r\n fatal?: boolean;\r\n /** Original error that caused this error */\r\n cause?: Error;\r\n}\r\n\r\n/**\r\n * Extended error props with digest for production error correlation\r\n */\r\nexport interface FlightErrorProps {\r\n /** The error object */\r\n error: Error & { digest?: string };\r\n /** Function to attempt recovery by re-rendering */\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * Reset details provided to onReset callback\r\n */\r\nexport interface ResetDetails {\r\n /** Reason for the reset */\r\n reason: 'imperative-api' | 'keys';\r\n /** Arguments passed to resetErrorBoundary (if imperative) */\r\n args?: unknown[];\r\n /** Previous resetKeys values (if keys changed) */\r\n prev?: unknown[];\r\n /** New resetKeys values (if keys changed) */\r\n next?: unknown[];\r\n}\r\n\r\n/**\r\n * Options for error boundary behavior\r\n */\r\nexport interface ErrorBoundaryOptions {\r\n /** Keys that trigger automatic reset when changed */\r\n resetKeys?: unknown[];\r\n /** Callback when error boundary resets */\r\n onReset?: (details: ResetDetails) => void;\r\n /** Callback when error is caught */\r\n onError?: (error: Error, info: { componentStack?: string }) => void;\r\n}\r\n\r\n// ============================================================================\r\n// FlightError Class\r\n// ============================================================================\r\n\r\n/**\r\n * Custom error class with status code and metadata support.\r\n * \r\n * You can use this class or regular Error - Flight handles both.\r\n * \r\n * @example\r\n * ```typescript\r\n * throw new FlightError({\r\n * statusCode: 404,\r\n * message: 'User not found',\r\n * data: { userId: '123' }\r\n * });\r\n * ```\r\n */\r\nexport class FlightError extends Error {\r\n /** HTTP status code */\r\n readonly statusCode: number;\r\n /** Short status message */\r\n readonly statusMessage: string;\r\n /** Additional error data */\r\n readonly data?: Record<string, unknown>;\r\n /** Whether this is a fatal error (shows full-screen) */\r\n readonly fatal: boolean;\r\n /** Unique digest for production error correlation */\r\n readonly digest?: string;\r\n\r\n constructor(options: FlightErrorOptions) {\r\n super(options.message || options.statusMessage || 'An error occurred');\r\n\r\n this.name = 'FlightError';\r\n this.statusCode = options.statusCode;\r\n this.statusMessage = options.statusMessage || getDefaultStatusMessage(options.statusCode);\r\n this.data = options.data;\r\n this.fatal = options.fatal ?? false;\r\n\r\n // Generate digest in production for error correlation\r\n // Using typeof check for SSR/browser compatibility\r\n if (isProduction()) {\r\n this.digest = generateDigest();\r\n }\r\n\r\n // Preserve original error stack if cause provided\r\n if (options.cause) {\r\n this.cause = options.cause;\r\n if (options.cause.stack) {\r\n this.stack = `${this.stack}\\nCaused by: ${options.cause.stack}`;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Convert to plain object for serialization\r\n */\r\n toJSON(): Record<string, unknown> {\r\n return {\r\n name: this.name,\r\n message: this.message,\r\n statusCode: this.statusCode,\r\n statusMessage: this.statusMessage,\r\n data: this.data,\r\n fatal: this.fatal,\r\n digest: this.digest,\r\n };\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// HTTP Error Classes (Convenience)\r\n// ============================================================================\r\n\r\n/**\r\n * 400 Bad Request error\r\n */\r\nexport class BadRequestError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 400, message, data });\r\n this.name = 'BadRequestError';\r\n }\r\n}\r\n\r\n/**\r\n * 401 Unauthorized error\r\n */\r\nexport class UnauthorizedError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 401, message: message || 'Unauthorized', data });\r\n this.name = 'UnauthorizedError';\r\n }\r\n}\r\n\r\n/**\r\n * 403 Forbidden error\r\n */\r\nexport class ForbiddenError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 403, message: message || 'Forbidden', data });\r\n this.name = 'ForbiddenError';\r\n }\r\n}\r\n\r\n/**\r\n * 404 Not Found error\r\n */\r\nexport class NotFoundError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 404, message: message || 'Not Found', data });\r\n this.name = 'NotFoundError';\r\n }\r\n}\r\n\r\n/**\r\n * 500 Internal Server Error\r\n */\r\nexport class InternalError extends FlightError {\r\n constructor(message?: string, data?: Record<string, unknown>) {\r\n super({ statusCode: 500, message: message || 'Internal Server Error', data });\r\n this.name = 'InternalError';\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create a FlightError with the specified options.\r\n * \r\n * This is a convenience function - you can also use `new FlightError()` directly\r\n * or just `throw new Error()` - Flight handles all cases.\r\n * \r\n * @example\r\n * ```typescript\r\n * // With full options\r\n * throw createError({\r\n * statusCode: 404,\r\n * message: 'Product not found',\r\n * data: { productId: 'abc123' }\r\n * });\r\n * \r\n * // Simple string shorthand (becomes 500 error)\r\n * throw createError('Something went wrong');\r\n * ```\r\n */\r\nexport function createError(options: FlightErrorOptions | string): FlightError {\r\n if (typeof options === 'string') {\r\n return new FlightError({ statusCode: 500, message: options });\r\n }\r\n return new FlightError(options);\r\n}\r\n\r\n/**\r\n * Create a 404 Not Found error.\r\n * Convenience function equivalent to `createError({ statusCode: 404, ... })`.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!user) {\r\n * throw notFound('User not found');\r\n * }\r\n * ```\r\n */\r\nexport function notFound(message?: string, data?: Record<string, unknown>): never {\r\n throw new NotFoundError(message, data);\r\n}\r\n\r\n/**\r\n * Create a 403 Forbidden error.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!user.isAdmin) {\r\n * throw forbidden('Admin access required');\r\n * }\r\n * ```\r\n */\r\nexport function forbidden(message?: string, data?: Record<string, unknown>): never {\r\n throw new ForbiddenError(message, data);\r\n}\r\n\r\n/**\r\n * Create a 401 Unauthorized error.\r\n * \r\n * @example\r\n * ```typescript\r\n * if (!session) {\r\n * throw unauthorized('Please log in to continue');\r\n * }\r\n * ```\r\n */\r\nexport function unauthorized(message?: string, data?: Record<string, unknown>): never {\r\n throw new UnauthorizedError(message, data);\r\n}\r\n\r\n// ============================================================================\r\n// Error State Management (Client-Side)\r\n// ============================================================================\r\n\r\n// Global error state for client-side\r\ndeclare global {\r\n interface Window {\r\n __FLIGHT_ERROR__?: FlightError | null;\r\n }\r\n}\r\n\r\n/**\r\n * Programmatically show an error page.\r\n * \r\n * This triggers the nearest error boundary or navigates to the error page.\r\n * Only works on the client side.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Show error with full options\r\n * showError({\r\n * statusCode: 500,\r\n * message: 'Connection lost'\r\n * });\r\n * \r\n * // Simple string shorthand\r\n * showError('Something went wrong');\r\n * ```\r\n */\r\nexport function showError(error: FlightErrorOptions | FlightError | string): void {\r\n let flightError: FlightError;\r\n\r\n if (typeof error === 'string') {\r\n flightError = new FlightError({ statusCode: 500, message: error });\r\n } else if (error instanceof FlightError) {\r\n flightError = error;\r\n } else {\r\n flightError = new FlightError(error);\r\n }\r\n\r\n // Client-side: dispatch custom event for error boundaries\r\n if (typeof window !== 'undefined') {\r\n window.__FLIGHT_ERROR__ = flightError;\r\n window.dispatchEvent(new CustomEvent('flight:error', {\r\n detail: flightError,\r\n bubbles: true\r\n }));\r\n }\r\n}\r\n\r\n/**\r\n * Clear the current error state and optionally redirect.\r\n * \r\n * Use this to dismiss an error and return to normal state.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Just clear the error\r\n * clearError();\r\n * \r\n * // Clear and redirect to home\r\n * clearError({ redirect: '/' });\r\n * ```\r\n */\r\nexport function clearError(options?: { redirect?: string }): void {\r\n if (typeof window !== 'undefined') {\r\n window.__FLIGHT_ERROR__ = null;\r\n window.dispatchEvent(new CustomEvent('flight:error-clear', { bubbles: true }));\r\n\r\n if (options?.redirect) {\r\n window.location.href = options.redirect;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Get the current error from global state.\r\n * Returns null if no error is active.\r\n */\r\nexport function getError(): FlightError | null {\r\n if (typeof window !== 'undefined') {\r\n return window.__FLIGHT_ERROR__ ?? null;\r\n }\r\n return null;\r\n}\r\n\r\n// ============================================================================\r\n// Type Guards\r\n// ============================================================================\r\n\r\n/**\r\n * Check if an error is a FlightError\r\n */\r\nexport function isFlightError(error: unknown): error is FlightError {\r\n return error instanceof FlightError;\r\n}\r\n\r\n/**\r\n * Check if an error is a NotFoundError (404)\r\n */\r\nexport function isNotFoundError(error: unknown): error is NotFoundError {\r\n return error instanceof NotFoundError ||\r\n (isFlightError(error) && error.statusCode === 404);\r\n}\r\n\r\n/**\r\n * Check if an error is a ForbiddenError (403)\r\n */\r\nexport function isForbiddenError(error: unknown): error is ForbiddenError {\r\n return error instanceof ForbiddenError ||\r\n (isFlightError(error) && error.statusCode === 403);\r\n}\r\n\r\n/**\r\n * Check if an error is an UnauthorizedError (401)\r\n */\r\nexport function isUnauthorizedError(error: unknown): error is UnauthorizedError {\r\n return error instanceof UnauthorizedError ||\r\n (isFlightError(error) && error.statusCode === 401);\r\n}\r\n\r\n/**\r\n * Get the status code from any error.\r\n * Returns 500 for non-FlightError errors.\r\n */\r\nexport function getErrorStatusCode(error: unknown): number {\r\n if (isFlightError(error)) {\r\n return error.statusCode;\r\n }\r\n return 500;\r\n}\r\n\r\n// ============================================================================\r\n// Response Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create an error Response from a FlightError.\r\n * \r\n * @example\r\n * ```typescript\r\n * try {\r\n * // ... some operation\r\n * } catch (error) {\r\n * return createErrorResponse(error);\r\n * }\r\n * ```\r\n */\r\nexport function createErrorResponse(error: unknown): Response {\r\n const flightError = isFlightError(error)\r\n ? error\r\n : new InternalError(error instanceof Error ? error.message : 'Unknown error');\r\n\r\n return new Response(\r\n JSON.stringify({\r\n error: flightError.statusMessage,\r\n message: flightError.message,\r\n statusCode: flightError.statusCode,\r\n digest: flightError.digest,\r\n ...(isDevelopment() && flightError.data\r\n ? { data: flightError.data }\r\n : {}),\r\n }),\r\n {\r\n status: flightError.statusCode,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Get default status message for HTTP status code\r\n */\r\nfunction getDefaultStatusMessage(statusCode: number): string {\r\n const messages: Record<number, string> = {\r\n 400: 'Bad Request',\r\n 401: 'Unauthorized',\r\n 403: 'Forbidden',\r\n 404: 'Not Found',\r\n 405: 'Method Not Allowed',\r\n 408: 'Request Timeout',\r\n 409: 'Conflict',\r\n 410: 'Gone',\r\n 422: 'Unprocessable Entity',\r\n 429: 'Too Many Requests',\r\n 500: 'Internal Server Error',\r\n 501: 'Not Implemented',\r\n 502: 'Bad Gateway',\r\n 503: 'Service Unavailable',\r\n 504: 'Gateway Timeout',\r\n };\r\n return messages[statusCode] || 'Error';\r\n}\r\n\r\n/**\r\n * Generate a short digest for error correlation.\r\n * Used in production to correlate client errors with server logs\r\n * without exposing stack traces.\r\n */\r\nfunction generateDigest(): string {\r\n // Use crypto if available (Node.js, modern browsers)\r\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\r\n return crypto.randomUUID().slice(0, 8);\r\n }\r\n // Fallback for older environments\r\n return Math.random().toString(36).slice(2, 10);\r\n}\r\n\r\n/**\r\n * Wrap an error with a digest if it doesn't have one.\r\n * Useful for adding correlation IDs to third-party errors.\r\n */\r\nexport function wrapWithDigest<T extends Error>(error: T): T & { digest: string } {\r\n const wrapped = error as T & { digest: string };\r\n if (!wrapped.digest) {\r\n wrapped.digest = generateDigest();\r\n }\r\n return wrapped;\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/index.ts"],"names":[],"mappings":"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","file":"chunk-IXMD5QH2.js","sourcesContent":["/**\r\n * Flight Configuration - User configuration system\r\n */\r\n\r\nimport type { RenderMode } from '../render/index.js';\r\nimport type { FlightAdapter } from '../adapters/index.js';\r\n\r\n// ============================================================================\r\n// Bundler Types (from @flight-framework/bundler)\r\n// ============================================================================\r\n\r\n/**\r\n * Bundler adapter interface.\r\n * Import the full type from @flight-framework/bundler for implementation.\r\n */\r\nexport interface BundlerAdapter {\r\n /** Adapter identifier */\r\n name: string;\r\n /** Bundler name (vite, esbuild, rolldown, etc.) */\r\n bundler: string;\r\n /** Bundler-specific options */\r\n options?: Record<string, unknown>;\r\n /** Create dev server */\r\n createDevServer(config: FlightConfig): Promise<unknown>;\r\n /** Build for production */\r\n build(config: FlightConfig): Promise<unknown>;\r\n}\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/** UI Framework configuration */\r\nexport interface UIConfig {\r\n /** The UI framework to use */\r\n framework?: 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'vanilla' | string;\r\n /** Framework-specific options */\r\n options?: Record<string, unknown>;\r\n}\r\n\r\n/** Rendering configuration */\r\nexport interface RenderConfig {\r\n /** Default render mode */\r\n default?: RenderMode;\r\n /** Per-route render mode overrides */\r\n routes?: Record<string, RenderMode>;\r\n}\r\n\r\n/** Development server options */\r\nexport interface DevConfig {\r\n /** Port to run dev server on */\r\n port?: number;\r\n /** Host to bind to */\r\n host?: string | boolean;\r\n /** Open browser on start */\r\n open?: boolean;\r\n /** HTTPS configuration */\r\n https?: boolean | {\r\n key?: string;\r\n cert?: string;\r\n };\r\n /** Proxy configuration */\r\n proxy?: Record<string, string | {\r\n target: string;\r\n changeOrigin?: boolean;\r\n rewrite?: (path: string) => string;\r\n }>;\r\n}\r\n\r\n/** Build configuration */\r\nexport interface BuildConfig {\r\n /** Output directory */\r\n outDir?: string;\r\n /** Source directory */\r\n srcDir?: string;\r\n /** Public assets directory */\r\n publicDir?: string;\r\n /** Routes directory */\r\n routesDir?: string;\r\n /** Generate sourcemaps */\r\n sourcemap?: boolean | 'inline' | 'hidden';\r\n /** Minify output */\r\n minify?: boolean | 'terser' | 'esbuild';\r\n /** Target environments */\r\n target?: string | string[];\r\n}\r\n\r\n/** Full Flight configuration (resolved) */\r\nexport interface FlightConfig {\r\n /** Root directory */\r\n root: string;\r\n /** Deployment adapter */\r\n adapter: FlightAdapter | null;\r\n /** Bundler adapter (Vite, esbuild, Rolldown, etc.) */\r\n bundler: BundlerAdapter | null;\r\n /** UI framework configuration */\r\n ui: UIConfig;\r\n /** Rendering configuration */\r\n rendering: RenderConfig;\r\n /** Development server options */\r\n dev: Required<DevConfig>;\r\n /** Build configuration */\r\n build: Required<BuildConfig>;\r\n /** Bundler-specific configuration (passed to adapter) */\r\n bundlerOptions?: Record<string, unknown>;\r\n /** @deprecated Use bundler adapter instead */\r\n vite?: Record<string, unknown>;\r\n /** Plugin configurations */\r\n plugins: FlightPlugin[];\r\n}\r\n\r\n/** Flight plugin interface */\r\nexport interface FlightPlugin {\r\n /** Plugin name */\r\n name: string;\r\n /** Hook into config resolution */\r\n config?: (config: FlightConfig) => FlightConfig | void | Promise<FlightConfig | void>;\r\n /** Hook into build start */\r\n buildStart?: () => void | Promise<void>;\r\n /** Hook into build end */\r\n buildEnd?: () => void | Promise<void>;\r\n /** Hook into dev server start */\r\n devStart?: () => void | Promise<void>;\r\n}\r\n\r\n/** User-provided configuration (partial) */\r\nexport interface FlightUserConfig {\r\n /** Root directory (defaults to process.cwd()) */\r\n root?: string;\r\n /** Deployment adapter */\r\n adapter?: FlightAdapter;\r\n /** Bundler adapter (Vite, esbuild, Rolldown, etc.) */\r\n bundler?: BundlerAdapter;\r\n /** UI framework configuration */\r\n ui?: UIConfig;\r\n /** Rendering configuration */\r\n rendering?: RenderConfig;\r\n /** Development server options */\r\n dev?: DevConfig;\r\n /** Build configuration */\r\n build?: BuildConfig;\r\n /** Bundler-specific configuration */\r\n bundlerOptions?: Record<string, unknown>;\r\n /** @deprecated Use bundler adapter instead */\r\n vite?: Record<string, unknown>;\r\n /** Plugins */\r\n plugins?: FlightPlugin[];\r\n}\r\n\r\n// ============================================================================\r\n// Configuration Factory\r\n// ============================================================================\r\n\r\n/** Default configuration values */\r\nconst DEFAULT_CONFIG: Omit<FlightConfig, 'root'> = {\r\n adapter: null,\r\n bundler: null,\r\n ui: {\r\n framework: 'vanilla',\r\n },\r\n rendering: {\r\n default: 'ssr',\r\n routes: {},\r\n },\r\n dev: {\r\n port: 5173,\r\n host: 'localhost',\r\n open: false,\r\n https: false,\r\n proxy: {},\r\n },\r\n build: {\r\n outDir: 'dist',\r\n srcDir: 'src',\r\n publicDir: 'public',\r\n routesDir: 'src/routes',\r\n sourcemap: false,\r\n minify: true,\r\n target: 'es2022',\r\n },\r\n plugins: [],\r\n};\r\n\r\n/**\r\n * Define Flight configuration\r\n * \r\n * @example\r\n * ```typescript\r\n * // flight.config.ts\r\n * import { defineConfig } from '@flight-framework/core';\r\n * import node from '@flight-framework/adapter-node';\r\n * \r\n * export default defineConfig({\r\n * adapter: node(),\r\n * ui: { framework: 'react' },\r\n * rendering: {\r\n * default: 'ssr',\r\n * routes: {\r\n * '/blog/*': 'ssg',\r\n * '/app/*': 'csr',\r\n * },\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function defineConfig(config: FlightUserConfig): FlightUserConfig {\r\n return config;\r\n}\r\n\r\n/**\r\n * Resolve user config to full config with defaults\r\n */\r\nexport function resolveConfig(userConfig: FlightUserConfig = {}): FlightConfig {\r\n return {\r\n root: userConfig.root ?? process.cwd(),\r\n adapter: userConfig.adapter ?? DEFAULT_CONFIG.adapter,\r\n bundler: userConfig.bundler ?? DEFAULT_CONFIG.bundler,\r\n ui: {\r\n ...DEFAULT_CONFIG.ui,\r\n ...userConfig.ui,\r\n },\r\n rendering: {\r\n ...DEFAULT_CONFIG.rendering,\r\n ...userConfig.rendering,\r\n },\r\n dev: {\r\n ...DEFAULT_CONFIG.dev,\r\n ...userConfig.dev,\r\n } as Required<DevConfig>,\r\n build: {\r\n ...DEFAULT_CONFIG.build,\r\n ...userConfig.build,\r\n } as Required<BuildConfig>,\r\n bundlerOptions: userConfig.bundlerOptions,\r\n vite: userConfig.vite,\r\n plugins: userConfig.plugins ?? [],\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Config Loading\r\n// ============================================================================\r\n\r\nconst CONFIG_FILES = [\r\n 'flight.config.ts',\r\n 'flight.config.js',\r\n 'flight.config.mjs',\r\n 'flight.config.mts',\r\n];\r\n\r\n/**\r\n * Find the config file in a directory\r\n */\r\nexport async function findConfigFile(root: string): Promise<string | null> {\r\n // Dynamic import for Node.js fs\r\n const { existsSync } = await import('node:fs');\r\n const { join } = await import('node:path');\r\n\r\n for (const file of CONFIG_FILES) {\r\n const path = join(root, file);\r\n if (existsSync(path)) {\r\n return path;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Load configuration from file\r\n */\r\nexport async function loadConfig(root: string = process.cwd()): Promise<FlightConfig> {\r\n const configFile = await findConfigFile(root);\r\n\r\n if (!configFile) {\r\n return resolveConfig({ root });\r\n }\r\n\r\n try {\r\n // Use dynamic import for the config file\r\n // On Windows, we need to convert the path to a file:// URL\r\n const { pathToFileURL } = await import('node:url');\r\n const configUrl = pathToFileURL(configFile).href;\r\n const module = await import(configUrl);\r\n const userConfig = module.default as FlightUserConfig;\r\n\r\n return resolveConfig({\r\n ...userConfig,\r\n root,\r\n });\r\n } catch (error) {\r\n console.error(`Failed to load config from ${configFile}:`, error);\r\n return resolveConfig({ root });\r\n }\r\n}\r\n"]}
@@ -1,14 +0,0 @@
1
- // src/plugins/server-boundary-plugin.ts
2
- function serverBoundaryPlugin(_options = {}) {
3
- console.warn(
4
- "[Flight] serverBoundaryPlugin is deprecated. Use runtime guards (assertServer, assertClient) instead."
5
- );
6
- return {
7
- name: "flight:server-boundary-deprecated"
8
- // No-op plugin - just shows warning
9
- };
10
- }
11
-
12
- export { serverBoundaryPlugin };
13
- //# sourceMappingURL=chunk-J7WEZXWH.js.map
14
- //# sourceMappingURL=chunk-J7WEZXWH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/plugins/server-boundary-plugin.ts"],"names":[],"mappings":";AAsCO,SAAS,oBAAA,CACZ,QAAA,GAAwC,EAAC,EACnC;AACN,EAAA,OAAA,CAAQ,IAAA;AAAA,IACJ;AAAA,GAEJ;AAEA,EAAA,OAAO;AAAA,IACH,IAAA,EAAM;AAAA;AAAA,GAEV;AACJ","file":"chunk-J7WEZXWH.js","sourcesContent":["/**\r\n * @flight-framework/core - Server Boundary Plugin (DEPRECATED)\r\n * \r\n * This plugin has been deprecated due to conflicts with serverActionsPlugin.\r\n * \r\n * The intended functionality (detecting server-only imports in client bundles)\r\n * is difficult to implement correctly with Vite's plugin system because:\r\n * \r\n * 1. It conflicts with serverActionsPlugin which transforms 'use server' files\r\n * 2. The resolveId hook runs before transforms, making detection unreliable\r\n * 3. Vite 6+ has different environment APIs that need careful handling\r\n * \r\n * For now, use runtime guards instead:\r\n * \r\n * @example\r\n * ```typescript\r\n * import { assertServer } from '@flight-framework/core';\r\n * \r\n * export function getSecretData() {\r\n * assertServer('getSecretData'); // Throws if called on client\r\n * return process.env.SECRET_KEY;\r\n * }\r\n * ```\r\n * \r\n * @deprecated Use runtime guards (assertServer, assertClient) instead\r\n */\r\n\r\nimport type { Plugin } from 'vite';\r\n\r\nexport interface ServerBoundaryPluginOptions {\r\n /** @deprecated This plugin is deprecated */\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * @deprecated This plugin has been deprecated due to conflicts with serverActionsPlugin.\r\n * Use runtime guards (assertServer, assertClient) from '@flight-framework/core' instead.\r\n */\r\nexport function serverBoundaryPlugin(\r\n _options: ServerBoundaryPluginOptions = {}\r\n): Plugin {\r\n console.warn(\r\n '[Flight] serverBoundaryPlugin is deprecated. ' +\r\n 'Use runtime guards (assertServer, assertClient) instead.'\r\n );\r\n\r\n return {\r\n name: 'flight:server-boundary-deprecated',\r\n // No-op plugin - just shows warning\r\n };\r\n}\r\n"]}