@morojs/moro 1.0.0

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 (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/dist/core/config/index.d.ts +19 -0
  4. package/dist/core/config/index.js +59 -0
  5. package/dist/core/config/index.js.map +1 -0
  6. package/dist/core/config/loader.d.ts +6 -0
  7. package/dist/core/config/loader.js +288 -0
  8. package/dist/core/config/loader.js.map +1 -0
  9. package/dist/core/config/schema.d.ts +335 -0
  10. package/dist/core/config/schema.js +286 -0
  11. package/dist/core/config/schema.js.map +1 -0
  12. package/dist/core/config/utils.d.ts +50 -0
  13. package/dist/core/config/utils.js +185 -0
  14. package/dist/core/config/utils.js.map +1 -0
  15. package/dist/core/database/adapters/drizzle.d.ts +29 -0
  16. package/dist/core/database/adapters/drizzle.js +366 -0
  17. package/dist/core/database/adapters/drizzle.js.map +1 -0
  18. package/dist/core/database/adapters/index.d.ts +8 -0
  19. package/dist/core/database/adapters/index.js +48 -0
  20. package/dist/core/database/adapters/index.js.map +1 -0
  21. package/dist/core/database/adapters/mongodb.d.ts +35 -0
  22. package/dist/core/database/adapters/mongodb.js +215 -0
  23. package/dist/core/database/adapters/mongodb.js.map +1 -0
  24. package/dist/core/database/adapters/mysql.d.ts +23 -0
  25. package/dist/core/database/adapters/mysql.js +149 -0
  26. package/dist/core/database/adapters/mysql.js.map +1 -0
  27. package/dist/core/database/adapters/postgresql.d.ts +24 -0
  28. package/dist/core/database/adapters/postgresql.js +160 -0
  29. package/dist/core/database/adapters/postgresql.js.map +1 -0
  30. package/dist/core/database/adapters/redis.d.ts +50 -0
  31. package/dist/core/database/adapters/redis.js +266 -0
  32. package/dist/core/database/adapters/redis.js.map +1 -0
  33. package/dist/core/database/adapters/sqlite.d.ts +23 -0
  34. package/dist/core/database/adapters/sqlite.js +194 -0
  35. package/dist/core/database/adapters/sqlite.js.map +1 -0
  36. package/dist/core/database/index.d.ts +2 -0
  37. package/dist/core/database/index.js +20 -0
  38. package/dist/core/database/index.js.map +1 -0
  39. package/dist/core/docs/index.d.ts +63 -0
  40. package/dist/core/docs/index.js +170 -0
  41. package/dist/core/docs/index.js.map +1 -0
  42. package/dist/core/docs/openapi-generator.d.ts +124 -0
  43. package/dist/core/docs/openapi-generator.js +413 -0
  44. package/dist/core/docs/openapi-generator.js.map +1 -0
  45. package/dist/core/docs/simple-docs.d.ts +21 -0
  46. package/dist/core/docs/simple-docs.js +268 -0
  47. package/dist/core/docs/simple-docs.js.map +1 -0
  48. package/dist/core/docs/swagger-ui.d.ts +28 -0
  49. package/dist/core/docs/swagger-ui.js +317 -0
  50. package/dist/core/docs/swagger-ui.js.map +1 -0
  51. package/dist/core/docs/zod-to-openapi.d.ts +29 -0
  52. package/dist/core/docs/zod-to-openapi.js +414 -0
  53. package/dist/core/docs/zod-to-openapi.js.map +1 -0
  54. package/dist/core/events/event-bus.d.ts +27 -0
  55. package/dist/core/events/event-bus.js +193 -0
  56. package/dist/core/events/event-bus.js.map +1 -0
  57. package/dist/core/events/index.d.ts +2 -0
  58. package/dist/core/events/index.js +7 -0
  59. package/dist/core/events/index.js.map +1 -0
  60. package/dist/core/framework.d.ts +57 -0
  61. package/dist/core/framework.js +432 -0
  62. package/dist/core/framework.js.map +1 -0
  63. package/dist/core/http/http-server.d.ts +114 -0
  64. package/dist/core/http/http-server.js +1154 -0
  65. package/dist/core/http/http-server.js.map +1 -0
  66. package/dist/core/http/index.d.ts +3 -0
  67. package/dist/core/http/index.js +10 -0
  68. package/dist/core/http/index.js.map +1 -0
  69. package/dist/core/http/router.d.ts +14 -0
  70. package/dist/core/http/router.js +113 -0
  71. package/dist/core/http/router.js.map +1 -0
  72. package/dist/core/logger/filters.d.ts +9 -0
  73. package/dist/core/logger/filters.js +134 -0
  74. package/dist/core/logger/filters.js.map +1 -0
  75. package/dist/core/logger/index.d.ts +3 -0
  76. package/dist/core/logger/index.js +26 -0
  77. package/dist/core/logger/index.js.map +1 -0
  78. package/dist/core/logger/logger.d.ts +49 -0
  79. package/dist/core/logger/logger.js +332 -0
  80. package/dist/core/logger/logger.js.map +1 -0
  81. package/dist/core/logger/outputs.d.ts +42 -0
  82. package/dist/core/logger/outputs.js +110 -0
  83. package/dist/core/logger/outputs.js.map +1 -0
  84. package/dist/core/middleware/built-in/adapters/cache/file.d.ts +15 -0
  85. package/dist/core/middleware/built-in/adapters/cache/file.js +128 -0
  86. package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -0
  87. package/dist/core/middleware/built-in/adapters/cache/index.d.ts +5 -0
  88. package/dist/core/middleware/built-in/adapters/cache/index.js +28 -0
  89. package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -0
  90. package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +11 -0
  91. package/dist/core/middleware/built-in/adapters/cache/memory.js +65 -0
  92. package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -0
  93. package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +17 -0
  94. package/dist/core/middleware/built-in/adapters/cache/redis.js +91 -0
  95. package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -0
  96. package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +21 -0
  97. package/dist/core/middleware/built-in/adapters/cdn/azure.js +40 -0
  98. package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -0
  99. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +14 -0
  100. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +77 -0
  101. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -0
  102. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +15 -0
  103. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +73 -0
  104. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -0
  105. package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +5 -0
  106. package/dist/core/middleware/built-in/adapters/cdn/index.js +28 -0
  107. package/dist/core/middleware/built-in/adapters/cdn/index.js.map +1 -0
  108. package/dist/core/middleware/built-in/adapters/index.d.ts +4 -0
  109. package/dist/core/middleware/built-in/adapters/index.js +26 -0
  110. package/dist/core/middleware/built-in/adapters/index.js.map +1 -0
  111. package/dist/core/middleware/built-in/auth.d.ts +2 -0
  112. package/dist/core/middleware/built-in/auth.js +38 -0
  113. package/dist/core/middleware/built-in/auth.js.map +1 -0
  114. package/dist/core/middleware/built-in/cache.d.ts +3 -0
  115. package/dist/core/middleware/built-in/cache.js +188 -0
  116. package/dist/core/middleware/built-in/cache.js.map +1 -0
  117. package/dist/core/middleware/built-in/cdn.d.ts +3 -0
  118. package/dist/core/middleware/built-in/cdn.js +115 -0
  119. package/dist/core/middleware/built-in/cdn.js.map +1 -0
  120. package/dist/core/middleware/built-in/cookie.d.ts +14 -0
  121. package/dist/core/middleware/built-in/cookie.js +68 -0
  122. package/dist/core/middleware/built-in/cookie.js.map +1 -0
  123. package/dist/core/middleware/built-in/cors.d.ts +2 -0
  124. package/dist/core/middleware/built-in/cors.js +29 -0
  125. package/dist/core/middleware/built-in/cors.js.map +1 -0
  126. package/dist/core/middleware/built-in/csp.d.ts +22 -0
  127. package/dist/core/middleware/built-in/csp.js +74 -0
  128. package/dist/core/middleware/built-in/csp.js.map +1 -0
  129. package/dist/core/middleware/built-in/csrf.d.ts +9 -0
  130. package/dist/core/middleware/built-in/csrf.js +66 -0
  131. package/dist/core/middleware/built-in/csrf.js.map +1 -0
  132. package/dist/core/middleware/built-in/error-tracker.d.ts +1 -0
  133. package/dist/core/middleware/built-in/error-tracker.js +19 -0
  134. package/dist/core/middleware/built-in/error-tracker.js.map +1 -0
  135. package/dist/core/middleware/built-in/index.d.ts +70 -0
  136. package/dist/core/middleware/built-in/index.js +70 -0
  137. package/dist/core/middleware/built-in/index.js.map +1 -0
  138. package/dist/core/middleware/built-in/performance-monitor.d.ts +1 -0
  139. package/dist/core/middleware/built-in/performance-monitor.js +22 -0
  140. package/dist/core/middleware/built-in/performance-monitor.js.map +1 -0
  141. package/dist/core/middleware/built-in/rate-limit.d.ts +6 -0
  142. package/dist/core/middleware/built-in/rate-limit.js +47 -0
  143. package/dist/core/middleware/built-in/rate-limit.js.map +1 -0
  144. package/dist/core/middleware/built-in/request-logger.d.ts +1 -0
  145. package/dist/core/middleware/built-in/request-logger.js +15 -0
  146. package/dist/core/middleware/built-in/request-logger.js.map +1 -0
  147. package/dist/core/middleware/built-in/session.d.ts +41 -0
  148. package/dist/core/middleware/built-in/session.js +209 -0
  149. package/dist/core/middleware/built-in/session.js.map +1 -0
  150. package/dist/core/middleware/built-in/sse.d.ts +6 -0
  151. package/dist/core/middleware/built-in/sse.js +73 -0
  152. package/dist/core/middleware/built-in/sse.js.map +1 -0
  153. package/dist/core/middleware/built-in/validation.d.ts +2 -0
  154. package/dist/core/middleware/built-in/validation.js +31 -0
  155. package/dist/core/middleware/built-in/validation.js.map +1 -0
  156. package/dist/core/middleware/index.d.ts +21 -0
  157. package/dist/core/middleware/index.js +152 -0
  158. package/dist/core/middleware/index.js.map +1 -0
  159. package/dist/core/modules/auto-discovery.d.ts +27 -0
  160. package/dist/core/modules/auto-discovery.js +255 -0
  161. package/dist/core/modules/auto-discovery.js.map +1 -0
  162. package/dist/core/modules/index.d.ts +2 -0
  163. package/dist/core/modules/index.js +11 -0
  164. package/dist/core/modules/index.js.map +1 -0
  165. package/dist/core/modules/modules.d.ts +10 -0
  166. package/dist/core/modules/modules.js +137 -0
  167. package/dist/core/modules/modules.js.map +1 -0
  168. package/dist/core/networking/index.d.ts +2 -0
  169. package/dist/core/networking/index.js +9 -0
  170. package/dist/core/networking/index.js.map +1 -0
  171. package/dist/core/networking/service-discovery.d.ts +38 -0
  172. package/dist/core/networking/service-discovery.js +233 -0
  173. package/dist/core/networking/service-discovery.js.map +1 -0
  174. package/dist/core/networking/websocket-manager.d.ts +27 -0
  175. package/dist/core/networking/websocket-manager.js +211 -0
  176. package/dist/core/networking/websocket-manager.js.map +1 -0
  177. package/dist/core/routing/app-integration.d.ts +42 -0
  178. package/dist/core/routing/app-integration.js +152 -0
  179. package/dist/core/routing/app-integration.js.map +1 -0
  180. package/dist/core/routing/index.d.ts +106 -0
  181. package/dist/core/routing/index.js +343 -0
  182. package/dist/core/routing/index.js.map +1 -0
  183. package/dist/core/runtime/aws-lambda-adapter.d.ts +43 -0
  184. package/dist/core/runtime/aws-lambda-adapter.js +108 -0
  185. package/dist/core/runtime/aws-lambda-adapter.js.map +1 -0
  186. package/dist/core/runtime/base-adapter.d.ts +16 -0
  187. package/dist/core/runtime/base-adapter.js +105 -0
  188. package/dist/core/runtime/base-adapter.js.map +1 -0
  189. package/dist/core/runtime/cloudflare-workers-adapter.d.ts +18 -0
  190. package/dist/core/runtime/cloudflare-workers-adapter.js +131 -0
  191. package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -0
  192. package/dist/core/runtime/index.d.ts +14 -0
  193. package/dist/core/runtime/index.js +56 -0
  194. package/dist/core/runtime/index.js.map +1 -0
  195. package/dist/core/runtime/node-adapter.d.ts +15 -0
  196. package/dist/core/runtime/node-adapter.js +204 -0
  197. package/dist/core/runtime/node-adapter.js.map +1 -0
  198. package/dist/core/runtime/vercel-edge-adapter.d.ts +10 -0
  199. package/dist/core/runtime/vercel-edge-adapter.js +106 -0
  200. package/dist/core/runtime/vercel-edge-adapter.js.map +1 -0
  201. package/dist/core/utilities/circuit-breaker.d.ts +14 -0
  202. package/dist/core/utilities/circuit-breaker.js +42 -0
  203. package/dist/core/utilities/circuit-breaker.js.map +1 -0
  204. package/dist/core/utilities/container.d.ts +116 -0
  205. package/dist/core/utilities/container.js +529 -0
  206. package/dist/core/utilities/container.js.map +1 -0
  207. package/dist/core/utilities/hooks.d.ts +24 -0
  208. package/dist/core/utilities/hooks.js +131 -0
  209. package/dist/core/utilities/hooks.js.map +1 -0
  210. package/dist/core/utilities/index.d.ts +4 -0
  211. package/dist/core/utilities/index.js +22 -0
  212. package/dist/core/utilities/index.js.map +1 -0
  213. package/dist/core/validation/index.d.ts +30 -0
  214. package/dist/core/validation/index.js +144 -0
  215. package/dist/core/validation/index.js.map +1 -0
  216. package/dist/index.d.ts +30 -0
  217. package/dist/index.js +72 -0
  218. package/dist/index.js.map +1 -0
  219. package/dist/moro.d.ts +82 -0
  220. package/dist/moro.js +679 -0
  221. package/dist/moro.js.map +1 -0
  222. package/dist/types/cache.d.ts +34 -0
  223. package/dist/types/cache.js +3 -0
  224. package/dist/types/cache.js.map +1 -0
  225. package/dist/types/cdn.d.ts +19 -0
  226. package/dist/types/cdn.js +3 -0
  227. package/dist/types/cdn.js.map +1 -0
  228. package/dist/types/core.d.ts +13 -0
  229. package/dist/types/core.js +3 -0
  230. package/dist/types/core.js.map +1 -0
  231. package/dist/types/database.d.ts +29 -0
  232. package/dist/types/database.js +3 -0
  233. package/dist/types/database.js.map +1 -0
  234. package/dist/types/discovery.d.ts +6 -0
  235. package/dist/types/discovery.js +3 -0
  236. package/dist/types/discovery.js.map +1 -0
  237. package/dist/types/events.d.ts +116 -0
  238. package/dist/types/events.js +3 -0
  239. package/dist/types/events.js.map +1 -0
  240. package/dist/types/hooks.d.ts +38 -0
  241. package/dist/types/hooks.js +3 -0
  242. package/dist/types/hooks.js.map +1 -0
  243. package/dist/types/http.d.ts +51 -0
  244. package/dist/types/http.js +3 -0
  245. package/dist/types/http.js.map +1 -0
  246. package/dist/types/logger.d.ts +77 -0
  247. package/dist/types/logger.js +3 -0
  248. package/dist/types/logger.js.map +1 -0
  249. package/dist/types/module.d.ts +91 -0
  250. package/dist/types/module.js +3 -0
  251. package/dist/types/module.js.map +1 -0
  252. package/dist/types/runtime.d.ts +48 -0
  253. package/dist/types/runtime.js +3 -0
  254. package/dist/types/runtime.js.map +1 -0
  255. package/dist/types/session.d.ts +66 -0
  256. package/dist/types/session.js +3 -0
  257. package/dist/types/session.js.map +1 -0
  258. package/package.json +176 -0
  259. package/src/core/config/index.ts +47 -0
  260. package/src/core/config/loader.ts +366 -0
  261. package/src/core/config/schema.ts +346 -0
  262. package/src/core/config/utils.ts +220 -0
  263. package/src/core/database/README.md +228 -0
  264. package/src/core/database/adapters/drizzle.ts +425 -0
  265. package/src/core/database/adapters/index.ts +45 -0
  266. package/src/core/database/adapters/mongodb.ts +292 -0
  267. package/src/core/database/adapters/mysql.ts +217 -0
  268. package/src/core/database/adapters/postgresql.ts +211 -0
  269. package/src/core/database/adapters/redis.ts +331 -0
  270. package/src/core/database/adapters/sqlite.ts +255 -0
  271. package/src/core/database/index.ts +3 -0
  272. package/src/core/docs/index.ts +245 -0
  273. package/src/core/docs/openapi-generator.ts +588 -0
  274. package/src/core/docs/simple-docs.ts +305 -0
  275. package/src/core/docs/swagger-ui.ts +370 -0
  276. package/src/core/docs/zod-to-openapi.ts +532 -0
  277. package/src/core/events/event-bus.ts +249 -0
  278. package/src/core/events/index.ts +12 -0
  279. package/src/core/framework.ts +621 -0
  280. package/src/core/http/http-server.ts +1421 -0
  281. package/src/core/http/index.ts +11 -0
  282. package/src/core/http/router.ts +153 -0
  283. package/src/core/logger/filters.ts +148 -0
  284. package/src/core/logger/index.ts +20 -0
  285. package/src/core/logger/logger.ts +434 -0
  286. package/src/core/logger/outputs.ts +136 -0
  287. package/src/core/middleware/built-in/adapters/cache/file.ts +106 -0
  288. package/src/core/middleware/built-in/adapters/cache/index.ts +26 -0
  289. package/src/core/middleware/built-in/adapters/cache/memory.ts +73 -0
  290. package/src/core/middleware/built-in/adapters/cache/redis.ts +103 -0
  291. package/src/core/middleware/built-in/adapters/cdn/azure.ts +68 -0
  292. package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +100 -0
  293. package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +92 -0
  294. package/src/core/middleware/built-in/adapters/cdn/index.ts +23 -0
  295. package/src/core/middleware/built-in/adapters/index.ts +7 -0
  296. package/src/core/middleware/built-in/auth.ts +39 -0
  297. package/src/core/middleware/built-in/cache.ts +228 -0
  298. package/src/core/middleware/built-in/cdn.ts +151 -0
  299. package/src/core/middleware/built-in/cookie.ts +90 -0
  300. package/src/core/middleware/built-in/cors.ts +38 -0
  301. package/src/core/middleware/built-in/csp.ts +107 -0
  302. package/src/core/middleware/built-in/csrf.ts +87 -0
  303. package/src/core/middleware/built-in/error-tracker.ts +16 -0
  304. package/src/core/middleware/built-in/index.ts +57 -0
  305. package/src/core/middleware/built-in/performance-monitor.ts +25 -0
  306. package/src/core/middleware/built-in/rate-limit.ts +60 -0
  307. package/src/core/middleware/built-in/request-logger.ts +14 -0
  308. package/src/core/middleware/built-in/session.ts +311 -0
  309. package/src/core/middleware/built-in/sse.ts +91 -0
  310. package/src/core/middleware/built-in/validation.ts +33 -0
  311. package/src/core/middleware/index.ts +188 -0
  312. package/src/core/modules/auto-discovery.ts +265 -0
  313. package/src/core/modules/index.ts +6 -0
  314. package/src/core/modules/modules.ts +125 -0
  315. package/src/core/networking/index.ts +7 -0
  316. package/src/core/networking/service-discovery.ts +309 -0
  317. package/src/core/networking/websocket-manager.ts +259 -0
  318. package/src/core/routing/app-integration.ts +229 -0
  319. package/src/core/routing/index.ts +519 -0
  320. package/src/core/runtime/aws-lambda-adapter.ts +157 -0
  321. package/src/core/runtime/base-adapter.ts +140 -0
  322. package/src/core/runtime/cloudflare-workers-adapter.ts +166 -0
  323. package/src/core/runtime/index.ts +74 -0
  324. package/src/core/runtime/node-adapter.ts +210 -0
  325. package/src/core/runtime/vercel-edge-adapter.ts +125 -0
  326. package/src/core/utilities/circuit-breaker.ts +46 -0
  327. package/src/core/utilities/container.ts +760 -0
  328. package/src/core/utilities/hooks.ts +148 -0
  329. package/src/core/utilities/index.ts +16 -0
  330. package/src/core/validation/index.ts +216 -0
  331. package/src/index.ts +120 -0
  332. package/src/moro.ts +842 -0
  333. package/src/types/cache.ts +38 -0
  334. package/src/types/cdn.ts +22 -0
  335. package/src/types/core.ts +17 -0
  336. package/src/types/database.ts +40 -0
  337. package/src/types/discovery.ts +7 -0
  338. package/src/types/events.ts +90 -0
  339. package/src/types/hooks.ts +47 -0
  340. package/src/types/http.ts +70 -0
  341. package/src/types/logger.ts +109 -0
  342. package/src/types/module.ts +87 -0
  343. package/src/types/runtime.ts +91 -0
  344. package/src/types/session.ts +89 -0
  345. package/tsconfig.json +21 -0
@@ -0,0 +1,588 @@
1
+ // OpenAPI Specification Generator for Moro Framework
2
+ // Extracts route information from intelligent routing and generates OpenAPI 3.0 specs
3
+
4
+ import { CompiledRoute, RouteSchema } from "../routing";
5
+ import {
6
+ zodToOpenAPI,
7
+ generateExampleFromSchema,
8
+ OpenAPISchema,
9
+ } from "./zod-to-openapi";
10
+ import { createFrameworkLogger } from "../logger";
11
+
12
+ const logger = createFrameworkLogger("OpenAPIGenerator");
13
+
14
+ // OpenAPI 3.0 specification structure
15
+ export interface OpenAPISpec {
16
+ openapi: string;
17
+ info: OpenAPIInfo;
18
+ servers?: OpenAPIServer[];
19
+ paths: Record<string, OpenAPIPath>;
20
+ components?: OpenAPIComponents;
21
+ tags?: OpenAPITag[];
22
+ }
23
+
24
+ export interface OpenAPIInfo {
25
+ title: string;
26
+ version: string;
27
+ description?: string;
28
+ contact?: {
29
+ name?: string;
30
+ url?: string;
31
+ email?: string;
32
+ };
33
+ license?: {
34
+ name: string;
35
+ url?: string;
36
+ };
37
+ }
38
+
39
+ export interface OpenAPIServer {
40
+ url: string;
41
+ description?: string;
42
+ }
43
+
44
+ export interface OpenAPIPath {
45
+ [method: string]: OpenAPIOperation;
46
+ }
47
+
48
+ export interface OpenAPIOperation {
49
+ summary?: string;
50
+ description?: string;
51
+ tags?: string[];
52
+ parameters?: OpenAPIParameter[];
53
+ requestBody?: OpenAPIRequestBody;
54
+ responses: Record<string, OpenAPIResponse>;
55
+ security?: OpenAPISecurityRequirement[];
56
+ }
57
+
58
+ export interface OpenAPIParameter {
59
+ name: string;
60
+ in: "query" | "path" | "header" | "cookie";
61
+ required?: boolean;
62
+ description?: string;
63
+ schema: OpenAPISchema;
64
+ example?: any;
65
+ }
66
+
67
+ export interface OpenAPIRequestBody {
68
+ description?: string;
69
+ required?: boolean;
70
+ content: Record<string, OpenAPIMediaType>;
71
+ }
72
+
73
+ export interface OpenAPIMediaType {
74
+ schema: OpenAPISchema;
75
+ example?: any;
76
+ examples?: Record<string, OpenAPIExample>;
77
+ }
78
+
79
+ export interface OpenAPIResponse {
80
+ description: string;
81
+ content?: Record<string, OpenAPIMediaType>;
82
+ headers?: Record<string, OpenAPIHeader>;
83
+ }
84
+
85
+ export interface OpenAPIHeader {
86
+ description?: string;
87
+ schema: OpenAPISchema;
88
+ }
89
+
90
+ export interface OpenAPIExample {
91
+ summary?: string;
92
+ description?: string;
93
+ value: any;
94
+ }
95
+
96
+ export interface OpenAPIComponents {
97
+ schemas?: Record<string, OpenAPISchema>;
98
+ responses?: Record<string, OpenAPIResponse>;
99
+ parameters?: Record<string, OpenAPIParameter>;
100
+ examples?: Record<string, OpenAPIExample>;
101
+ securitySchemes?: Record<string, OpenAPISecurityScheme>;
102
+ }
103
+
104
+ export interface OpenAPISecurityScheme {
105
+ type: "apiKey" | "http" | "oauth2" | "openIdConnect";
106
+ description?: string;
107
+ name?: string;
108
+ in?: "query" | "header" | "cookie";
109
+ scheme?: string;
110
+ bearerFormat?: string;
111
+ }
112
+
113
+ export interface OpenAPISecurityRequirement {
114
+ [name: string]: string[];
115
+ }
116
+
117
+ export interface OpenAPITag {
118
+ name: string;
119
+ description?: string;
120
+ }
121
+
122
+ // Generation options
123
+ export interface GenerationOptions {
124
+ info: OpenAPIInfo;
125
+ servers?: OpenAPIServer[];
126
+ includeExamples?: boolean;
127
+ includeSchemas?: boolean;
128
+ groupByTags?: boolean;
129
+ securitySchemes?: Record<string, OpenAPISecurityScheme>;
130
+ }
131
+
132
+ // OpenAPI generator class
133
+ export class OpenAPIGenerator {
134
+ private routes: CompiledRoute[] = [];
135
+ private schemas = new Map<string, OpenAPISchema>();
136
+ private tags = new Set<string>();
137
+
138
+ constructor(private options: GenerationOptions) {
139
+ logger.debug("OpenAPI Generator initialized", "Initialization", {
140
+ includeExamples: options.includeExamples,
141
+ includeSchemas: options.includeSchemas,
142
+ });
143
+ }
144
+
145
+ // Add routes to the generator
146
+ addRoutes(routes: CompiledRoute[]): void {
147
+ this.routes.push(...routes);
148
+
149
+ // Extract tags from routes
150
+ routes.forEach((route) => {
151
+ if (route.schema.tags) {
152
+ route.schema.tags.forEach((tag) => this.tags.add(tag));
153
+ }
154
+ });
155
+
156
+ logger.debug(
157
+ `Added ${routes.length} routes to documentation`,
158
+ "RouteAddition",
159
+ {
160
+ totalRoutes: this.routes.length,
161
+ uniqueTags: this.tags.size,
162
+ },
163
+ );
164
+ }
165
+
166
+ // Generate complete OpenAPI specification
167
+ generate(): OpenAPISpec {
168
+ logger.info("Generating OpenAPI specification", "Generation", {
169
+ routeCount: this.routes.length,
170
+ tagCount: this.tags.size,
171
+ });
172
+
173
+ const spec: OpenAPISpec = {
174
+ openapi: "3.0.3",
175
+ info: this.options.info,
176
+ servers: this.options.servers || [
177
+ { url: "http://localhost:3000", description: "Development server" },
178
+ ],
179
+ paths: this.generatePaths(),
180
+ tags: this.generateTags(),
181
+ };
182
+
183
+ // Add components if schemas are included
184
+ if (this.options.includeSchemas && this.schemas.size > 0) {
185
+ spec.components = {
186
+ schemas: Object.fromEntries(this.schemas),
187
+ securitySchemes: this.options.securitySchemes,
188
+ };
189
+ }
190
+
191
+ logger.info("OpenAPI specification generated successfully", "Generation", {
192
+ pathCount: Object.keys(spec.paths).length,
193
+ schemaCount: this.schemas.size,
194
+ tagCount: spec.tags?.length || 0,
195
+ });
196
+
197
+ return spec;
198
+ }
199
+
200
+ // Generate paths from routes
201
+ private generatePaths(): Record<string, OpenAPIPath> {
202
+ const paths: Record<string, OpenAPIPath> = {};
203
+
204
+ for (const route of this.routes) {
205
+ const path = this.convertPathToOpenAPI(route.schema.path);
206
+ const method = route.schema.method.toLowerCase();
207
+
208
+ if (!paths[path]) {
209
+ paths[path] = {};
210
+ }
211
+
212
+ paths[path][method] = this.generateOperation(route.schema);
213
+ }
214
+
215
+ return paths;
216
+ }
217
+
218
+ // Generate OpenAPI operation from route schema
219
+ private generateOperation(route: RouteSchema): OpenAPIOperation {
220
+ const operation: OpenAPIOperation = {
221
+ summary: route.description || `${route.method} ${route.path}`,
222
+ description: route.description,
223
+ tags: route.tags,
224
+ responses: this.generateResponses(route),
225
+ };
226
+
227
+ // Add parameters (query and path)
228
+ const parameters = this.generateParameters(route);
229
+ if (parameters.length > 0) {
230
+ operation.parameters = parameters;
231
+ }
232
+
233
+ // Add request body (for POST, PUT, PATCH)
234
+ if (
235
+ ["POST", "PUT", "PATCH"].includes(route.method) &&
236
+ route.validation?.body
237
+ ) {
238
+ operation.requestBody = this.generateRequestBody(route);
239
+ }
240
+
241
+ // Add security if auth is required
242
+ if (route.auth) {
243
+ operation.security = this.generateSecurity(route);
244
+ }
245
+
246
+ return operation;
247
+ }
248
+
249
+ // Generate parameters from validation schemas
250
+ private generateParameters(route: RouteSchema): OpenAPIParameter[] {
251
+ const parameters: OpenAPIParameter[] = [];
252
+
253
+ // Path parameters
254
+ if (route.validation?.params) {
255
+ const paramSchema = zodToOpenAPI(route.validation.params, this.options);
256
+ if (paramSchema.properties) {
257
+ for (const [name, schema] of Object.entries(paramSchema.properties)) {
258
+ parameters.push({
259
+ name,
260
+ in: "path",
261
+ required: true,
262
+ schema,
263
+ description: schema.description,
264
+ example: this.options.includeExamples ? schema.example : undefined,
265
+ });
266
+ }
267
+ }
268
+ }
269
+
270
+ // Query parameters
271
+ if (route.validation?.query) {
272
+ const querySchema = zodToOpenAPI(route.validation.query, this.options);
273
+ if (querySchema.properties) {
274
+ for (const [name, schema] of Object.entries(querySchema.properties)) {
275
+ const isRequired = querySchema.required?.includes(name) || false;
276
+ parameters.push({
277
+ name,
278
+ in: "query",
279
+ required: isRequired,
280
+ schema,
281
+ description: schema.description,
282
+ example: this.options.includeExamples ? schema.example : undefined,
283
+ });
284
+ }
285
+ }
286
+ }
287
+
288
+ // Header parameters
289
+ if (route.validation?.headers) {
290
+ const headerSchema = zodToOpenAPI(route.validation.headers, this.options);
291
+ if (headerSchema.properties) {
292
+ for (const [name, schema] of Object.entries(headerSchema.properties)) {
293
+ const isRequired = headerSchema.required?.includes(name) || false;
294
+ parameters.push({
295
+ name,
296
+ in: "header",
297
+ required: isRequired,
298
+ schema,
299
+ description: schema.description,
300
+ example: this.options.includeExamples ? schema.example : undefined,
301
+ });
302
+ }
303
+ }
304
+ }
305
+
306
+ return parameters;
307
+ }
308
+
309
+ // Generate request body from validation schema
310
+ private generateRequestBody(route: RouteSchema): OpenAPIRequestBody {
311
+ if (!route.validation?.body) {
312
+ return {
313
+ description: "Request body",
314
+ required: true,
315
+ content: {
316
+ "application/json": {
317
+ schema: { type: "object" },
318
+ },
319
+ },
320
+ };
321
+ }
322
+
323
+ const bodySchema = zodToOpenAPI(route.validation.body, this.options);
324
+ const example = this.options.includeExamples
325
+ ? generateExampleFromSchema(route.validation.body)
326
+ : undefined;
327
+
328
+ return {
329
+ description: "Request body",
330
+ required: true,
331
+ content: {
332
+ "application/json": {
333
+ schema: bodySchema,
334
+ example,
335
+ },
336
+ },
337
+ };
338
+ }
339
+
340
+ // Generate responses
341
+ private generateResponses(
342
+ route: RouteSchema,
343
+ ): Record<string, OpenAPIResponse> {
344
+ const responses: Record<string, OpenAPIResponse> = {};
345
+
346
+ // Success response
347
+ responses["200"] = {
348
+ description: "Successful response",
349
+ content: {
350
+ "application/json": {
351
+ schema: {
352
+ type: "object",
353
+ properties: {
354
+ success: { type: "boolean", example: true },
355
+ data: { type: "object", description: "Response data" },
356
+ message: { type: "string", example: "Operation successful" },
357
+ },
358
+ },
359
+ },
360
+ },
361
+ };
362
+
363
+ // Add 201 for POST requests
364
+ if (route.method === "POST") {
365
+ responses["201"] = {
366
+ description: "Resource created successfully",
367
+ content: {
368
+ "application/json": {
369
+ schema: {
370
+ type: "object",
371
+ properties: {
372
+ success: { type: "boolean", example: true },
373
+ data: { type: "object", description: "Created resource" },
374
+ message: {
375
+ type: "string",
376
+ example: "Resource created successfully",
377
+ },
378
+ },
379
+ },
380
+ },
381
+ },
382
+ };
383
+ }
384
+
385
+ // Validation error response
386
+ if (route.validation) {
387
+ responses["400"] = {
388
+ description: "Validation error",
389
+ content: {
390
+ "application/json": {
391
+ schema: {
392
+ type: "object",
393
+ properties: {
394
+ success: { type: "boolean", example: false },
395
+ error: { type: "string", example: "Validation failed" },
396
+ details: {
397
+ type: "array",
398
+ items: {
399
+ type: "object",
400
+ properties: {
401
+ field: { type: "string", example: "email" },
402
+ message: {
403
+ type: "string",
404
+ example: "Invalid email address",
405
+ },
406
+ code: { type: "string", example: "invalid_format" },
407
+ },
408
+ },
409
+ },
410
+ requestId: { type: "string", example: "req_123456" },
411
+ },
412
+ },
413
+ },
414
+ },
415
+ };
416
+ }
417
+
418
+ // Auth error response
419
+ if (route.auth) {
420
+ responses["401"] = {
421
+ description: "Authentication required",
422
+ content: {
423
+ "application/json": {
424
+ schema: {
425
+ type: "object",
426
+ properties: {
427
+ success: { type: "boolean", example: false },
428
+ error: { type: "string", example: "Authentication required" },
429
+ requestId: { type: "string", example: "req_123456" },
430
+ },
431
+ },
432
+ },
433
+ },
434
+ };
435
+
436
+ responses["403"] = {
437
+ description: "Insufficient permissions",
438
+ content: {
439
+ "application/json": {
440
+ schema: {
441
+ type: "object",
442
+ properties: {
443
+ success: { type: "boolean", example: false },
444
+ error: { type: "string", example: "Insufficient permissions" },
445
+ requestId: { type: "string", example: "req_123456" },
446
+ },
447
+ },
448
+ },
449
+ },
450
+ };
451
+ }
452
+
453
+ // Rate limit error response
454
+ if (route.rateLimit) {
455
+ responses["429"] = {
456
+ description: "Rate limit exceeded",
457
+ content: {
458
+ "application/json": {
459
+ schema: {
460
+ type: "object",
461
+ properties: {
462
+ success: { type: "boolean", example: false },
463
+ error: { type: "string", example: "Rate limit exceeded" },
464
+ retryAfter: { type: "number", example: 60 },
465
+ requestId: { type: "string", example: "req_123456" },
466
+ },
467
+ },
468
+ },
469
+ },
470
+ };
471
+ }
472
+
473
+ // Server error response
474
+ responses["500"] = {
475
+ description: "Internal server error",
476
+ content: {
477
+ "application/json": {
478
+ schema: {
479
+ type: "object",
480
+ properties: {
481
+ success: { type: "boolean", example: false },
482
+ error: { type: "string", example: "Internal server error" },
483
+ requestId: { type: "string", example: "req_123456" },
484
+ },
485
+ },
486
+ },
487
+ },
488
+ };
489
+
490
+ return responses;
491
+ }
492
+
493
+ // Generate security requirements
494
+ private generateSecurity(route: RouteSchema): OpenAPISecurityRequirement[] {
495
+ if (!route.auth) return [];
496
+
497
+ const security: OpenAPISecurityRequirement[] = [];
498
+
499
+ // Default to bearer token if no specific scheme is defined
500
+ security.push({
501
+ bearerAuth: route.auth.roles || [],
502
+ });
503
+
504
+ return security;
505
+ }
506
+
507
+ // Generate tags
508
+ private generateTags(): OpenAPITag[] {
509
+ return Array.from(this.tags).map((tag) => ({
510
+ name: tag,
511
+ description: `Operations related to ${tag}`,
512
+ }));
513
+ }
514
+
515
+ // Convert Moro path format to OpenAPI path format
516
+ private convertPathToOpenAPI(path: string): string {
517
+ // Convert :param to {param} format
518
+ return path.replace(/:([^/]+)/g, "{$1}");
519
+ }
520
+
521
+ // Generate JSON representation
522
+ generateJSON(): string {
523
+ return JSON.stringify(this.generate(), null, 2);
524
+ }
525
+
526
+ // Generate YAML representation (basic implementation)
527
+ generateYAML(): string {
528
+ const spec = this.generate();
529
+ return this.objectToYAML(spec, 0);
530
+ }
531
+
532
+ // Simple YAML converter (basic implementation)
533
+ private objectToYAML(obj: any, indent: number = 0): string {
534
+ const spaces = " ".repeat(indent);
535
+ let yaml = "";
536
+
537
+ for (const [key, value] of Object.entries(obj)) {
538
+ if (value === null || value === undefined) continue;
539
+
540
+ yaml += `${spaces}${key}:`;
541
+
542
+ if (typeof value === "object" && !Array.isArray(value)) {
543
+ yaml += "\n" + this.objectToYAML(value, indent + 1);
544
+ } else if (Array.isArray(value)) {
545
+ yaml += "\n";
546
+ for (const item of value) {
547
+ if (typeof item === "object") {
548
+ yaml += `${spaces} -\n` + this.objectToYAML(item, indent + 2);
549
+ } else {
550
+ yaml += `${spaces} - ${item}\n`;
551
+ }
552
+ }
553
+ } else if (typeof value === "string") {
554
+ yaml += ` "${value}"\n`;
555
+ } else {
556
+ yaml += ` ${value}\n`;
557
+ }
558
+ }
559
+
560
+ return yaml;
561
+ }
562
+ }
563
+
564
+ // Convenience function to generate OpenAPI from routes
565
+ export function generateOpenAPIFromRoutes(
566
+ routes: CompiledRoute[],
567
+ options: GenerationOptions,
568
+ ): OpenAPISpec {
569
+ const generator = new OpenAPIGenerator(options);
570
+ generator.addRoutes(routes);
571
+ return generator.generate();
572
+ }
573
+
574
+ // Default security schemes
575
+ export const defaultSecuritySchemes: Record<string, OpenAPISecurityScheme> = {
576
+ bearerAuth: {
577
+ type: "http",
578
+ scheme: "bearer",
579
+ bearerFormat: "JWT",
580
+ description: "Bearer token authentication",
581
+ },
582
+ apiKey: {
583
+ type: "apiKey",
584
+ in: "header",
585
+ name: "X-API-Key",
586
+ description: "API key authentication",
587
+ },
588
+ };