@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,434 @@
1
+ // Moro Logger - Beautiful, Fast, Feature-Rich
2
+ import { performance } from "perf_hooks";
3
+ import {
4
+ LogLevel,
5
+ LogEntry,
6
+ LoggerOptions,
7
+ Logger,
8
+ LogOutput,
9
+ LogFilter,
10
+ LogMetrics,
11
+ ColorScheme,
12
+ } from "../../types/logger";
13
+
14
+ export class MoroLogger implements Logger {
15
+ private level: LogLevel = "info";
16
+ private options: LoggerOptions;
17
+ private outputs: Map<string, LogOutput> = new Map();
18
+ private filters: Map<string, LogFilter> = new Map();
19
+ private history: LogEntry[] = [];
20
+ private timers: Map<string, number> = new Map();
21
+ private metrics: LogMetrics = {
22
+ totalLogs: 0,
23
+ logsByLevel: { debug: 0, info: 0, warn: 0, error: 0, fatal: 0 },
24
+ logsByContext: {},
25
+ averageLogRate: 0,
26
+ errorRate: 0,
27
+ memoryUsage: 0,
28
+ };
29
+ private startTime = Date.now();
30
+ private contextPrefix?: string;
31
+ private contextMetadata?: Record<string, any>;
32
+
33
+ private static readonly LEVELS: Record<LogLevel, number> = {
34
+ debug: 0,
35
+ info: 1,
36
+ warn: 2,
37
+ error: 3,
38
+ fatal: 4,
39
+ };
40
+
41
+ private static readonly COLORS: ColorScheme = {
42
+ debug: "\x1b[36m", // Cyan
43
+ info: "\x1b[32m", // Green
44
+ warn: "\x1b[33m", // Yellow
45
+ error: "\x1b[31m", // Red
46
+ fatal: "\x1b[35m", // Magenta
47
+ timestamp: "\x1b[90m", // Gray
48
+ context: "\x1b[34m", // Blue
49
+ metadata: "\x1b[37m", // White
50
+ performance: "\x1b[36m", // Cyan
51
+ };
52
+
53
+ private static readonly RESET = "\x1b[0m";
54
+ private static readonly BOLD = "\x1b[1m";
55
+
56
+ constructor(options: LoggerOptions = {}) {
57
+ this.options = {
58
+ level: "info",
59
+ enableColors: true,
60
+ enableTimestamp: true,
61
+ enableContext: true,
62
+ enableMetadata: true,
63
+ enablePerformance: true,
64
+ format: "pretty",
65
+ outputs: [],
66
+ filters: [],
67
+ maxEntries: 1000,
68
+ ...options,
69
+ };
70
+
71
+ this.level = this.options.level || "info";
72
+
73
+ // Add default console output
74
+ this.addOutput({
75
+ name: "console",
76
+ write: this.writeToConsole.bind(this),
77
+ format: this.options.format,
78
+ });
79
+
80
+ // Add custom outputs
81
+ this.options.outputs?.forEach((output) => this.addOutput(output));
82
+ this.options.filters?.forEach((filter) => this.addFilter(filter));
83
+ }
84
+
85
+ debug(
86
+ message: string,
87
+ context?: string,
88
+ metadata?: Record<string, any>,
89
+ ): void {
90
+ this.log("debug", message, context, metadata);
91
+ }
92
+
93
+ info(
94
+ message: string,
95
+ context?: string,
96
+ metadata?: Record<string, any>,
97
+ ): void {
98
+ this.log("info", message, context, metadata);
99
+ }
100
+
101
+ warn(
102
+ message: string,
103
+ context?: string,
104
+ metadata?: Record<string, any>,
105
+ ): void {
106
+ this.log("warn", message, context, metadata);
107
+ }
108
+
109
+ error(
110
+ message: string | Error,
111
+ context?: string,
112
+ metadata?: Record<string, any>,
113
+ ): void {
114
+ const msg = message instanceof Error ? message.message : message;
115
+ const stack = message instanceof Error ? message.stack : undefined;
116
+ this.log("error", msg, context, { ...metadata, stack });
117
+ }
118
+
119
+ fatal(
120
+ message: string | Error,
121
+ context?: string,
122
+ metadata?: Record<string, any>,
123
+ ): void {
124
+ const msg = message instanceof Error ? message.message : message;
125
+ const stack = message instanceof Error ? message.stack : undefined;
126
+ this.log("fatal", msg, context, { ...metadata, stack });
127
+ }
128
+
129
+ time(label: string): void {
130
+ this.timers.set(label, performance.now());
131
+ }
132
+
133
+ timeEnd(
134
+ label: string,
135
+ context?: string,
136
+ metadata?: Record<string, any>,
137
+ ): void {
138
+ const startTime = this.timers.get(label);
139
+ if (startTime !== undefined) {
140
+ const duration = performance.now() - startTime;
141
+ this.timers.delete(label);
142
+
143
+ this.log("info", `Timer: ${label}`, context, {
144
+ ...metadata,
145
+ performance: { duration: Math.round(duration * 100) / 100 },
146
+ });
147
+ }
148
+ }
149
+
150
+ child(context: string, metadata?: Record<string, any>): Logger {
151
+ const childLogger = new MoroLogger(this.options);
152
+ childLogger.contextPrefix = this.contextPrefix
153
+ ? `${this.contextPrefix}:${context}`
154
+ : context;
155
+ childLogger.contextMetadata = { ...this.contextMetadata, ...metadata };
156
+ childLogger.outputs = this.outputs;
157
+ childLogger.filters = this.filters;
158
+ return childLogger;
159
+ }
160
+
161
+ setLevel(level: LogLevel): void {
162
+ this.level = level;
163
+ }
164
+
165
+ addOutput(output: LogOutput): void {
166
+ this.outputs.set(output.name, output);
167
+ }
168
+
169
+ removeOutput(name: string): void {
170
+ this.outputs.delete(name);
171
+ }
172
+
173
+ addFilter(filter: LogFilter): void {
174
+ this.filters.set(filter.name, filter);
175
+ }
176
+
177
+ removeFilter(name: string): void {
178
+ this.filters.delete(name);
179
+ }
180
+
181
+ getHistory(count?: number): LogEntry[] {
182
+ const entries = [...this.history];
183
+ return count ? entries.slice(-count) : entries;
184
+ }
185
+
186
+ getMetrics(): LogMetrics {
187
+ const now = Date.now();
188
+ const uptime = (now - this.startTime) / 1000; // seconds
189
+ const avgRate = uptime > 0 ? this.metrics.totalLogs / uptime : 0;
190
+ const errorCount =
191
+ this.metrics.logsByLevel.error + this.metrics.logsByLevel.fatal;
192
+ const errorRate =
193
+ this.metrics.totalLogs > 0
194
+ ? (errorCount / this.metrics.totalLogs) * 100
195
+ : 0;
196
+
197
+ return {
198
+ ...this.metrics,
199
+ averageLogRate: Math.round(avgRate * 100) / 100,
200
+ errorRate: Math.round(errorRate * 100) / 100,
201
+ memoryUsage: process.memoryUsage().heapUsed / 1024 / 1024, // MB
202
+ };
203
+ }
204
+
205
+ clear(): void {
206
+ this.history = [];
207
+ this.metrics = {
208
+ totalLogs: 0,
209
+ logsByLevel: { debug: 0, info: 0, warn: 0, error: 0, fatal: 0 },
210
+ logsByContext: {},
211
+ averageLogRate: 0,
212
+ errorRate: 0,
213
+ memoryUsage: 0,
214
+ };
215
+ }
216
+
217
+ private log(
218
+ level: LogLevel,
219
+ message: string,
220
+ context?: string,
221
+ metadata?: Record<string, any>,
222
+ ): void {
223
+ // Check level threshold
224
+ if (MoroLogger.LEVELS[level] < MoroLogger.LEVELS[this.level]) {
225
+ return;
226
+ }
227
+
228
+ // Create log entry
229
+ const entry: LogEntry = {
230
+ timestamp: new Date(),
231
+ level,
232
+ message,
233
+ context: this.contextPrefix
234
+ ? context
235
+ ? `${this.contextPrefix}:${context}`
236
+ : this.contextPrefix
237
+ : context,
238
+ metadata: { ...this.contextMetadata, ...metadata },
239
+ performance: this.options.enablePerformance
240
+ ? {
241
+ memory: process.memoryUsage().heapUsed / 1024 / 1024,
242
+ }
243
+ : undefined,
244
+ };
245
+
246
+ // Apply filters
247
+ for (const filter of this.filters.values()) {
248
+ if (!filter.filter(entry)) {
249
+ return;
250
+ }
251
+ }
252
+
253
+ // Update metrics
254
+ this.updateMetrics(entry);
255
+
256
+ // Store in history
257
+ this.history.push(entry);
258
+ if (this.history.length > (this.options.maxEntries || 1000)) {
259
+ this.history.shift();
260
+ }
261
+
262
+ // Write to outputs
263
+ for (const output of this.outputs.values()) {
264
+ if (
265
+ !output.level ||
266
+ MoroLogger.LEVELS[level] >= MoroLogger.LEVELS[output.level]
267
+ ) {
268
+ try {
269
+ output.write(entry);
270
+ } catch (error) {
271
+ console.error("Logger output error:", error);
272
+ }
273
+ }
274
+ }
275
+ }
276
+
277
+ private updateMetrics(entry: LogEntry): void {
278
+ this.metrics.totalLogs++;
279
+ this.metrics.logsByLevel[entry.level]++;
280
+
281
+ if (entry.context) {
282
+ this.metrics.logsByContext[entry.context] =
283
+ (this.metrics.logsByContext[entry.context] || 0) + 1;
284
+ }
285
+ }
286
+
287
+ private writeToConsole(entry: LogEntry): void {
288
+ const format = this.options.format || "pretty";
289
+
290
+ if (format === "json") {
291
+ console.log(JSON.stringify(entry));
292
+ return;
293
+ }
294
+
295
+ if (format === "compact") {
296
+ const level = entry.level.toUpperCase().padEnd(5);
297
+ const context = entry.context ? `[${entry.context}] ` : "";
298
+ console.log(`${level} ${context}${entry.message}`);
299
+ return;
300
+ }
301
+
302
+ // Pretty format (default)
303
+ this.writePrettyLog(entry);
304
+ }
305
+
306
+ private writePrettyLog(entry: LogEntry): void {
307
+ const colors = this.options.enableColors !== false;
308
+ const parts: string[] = [];
309
+
310
+ // Timestamp
311
+ if (this.options.enableTimestamp !== false) {
312
+ const timestamp = entry.timestamp
313
+ .toISOString()
314
+ .replace("T", " ")
315
+ .slice(0, 19);
316
+ parts.push(
317
+ colors
318
+ ? `${MoroLogger.COLORS.timestamp}${timestamp}${MoroLogger.RESET}`
319
+ : timestamp,
320
+ );
321
+ }
322
+
323
+ // Level with color (remove icons)
324
+ const levelColor = colors ? MoroLogger.COLORS[entry.level] : "";
325
+ const levelReset = colors ? MoroLogger.RESET : "";
326
+ const levelText = entry.level.toUpperCase();
327
+ parts.push(`${levelColor}${MoroLogger.BOLD}${levelText}${levelReset}`);
328
+
329
+ // Context
330
+ if (entry.context && this.options.enableContext !== false) {
331
+ const contextColor = colors ? MoroLogger.COLORS.context : "";
332
+ parts.push(`${contextColor}[${entry.context}]${levelReset}`);
333
+ }
334
+
335
+ // Message
336
+ parts.push(entry.message);
337
+
338
+ // Performance info
339
+ if (entry.performance && this.options.enablePerformance !== false) {
340
+ const perfColor = colors ? MoroLogger.COLORS.performance : "";
341
+ const perfParts: string[] = [];
342
+
343
+ if (entry.performance.duration !== undefined) {
344
+ perfParts.push(`${entry.performance.duration}ms`);
345
+ }
346
+ if (entry.performance.memory !== undefined) {
347
+ perfParts.push(`${Math.round(entry.performance.memory)}MB`);
348
+ }
349
+
350
+ if (perfParts.length > 0) {
351
+ parts.push(`${perfColor}(${perfParts.join(", ")})${levelReset}`);
352
+ }
353
+ }
354
+
355
+ // Metadata
356
+ if (
357
+ entry.metadata &&
358
+ Object.keys(entry.metadata).length > 0 &&
359
+ this.options.enableMetadata !== false
360
+ ) {
361
+ const metaColor = colors ? MoroLogger.COLORS.metadata : "";
362
+ const cleanMetadata = { ...entry.metadata };
363
+ delete cleanMetadata.stack; // Handle stack separately
364
+
365
+ if (Object.keys(cleanMetadata).length > 0) {
366
+ parts.push(`${metaColor}${JSON.stringify(cleanMetadata)}${levelReset}`);
367
+ }
368
+ }
369
+
370
+ // Output main log line
371
+ console.log(parts.join(" "));
372
+
373
+ // Stack trace for errors
374
+ if (
375
+ entry.metadata?.stack &&
376
+ (entry.level === "error" || entry.level === "fatal")
377
+ ) {
378
+ const stackColor = colors ? MoroLogger.COLORS.error : "";
379
+ console.log(`${stackColor}${entry.metadata.stack}${levelReset}`);
380
+ }
381
+ }
382
+ }
383
+
384
+ // Global logger instance
385
+ const initialLogLevel =
386
+ process.env.LOG_LEVEL ||
387
+ process.env.MORO_LOG_LEVEL ||
388
+ (process.env.NODE_ENV === "production" ? "warn" : "debug");
389
+
390
+ export const logger = new MoroLogger({
391
+ level: initialLogLevel as LogLevel,
392
+ enableColors: !process.env.NO_COLOR,
393
+ format: (process.env.LOG_FORMAT as any) || "pretty",
394
+ });
395
+
396
+ /**
397
+ * Configure the global logger with new settings
398
+ * This allows runtime configuration of the logger
399
+ */
400
+ export function configureGlobalLogger(options: Partial<LoggerOptions>): void {
401
+ if (options.level) {
402
+ logger.setLevel(options.level);
403
+ }
404
+ // Additional configuration options can be added here as needed
405
+ // For now, focusing on level which is the most critical
406
+ }
407
+
408
+ /**
409
+ * Apply logging configuration from the config system and/or createApp options
410
+ */
411
+ export function applyLoggingConfiguration(
412
+ configLogging?: any,
413
+ appOptions?: Partial<LoggerOptions> | boolean,
414
+ ): void {
415
+ // First apply config system settings (from environment variables)
416
+ if (configLogging?.level) {
417
+ configureGlobalLogger({ level: configLogging.level });
418
+ }
419
+
420
+ // Then apply createApp options (these take precedence)
421
+ if (appOptions !== undefined) {
422
+ if (appOptions === false) {
423
+ // Disable logging by setting to fatal level
424
+ configureGlobalLogger({ level: "fatal" });
425
+ } else if (typeof appOptions === "object") {
426
+ configureGlobalLogger(appOptions);
427
+ }
428
+ }
429
+ }
430
+
431
+ // Framework-specific logger
432
+ export const createFrameworkLogger = (context: string) => {
433
+ return logger.child("Moro", { framework: "moro", context });
434
+ };
@@ -0,0 +1,136 @@
1
+ // Advanced Logger Outputs
2
+ import { writeFile, appendFile, mkdir } from "fs/promises";
3
+ import { join, dirname } from "path";
4
+ import { LogEntry, LogOutput } from "../../types/logger";
5
+
6
+ // File output for persistent logging
7
+ export class FileOutput implements LogOutput {
8
+ name = "file";
9
+
10
+ constructor(
11
+ private filePath: string,
12
+ private options: {
13
+ format?: "json" | "pretty";
14
+ maxSize?: number; // MB
15
+ rotate?: boolean;
16
+ } = {},
17
+ ) {}
18
+
19
+ async write(entry: LogEntry): Promise<void> {
20
+ try {
21
+ // Ensure directory exists
22
+ await mkdir(dirname(this.filePath), { recursive: true });
23
+
24
+ const format = this.options.format || "json";
25
+ const line =
26
+ format === "json"
27
+ ? JSON.stringify(entry) + "\n"
28
+ : this.formatPretty(entry) + "\n";
29
+
30
+ await appendFile(this.filePath, line, "utf8");
31
+
32
+ // TODO: Implement log rotation if needed
33
+ } catch (error) {
34
+ console.error("File logger error:", error);
35
+ }
36
+ }
37
+
38
+ private formatPretty(entry: LogEntry): string {
39
+ const timestamp = entry.timestamp.toISOString();
40
+ const level = entry.level.toUpperCase().padEnd(5);
41
+ const context = entry.context ? `[${entry.context}] ` : "";
42
+ const metadata =
43
+ entry.metadata && Object.keys(entry.metadata).length > 0
44
+ ? ` ${JSON.stringify(entry.metadata)}`
45
+ : "";
46
+
47
+ return `${timestamp} ${level} ${context}${entry.message}${metadata}`;
48
+ }
49
+ }
50
+
51
+ // HTTP webhook output for external logging services
52
+ export class WebhookOutput implements LogOutput {
53
+ name = "webhook";
54
+
55
+ constructor(
56
+ private url: string,
57
+ private options: {
58
+ headers?: Record<string, string>;
59
+ batch?: boolean;
60
+ batchSize?: number;
61
+ timeout?: number;
62
+ } = {},
63
+ ) {}
64
+
65
+ async write(entry: LogEntry): Promise<void> {
66
+ try {
67
+ const response = await fetch(this.url, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ ...this.options.headers,
72
+ },
73
+ body: JSON.stringify(entry),
74
+ signal: AbortSignal.timeout(this.options.timeout || 5000),
75
+ });
76
+
77
+ if (!response.ok) {
78
+ throw new Error(`Webhook failed: ${response.status}`);
79
+ }
80
+ } catch (error) {
81
+ console.error("Webhook logger error:", error);
82
+ }
83
+ }
84
+ }
85
+
86
+ // Memory buffer output for testing and debugging
87
+ export class MemoryOutput implements LogOutput {
88
+ name = "memory";
89
+ private buffer: LogEntry[] = [];
90
+
91
+ constructor(private maxSize: number = 1000) {}
92
+
93
+ write(entry: LogEntry): void {
94
+ this.buffer.push(entry);
95
+ if (this.buffer.length > this.maxSize) {
96
+ this.buffer.shift();
97
+ }
98
+ }
99
+
100
+ getEntries(): LogEntry[] {
101
+ return [...this.buffer];
102
+ }
103
+
104
+ clear(): void {
105
+ this.buffer = [];
106
+ }
107
+ }
108
+
109
+ // Stream output for custom processing
110
+ export class StreamOutput implements LogOutput {
111
+ name = "stream";
112
+ format?: "pretty" | "json" | "compact";
113
+
114
+ constructor(
115
+ private stream: NodeJS.WritableStream,
116
+ format: "json" | "pretty" = "json",
117
+ ) {
118
+ this.format = format;
119
+ }
120
+
121
+ write(entry: LogEntry): void {
122
+ const data =
123
+ this.format === "json"
124
+ ? JSON.stringify(entry) + "\n"
125
+ : this.formatPretty(entry) + "\n";
126
+
127
+ this.stream.write(data);
128
+ }
129
+
130
+ private formatPretty(entry: LogEntry): string {
131
+ const timestamp = entry.timestamp.toISOString();
132
+ const level = entry.level.toUpperCase().padEnd(5);
133
+ const context = entry.context ? `[${entry.context}] ` : "";
134
+ return `${timestamp} ${level} ${context}${entry.message}`;
135
+ }
136
+ }
@@ -0,0 +1,106 @@
1
+ // File System Cache Adapter
2
+ import { CacheAdapter } from "../../../../../types/cache";
3
+ import { createFrameworkLogger } from "../../../../logger";
4
+
5
+ const logger = createFrameworkLogger("FileCacheAdapter");
6
+
7
+ export class FileCacheAdapter implements CacheAdapter {
8
+ private cacheDir: string;
9
+
10
+ constructor(options: { cacheDir?: string } = {}) {
11
+ this.cacheDir = options.cacheDir || "./cache";
12
+ this.ensureCacheDir();
13
+ }
14
+
15
+ private async ensureCacheDir(): Promise<void> {
16
+ const fs = await import("fs/promises");
17
+ try {
18
+ await fs.mkdir(this.cacheDir, { recursive: true });
19
+ } catch (error) {
20
+ logger.error("Failed to create cache directory", "FileCache", { error });
21
+ }
22
+ }
23
+
24
+ private getFilePath(key: string): string {
25
+ const crypto = require("crypto");
26
+ const hash = crypto.createHash("md5").update(key).digest("hex");
27
+ return `${this.cacheDir}/${hash}.json`;
28
+ }
29
+
30
+ async get(key: string): Promise<any> {
31
+ try {
32
+ const fs = await import("fs/promises");
33
+ const filePath = this.getFilePath(key);
34
+ const data = await fs.readFile(filePath, "utf-8");
35
+ const parsed = JSON.parse(data);
36
+
37
+ if (Date.now() > parsed.expires) {
38
+ await this.del(key);
39
+ return null;
40
+ }
41
+
42
+ return parsed.value;
43
+ } catch (error) {
44
+ return null;
45
+ }
46
+ }
47
+
48
+ async set(key: string, value: any, ttl: number = 3600): Promise<void> {
49
+ try {
50
+ const fs = await import("fs/promises");
51
+ const filePath = this.getFilePath(key);
52
+ const expires = Date.now() + ttl * 1000;
53
+ const data = JSON.stringify({ value, expires });
54
+
55
+ await fs.writeFile(filePath, data);
56
+ logger.debug(`Cached item to file: ${key} (TTL: ${ttl}s)`, "FileCache");
57
+ } catch (error) {
58
+ logger.error("File cache set error", "FileCache", { key, error });
59
+ }
60
+ }
61
+
62
+ async del(key: string): Promise<void> {
63
+ try {
64
+ const fs = await import("fs/promises");
65
+ const filePath = this.getFilePath(key);
66
+ await fs.unlink(filePath);
67
+ logger.debug(`Deleted file cache item: ${key}`, "FileCache");
68
+ } catch (error) {
69
+ // File might not exist, which is okay
70
+ }
71
+ }
72
+
73
+ async clear(): Promise<void> {
74
+ try {
75
+ const fs = await import("fs/promises");
76
+ const files = await fs.readdir(this.cacheDir);
77
+
78
+ await Promise.all(
79
+ files.map((file) => fs.unlink(`${this.cacheDir}/${file}`)),
80
+ );
81
+
82
+ logger.debug("Cleared all file cache items", "FileCache");
83
+ } catch (error) {
84
+ logger.error("File cache clear error", "FileCache", { error });
85
+ }
86
+ }
87
+
88
+ async exists(key: string): Promise<boolean> {
89
+ const value = await this.get(key);
90
+ return value !== null;
91
+ }
92
+
93
+ async ttl(key: string): Promise<number> {
94
+ try {
95
+ const fs = await import("fs/promises");
96
+ const filePath = this.getFilePath(key);
97
+ const data = await fs.readFile(filePath, "utf-8");
98
+ const parsed = JSON.parse(data);
99
+
100
+ const remaining = Math.floor((parsed.expires - Date.now()) / 1000);
101
+ return remaining > 0 ? remaining : -1;
102
+ } catch (error) {
103
+ return -1;
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,26 @@
1
+ // Cache Adapters
2
+ export { MemoryCacheAdapter } from "./memory";
3
+ export { RedisCacheAdapter } from "./redis";
4
+ export { FileCacheAdapter } from "./file";
5
+
6
+ import { MemoryCacheAdapter } from "./memory";
7
+ import { RedisCacheAdapter } from "./redis";
8
+ import { FileCacheAdapter } from "./file";
9
+ import { CacheAdapter } from "../../../../../types/cache";
10
+
11
+ // Adapter factory function for auto-loading
12
+ export function createCacheAdapter(
13
+ type: string,
14
+ options: any = {},
15
+ ): CacheAdapter {
16
+ switch (type.toLowerCase()) {
17
+ case "memory":
18
+ return new MemoryCacheAdapter();
19
+ case "redis":
20
+ return new RedisCacheAdapter(options);
21
+ case "file":
22
+ return new FileCacheAdapter(options);
23
+ default:
24
+ throw new Error(`Unknown cache adapter type: ${type}`);
25
+ }
26
+ }