@stacksjs/bun-router 0.0.5 → 0.0.6

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 (269) hide show
  1. package/dist/auth.d.ts +134 -0
  2. package/dist/cache/lru-cache.d.ts +139 -0
  3. package/dist/cache/middleware-memoization.d.ts +151 -0
  4. package/dist/cache/route-cache-warmer.d.ts +161 -0
  5. package/dist/cache/sqlite-cache.d.ts +209 -0
  6. package/dist/cache/streaming-cache.d.ts +132 -0
  7. package/dist/cli/colors.d.ts +15 -0
  8. package/dist/cli/index.d.ts +10 -0
  9. package/dist/cli/middleware.d.ts +31 -0
  10. package/dist/cli/openapi.d.ts +17 -0
  11. package/dist/cli/router.d.ts +15 -0
  12. package/dist/cli/routes.d.ts +29 -0
  13. package/dist/cli/utils.d.ts +74 -0
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.js +1 -1
  16. package/dist/config.d.ts +7 -0
  17. package/dist/container/container.d.ts +273 -0
  18. package/dist/container/contextual-binding.d.ts +240 -0
  19. package/dist/container/decorators.d.ts +141 -0
  20. package/dist/container/service-provider.d.ts +285 -0
  21. package/dist/development/hot-reload.d.ts +187 -0
  22. package/dist/development/index.d.ts +167 -0
  23. package/dist/development/performance-profiler.d.ts +217 -0
  24. package/dist/development/route-debugger.d.ts +154 -0
  25. package/dist/development/route-inspector.d.ts +211 -0
  26. package/dist/development/typescript-utilities.d.ts +209 -0
  27. package/dist/docs.d.ts +11 -0
  28. package/dist/errors/circuit-breaker.d.ts +195 -0
  29. package/dist/errors/error-handler.d.ts +88 -0
  30. package/dist/errors/error-reporting.d.ts +144 -0
  31. package/dist/errors/exceptions.d.ts +184 -0
  32. package/dist/errors/graceful-degradation.d.ts +154 -0
  33. package/dist/errors/index.d.ts +9 -0
  34. package/dist/errors/router-errors.d.ts +110 -0
  35. package/dist/file-serving/static-files.d.ts +143 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +319 -205
  38. package/dist/middleware/auth.d.ts +63 -0
  39. package/dist/middleware/content_security_policy.d.ts +53 -0
  40. package/dist/middleware/cors.d.ts +5 -0
  41. package/dist/middleware/csrf.d.ts +7 -0
  42. package/dist/middleware/ddos_protection.d.ts +39 -0
  43. package/dist/middleware/file_security.d.ts +26 -0
  44. package/dist/middleware/file_upload.d.ts +38 -0
  45. package/dist/middleware/helmet.d.ts +54 -0
  46. package/dist/middleware/index.d.ts +44 -0
  47. package/dist/middleware/input_validation.d.ts +45 -0
  48. package/dist/middleware/json_body.d.ts +4 -0
  49. package/dist/middleware/performance_alerting.d.ts +87 -0
  50. package/dist/middleware/performance_dashboard.d.ts +87 -0
  51. package/dist/middleware/performance_monitor.d.ts +209 -0
  52. package/dist/middleware/pipeline.d.ts +131 -0
  53. package/dist/middleware/rate_limit.d.ts +36 -0
  54. package/dist/middleware/request_id.d.ts +4 -0
  55. package/dist/middleware/request_signing.d.ts +153 -0
  56. package/dist/middleware/request_tracer.d.ts +72 -0
  57. package/dist/middleware/response_cache.d.ts +97 -0
  58. package/dist/middleware/security.d.ts +69 -0
  59. package/dist/middleware/security_suite.d.ts +46 -0
  60. package/dist/middleware/session.d.ts +23 -0
  61. package/dist/model-binding/index.d.ts +2 -0
  62. package/dist/model-binding/model-middleware.d.ts +118 -0
  63. package/dist/model-binding/model-registry.d.ts +164 -0
  64. package/dist/model-binding.d.ts +185 -0
  65. package/dist/model-resolver-factory.d.ts +31 -0
  66. package/dist/observability/correlation.d.ts +187 -0
  67. package/dist/observability/health-checks.d.ts +186 -0
  68. package/dist/observability/index.d.ts +60 -0
  69. package/dist/observability/integration.d.ts +147 -0
  70. package/dist/observability/metrics.d.ts +184 -0
  71. package/dist/observability/tracing.d.ts +187 -0
  72. package/dist/optimization/bun-utilities.d.ts +224 -0
  73. package/dist/query-builder-integration.d.ts +36 -0
  74. package/dist/request/context.d.ts +34 -0
  75. package/dist/request/enhanced-request.d.ts +213 -0
  76. package/dist/request/macros.d.ts +300 -0
  77. package/dist/response/macros.d.ts +245 -0
  78. package/dist/response/response-factory.d.ts +133 -0
  79. package/dist/router/api-routes.d.ts +5 -0
  80. package/dist/router/file-based-routing.d.ts +118 -0
  81. package/dist/router/file-streaming.d.ts +5 -0
  82. package/dist/router/fluent-router.d.ts +315 -0
  83. package/dist/router/fluent-routing.d.ts +271 -0
  84. package/dist/router/group-organization.d.ts +5 -0
  85. package/dist/router/handler-resolver.d.ts +24 -0
  86. package/dist/router/http-methods.d.ts +10 -0
  87. package/dist/router/index.d.ts +113 -0
  88. package/dist/router/middleware-groups.d.ts +94 -0
  89. package/dist/router/middleware-integration.d.ts +112 -0
  90. package/dist/router/middleware.d.ts +5 -0
  91. package/dist/router/model-binding.d.ts +5 -0
  92. package/dist/router/optimized-route-matching.d.ts +6 -0
  93. package/dist/router/route-building.d.ts +5 -0
  94. package/dist/router/route-compiler.d.ts +153 -0
  95. package/dist/router/route-matching.d.ts +5 -0
  96. package/dist/router/route-trie.d.ts +114 -0
  97. package/dist/router/router.d.ts +276 -0
  98. package/dist/router/server.d.ts +5 -0
  99. package/dist/router/validation-integration.d.ts +170 -0
  100. package/dist/router/view-rendering.d.ts +5 -0
  101. package/dist/router/websocket.d.ts +5 -0
  102. package/dist/routing/route-caching.d.ts +129 -0
  103. package/dist/routing/route-throttling.d.ts +150 -0
  104. package/dist/routing/subdomain-routing.d.ts +206 -0
  105. package/dist/session/database-store.d.ts +51 -0
  106. package/dist/session/file-store.d.ts +22 -0
  107. package/dist/session/index.d.ts +106 -0
  108. package/dist/session/memory-store.d.ts +21 -0
  109. package/dist/session/redis-store.d.ts +31 -0
  110. package/dist/streaming/index.d.ts +3 -0
  111. package/dist/streaming/sse-handler.d.ts +138 -0
  112. package/dist/streaming/stream-handler.d.ts +114 -0
  113. package/dist/testing/auth-testing.d.ts +156 -0
  114. package/dist/testing/file-upload-testing.d.ts +190 -0
  115. package/dist/testing/index.d.ts +10 -0
  116. package/dist/testing/middleware-testing.d.ts +138 -0
  117. package/dist/testing/model-binding-testing.d.ts +186 -0
  118. package/dist/testing/performance-testing.d.ts +235 -0
  119. package/dist/testing/test-client.d.ts +117 -0
  120. package/dist/testing/test-request.d.ts +85 -0
  121. package/dist/testing/test-response.d.ts +90 -0
  122. package/dist/testing/types.d.ts +207 -0
  123. package/dist/testing/websocket-testing.d.ts +227 -0
  124. package/dist/types/controller-types.d.ts +208 -0
  125. package/dist/types/core.d.ts +543 -0
  126. package/dist/types/middleware-types.d.ts +227 -0
  127. package/dist/types/request-response-augmentation.d.ts +261 -0
  128. package/dist/types/route-inference.d.ts +168 -0
  129. package/dist/types.d.ts +1776 -0
  130. package/dist/url.d.ts +56 -0
  131. package/dist/utils/index.d.ts +1 -0
  132. package/dist/utils/query-preservation.d.ts +48 -0
  133. package/dist/utils.d.ts +69 -0
  134. package/dist/validation/validator.d.ts +140 -0
  135. package/dist/websocket/clustering.d.ts +185 -0
  136. package/package.json +3 -2
  137. package/src/auth.ts +469 -0
  138. package/src/cache/lru-cache.ts +457 -0
  139. package/src/cache/middleware-memoization.ts +531 -0
  140. package/src/cache/route-cache-warmer.ts +486 -0
  141. package/src/cache/sqlite-cache.ts +783 -0
  142. package/src/cache/streaming-cache.ts +572 -0
  143. package/src/cli/colors.ts +29 -0
  144. package/src/cli/index.ts +287 -0
  145. package/src/cli/middleware.ts +291 -0
  146. package/src/cli/openapi.ts +407 -0
  147. package/src/cli/router.ts +188 -0
  148. package/src/cli/routes.ts +265 -0
  149. package/src/cli/utils.ts +531 -0
  150. package/src/cli.ts +5 -0
  151. package/src/config.ts +322 -0
  152. package/src/container/container.ts +740 -0
  153. package/src/container/contextual-binding.ts +603 -0
  154. package/src/container/decorators.ts +359 -0
  155. package/src/container/service-provider.ts +596 -0
  156. package/src/development/hot-reload.ts +673 -0
  157. package/src/development/index.ts +499 -0
  158. package/src/development/performance-profiler.ts +717 -0
  159. package/src/development/route-debugger.ts +527 -0
  160. package/src/development/route-inspector.ts +749 -0
  161. package/src/development/typescript-utilities.ts +678 -0
  162. package/src/docs.ts +397 -0
  163. package/src/errors/circuit-breaker.ts +732 -0
  164. package/src/errors/error-handler.ts +569 -0
  165. package/src/errors/error-reporting.ts +672 -0
  166. package/src/errors/exceptions.ts +536 -0
  167. package/src/errors/graceful-degradation.ts +621 -0
  168. package/src/errors/index.ts +21 -0
  169. package/src/errors/router-errors.ts +632 -0
  170. package/src/file-serving/static-files.ts +581 -0
  171. package/src/index.ts +14 -0
  172. package/src/middleware/auth.ts +219 -0
  173. package/src/middleware/content_security_policy.ts +215 -0
  174. package/src/middleware/cors.ts +74 -0
  175. package/src/middleware/csrf.ts +108 -0
  176. package/src/middleware/ddos_protection.ts +255 -0
  177. package/src/middleware/file_security.ts +191 -0
  178. package/src/middleware/file_upload.ts +264 -0
  179. package/src/middleware/helmet.ts +268 -0
  180. package/src/middleware/index.ts +117 -0
  181. package/src/middleware/input_validation.ts +449 -0
  182. package/src/middleware/json_body.ts +37 -0
  183. package/src/middleware/performance_alerting.ts +538 -0
  184. package/src/middleware/performance_dashboard.ts +661 -0
  185. package/src/middleware/performance_monitor.ts +943 -0
  186. package/src/middleware/pipeline.ts +489 -0
  187. package/src/middleware/rate_limit.ts +245 -0
  188. package/src/middleware/request_id.ts +36 -0
  189. package/src/middleware/request_signing.ts +636 -0
  190. package/src/middleware/request_tracer.ts +636 -0
  191. package/src/middleware/response_cache.ts +743 -0
  192. package/src/middleware/security.ts +482 -0
  193. package/src/middleware/security_suite.ts +257 -0
  194. package/src/middleware/session.ts +91 -0
  195. package/src/model-binding/index.ts +18 -0
  196. package/src/model-binding/model-middleware.ts +425 -0
  197. package/src/model-binding/model-registry.ts +550 -0
  198. package/src/model-binding.ts +370 -0
  199. package/src/model-resolver-factory.ts +106 -0
  200. package/src/observability/correlation.ts +691 -0
  201. package/src/observability/health-checks.ts +729 -0
  202. package/src/observability/index.ts +184 -0
  203. package/src/observability/integration.ts +548 -0
  204. package/src/observability/metrics.ts +753 -0
  205. package/src/observability/tracing.ts +638 -0
  206. package/src/optimization/bun-utilities.ts +778 -0
  207. package/src/query-builder-integration.ts +137 -0
  208. package/src/request/context.ts +62 -0
  209. package/src/request/enhanced-request.ts +857 -0
  210. package/src/request/macros.ts +688 -0
  211. package/src/response/macros.ts +612 -0
  212. package/src/response/response-factory.ts +588 -0
  213. package/src/router/api-routes.ts +243 -0
  214. package/src/router/file-based-routing.ts +670 -0
  215. package/src/router/file-streaming.ts +372 -0
  216. package/src/router/fluent-router.ts +927 -0
  217. package/src/router/fluent-routing.ts +797 -0
  218. package/src/router/group-organization.ts +213 -0
  219. package/src/router/handler-resolver.ts +291 -0
  220. package/src/router/http-methods.ts +377 -0
  221. package/src/router/index.ts +185 -0
  222. package/src/router/middleware-groups.ts +222 -0
  223. package/src/router/middleware-integration.ts +399 -0
  224. package/src/router/middleware.ts +231 -0
  225. package/src/router/model-binding.ts +215 -0
  226. package/src/router/optimized-route-matching.ts +253 -0
  227. package/src/router/route-building.ts +212 -0
  228. package/src/router/route-compiler.ts +702 -0
  229. package/src/router/route-matching.ts +349 -0
  230. package/src/router/route-trie.ts +464 -0
  231. package/src/router/router.ts +1508 -0
  232. package/src/router/server.ts +406 -0
  233. package/src/router/validation-integration.ts +443 -0
  234. package/src/router/view-rendering.ts +233 -0
  235. package/src/router/websocket.ts +100 -0
  236. package/src/routing/route-caching.ts +402 -0
  237. package/src/routing/route-throttling.ts +469 -0
  238. package/src/routing/subdomain-routing.ts +492 -0
  239. package/src/session/database-store.ts +109 -0
  240. package/src/session/file-store.ts +148 -0
  241. package/src/session/index.ts +244 -0
  242. package/src/session/memory-store.ts +88 -0
  243. package/src/session/redis-store.ts +93 -0
  244. package/src/streaming/index.ts +17 -0
  245. package/src/streaming/sse-handler.ts +482 -0
  246. package/src/streaming/stream-handler.ts +552 -0
  247. package/src/testing/auth-testing.ts +446 -0
  248. package/src/testing/file-upload-testing.ts +543 -0
  249. package/src/testing/index.ts +10 -0
  250. package/src/testing/middleware-testing.ts +322 -0
  251. package/src/testing/model-binding-testing.ts +645 -0
  252. package/src/testing/performance-testing.ts +738 -0
  253. package/src/testing/test-client.ts +310 -0
  254. package/src/testing/test-request.ts +315 -0
  255. package/src/testing/test-response.ts +332 -0
  256. package/src/testing/types.ts +224 -0
  257. package/src/testing/websocket-testing.ts +590 -0
  258. package/src/types/controller-types.ts +385 -0
  259. package/src/types/core.ts +683 -0
  260. package/src/types/middleware-types.ts +419 -0
  261. package/src/types/request-response-augmentation.ts +489 -0
  262. package/src/types/route-inference.ts +357 -0
  263. package/src/types.ts +2049 -0
  264. package/src/url.ts +126 -0
  265. package/src/utils/index.ts +1 -0
  266. package/src/utils/query-preservation.ts +201 -0
  267. package/src/utils.ts +327 -0
  268. package/src/validation/validator.ts +685 -0
  269. package/src/websocket/clustering.ts +762 -0
