@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,228 @@
1
+ // Built-in Cache Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import {
4
+ CacheAdapter,
5
+ CacheOptions,
6
+ CachedResponse,
7
+ } from "../../../types/cache";
8
+ import { createFrameworkLogger } from "../../logger";
9
+ import { createCacheAdapter } from "./adapters/cache";
10
+
11
+ const logger = createFrameworkLogger("CacheMiddleware");
12
+
13
+ export const cache = (options: CacheOptions = {}): MiddlewareInterface => ({
14
+ name: "cache",
15
+ version: "1.0.0",
16
+ metadata: {
17
+ name: "cache",
18
+ version: "1.0.0",
19
+ description: "Built-in cache middleware with pluggable storage adapters",
20
+ author: "MoroJS Team",
21
+ },
22
+
23
+ install: async (hooks: any, middlewareOptions: any = {}) => {
24
+ logger.debug("Installing cache middleware", "Installation");
25
+
26
+ // Initialize storage adapter
27
+ let storageAdapter: CacheAdapter;
28
+
29
+ if (
30
+ options.adapter &&
31
+ typeof options.adapter === "object" &&
32
+ "get" in options.adapter
33
+ ) {
34
+ storageAdapter = options.adapter as CacheAdapter;
35
+ } else if (typeof options.adapter === "string") {
36
+ storageAdapter = createCacheAdapter(
37
+ options.adapter,
38
+ options.adapterOptions,
39
+ );
40
+ } else {
41
+ // Default to memory cache
42
+ storageAdapter = createCacheAdapter("memory");
43
+ }
44
+
45
+ // Cache key generation
46
+ const generateCacheKey = (req: any, strategy?: any): string => {
47
+ const prefix = options.keyPrefix || "moro:cache:";
48
+
49
+ if (strategy?.key) {
50
+ return `${prefix}${strategy.key(req)}`;
51
+ }
52
+
53
+ // Default key: method + path + query
54
+ const query = new URLSearchParams(req.query || {}).toString();
55
+ return `${prefix}${req.method}:${req.path}${query ? `?${query}` : ""}`;
56
+ };
57
+
58
+ // Find matching strategy
59
+ const findStrategy = (req: any): any | undefined => {
60
+ if (!options.strategies) return undefined;
61
+
62
+ for (const [pattern, strategy] of Object.entries(options.strategies)) {
63
+ const regex = new RegExp(pattern);
64
+ if (regex.test(req.path)) {
65
+ return strategy;
66
+ }
67
+ }
68
+
69
+ return undefined;
70
+ };
71
+
72
+ hooks.before("request", async (context: HookContext) => {
73
+ const req = context.request as any;
74
+ const res = context.response as any;
75
+
76
+ // Only cache GET requests by default
77
+ if (req.method !== "GET") {
78
+ return;
79
+ }
80
+
81
+ const strategy = findStrategy(req);
82
+ const cacheKey = generateCacheKey(req, strategy);
83
+
84
+ // Check if caching is disabled for this request
85
+ if (strategy?.condition && !strategy.condition(req, res)) {
86
+ return;
87
+ }
88
+
89
+ try {
90
+ // Try to get from cache
91
+ const cachedResponse = await storageAdapter.get(cacheKey);
92
+
93
+ if (cachedResponse) {
94
+ logger.debug(`Cache hit: ${cacheKey}`, "CacheHit");
95
+
96
+ // Set cache headers
97
+ res.setHeader("X-Cache", "HIT");
98
+ res.setHeader("X-Cache-Key", cacheKey);
99
+
100
+ // Set HTTP cache headers
101
+ if (options.maxAge) {
102
+ res.setHeader("Cache-Control", `public, max-age=${options.maxAge}`);
103
+ }
104
+
105
+ if (options.vary && options.vary.length > 0) {
106
+ res.setHeader("Vary", options.vary.join(", "));
107
+ }
108
+
109
+ // Send cached response
110
+ res.status(cachedResponse.status || 200);
111
+
112
+ // Set cached headers
113
+ if (cachedResponse.headers) {
114
+ Object.entries(cachedResponse.headers).forEach(([key, value]) => {
115
+ res.setHeader(key, value as string);
116
+ });
117
+ }
118
+
119
+ if (cachedResponse.contentType) {
120
+ res.setHeader("Content-Type", cachedResponse.contentType);
121
+ }
122
+
123
+ res.send(cachedResponse.body);
124
+
125
+ // Mark as handled
126
+ (context as any).handled = true;
127
+ return;
128
+ }
129
+
130
+ logger.debug(`Cache miss: ${cacheKey}`, "CacheMiss");
131
+ res.setHeader("X-Cache", "MISS");
132
+ res.setHeader("X-Cache-Key", cacheKey);
133
+ } catch (error) {
134
+ logger.error("Cache retrieval error", "CacheError", {
135
+ error,
136
+ key: cacheKey,
137
+ });
138
+ }
139
+
140
+ // Store original response methods
141
+ const originalJson = res.json;
142
+ const originalSend = res.send;
143
+ const originalEnd = res.end;
144
+
145
+ // Wrap response methods to cache the response
146
+ const cacheResponse = async (body: any, contentType?: string) => {
147
+ try {
148
+ const ttl = strategy?.ttl || options.defaultTtl || 3600;
149
+
150
+ const cacheData: CachedResponse = {
151
+ body,
152
+ status: res.statusCode,
153
+ headers: res.getHeaders ? res.getHeaders() : {},
154
+ contentType: contentType || res.getHeader("Content-Type"),
155
+ timestamp: Date.now(),
156
+ };
157
+
158
+ await storageAdapter.set(cacheKey, cacheData, ttl);
159
+ logger.debug(
160
+ `Response cached: ${cacheKey} (TTL: ${ttl}s)`,
161
+ "CacheSet",
162
+ );
163
+ } catch (error) {
164
+ logger.error("Cache storage error", "CacheError", {
165
+ error,
166
+ key: cacheKey,
167
+ });
168
+ }
169
+ };
170
+
171
+ // Override response methods
172
+ res.json = function (data: any) {
173
+ cacheResponse(data, "application/json");
174
+ return originalJson.call(this, data);
175
+ };
176
+
177
+ res.send = function (data: any) {
178
+ cacheResponse(data);
179
+ return originalSend.call(this, data);
180
+ };
181
+
182
+ res.end = function (data?: any) {
183
+ if (data) {
184
+ cacheResponse(data);
185
+ }
186
+ return originalEnd.call(this, data);
187
+ };
188
+
189
+ // Add cache control methods
190
+ res.cacheControl = (directives: any) => {
191
+ const parts: string[] = [];
192
+
193
+ if (directives.public) parts.push("public");
194
+ if (directives.private) parts.push("private");
195
+ if (directives.noCache) parts.push("no-cache");
196
+ if (directives.noStore) parts.push("no-store");
197
+ if (directives.mustRevalidate) parts.push("must-revalidate");
198
+ if (directives.immutable) parts.push("immutable");
199
+
200
+ if (typeof directives.maxAge === "number")
201
+ parts.push(`max-age=${directives.maxAge}`);
202
+ if (typeof directives.staleWhileRevalidate === "number") {
203
+ parts.push(
204
+ `stale-while-revalidate=${directives.staleWhileRevalidate}`,
205
+ );
206
+ }
207
+
208
+ res.setHeader("Cache-Control", parts.join(", "));
209
+ return res;
210
+ };
211
+
212
+ // Add ETag generation
213
+ if (options.etag !== false) {
214
+ res.generateETag = (content: string | Buffer) => {
215
+ const crypto = require("crypto");
216
+ const hash = crypto.createHash("md5").update(content).digest("hex");
217
+ const prefix = options.etag === "weak" ? "W/" : "";
218
+ return `${prefix}"${hash}"`;
219
+ };
220
+ }
221
+ });
222
+
223
+ logger.info("Cache middleware installed", "Installation", {
224
+ adapter: typeof options.adapter === "string" ? options.adapter : "custom",
225
+ strategies: Object.keys(options.strategies || {}).length,
226
+ });
227
+ },
228
+ });
@@ -0,0 +1,151 @@
1
+ // Built-in CDN Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import { CDNAdapter, CDNOptions } from "../../../types/cdn";
4
+ import { createFrameworkLogger } from "../../logger";
5
+ import { createCDNAdapter } from "./adapters/cdn";
6
+
7
+ const logger = createFrameworkLogger("CDNMiddleware");
8
+
9
+ export const cdn = (options: CDNOptions = {}): MiddlewareInterface => ({
10
+ name: "cdn",
11
+ version: "1.0.0",
12
+ metadata: {
13
+ name: "cdn",
14
+ version: "1.0.0",
15
+ description: "Built-in CDN middleware with pluggable provider adapters",
16
+ author: "MoroJS Team",
17
+ },
18
+
19
+ install: async (hooks: any, middlewareOptions: any = {}) => {
20
+ logger.debug("Installing CDN middleware", "Installation");
21
+
22
+ // Initialize CDN adapter
23
+ let cdnAdapter: CDNAdapter | null = null;
24
+
25
+ if (
26
+ options.adapter &&
27
+ typeof options.adapter === "object" &&
28
+ "purge" in options.adapter
29
+ ) {
30
+ cdnAdapter = options.adapter as CDNAdapter;
31
+ } else if (typeof options.adapter === "string") {
32
+ cdnAdapter = createCDNAdapter(options.adapter, options.adapterOptions);
33
+ }
34
+
35
+ if (!cdnAdapter) {
36
+ logger.warn(
37
+ "No CDN adapter configured, CDN features will be disabled",
38
+ "Installation",
39
+ );
40
+ return;
41
+ }
42
+
43
+ hooks.before("request", async (context: HookContext) => {
44
+ const req = context.request as any;
45
+ const res = context.response as any;
46
+
47
+ // Set CDN headers on all responses
48
+ if (cdnAdapter) {
49
+ cdnAdapter.setHeaders(res);
50
+ }
51
+
52
+ // Add CDN methods to response
53
+ res.purgeCDN = async (urls?: string[]) => {
54
+ if (!cdnAdapter) {
55
+ logger.warn(
56
+ "CDN purge requested but no adapter configured",
57
+ "CDNPurge",
58
+ );
59
+ return;
60
+ }
61
+
62
+ try {
63
+ const urlsToPurge = urls || [req.path];
64
+ await cdnAdapter.purge(urlsToPurge);
65
+ logger.info(
66
+ `CDN cache purged: ${urlsToPurge.join(", ")}`,
67
+ "CDNPurge",
68
+ );
69
+ } catch (error) {
70
+ logger.error("CDN purge failed", "CDNError", { error, urls });
71
+ throw error;
72
+ }
73
+ };
74
+
75
+ res.prefetchCDN = async (urls: string[]) => {
76
+ if (!cdnAdapter || !cdnAdapter.prefetch) {
77
+ logger.warn(
78
+ "CDN prefetch requested but not supported by adapter",
79
+ "CDNPrefetch",
80
+ );
81
+ return;
82
+ }
83
+
84
+ try {
85
+ await cdnAdapter.prefetch(urls);
86
+ logger.info(
87
+ `CDN prefetch requested: ${urls.join(", ")}`,
88
+ "CDNPrefetch",
89
+ );
90
+ } catch (error) {
91
+ logger.error("CDN prefetch failed", "CDNError", { error, urls });
92
+ }
93
+ };
94
+
95
+ res.getCDNStats = async () => {
96
+ if (!cdnAdapter || !cdnAdapter.getStats) {
97
+ logger.warn(
98
+ "CDN stats requested but not supported by adapter",
99
+ "CDNStats",
100
+ );
101
+ return null;
102
+ }
103
+
104
+ try {
105
+ const stats = await cdnAdapter.getStats();
106
+ logger.debug("CDN stats retrieved", "CDNStats");
107
+ return stats;
108
+ } catch (error) {
109
+ logger.error("CDN stats retrieval failed", "CDNError", { error });
110
+ return null;
111
+ }
112
+ };
113
+ });
114
+
115
+ // Auto-invalidation on certain patterns
116
+ if (options.autoInvalidate && options.invalidationPatterns) {
117
+ hooks.after("response", async (context: HookContext) => {
118
+ const req = context.request as any;
119
+ const res = context.response as any;
120
+
121
+ // Check if this request matches invalidation patterns
122
+ const shouldInvalidate = options.invalidationPatterns?.some(
123
+ (pattern) => {
124
+ const regex = new RegExp(pattern);
125
+ return regex.test(req.path);
126
+ },
127
+ );
128
+
129
+ if (shouldInvalidate && cdnAdapter) {
130
+ try {
131
+ await cdnAdapter.purge([req.path]);
132
+ logger.debug(
133
+ `Auto-invalidated CDN cache for: ${req.path}`,
134
+ "CDNAutoInvalidate",
135
+ );
136
+ } catch (error) {
137
+ logger.error("CDN auto-invalidation failed", "CDNError", {
138
+ error,
139
+ path: req.path,
140
+ });
141
+ }
142
+ }
143
+ });
144
+ }
145
+
146
+ logger.info("CDN middleware installed", "Installation", {
147
+ adapter: typeof options.adapter === "string" ? options.adapter : "custom",
148
+ autoInvalidate: !!options.autoInvalidate,
149
+ });
150
+ },
151
+ });
@@ -0,0 +1,90 @@
1
+ // Cookie Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ const logger = createFrameworkLogger("CookieMiddleware");
6
+
7
+ export interface CookieOptions {
8
+ maxAge?: number;
9
+ expires?: Date;
10
+ httpOnly?: boolean;
11
+ secure?: boolean;
12
+ sameSite?: "strict" | "lax" | "none";
13
+ domain?: string;
14
+ path?: string;
15
+ }
16
+
17
+ export const cookie = (
18
+ options: {
19
+ secret?: string;
20
+ signed?: boolean;
21
+ } = {},
22
+ ): MiddlewareInterface => ({
23
+ name: "cookie",
24
+ version: "1.0.0",
25
+ metadata: {
26
+ name: "cookie",
27
+ version: "1.0.0",
28
+ description: "Cookie parsing and setting middleware with security features",
29
+ author: "MoroJS Team",
30
+ },
31
+
32
+ install: async (hooks: any, options: any = {}) => {
33
+ logger.debug("Installing cookie middleware", "Installation");
34
+
35
+ hooks.before("request", async (context: HookContext) => {
36
+ const req = context.request as any;
37
+ const res = context.response as any;
38
+
39
+ // Parse cookies from request
40
+ req.cookies = parseCookies(req.headers.cookie || "");
41
+
42
+ // Add cookie methods to response
43
+ res.cookie = (
44
+ name: string,
45
+ value: string,
46
+ options: CookieOptions = {},
47
+ ) => {
48
+ const cookieValue = encodeURIComponent(value);
49
+ let cookieString = `${name}=${cookieValue}`;
50
+
51
+ if (options.maxAge) cookieString += `; Max-Age=${options.maxAge}`;
52
+ if (options.expires)
53
+ cookieString += `; Expires=${options.expires.toUTCString()}`;
54
+ if (options.httpOnly) cookieString += "; HttpOnly";
55
+ if (options.secure) cookieString += "; Secure";
56
+ if (options.sameSite) cookieString += `; SameSite=${options.sameSite}`;
57
+ if (options.domain) cookieString += `; Domain=${options.domain}`;
58
+ if (options.path) cookieString += `; Path=${options.path}`;
59
+
60
+ const existingCookies = res.getHeader("Set-Cookie") || [];
61
+ const cookies = Array.isArray(existingCookies)
62
+ ? [...existingCookies]
63
+ : [existingCookies as string];
64
+ cookies.push(cookieString);
65
+ res.setHeader("Set-Cookie", cookies);
66
+
67
+ return res;
68
+ };
69
+
70
+ res.clearCookie = (name: string, options: CookieOptions = {}) => {
71
+ const clearOptions = { ...options, expires: new Date(0), maxAge: 0 };
72
+ return res.cookie(name, "", clearOptions);
73
+ };
74
+ });
75
+ },
76
+ });
77
+
78
+ function parseCookies(cookieHeader: string): Record<string, string> {
79
+ const cookies: Record<string, string> = {};
80
+ if (!cookieHeader) return cookies;
81
+
82
+ cookieHeader.split(";").forEach((cookie) => {
83
+ const [name, value] = cookie.trim().split("=");
84
+ if (name && value) {
85
+ cookies[name] = decodeURIComponent(value);
86
+ }
87
+ });
88
+
89
+ return cookies;
90
+ }
@@ -0,0 +1,38 @@
1
+ // CORS Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ const logger = createFrameworkLogger("CorsMiddleware");
6
+
7
+ export const cors = (options: any = {}): MiddlewareInterface => ({
8
+ name: "cors",
9
+ version: "1.0.0",
10
+ metadata: {
11
+ name: "cors",
12
+ version: "1.0.0",
13
+ description: "Cross-Origin Resource Sharing middleware",
14
+ author: "MoroJS Team",
15
+ },
16
+
17
+ install: async (hooks: any, options: any = {}) => {
18
+ logger.debug("Installing CORS middleware", "Installation", { options });
19
+
20
+ hooks.before("request", async (context: HookContext) => {
21
+ const response = context.response as any;
22
+
23
+ response.setHeader("Access-Control-Allow-Origin", options.origin || "*");
24
+ response.setHeader(
25
+ "Access-Control-Allow-Methods",
26
+ options.methods || "GET,POST,PUT,DELETE,OPTIONS",
27
+ );
28
+ response.setHeader(
29
+ "Access-Control-Allow-Headers",
30
+ options.headers || "Content-Type,Authorization",
31
+ );
32
+
33
+ if (options.credentials) {
34
+ response.setHeader("Access-Control-Allow-Credentials", "true");
35
+ }
36
+ });
37
+ },
38
+ });
@@ -0,0 +1,107 @@
1
+ // Content Security Policy Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ const logger = createFrameworkLogger("CSPMiddleware");
6
+
7
+ export const csp = (
8
+ options: {
9
+ directives?: {
10
+ defaultSrc?: string[];
11
+ scriptSrc?: string[];
12
+ styleSrc?: string[];
13
+ imgSrc?: string[];
14
+ connectSrc?: string[];
15
+ fontSrc?: string[];
16
+ objectSrc?: string[];
17
+ mediaSrc?: string[];
18
+ frameSrc?: string[];
19
+ childSrc?: string[];
20
+ workerSrc?: string[];
21
+ formAction?: string[];
22
+ upgradeInsecureRequests?: boolean;
23
+ blockAllMixedContent?: boolean;
24
+ };
25
+ reportOnly?: boolean;
26
+ reportUri?: string;
27
+ nonce?: boolean;
28
+ } = {},
29
+ ): MiddlewareInterface => ({
30
+ name: "csp",
31
+ version: "1.0.0",
32
+ metadata: {
33
+ name: "csp",
34
+ version: "1.0.0",
35
+ description:
36
+ "Content Security Policy middleware with nonce support and violation reporting",
37
+ author: "MoroJS Team",
38
+ },
39
+
40
+ install: async (hooks: any, middlewareOptions: any = {}) => {
41
+ logger.debug("Installing CSP middleware", "Installation");
42
+
43
+ hooks.before("request", async (context: HookContext) => {
44
+ const req = context.request as any;
45
+ const res = context.response as any;
46
+
47
+ const directives = options.directives || {
48
+ defaultSrc: ["'self'"],
49
+ scriptSrc: ["'self'"],
50
+ styleSrc: ["'self'", "'unsafe-inline'"],
51
+ imgSrc: ["'self'", "data:", "https:"],
52
+ connectSrc: ["'self'"],
53
+ fontSrc: ["'self'"],
54
+ objectSrc: ["'none'"],
55
+ mediaSrc: ["'self'"],
56
+ frameSrc: ["'none'"],
57
+ };
58
+
59
+ // Generate nonce if requested
60
+ let nonce: string | undefined;
61
+ if (options.nonce) {
62
+ const crypto = require("crypto");
63
+ nonce = crypto.randomBytes(16).toString("base64");
64
+ req.cspNonce = nonce;
65
+ }
66
+
67
+ // Build CSP header value
68
+ const cspParts: string[] = [];
69
+
70
+ for (const [directive, sources] of Object.entries(directives)) {
71
+ if (directive === "upgradeInsecureRequests" && sources === true) {
72
+ cspParts.push("upgrade-insecure-requests");
73
+ } else if (directive === "blockAllMixedContent" && sources === true) {
74
+ cspParts.push("block-all-mixed-content");
75
+ } else if (Array.isArray(sources)) {
76
+ let sourceList = sources.join(" ");
77
+
78
+ // Add nonce to script-src and style-src if enabled
79
+ if (
80
+ nonce &&
81
+ (directive === "scriptSrc" || directive === "styleSrc")
82
+ ) {
83
+ sourceList += ` 'nonce-${nonce}'`;
84
+ }
85
+
86
+ // Convert camelCase to kebab-case
87
+ const kebabDirective = directive
88
+ .replace(/([A-Z])/g, "-$1")
89
+ .toLowerCase();
90
+ cspParts.push(`${kebabDirective} ${sourceList}`);
91
+ }
92
+ }
93
+
94
+ // Add report-uri if specified
95
+ if (options.reportUri) {
96
+ cspParts.push(`report-uri ${options.reportUri}`);
97
+ }
98
+
99
+ const cspValue = cspParts.join("; ");
100
+ const headerName = options.reportOnly
101
+ ? "Content-Security-Policy-Report-Only"
102
+ : "Content-Security-Policy";
103
+
104
+ res.setHeader(headerName, cspValue);
105
+ });
106
+ },
107
+ });
@@ -0,0 +1,87 @@
1
+ // CSRF Protection Middleware
2
+ import { MiddlewareInterface, HookContext } from "../../../types/hooks";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ const logger = createFrameworkLogger("CSRFMiddleware");
6
+
7
+ export const csrf = (
8
+ options: {
9
+ secret?: string;
10
+ tokenLength?: number;
11
+ cookieName?: string;
12
+ headerName?: string;
13
+ ignoreMethods?: string[];
14
+ sameSite?: boolean;
15
+ } = {},
16
+ ): MiddlewareInterface => ({
17
+ name: "csrf",
18
+ version: "1.0.0",
19
+ metadata: {
20
+ name: "csrf",
21
+ version: "1.0.0",
22
+ description:
23
+ "CSRF protection middleware with token generation and validation",
24
+ author: "MoroJS Team",
25
+ },
26
+
27
+ install: async (hooks: any, middlewareOptions: any = {}) => {
28
+ logger.debug("Installing CSRF middleware", "Installation");
29
+
30
+ const secret = options.secret || "moro-csrf-secret";
31
+ const tokenLength = options.tokenLength || 32;
32
+ const cookieName = options.cookieName || "_csrf";
33
+ const headerName = options.headerName || "x-csrf-token";
34
+ const ignoreMethods = options.ignoreMethods || ["GET", "HEAD", "OPTIONS"];
35
+
36
+ const generateToken = () => {
37
+ const crypto = require("crypto");
38
+ return crypto.randomBytes(tokenLength).toString("hex");
39
+ };
40
+
41
+ const verifyToken = (token: string, sessionToken: string) => {
42
+ return token && sessionToken && token === sessionToken;
43
+ };
44
+
45
+ hooks.before("request", async (context: HookContext) => {
46
+ const req = context.request as any;
47
+ const res = context.response as any;
48
+
49
+ // Add CSRF token generation method
50
+ req.csrfToken = () => {
51
+ if (!req._csrfToken) {
52
+ req._csrfToken = generateToken();
53
+ // Set token in cookie
54
+ res.cookie(cookieName, req._csrfToken, {
55
+ httpOnly: true,
56
+ sameSite: options.sameSite !== false ? "strict" : undefined,
57
+ secure:
58
+ req.headers["x-forwarded-proto"] === "https" ||
59
+ (req.socket as any).encrypted,
60
+ });
61
+ }
62
+ return req._csrfToken;
63
+ };
64
+
65
+ // Skip verification for safe methods
66
+ if (ignoreMethods.includes(req.method!)) {
67
+ return;
68
+ }
69
+
70
+ // Get token from header or body
71
+ const token =
72
+ req.headers[headerName] ||
73
+ (req.body && req.body._csrf) ||
74
+ (req.query && req.query._csrf);
75
+
76
+ // Get session token from cookie
77
+ const sessionToken = req.cookies?.[cookieName];
78
+
79
+ if (!verifyToken(token as string, sessionToken || "")) {
80
+ const error = new Error("Invalid CSRF token");
81
+ (error as any).status = 403;
82
+ (error as any).code = "CSRF_TOKEN_MISMATCH";
83
+ throw error;
84
+ }
85
+ });
86
+ },
87
+ });