@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,331 @@
1
+ // Database Redis Adapter
2
+ import { DatabaseAdapter, DatabaseTransaction } from "../../../types/database";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ interface RedisConfig {
6
+ host?: string;
7
+ port?: number;
8
+ password?: string;
9
+ db?: number;
10
+ keyPrefix?: string;
11
+ maxRetriesPerRequest?: number;
12
+ retryDelayOnFailover?: number;
13
+ lazyConnect?: boolean;
14
+ cluster?: {
15
+ enableReadyCheck?: boolean;
16
+ redisOptions?: any;
17
+ nodes: Array<{ host: string; port: number }>;
18
+ };
19
+ }
20
+
21
+ export class RedisAdapter implements DatabaseAdapter {
22
+ private client: any;
23
+ private logger = createFrameworkLogger("Redis");
24
+ private keyPrefix: string;
25
+
26
+ constructor(config: RedisConfig = {}) {
27
+ try {
28
+ const Redis = require("ioredis");
29
+ this.keyPrefix = config.keyPrefix || "moro:";
30
+
31
+ if (config.cluster) {
32
+ // Redis Cluster
33
+ this.client = new Redis.Cluster(config.cluster.nodes, {
34
+ enableReadyCheck: config.cluster.enableReadyCheck || false,
35
+ redisOptions: config.cluster.redisOptions || {},
36
+ });
37
+ } else {
38
+ // Single Redis instance
39
+ this.client = new Redis({
40
+ host: config.host || "localhost",
41
+ port: config.port || 6379,
42
+ password: config.password,
43
+ db: config.db || 0,
44
+ maxRetriesPerRequest: config.maxRetriesPerRequest || 3,
45
+ retryDelayOnFailover: config.retryDelayOnFailover || 100,
46
+ lazyConnect: config.lazyConnect || true,
47
+ });
48
+ }
49
+
50
+ this.client.on("error", (err: Error) => {
51
+ this.logger.error("Redis client error", "Redis", {
52
+ error: err.message,
53
+ });
54
+ });
55
+
56
+ this.client.on("connect", () => {
57
+ this.logger.info("Redis connected", "Connection");
58
+ });
59
+
60
+ this.client.on("disconnect", () => {
61
+ this.logger.warn("Redis disconnected", "Connection");
62
+ });
63
+
64
+ this.logger.info("Redis adapter initialized", "Redis");
65
+ } catch (error) {
66
+ throw new Error(
67
+ "ioredis package is required for Redis adapter. Install it with: npm install ioredis",
68
+ );
69
+ }
70
+ }
71
+
72
+ private prefixKey(key: string): string {
73
+ return `${this.keyPrefix}${key}`;
74
+ }
75
+
76
+ async connect(): Promise<void> {
77
+ try {
78
+ await this.client.ping();
79
+ this.logger.info("Redis connection established", "Connection");
80
+ } catch (error) {
81
+ this.logger.error("Redis connection failed", "Connection", {
82
+ error: error instanceof Error ? error.message : String(error),
83
+ });
84
+ throw error;
85
+ }
86
+ }
87
+
88
+ async disconnect(): Promise<void> {
89
+ await this.client.quit();
90
+ }
91
+
92
+ // For Redis, we adapt the SQL-like interface to key-value operations
93
+ async query<T = any>(pattern: string, _params?: any[]): Promise<T[]> {
94
+ try {
95
+ const keys = await this.client.keys(this.prefixKey(pattern));
96
+ if (keys.length === 0) return [];
97
+
98
+ const values = await this.client.mget(keys);
99
+ return values.map((value: string, index: number) => ({
100
+ key: keys[index].replace(this.keyPrefix, ""),
101
+ value: value ? JSON.parse(value) : null,
102
+ }));
103
+ } catch (error) {
104
+ this.logger.error("Redis query failed", "Query", {
105
+ pattern,
106
+ error: error instanceof Error ? error.message : String(error),
107
+ });
108
+ throw error;
109
+ }
110
+ }
111
+
112
+ async queryOne<T = any>(key: string, _params?: any[]): Promise<T | null> {
113
+ try {
114
+ const value = await this.client.get(this.prefixKey(key));
115
+ return value ? JSON.parse(value) : null;
116
+ } catch (error) {
117
+ this.logger.error("Redis queryOne failed", "Query", {
118
+ key,
119
+ error: error instanceof Error ? error.message : String(error),
120
+ });
121
+ throw error;
122
+ }
123
+ }
124
+
125
+ async insert<T = any>(key: string, data: Record<string, any>): Promise<T> {
126
+ try {
127
+ const value = JSON.stringify(data);
128
+ await this.client.set(this.prefixKey(key), value);
129
+ return data as T;
130
+ } catch (error) {
131
+ this.logger.error("Redis insert failed", "Insert", {
132
+ key,
133
+ error: error instanceof Error ? error.message : String(error),
134
+ });
135
+ throw error;
136
+ }
137
+ }
138
+
139
+ async update<T = any>(
140
+ key: string,
141
+ data: Record<string, any>,
142
+ _where?: Record<string, any>,
143
+ ): Promise<T> {
144
+ try {
145
+ // For Redis, we'll merge with existing data if it exists
146
+ const existing = await this.queryOne(key);
147
+ const merged = existing ? { ...existing, ...data } : data;
148
+ const value = JSON.stringify(merged);
149
+ await this.client.set(this.prefixKey(key), value);
150
+ return merged as T;
151
+ } catch (error) {
152
+ this.logger.error("Redis update failed", "Update", {
153
+ key,
154
+ error: error instanceof Error ? error.message : String(error),
155
+ });
156
+ throw error;
157
+ }
158
+ }
159
+
160
+ async delete(pattern: string, _where?: Record<string, any>): Promise<number> {
161
+ try {
162
+ const keys = await this.client.keys(this.prefixKey(pattern));
163
+ if (keys.length === 0) return 0;
164
+
165
+ const deletedCount = await this.client.del(...keys);
166
+ return deletedCount;
167
+ } catch (error) {
168
+ this.logger.error("Redis delete failed", "Delete", {
169
+ pattern,
170
+ error: error instanceof Error ? error.message : String(error),
171
+ });
172
+ throw error;
173
+ }
174
+ }
175
+
176
+ async transaction<T>(
177
+ callback: (tx: DatabaseTransaction) => Promise<T>,
178
+ ): Promise<T> {
179
+ const multi = this.client.multi();
180
+ const transaction = new RedisTransaction(multi, this.keyPrefix);
181
+
182
+ try {
183
+ const result = await callback(transaction);
184
+ await multi.exec();
185
+ return result;
186
+ } catch (error) {
187
+ // Redis doesn't have rollback, but we can discard the multi
188
+ multi.discard();
189
+ throw error;
190
+ }
191
+ }
192
+
193
+ // Redis-specific methods
194
+ async set(key: string, value: any, ttl?: number): Promise<void> {
195
+ const prefixedKey = this.prefixKey(key);
196
+ if (ttl) {
197
+ await this.client.setex(prefixedKey, ttl, JSON.stringify(value));
198
+ } else {
199
+ await this.client.set(prefixedKey, JSON.stringify(value));
200
+ }
201
+ }
202
+
203
+ async get(key: string): Promise<any> {
204
+ const value = await this.client.get(this.prefixKey(key));
205
+ return value ? JSON.parse(value) : null;
206
+ }
207
+
208
+ async exists(key: string): Promise<boolean> {
209
+ const result = await this.client.exists(this.prefixKey(key));
210
+ return result === 1;
211
+ }
212
+
213
+ async expire(key: string, ttl: number): Promise<boolean> {
214
+ const result = await this.client.expire(this.prefixKey(key), ttl);
215
+ return result === 1;
216
+ }
217
+
218
+ async incr(key: string): Promise<number> {
219
+ return await this.client.incr(this.prefixKey(key));
220
+ }
221
+
222
+ async decr(key: string): Promise<number> {
223
+ return await this.client.decr(this.prefixKey(key));
224
+ }
225
+
226
+ async hset(hash: string, field: string, value: any): Promise<void> {
227
+ await this.client.hset(this.prefixKey(hash), field, JSON.stringify(value));
228
+ }
229
+
230
+ async hget(hash: string, field: string): Promise<any> {
231
+ const value = await this.client.hget(this.prefixKey(hash), field);
232
+ return value ? JSON.parse(value) : null;
233
+ }
234
+
235
+ async hgetall(hash: string): Promise<Record<string, any>> {
236
+ const result = await this.client.hgetall(this.prefixKey(hash));
237
+ const parsed: Record<string, any> = {};
238
+ for (const [key, value] of Object.entries(result)) {
239
+ parsed[key] = JSON.parse(value as string);
240
+ }
241
+ return parsed;
242
+ }
243
+
244
+ async lpush(list: string, ...values: any[]): Promise<number> {
245
+ const serialized = values.map((v) => JSON.stringify(v));
246
+ return await this.client.lpush(this.prefixKey(list), ...serialized);
247
+ }
248
+
249
+ async rpop(list: string): Promise<any> {
250
+ const value = await this.client.rpop(this.prefixKey(list));
251
+ return value ? JSON.parse(value) : null;
252
+ }
253
+
254
+ async lrange(list: string, start: number, stop: number): Promise<any[]> {
255
+ const values = await this.client.lrange(this.prefixKey(list), start, stop);
256
+ return values.map((v: string) => JSON.parse(v));
257
+ }
258
+
259
+ async publish(channel: string, message: any): Promise<number> {
260
+ return await this.client.publish(channel, JSON.stringify(message));
261
+ }
262
+
263
+ async subscribe(
264
+ channel: string,
265
+ callback: (message: any) => void,
266
+ ): Promise<void> {
267
+ const subscriber = this.client.duplicate();
268
+ subscriber.subscribe(channel);
269
+ subscriber.on("message", (_channel: string, message: string) => {
270
+ callback(JSON.parse(message));
271
+ });
272
+ }
273
+
274
+ getClient() {
275
+ return this.client;
276
+ }
277
+ }
278
+
279
+ class RedisTransaction implements DatabaseTransaction {
280
+ constructor(
281
+ private multi: any,
282
+ private keyPrefix: string,
283
+ ) {}
284
+
285
+ private prefixKey(key: string): string {
286
+ return `${this.keyPrefix}${key}`;
287
+ }
288
+
289
+ async query<T = any>(pattern: string, _params?: any[]): Promise<T[]> {
290
+ // Note: Redis transactions can't perform read operations during MULTI
291
+ // This is a limitation of Redis transactions
292
+ throw new Error(
293
+ "Redis transactions cannot perform read operations. Use regular operations instead.",
294
+ );
295
+ }
296
+
297
+ async queryOne<T = any>(_key: string, _params?: any[]): Promise<T | null> {
298
+ throw new Error(
299
+ "Redis transactions cannot perform read operations. Use regular operations instead.",
300
+ );
301
+ }
302
+
303
+ async insert<T = any>(key: string, data: Record<string, any>): Promise<T> {
304
+ const value = JSON.stringify(data);
305
+ this.multi.set(this.prefixKey(key), value);
306
+ return data as T;
307
+ }
308
+
309
+ async update<T = any>(
310
+ key: string,
311
+ data: Record<string, any>,
312
+ _where?: Record<string, any>,
313
+ ): Promise<T> {
314
+ const value = JSON.stringify(data);
315
+ this.multi.set(this.prefixKey(key), value);
316
+ return data as T;
317
+ }
318
+
319
+ async delete(pattern: string, _where?: Record<string, any>): Promise<number> {
320
+ this.multi.del(this.prefixKey(pattern));
321
+ return 1; // We can't know the actual count in a transaction
322
+ }
323
+
324
+ async commit(): Promise<void> {
325
+ await this.multi.exec();
326
+ }
327
+
328
+ async rollback(): Promise<void> {
329
+ this.multi.discard();
330
+ }
331
+ }
@@ -0,0 +1,255 @@
1
+ // Database SQLite Adapter
2
+ import { DatabaseAdapter, DatabaseTransaction } from "../../../types/database";
3
+ import { createFrameworkLogger } from "../../logger";
4
+
5
+ interface SQLiteConfig {
6
+ filename?: string;
7
+ memory?: boolean;
8
+ readonly?: boolean;
9
+ fileMustExist?: boolean;
10
+ timeout?: number;
11
+ verbose?: boolean;
12
+ }
13
+
14
+ export class SQLiteAdapter implements DatabaseAdapter {
15
+ private db: any;
16
+ private logger = createFrameworkLogger("SQLite");
17
+
18
+ constructor(config: SQLiteConfig = {}) {
19
+ try {
20
+ const Database = require("better-sqlite3");
21
+ const filename = config.memory
22
+ ? ":memory:"
23
+ : config.filename || "moro_app.db";
24
+ this.db = new Database(filename, {
25
+ readonly: config.readonly || false,
26
+ fileMustExist: config.fileMustExist || false,
27
+ timeout: config.timeout || 5000,
28
+ verbose: config.verbose
29
+ ? this.logger.debug.bind(this.logger)
30
+ : undefined,
31
+ });
32
+
33
+ // Enable foreign keys
34
+ this.db.pragma("foreign_keys = ON");
35
+
36
+ this.logger.info("SQLite connection established", "Connection", {
37
+ filename,
38
+ });
39
+ } catch (error) {
40
+ throw new Error(
41
+ "better-sqlite3 package is required for SQLite adapter. Install it with: npm install better-sqlite3",
42
+ );
43
+ }
44
+ }
45
+
46
+ async connect(): Promise<void> {
47
+ // SQLite doesn't require explicit connection - it's handled in constructor
48
+ this.logger.info("SQLite adapter ready", "Connection");
49
+ }
50
+
51
+ async disconnect(): Promise<void> {
52
+ this.db.close();
53
+ }
54
+
55
+ async query<T = any>(sql: string, params?: any[]): Promise<T[]> {
56
+ try {
57
+ const stmt = this.db.prepare(sql);
58
+ const results = stmt.all(params || []);
59
+ return results as T[];
60
+ } catch (error) {
61
+ this.logger.error("SQLite query failed", "Query", {
62
+ sql,
63
+ error: error instanceof Error ? error.message : String(error),
64
+ });
65
+ throw error;
66
+ }
67
+ }
68
+
69
+ async queryOne<T = any>(sql: string, params?: any[]): Promise<T | null> {
70
+ try {
71
+ const stmt = this.db.prepare(sql);
72
+ const result = stmt.get(params || []);
73
+ return (result as T) || null;
74
+ } catch (error) {
75
+ this.logger.error("SQLite queryOne failed", "Query", {
76
+ sql,
77
+ error: error instanceof Error ? error.message : String(error),
78
+ });
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ async insert<T = any>(table: string, data: Record<string, any>): Promise<T> {
84
+ const keys = Object.keys(data);
85
+ const values = Object.values(data);
86
+ const placeholders = keys.map(() => "?").join(", ");
87
+
88
+ const sql = `INSERT INTO ${table} (${keys.join(", ")}) VALUES (${placeholders})`;
89
+
90
+ try {
91
+ const stmt = this.db.prepare(sql);
92
+ const info = stmt.run(values);
93
+
94
+ // Return the inserted record
95
+ const insertedRecord = await this.queryOne<T>(
96
+ `SELECT * FROM ${table} WHERE rowid = ?`,
97
+ [info.lastInsertRowid],
98
+ );
99
+
100
+ return insertedRecord!;
101
+ } catch (error) {
102
+ this.logger.error("SQLite insert failed", "Insert", {
103
+ table,
104
+ error: error instanceof Error ? error.message : String(error),
105
+ });
106
+ throw error;
107
+ }
108
+ }
109
+
110
+ async update<T = any>(
111
+ table: string,
112
+ data: Record<string, any>,
113
+ where: Record<string, any>,
114
+ ): Promise<T> {
115
+ const setClause = Object.keys(data)
116
+ .map((key) => `${key} = ?`)
117
+ .join(", ");
118
+ const whereClause = Object.keys(where)
119
+ .map((key) => `${key} = ?`)
120
+ .join(" AND ");
121
+
122
+ const sql = `UPDATE ${table} SET ${setClause} WHERE ${whereClause}`;
123
+ const params = [...Object.values(data), ...Object.values(where)];
124
+
125
+ try {
126
+ const stmt = this.db.prepare(sql);
127
+ stmt.run(params);
128
+
129
+ // Return the updated record
130
+ const updatedRecord = await this.queryOne<T>(
131
+ `SELECT * FROM ${table} WHERE ${whereClause}`,
132
+ Object.values(where),
133
+ );
134
+
135
+ return updatedRecord!;
136
+ } catch (error) {
137
+ this.logger.error("SQLite update failed", "Update", {
138
+ table,
139
+ error: error instanceof Error ? error.message : String(error),
140
+ });
141
+ throw error;
142
+ }
143
+ }
144
+
145
+ async delete(table: string, where: Record<string, any>): Promise<number> {
146
+ const whereClause = Object.keys(where)
147
+ .map((key) => `${key} = ?`)
148
+ .join(" AND ");
149
+ const sql = `DELETE FROM ${table} WHERE ${whereClause}`;
150
+
151
+ try {
152
+ const stmt = this.db.prepare(sql);
153
+ const info = stmt.run(Object.values(where));
154
+ return info.changes;
155
+ } catch (error) {
156
+ this.logger.error("SQLite delete failed", "Delete", {
157
+ table,
158
+ error: error instanceof Error ? error.message : String(error),
159
+ });
160
+ throw error;
161
+ }
162
+ }
163
+
164
+ async transaction<T>(
165
+ callback: (tx: DatabaseTransaction) => Promise<T>,
166
+ ): Promise<T> {
167
+ const transaction = this.db.transaction(async () => {
168
+ const tx = new SQLiteTransaction(this.db);
169
+ return await callback(tx);
170
+ });
171
+
172
+ return transaction();
173
+ }
174
+ }
175
+
176
+ class SQLiteTransaction implements DatabaseTransaction {
177
+ constructor(private db: any) {}
178
+
179
+ async query<T = any>(sql: string, params?: any[]): Promise<T[]> {
180
+ const stmt = this.db.prepare(sql);
181
+ const results = stmt.all(params || []);
182
+ return results as T[];
183
+ }
184
+
185
+ async queryOne<T = any>(sql: string, params?: any[]): Promise<T | null> {
186
+ const stmt = this.db.prepare(sql);
187
+ const result = stmt.get(params || []);
188
+ return (result as T) || null;
189
+ }
190
+
191
+ async insert<T = any>(table: string, data: Record<string, any>): Promise<T> {
192
+ const keys = Object.keys(data);
193
+ const values = Object.values(data);
194
+ const placeholders = keys.map(() => "?").join(", ");
195
+
196
+ const sql = `INSERT INTO ${table} (${keys.join(", ")}) VALUES (${placeholders})`;
197
+ const stmt = this.db.prepare(sql);
198
+ const info = stmt.run(values);
199
+
200
+ const insertedRecord = await this.queryOne<T>(
201
+ `SELECT * FROM ${table} WHERE rowid = ?`,
202
+ [info.lastInsertRowid],
203
+ );
204
+
205
+ return insertedRecord!;
206
+ }
207
+
208
+ async update<T = any>(
209
+ table: string,
210
+ data: Record<string, any>,
211
+ where: Record<string, any>,
212
+ ): Promise<T> {
213
+ const setClause = Object.keys(data)
214
+ .map((key) => `${key} = ?`)
215
+ .join(", ");
216
+ const whereClause = Object.keys(where)
217
+ .map((key) => `${key} = ?`)
218
+ .join(" AND ");
219
+
220
+ const sql = `UPDATE ${table} SET ${setClause} WHERE ${whereClause}`;
221
+ const params = [...Object.values(data), ...Object.values(where)];
222
+
223
+ const stmt = this.db.prepare(sql);
224
+ stmt.run(params);
225
+
226
+ const updatedRecord = await this.queryOne<T>(
227
+ `SELECT * FROM ${table} WHERE ${whereClause}`,
228
+ Object.values(where),
229
+ );
230
+
231
+ return updatedRecord!;
232
+ }
233
+
234
+ async delete(table: string, where: Record<string, any>): Promise<number> {
235
+ const whereClause = Object.keys(where)
236
+ .map((key) => `${key} = ?`)
237
+ .join(" AND ");
238
+ const sql = `DELETE FROM ${table} WHERE ${whereClause}`;
239
+
240
+ const stmt = this.db.prepare(sql);
241
+ const info = stmt.run(Object.values(where));
242
+ return info.changes;
243
+ }
244
+
245
+ async commit(): Promise<void> {
246
+ // SQLite transactions are handled automatically by better-sqlite3
247
+ // This is just for interface compatibility
248
+ }
249
+
250
+ async rollback(): Promise<void> {
251
+ // SQLite transactions are handled automatically by better-sqlite3
252
+ // This is just for interface compatibility
253
+ throw new Error("Transaction rollback");
254
+ }
255
+ }
@@ -0,0 +1,3 @@
1
+ // Database Module
2
+ export * from "./adapters";
3
+ export * from "../../types/database";