package/src/docs.ts ADDED
@@ -0,0 +1,397 @@
1
+ import { join } from 'node:path'
2
+ import process from 'node:process'
3
+
4
+ interface DocsOptions {
5
+ verbose?: boolean
6
+ output?: string
7
+ groupBy?: 'path' | 'method' | 'tag'
8
+ includeExamples?: boolean
9
+ }
10
+
11
+ interface RouteDoc {
12
+ path: string
13
+ method: string
14
+ description?: string
15
+ params?: { [key: string]: string }
16
+ query?: { [key: string]: string }
17
+ body?: { [key: string]: string }
18
+ responses?: { [key: string]: string }
19
+ middleware?: string[]
20
+ tags?: string[]
21
+ examples?: {
22
+ request?: string
23
+ response?: string
24
+ }[]
25
+ deprecated?: boolean
26
+ security?: string[]
27
+ }
28
+
29
+ /**
30
+ * Extracts route parameters from a path
31
+ * @example "/users/{id}" -> { id: "string" }
32
+ */
33
+ function extractRouteParams(path: string): { [key: string]: string } {
34
+ const params: { [key: string]: string } = {}
35
+ const matches = path.match(/\{([^}]+)\}/g)
36
+
37
+ if (matches) {
38
+ matches.forEach((match) => {
39
+ const param = match.slice(1, -1)
40
+ // Check for type annotations in the parameter name
41
+ const [name, type] = param.split(':')
42
+ params[name] = type || 'string'
43
+ })
44
+ }
45
+
46
+ return params
47
+ }
48
+
49
+ /**
50
+ * Attempts to load JSDoc comments from an action handler file
51
+ */
52
+ async function loadActionDocs(handlerPath: string): Promise<Partial<RouteDoc>> {
53
+ try {
54
+ const fullPath = join(process.cwd(), 'src/actions', `${handlerPath.replace(/\//g, '_').toLowerCase()}.ts`)
55
+ const source = await Bun.file(fullPath).text()
56
+
57
+ // Basic JSDoc parser
58
+ const docComment = source.match(/\/\*\*([\s\S]*?)\*\//)
59
+ if (!docComment)
60
+ return {}
61
+
62
+ const doc = docComment[1]
63
+
64
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
65
+ const description = doc.match(/@description\s+(.+?)(?=@|\n\s*\*\/|$)/s)?.[1].trim() || ''
66
+ const params: { [key: string]: string } = {}
67
+ const query: { [key: string]: string } = {}
68
+ const body: { [key: string]: string } = {}
69
+ const responses: { [key: string]: string } = {}
70
+ const examples: { request?: string, response?: string }[] = []
71
+ const tags: string[] = []
72
+ const security: string[] = []
73
+
74
+ // Parse @tags
75
+ const tagMatches = doc.match(/@tags?\s+(.+)/g)
76
+ if (tagMatches) {
77
+ tagMatches.forEach((match) => {
78
+ const tag = match.replace(/@tags?\s+/, '').trim()
79
+ tags.push(...tag.split(/\s*,\s*/))
80
+ })
81
+ }
82
+
83
+ // Parse @security
84
+ const securityMatches = doc.match(/@security\s+(.+)/g)
85
+ if (securityMatches) {
86
+ securityMatches.forEach((match) => {
87
+ const scheme = match.replace(/@security\s+/, '').trim()
88
+ security.push(scheme)
89
+ })
90
+ }
91
+
92
+ // Parse @param with enhanced type support
93
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
94
+ const paramMatches = doc.matchAll(/@param\s+\{([^}]+)\}\s+(\w+(?:\.\w+)?)\s+(.+?)(?=@|\n\s*\*\/|$)/gs)
95
+ for (const match of paramMatches) {
96
+ const [, type, name, desc] = match
97
+ const cleanDesc = desc.trim()
98
+ if (name.startsWith('query.')) {
99
+ query[name.slice(6)] = `${type} - ${cleanDesc}`
100
+ }
101
+ else if (name.startsWith('body.')) {
102
+ body[name.slice(5)] = `${type} - ${cleanDesc}`
103
+ }
104
+ else {
105
+ params[name] = `${type} - ${cleanDesc}`
106
+ }
107
+ }
108
+
109
+ // Parse @response with enhanced status code descriptions
110
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
111
+ const responseMatches = doc.matchAll(/@response\s+\{(\d+)\}\s+(.+?)(?=@|\n\s*\*\/|$)/gs)
112
+ for (const match of responseMatches) {
113
+ const [, code, desc] = match
114
+ responses[code] = desc.trim()
115
+ }
116
+
117
+ // Parse @example blocks
118
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
119
+ const exampleMatches = doc.matchAll(/@example\s+(request|response)[\t\v\f\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*\n\s*```(?:json)?\s*\n([\s\S]*?)\n\s*```/g)
120
+ let currentExample: { request?: string, response?: string } = {}
121
+
122
+ for (const match of exampleMatches) {
123
+ const [, type, content] = match
124
+ if (type === 'request') {
125
+ currentExample = { request: content.trim() }
126
+ }
127
+ else if (type === 'response') {
128
+ currentExample.response = content.trim()
129
+ examples.push(currentExample)
130
+ currentExample = {}
131
+ }
132
+ }
133
+
134
+ // Check for @deprecated tag
135
+ const deprecated = doc.includes('@deprecated')
136
+
137
+ return {
138
+ description,
139
+ params,
140
+ query,
141
+ body,
142
+ responses,
143
+ examples: examples.length > 0 ? examples : undefined,
144
+ tags: tags.length > 0 ? tags : undefined,
145
+ security: security.length > 0 ? security : undefined,
146
+ deprecated,
147
+ }
148
+ }
149
+ catch (error) {
150
+ if (error instanceof Error) {
151
+ console.warn(`Failed to load docs for ${handlerPath}:`, error.message)
152
+ }
153
+ return {}
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Generates markdown documentation for routes
159
+ */
160
+ function generateMarkdown(routes: RouteDoc[], options: DocsOptions): string {
161
+ let markdown = '# API Reference\n\n'
162
+
163
+ // Add table of contents
164
+ markdown += '## Table of Contents\n\n'
165
+
166
+ // Group routes based on option
167
+ const groupedRoutes = routes.reduce((groups: { [key: string]: RouteDoc[] }, route) => {
168
+ let key: string
169
+ switch (options.groupBy) {
170
+ case 'method':
171
+ key = route.method
172
+ break
173
+ case 'tag':
174
+ if (route.tags?.length) {
175
+ route.tags.forEach((tag) => {
176
+ if (!groups[tag])
177
+ groups[tag] = []
178
+ groups[tag].push(route)
179
+ })
180
+ return groups
181
+ }
182
+ key = 'untagged'
183
+ break
184
+ default: // 'path'
185
+ key = route.path.split('/')[1] || 'root'
186
+ }
187
+ if (!groups[key])
188
+ groups[key] = []
189
+ groups[key].push(route)
190
+ return groups
191
+ }, {})
192
+
193
+ // Add ToC entries
194
+ for (const group of Object.keys(groupedRoutes).sort()) {
195
+ markdown += `- [${group.charAt(0).toUpperCase() + group.slice(1)}](#${group.toLowerCase()})\n`
196
+ }
197
+ markdown += '\n'
198
+
199
+ // Generate markdown for each group
200
+ for (const [group, routes] of Object.entries(groupedRoutes).sort()) {
201
+ markdown += `## ${group.charAt(0).toUpperCase() + group.slice(1)}\n\n`
202
+
203
+ for (const route of routes) {
204
+ const methodBadge = `![${route.method}](https://img.shields.io/badge/-${route.method}-${getMethodColor(route.method)})`
205
+ markdown += `### ${methodBadge} ${route.path}\n\n`
206
+
207
+ if (route.deprecated) {
208
+ markdown += '> ⚠️ **Deprecated**\n\n'
209
+ }
210
+
211
+ if (route.description) {
212
+ markdown += `${route.description}\n\n`
213
+ }
214
+
215
+ if (route.security?.length) {
216
+ markdown += '**Security:**\n\n'
217
+ for (const scheme of route.security) {
218
+ markdown += `- ${scheme}\n`
219
+ }
220
+ markdown += '\n'
221
+ }
222
+
223
+ if (route.middleware?.length) {
224
+ markdown += '**Middleware:**\n\n'
225
+ for (const mw of route.middleware) {
226
+ markdown += `- ${mw}\n`
227
+ }
228
+ markdown += '\n'
229
+ }
230
+
231
+ if (Object.keys(route.params || {}).length) {
232
+ markdown += '**URL Parameters:**\n\n'
233
+ markdown += '| Parameter | Description |\n'
234
+ markdown += '|-----------|-------------|\n'
235
+ for (const [name, desc] of Object.entries(route.params!)) {
236
+ markdown += `| ${name} | ${desc} |\n`
237
+ }
238
+ markdown += '\n'
239
+ }
240
+
241
+ if (Object.keys(route.query || {}).length) {
242
+ markdown += '**Query Parameters:**\n\n'
243
+ markdown += '| Parameter | Description |\n'
244
+ markdown += '|-----------|-------------|\n'
245
+ for (const [name, desc] of Object.entries(route.query!)) {
246
+ markdown += `| ${name} | ${desc} |\n`
247
+ }
248
+ markdown += '\n'
249
+ }
250
+
251
+ if (Object.keys(route.body || {}).length) {
252
+ markdown += '**Request Body:**\n\n'
253
+ markdown += '| Field | Description |\n'
254
+ markdown += '|-------|-------------|\n'
255
+ for (const [name, desc] of Object.entries(route.body!)) {
256
+ markdown += `| ${name} | ${desc} |\n`
257
+ }
258
+ markdown += '\n'
259
+ }
260
+
261
+ if (Object.keys(route.responses || {}).length) {
262
+ markdown += '**Responses:**\n\n'
263
+ markdown += '| Status | Description |\n'
264
+ markdown += '|--------|-------------|\n'
265
+ for (const [code, desc] of Object.entries(route.responses!)) {
266
+ markdown += `| ${code} | ${desc} |\n`
267
+ }
268
+ markdown += '\n'
269
+ }
270
+
271
+ if (options.includeExamples && route.examples?.length) {
272
+ markdown += '**Examples:**\n\n'
273
+ route.examples.forEach((example, index) => {
274
+ if (index > 0)
275
+ markdown += '\n'
276
+ if (example.request) {
277
+ markdown += `\`\`\`json\n# Request\n${example.request}\n\`\`\`\n\n`
278
+ }
279
+ if (example.response) {
280
+ markdown += `\`\`\`json\n# Response\n${example.response}\n\`\`\`\n\n`
281
+ }
282
+ })
283
+ }
284
+
285
+ markdown += '---\n\n'
286
+ }
287
+ }
288
+
289
+ return markdown
290
+ }
291
+
292
+ /**
293
+ * Get badge color for HTTP method
294
+ */
295
+ function getMethodColor(method: string): string {
296
+ const colors: Record<string, string> = {
297
+ GET: '32CD32', // green
298
+ POST: '4169E1', // blue
299
+ PUT: 'FF8C00', // orange
300
+ PATCH: 'BA55D3', // purple
301
+ DELETE: 'DC143C', // red
302
+ OPTIONS: '808080', // gray
303
+ HEAD: '808080', // gray
304
+ }
305
+ return colors[method] || '808080'
306
+ }
307
+
308
+ /**
309
+ * Generates API documentation from route definitions
310
+ */
311
+ export async function generateApiDocs(options: DocsOptions = {}): Promise<void> {
312
+ const {
313
+ output = 'api-reference.md',
314
+ verbose = false,
315
+ groupBy = 'path',
316
+ includeExamples = true,
317
+ } = options
318
+
319
+ try {
320
+ // Load API routes
321
+ const apiPath = join(process.cwd(), 'routes/api.ts')
322
+ const webPath = join(process.cwd(), 'routes/web.ts')
323
+
324
+ const routes: RouteDoc[] = []
325
+
326
+ // Process API routes
327
+ try {
328
+ const apiRoutes = await import(apiPath)
329
+ if (apiRoutes.default) {
330
+ const routeDefs = Array.isArray(apiRoutes.default) ? apiRoutes.default : [apiRoutes.default]
331
+ for (const route of routeDefs) {
332
+ const routeDoc: RouteDoc = {
333
+ path: route.path,
334
+ method: route.method,
335
+ middleware: Array.isArray(route.middleware)
336
+ ? route.middleware.map((m: string | ((_request: Request) => Promise<Request | Response>)) =>
337
+ typeof m === 'string' ? m : 'function',
338
+ )
339
+ : undefined,
340
+ params: extractRouteParams(route.path),
341
+ }
342
+
343
+ if (typeof route.handler === 'string') {
344
+ const actionDocs = await loadActionDocs(route.handler)
345
+ Object.assign(routeDoc, actionDocs)
346
+ }
347
+
348
+ routes.push(routeDoc)
349
+ }
350
+ }
351
+ }
352
+ catch {
353
+ if (verbose) {
354
+ console.warn('No API routes found')
355
+ }
356
+ }
357
+
358
+ // Process web routes
359
+ try {
360
+ const webRoutes = await import(webPath)
361
+ if (webRoutes.default) {
362
+ const routeDefs = Array.isArray(webRoutes.default) ? webRoutes.default : [webRoutes.default]
363
+ for (const route of routeDefs) {
364
+ const routeDoc: RouteDoc = {
365
+ path: route.path,
366
+ method: route.method,
367
+ middleware: Array.isArray(route.middleware)
368
+ ? route.middleware.map((m: string | ((_request: Request) => Promise<Request | Response>)) =>
369
+ typeof m === 'string' ? m : 'function',
370
+ )
371
+ : undefined,
372
+ params: extractRouteParams(route.path),
373
+ }
374
+
375
+ if (typeof route.handler === 'string') {
376
+ const actionDocs = await loadActionDocs(route.handler)
377
+ Object.assign(routeDoc, actionDocs)
378
+ }
379
+
380
+ routes.push(routeDoc)
381
+ }
382
+ }
383
+ }
384
+ catch {
385
+ if (verbose) {
386
+ console.warn('No web routes found')
387
+ }
388
+ }
389
+
390
+ // Generate and write markdown
391
+ const markdown = generateMarkdown(routes, { groupBy, includeExamples })
392
+ await Bun.write(output, markdown)
393
+ }
394
+ catch (error) {
395
+ throw new Error(`Failed to generate API documentation: ${error instanceof Error ? error.message : String(error)}`)
396
+ }
397
+ }