nestlens 0.1.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 (359) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/dist/__tests__/api/api.controller.spec.d.ts +2 -0
  4. package/dist/__tests__/api/api.controller.spec.d.ts.map +1 -0
  5. package/dist/__tests__/api/api.controller.spec.js +982 -0
  6. package/dist/__tests__/api/api.controller.spec.js.map +1 -0
  7. package/dist/__tests__/api/api.guard.spec.d.ts +2 -0
  8. package/dist/__tests__/api/api.guard.spec.d.ts.map +1 -0
  9. package/dist/__tests__/api/api.guard.spec.js +572 -0
  10. package/dist/__tests__/api/api.guard.spec.js.map +1 -0
  11. package/dist/__tests__/api/dashboard.controller.spec.d.ts +2 -0
  12. package/dist/__tests__/api/dashboard.controller.spec.d.ts.map +1 -0
  13. package/dist/__tests__/api/dashboard.controller.spec.js +474 -0
  14. package/dist/__tests__/api/dashboard.controller.spec.js.map +1 -0
  15. package/dist/__tests__/api/tag.controller.spec.d.ts +2 -0
  16. package/dist/__tests__/api/tag.controller.spec.d.ts.map +1 -0
  17. package/dist/__tests__/api/tag.controller.spec.js +280 -0
  18. package/dist/__tests__/api/tag.controller.spec.js.map +1 -0
  19. package/dist/__tests__/collector.service.spec.d.ts +2 -0
  20. package/dist/__tests__/collector.service.spec.d.ts.map +1 -0
  21. package/dist/__tests__/collector.service.spec.js +240 -0
  22. package/dist/__tests__/collector.service.spec.js.map +1 -0
  23. package/dist/__tests__/core/collector.service.spec.d.ts +2 -0
  24. package/dist/__tests__/core/collector.service.spec.d.ts.map +1 -0
  25. package/dist/__tests__/core/collector.service.spec.js +526 -0
  26. package/dist/__tests__/core/collector.service.spec.js.map +1 -0
  27. package/dist/__tests__/core/family-hash.service.spec.d.ts +2 -0
  28. package/dist/__tests__/core/family-hash.service.spec.d.ts.map +1 -0
  29. package/dist/__tests__/core/family-hash.service.spec.js +1117 -0
  30. package/dist/__tests__/core/family-hash.service.spec.js.map +1 -0
  31. package/dist/__tests__/core/pruning.service.spec.d.ts +2 -0
  32. package/dist/__tests__/core/pruning.service.spec.d.ts.map +1 -0
  33. package/dist/__tests__/core/pruning.service.spec.js +224 -0
  34. package/dist/__tests__/core/pruning.service.spec.js.map +1 -0
  35. package/dist/__tests__/core/storage/sqlite.storage.spec.d.ts +2 -0
  36. package/dist/__tests__/core/storage/sqlite.storage.spec.d.ts.map +1 -0
  37. package/dist/__tests__/core/storage/sqlite.storage.spec.js +853 -0
  38. package/dist/__tests__/core/storage/sqlite.storage.spec.js.map +1 -0
  39. package/dist/__tests__/core/tag.service.spec.d.ts +2 -0
  40. package/dist/__tests__/core/tag.service.spec.d.ts.map +1 -0
  41. package/dist/__tests__/core/tag.service.spec.js +994 -0
  42. package/dist/__tests__/core/tag.service.spec.js.map +1 -0
  43. package/dist/__tests__/family-hash.service.spec.d.ts +2 -0
  44. package/dist/__tests__/family-hash.service.spec.d.ts.map +1 -0
  45. package/dist/__tests__/family-hash.service.spec.js +325 -0
  46. package/dist/__tests__/family-hash.service.spec.js.map +1 -0
  47. package/dist/__tests__/filters/api-filters.spec.d.ts +2 -0
  48. package/dist/__tests__/filters/api-filters.spec.d.ts.map +1 -0
  49. package/dist/__tests__/filters/api-filters.spec.js +172 -0
  50. package/dist/__tests__/filters/api-filters.spec.js.map +1 -0
  51. package/dist/__tests__/filters/entry-factories.d.ts +20 -0
  52. package/dist/__tests__/filters/entry-factories.d.ts.map +1 -0
  53. package/dist/__tests__/filters/entry-factories.js +288 -0
  54. package/dist/__tests__/filters/entry-factories.js.map +1 -0
  55. package/dist/__tests__/filters/filter-contract.spec.d.ts +2 -0
  56. package/dist/__tests__/filters/filter-contract.spec.d.ts.map +1 -0
  57. package/dist/__tests__/filters/filter-contract.spec.js +230 -0
  58. package/dist/__tests__/filters/filter-contract.spec.js.map +1 -0
  59. package/dist/__tests__/filters/filter-test-data.d.ts +26 -0
  60. package/dist/__tests__/filters/filter-test-data.d.ts.map +1 -0
  61. package/dist/__tests__/filters/filter-test-data.js +374 -0
  62. package/dist/__tests__/filters/filter-test-data.js.map +1 -0
  63. package/dist/__tests__/filters/storage-filters.spec.d.ts +2 -0
  64. package/dist/__tests__/filters/storage-filters.spec.d.ts.map +1 -0
  65. package/dist/__tests__/filters/storage-filters.spec.js +699 -0
  66. package/dist/__tests__/filters/storage-filters.spec.js.map +1 -0
  67. package/dist/__tests__/filters/test-utils.d.ts +23 -0
  68. package/dist/__tests__/filters/test-utils.d.ts.map +1 -0
  69. package/dist/__tests__/filters/test-utils.js +54 -0
  70. package/dist/__tests__/filters/test-utils.js.map +1 -0
  71. package/dist/__tests__/nestlens.module.spec.d.ts +2 -0
  72. package/dist/__tests__/nestlens.module.spec.d.ts.map +1 -0
  73. package/dist/__tests__/nestlens.module.spec.js +620 -0
  74. package/dist/__tests__/nestlens.module.spec.js.map +1 -0
  75. package/dist/__tests__/pruning.service.spec.d.ts +2 -0
  76. package/dist/__tests__/pruning.service.spec.d.ts.map +1 -0
  77. package/dist/__tests__/pruning.service.spec.js +142 -0
  78. package/dist/__tests__/pruning.service.spec.js.map +1 -0
  79. package/dist/__tests__/setup.d.ts +7 -0
  80. package/dist/__tests__/setup.d.ts.map +1 -0
  81. package/dist/__tests__/setup.js +24 -0
  82. package/dist/__tests__/setup.js.map +1 -0
  83. package/dist/__tests__/tag.service.spec.d.ts +2 -0
  84. package/dist/__tests__/tag.service.spec.d.ts.map +1 -0
  85. package/dist/__tests__/tag.service.spec.js +482 -0
  86. package/dist/__tests__/tag.service.spec.js.map +1 -0
  87. package/dist/__tests__/watchers/batch.watcher.spec.d.ts +2 -0
  88. package/dist/__tests__/watchers/batch.watcher.spec.d.ts.map +1 -0
  89. package/dist/__tests__/watchers/batch.watcher.spec.js +515 -0
  90. package/dist/__tests__/watchers/batch.watcher.spec.js.map +1 -0
  91. package/dist/__tests__/watchers/cache.watcher.spec.d.ts +2 -0
  92. package/dist/__tests__/watchers/cache.watcher.spec.d.ts.map +1 -0
  93. package/dist/__tests__/watchers/cache.watcher.spec.js +395 -0
  94. package/dist/__tests__/watchers/cache.watcher.spec.js.map +1 -0
  95. package/dist/__tests__/watchers/command.watcher.spec.d.ts +2 -0
  96. package/dist/__tests__/watchers/command.watcher.spec.d.ts.map +1 -0
  97. package/dist/__tests__/watchers/command.watcher.spec.js +598 -0
  98. package/dist/__tests__/watchers/command.watcher.spec.js.map +1 -0
  99. package/dist/__tests__/watchers/dump.watcher.spec.d.ts +2 -0
  100. package/dist/__tests__/watchers/dump.watcher.spec.d.ts.map +1 -0
  101. package/dist/__tests__/watchers/dump.watcher.spec.js +724 -0
  102. package/dist/__tests__/watchers/dump.watcher.spec.js.map +1 -0
  103. package/dist/__tests__/watchers/event.watcher.spec.d.ts +2 -0
  104. package/dist/__tests__/watchers/event.watcher.spec.d.ts.map +1 -0
  105. package/dist/__tests__/watchers/event.watcher.spec.js +316 -0
  106. package/dist/__tests__/watchers/event.watcher.spec.js.map +1 -0
  107. package/dist/__tests__/watchers/exception.watcher.spec.d.ts +2 -0
  108. package/dist/__tests__/watchers/exception.watcher.spec.d.ts.map +1 -0
  109. package/dist/__tests__/watchers/exception.watcher.spec.js +495 -0
  110. package/dist/__tests__/watchers/exception.watcher.spec.js.map +1 -0
  111. package/dist/__tests__/watchers/gate.watcher.spec.d.ts +2 -0
  112. package/dist/__tests__/watchers/gate.watcher.spec.d.ts.map +1 -0
  113. package/dist/__tests__/watchers/gate.watcher.spec.js +683 -0
  114. package/dist/__tests__/watchers/gate.watcher.spec.js.map +1 -0
  115. package/dist/__tests__/watchers/http-client.watcher.spec.d.ts +2 -0
  116. package/dist/__tests__/watchers/http-client.watcher.spec.d.ts.map +1 -0
  117. package/dist/__tests__/watchers/http-client.watcher.spec.js +888 -0
  118. package/dist/__tests__/watchers/http-client.watcher.spec.js.map +1 -0
  119. package/dist/__tests__/watchers/job.watcher.spec.d.ts +2 -0
  120. package/dist/__tests__/watchers/job.watcher.spec.d.ts.map +1 -0
  121. package/dist/__tests__/watchers/job.watcher.spec.js +513 -0
  122. package/dist/__tests__/watchers/job.watcher.spec.js.map +1 -0
  123. package/dist/__tests__/watchers/log.watcher.spec.d.ts +2 -0
  124. package/dist/__tests__/watchers/log.watcher.spec.d.ts.map +1 -0
  125. package/dist/__tests__/watchers/log.watcher.spec.js +428 -0
  126. package/dist/__tests__/watchers/log.watcher.spec.js.map +1 -0
  127. package/dist/__tests__/watchers/mail.watcher.spec.d.ts +2 -0
  128. package/dist/__tests__/watchers/mail.watcher.spec.d.ts.map +1 -0
  129. package/dist/__tests__/watchers/mail.watcher.spec.js +425 -0
  130. package/dist/__tests__/watchers/mail.watcher.spec.js.map +1 -0
  131. package/dist/__tests__/watchers/model.watcher.spec.d.ts +2 -0
  132. package/dist/__tests__/watchers/model.watcher.spec.d.ts.map +1 -0
  133. package/dist/__tests__/watchers/model.watcher.spec.js +675 -0
  134. package/dist/__tests__/watchers/model.watcher.spec.js.map +1 -0
  135. package/dist/__tests__/watchers/notification.watcher.spec.d.ts +2 -0
  136. package/dist/__tests__/watchers/notification.watcher.spec.d.ts.map +1 -0
  137. package/dist/__tests__/watchers/notification.watcher.spec.js +595 -0
  138. package/dist/__tests__/watchers/notification.watcher.spec.js.map +1 -0
  139. package/dist/__tests__/watchers/query/types.spec.d.ts +2 -0
  140. package/dist/__tests__/watchers/query/types.spec.d.ts.map +1 -0
  141. package/dist/__tests__/watchers/query/types.spec.js +292 -0
  142. package/dist/__tests__/watchers/query/types.spec.js.map +1 -0
  143. package/dist/__tests__/watchers/query.watcher.spec.d.ts +2 -0
  144. package/dist/__tests__/watchers/query.watcher.spec.d.ts.map +1 -0
  145. package/dist/__tests__/watchers/query.watcher.spec.js +597 -0
  146. package/dist/__tests__/watchers/query.watcher.spec.js.map +1 -0
  147. package/dist/__tests__/watchers/redis.watcher.spec.d.ts +2 -0
  148. package/dist/__tests__/watchers/redis.watcher.spec.d.ts.map +1 -0
  149. package/dist/__tests__/watchers/redis.watcher.spec.js +634 -0
  150. package/dist/__tests__/watchers/redis.watcher.spec.js.map +1 -0
  151. package/dist/__tests__/watchers/request.watcher.spec.d.ts +2 -0
  152. package/dist/__tests__/watchers/request.watcher.spec.d.ts.map +1 -0
  153. package/dist/__tests__/watchers/request.watcher.spec.js +1017 -0
  154. package/dist/__tests__/watchers/request.watcher.spec.js.map +1 -0
  155. package/dist/__tests__/watchers/schedule.watcher.spec.d.ts +2 -0
  156. package/dist/__tests__/watchers/schedule.watcher.spec.d.ts.map +1 -0
  157. package/dist/__tests__/watchers/schedule.watcher.spec.js +338 -0
  158. package/dist/__tests__/watchers/schedule.watcher.spec.js.map +1 -0
  159. package/dist/__tests__/watchers/view.watcher.spec.d.ts +2 -0
  160. package/dist/__tests__/watchers/view.watcher.spec.d.ts.map +1 -0
  161. package/dist/__tests__/watchers/view.watcher.spec.js +564 -0
  162. package/dist/__tests__/watchers/view.watcher.spec.js.map +1 -0
  163. package/dist/api/api.controller.d.ts +193 -0
  164. package/dist/api/api.controller.d.ts.map +1 -0
  165. package/dist/api/api.controller.js +562 -0
  166. package/dist/api/api.controller.js.map +1 -0
  167. package/dist/api/api.guard.d.ts +77 -0
  168. package/dist/api/api.guard.d.ts.map +1 -0
  169. package/dist/api/api.guard.js +294 -0
  170. package/dist/api/api.guard.js.map +1 -0
  171. package/dist/api/dashboard.controller.d.ts +49 -0
  172. package/dist/api/dashboard.controller.d.ts.map +1 -0
  173. package/dist/api/dashboard.controller.js +472 -0
  174. package/dist/api/dashboard.controller.js.map +1 -0
  175. package/dist/api/index.d.ts +5 -0
  176. package/dist/api/index.d.ts.map +1 -0
  177. package/dist/api/index.js +21 -0
  178. package/dist/api/index.js.map +1 -0
  179. package/dist/api/tag.controller.d.ts +65 -0
  180. package/dist/api/tag.controller.d.ts.map +1 -0
  181. package/dist/api/tag.controller.js +149 -0
  182. package/dist/api/tag.controller.js.map +1 -0
  183. package/dist/core/collector.service.d.ts +80 -0
  184. package/dist/core/collector.service.d.ts.map +1 -0
  185. package/dist/core/collector.service.js +255 -0
  186. package/dist/core/collector.service.js.map +1 -0
  187. package/dist/core/family-hash.service.d.ts +64 -0
  188. package/dist/core/family-hash.service.d.ts.map +1 -0
  189. package/dist/core/family-hash.service.js +281 -0
  190. package/dist/core/family-hash.service.js.map +1 -0
  191. package/dist/core/index.d.ts +4 -0
  192. package/dist/core/index.d.ts.map +1 -0
  193. package/dist/core/index.js +20 -0
  194. package/dist/core/index.js.map +1 -0
  195. package/dist/core/pruning.service.d.ts +16 -0
  196. package/dist/core/pruning.service.d.ts.map +1 -0
  197. package/dist/core/pruning.service.js +71 -0
  198. package/dist/core/pruning.service.js.map +1 -0
  199. package/dist/core/storage/index.d.ts +3 -0
  200. package/dist/core/storage/index.d.ts.map +1 -0
  201. package/dist/core/storage/index.js +19 -0
  202. package/dist/core/storage/index.js.map +1 -0
  203. package/dist/core/storage/sqlite.storage.d.ts +60 -0
  204. package/dist/core/storage/sqlite.storage.d.ts.map +1 -0
  205. package/dist/core/storage/sqlite.storage.js +929 -0
  206. package/dist/core/storage/sqlite.storage.js.map +1 -0
  207. package/dist/core/storage/storage.interface.d.ts +122 -0
  208. package/dist/core/storage/storage.interface.d.ts.map +1 -0
  209. package/dist/core/storage/storage.interface.js +5 -0
  210. package/dist/core/storage/storage.interface.js.map +1 -0
  211. package/dist/core/tag.service.d.ts +71 -0
  212. package/dist/core/tag.service.d.ts.map +1 -0
  213. package/dist/core/tag.service.js +568 -0
  214. package/dist/core/tag.service.js.map +1 -0
  215. package/dist/dashboard/public/assets/BatchesPage-DFT4fKlJ.js +1 -0
  216. package/dist/dashboard/public/assets/CachePage-CRy1Tjb8.js +1 -0
  217. package/dist/dashboard/public/assets/ClickableBadge-CV5J3THx.js +1 -0
  218. package/dist/dashboard/public/assets/CommandsPage-DdRnTm-W.js +1 -0
  219. package/dist/dashboard/public/assets/DashboardPage-CjaRZXYy.js +26 -0
  220. package/dist/dashboard/public/assets/DataTable-B6o9H8lh.js +88 -0
  221. package/dist/dashboard/public/assets/DumpsPage-DO8y1RTg.js +1 -0
  222. package/dist/dashboard/public/assets/EntryDetailPage-By-YcAGL.js +125 -0
  223. package/dist/dashboard/public/assets/EventsPage-u-r4AiT4.js +1 -0
  224. package/dist/dashboard/public/assets/ExceptionsPage-DXUcARr1.js +6 -0
  225. package/dist/dashboard/public/assets/GatesPage-DpeP7CDZ.js +1 -0
  226. package/dist/dashboard/public/assets/HttpClientPage-BJ4-5E6t.js +1 -0
  227. package/dist/dashboard/public/assets/JobsPage-Dv3KaX2x.js +1 -0
  228. package/dist/dashboard/public/assets/LogsPage-D0Q3yDb1.js +1 -0
  229. package/dist/dashboard/public/assets/MailPage-Bf8C6WF6.js +1 -0
  230. package/dist/dashboard/public/assets/ModelsPage-BMHncI5y.js +1 -0
  231. package/dist/dashboard/public/assets/NotificationsPage-D5-I-Oxb.js +1 -0
  232. package/dist/dashboard/public/assets/QueriesPage-oNp0i6Gt.js +1 -0
  233. package/dist/dashboard/public/assets/RedisPage-_GeS2OD8.js +1 -0
  234. package/dist/dashboard/public/assets/RequestsPage-BCwqu9US.js +1 -0
  235. package/dist/dashboard/public/assets/SchedulePage-CR0P-oX6.js +1 -0
  236. package/dist/dashboard/public/assets/ViewsPage-Dsy5ECRA.js +1 -0
  237. package/dist/dashboard/public/assets/calendar-DfK3x-6B.js +6 -0
  238. package/dist/dashboard/public/assets/circle-check-big-DcsYW8y8.js +6 -0
  239. package/dist/dashboard/public/assets/format-BFldcnCk.js +1 -0
  240. package/dist/dashboard/public/assets/index-DmeA1maE.css +1 -0
  241. package/dist/dashboard/public/assets/index-rkbGYdU7.js +351 -0
  242. package/dist/dashboard/public/assets/types-Cldoe2db.js +1 -0
  243. package/dist/dashboard/public/assets/vendor-B2nVRih0.js +43 -0
  244. package/dist/dashboard/public/assets/zap-DqtRi0JM.js +6 -0
  245. package/dist/dashboard/public/index.html +15 -0
  246. package/dist/dashboard/public/nestlens-icon.svg +9 -0
  247. package/dist/index.d.ts +22 -0
  248. package/dist/index.d.ts.map +1 -0
  249. package/dist/index.js +69 -0
  250. package/dist/index.js.map +1 -0
  251. package/dist/nestlens.config.d.ts +216 -0
  252. package/dist/nestlens.config.d.ts.map +1 -0
  253. package/dist/nestlens.config.js +57 -0
  254. package/dist/nestlens.config.js.map +1 -0
  255. package/dist/nestlens.module.d.ts +10 -0
  256. package/dist/nestlens.module.d.ts.map +1 -0
  257. package/dist/nestlens.module.js +211 -0
  258. package/dist/nestlens.module.js.map +1 -0
  259. package/dist/types/entry.types.d.ts +368 -0
  260. package/dist/types/entry.types.d.ts.map +1 -0
  261. package/dist/types/entry.types.js +3 -0
  262. package/dist/types/entry.types.js.map +1 -0
  263. package/dist/types/index.d.ts +4 -0
  264. package/dist/types/index.d.ts.map +1 -0
  265. package/dist/types/index.js +20 -0
  266. package/dist/types/index.js.map +1 -0
  267. package/dist/types/request.types.d.ts +9 -0
  268. package/dist/types/request.types.d.ts.map +1 -0
  269. package/dist/types/request.types.js +3 -0
  270. package/dist/types/request.types.js.map +1 -0
  271. package/dist/types/tag.types.d.ts +32 -0
  272. package/dist/types/tag.types.d.ts.map +1 -0
  273. package/dist/types/tag.types.js +3 -0
  274. package/dist/types/tag.types.js.map +1 -0
  275. package/dist/watchers/batch.watcher.d.ts +48 -0
  276. package/dist/watchers/batch.watcher.d.ts.map +1 -0
  277. package/dist/watchers/batch.watcher.js +185 -0
  278. package/dist/watchers/batch.watcher.js.map +1 -0
  279. package/dist/watchers/cache.watcher.d.ts +19 -0
  280. package/dist/watchers/cache.watcher.d.ts.map +1 -0
  281. package/dist/watchers/cache.watcher.js +158 -0
  282. package/dist/watchers/cache.watcher.js.map +1 -0
  283. package/dist/watchers/command.watcher.d.ts +32 -0
  284. package/dist/watchers/command.watcher.d.ts.map +1 -0
  285. package/dist/watchers/command.watcher.js +174 -0
  286. package/dist/watchers/command.watcher.js.map +1 -0
  287. package/dist/watchers/dump.watcher.d.ts +52 -0
  288. package/dist/watchers/dump.watcher.d.ts.map +1 -0
  289. package/dist/watchers/dump.watcher.js +234 -0
  290. package/dist/watchers/dump.watcher.js.map +1 -0
  291. package/dist/watchers/event.watcher.d.ts +20 -0
  292. package/dist/watchers/event.watcher.d.ts.map +1 -0
  293. package/dist/watchers/event.watcher.js +123 -0
  294. package/dist/watchers/event.watcher.js.map +1 -0
  295. package/dist/watchers/exception.watcher.d.ts +15 -0
  296. package/dist/watchers/exception.watcher.d.ts.map +1 -0
  297. package/dist/watchers/exception.watcher.js +117 -0
  298. package/dist/watchers/exception.watcher.js.map +1 -0
  299. package/dist/watchers/gate.watcher.d.ts +40 -0
  300. package/dist/watchers/gate.watcher.d.ts.map +1 -0
  301. package/dist/watchers/gate.watcher.js +200 -0
  302. package/dist/watchers/gate.watcher.js.map +1 -0
  303. package/dist/watchers/http-client.watcher.d.ts +34 -0
  304. package/dist/watchers/http-client.watcher.d.ts.map +1 -0
  305. package/dist/watchers/http-client.watcher.js +259 -0
  306. package/dist/watchers/http-client.watcher.js.map +1 -0
  307. package/dist/watchers/index.d.ts +19 -0
  308. package/dist/watchers/index.d.ts.map +1 -0
  309. package/dist/watchers/index.js +35 -0
  310. package/dist/watchers/index.js.map +1 -0
  311. package/dist/watchers/job.watcher.d.ts +27 -0
  312. package/dist/watchers/job.watcher.d.ts.map +1 -0
  313. package/dist/watchers/job.watcher.js +190 -0
  314. package/dist/watchers/job.watcher.js.map +1 -0
  315. package/dist/watchers/log.watcher.d.ts +26 -0
  316. package/dist/watchers/log.watcher.d.ts.map +1 -0
  317. package/dist/watchers/log.watcher.js +122 -0
  318. package/dist/watchers/log.watcher.js.map +1 -0
  319. package/dist/watchers/mail.watcher.d.ts +26 -0
  320. package/dist/watchers/mail.watcher.d.ts.map +1 -0
  321. package/dist/watchers/mail.watcher.js +154 -0
  322. package/dist/watchers/mail.watcher.js.map +1 -0
  323. package/dist/watchers/model.watcher.d.ts +54 -0
  324. package/dist/watchers/model.watcher.d.ts.map +1 -0
  325. package/dist/watchers/model.watcher.js +343 -0
  326. package/dist/watchers/model.watcher.js.map +1 -0
  327. package/dist/watchers/notification.watcher.d.ts +48 -0
  328. package/dist/watchers/notification.watcher.d.ts.map +1 -0
  329. package/dist/watchers/notification.watcher.js +215 -0
  330. package/dist/watchers/notification.watcher.js.map +1 -0
  331. package/dist/watchers/query/index.d.ts +3 -0
  332. package/dist/watchers/query/index.d.ts.map +1 -0
  333. package/dist/watchers/query/index.js +19 -0
  334. package/dist/watchers/query/index.js.map +1 -0
  335. package/dist/watchers/query/query.watcher.d.ts +27 -0
  336. package/dist/watchers/query/query.watcher.d.ts.map +1 -0
  337. package/dist/watchers/query/query.watcher.js +167 -0
  338. package/dist/watchers/query/query.watcher.js.map +1 -0
  339. package/dist/watchers/query/types.d.ts +60 -0
  340. package/dist/watchers/query/types.d.ts.map +1 -0
  341. package/dist/watchers/query/types.js +55 -0
  342. package/dist/watchers/query/types.js.map +1 -0
  343. package/dist/watchers/redis.watcher.d.ts +43 -0
  344. package/dist/watchers/redis.watcher.d.ts.map +1 -0
  345. package/dist/watchers/redis.watcher.js +225 -0
  346. package/dist/watchers/redis.watcher.js.map +1 -0
  347. package/dist/watchers/request.watcher.d.ts +21 -0
  348. package/dist/watchers/request.watcher.d.ts.map +1 -0
  349. package/dist/watchers/request.watcher.js +287 -0
  350. package/dist/watchers/request.watcher.js.map +1 -0
  351. package/dist/watchers/schedule.watcher.d.ts +25 -0
  352. package/dist/watchers/schedule.watcher.d.ts.map +1 -0
  353. package/dist/watchers/schedule.watcher.js +168 -0
  354. package/dist/watchers/schedule.watcher.js.map +1 -0
  355. package/dist/watchers/view.watcher.d.ts +51 -0
  356. package/dist/watchers/view.watcher.d.ts.map +1 -0
  357. package/dist/watchers/view.watcher.js +219 -0
  358. package/dist/watchers/view.watcher.js.map +1 -0
  359. package/package.json +86 -0
@@ -0,0 +1,982 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const testing_1 = require("@nestjs/testing");
4
+ const api_controller_1 = require("../../api/api.controller");
5
+ const nestlens_config_1 = require("../../nestlens.config");
6
+ const storage_interface_1 = require("../../core/storage/storage.interface");
7
+ const pruning_service_1 = require("../../core/pruning.service");
8
+ const collector_service_1 = require("../../core/collector.service");
9
+ describe('NestLensApiController', () => {
10
+ let controller;
11
+ let mockStorage;
12
+ let mockConfig;
13
+ let mockPruningService;
14
+ let mockCollectorService;
15
+ const createMockEntry = (overrides = {}) => ({
16
+ id: 1,
17
+ type: 'request',
18
+ requestId: 'req-123',
19
+ timestamp: new Date().toISOString(),
20
+ payload: {},
21
+ ...overrides,
22
+ });
23
+ beforeEach(async () => {
24
+ // Arrange
25
+ mockStorage = {
26
+ find: jest.fn(),
27
+ findById: jest.fn(),
28
+ findWithCursor: jest.fn(),
29
+ findByFamilyHash: jest.fn(),
30
+ count: jest.fn(),
31
+ getStats: jest.fn(),
32
+ getStorageStats: jest.fn(),
33
+ getLatestSequence: jest.fn(),
34
+ hasEntriesAfter: jest.fn(),
35
+ getGroupedByFamilyHash: jest.fn(),
36
+ prune: jest.fn(),
37
+ clear: jest.fn(),
38
+ resolveEntry: jest.fn(),
39
+ unresolveEntry: jest.fn(),
40
+ save: jest.fn(),
41
+ };
42
+ mockConfig = {
43
+ enabled: true,
44
+ pruning: {
45
+ enabled: true,
46
+ maxAge: 24,
47
+ interval: 60,
48
+ },
49
+ };
50
+ mockPruningService = {
51
+ prune: jest.fn(),
52
+ };
53
+ mockCollectorService = {
54
+ pause: jest.fn(),
55
+ resume: jest.fn(),
56
+ getRecordingStatus: jest.fn(),
57
+ };
58
+ const module = await testing_1.Test.createTestingModule({
59
+ controllers: [api_controller_1.NestLensApiController],
60
+ providers: [
61
+ { provide: storage_interface_1.STORAGE, useValue: mockStorage },
62
+ { provide: nestlens_config_1.NESTLENS_CONFIG, useValue: mockConfig },
63
+ { provide: pruning_service_1.PruningService, useValue: mockPruningService },
64
+ { provide: collector_service_1.CollectorService, useValue: mockCollectorService },
65
+ ],
66
+ }).compile();
67
+ controller = module.get(api_controller_1.NestLensApiController);
68
+ });
69
+ afterEach(() => {
70
+ jest.clearAllMocks();
71
+ });
72
+ describe('constructor', () => {
73
+ it('should be defined', () => {
74
+ // Assert
75
+ expect(controller).toBeDefined();
76
+ });
77
+ it('should calculate next prune run based on interval', () => {
78
+ // Assert
79
+ expect(controller['nextPruneRun']).toBeDefined();
80
+ expect(controller['nextPruneRun'].getTime()).toBeGreaterThan(Date.now());
81
+ });
82
+ });
83
+ describe('getEntries', () => {
84
+ it('should return entries with default pagination', async () => {
85
+ // Arrange
86
+ const entries = [createMockEntry()];
87
+ mockStorage.find.mockResolvedValue(entries);
88
+ mockStorage.count.mockResolvedValue(1);
89
+ // Act
90
+ const result = await controller.getEntries();
91
+ // Assert
92
+ expect(mockStorage.find).toHaveBeenCalledWith({
93
+ type: undefined,
94
+ requestId: undefined,
95
+ limit: 50,
96
+ offset: 0,
97
+ from: undefined,
98
+ to: undefined,
99
+ });
100
+ expect(result.data).toEqual(entries);
101
+ expect(result.meta).toEqual({ total: 1, limit: 50, offset: 0 });
102
+ });
103
+ it('should filter by entry type', async () => {
104
+ // Arrange
105
+ const entries = [createMockEntry({ type: 'query' })];
106
+ mockStorage.find.mockResolvedValue(entries);
107
+ mockStorage.count.mockResolvedValue(1);
108
+ // Act
109
+ const result = await controller.getEntries('query');
110
+ // Assert
111
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ type: 'query' }));
112
+ expect(result.data).toEqual(entries);
113
+ });
114
+ it('should filter by requestId', async () => {
115
+ // Arrange
116
+ const requestId = 'req-456';
117
+ mockStorage.find.mockResolvedValue([]);
118
+ mockStorage.count.mockResolvedValue(0);
119
+ // Act
120
+ await controller.getEntries(undefined, requestId);
121
+ // Assert
122
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ requestId }));
123
+ });
124
+ it('should handle custom pagination', async () => {
125
+ // Arrange
126
+ mockStorage.find.mockResolvedValue([]);
127
+ mockStorage.count.mockResolvedValue(100);
128
+ // Act
129
+ const result = await controller.getEntries(undefined, undefined, '25', '50');
130
+ // Assert
131
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ limit: 25, offset: 50 }));
132
+ expect(result.meta).toEqual({ total: 100, limit: 25, offset: 50 });
133
+ });
134
+ it('should filter by date range', async () => {
135
+ // Arrange
136
+ const from = '2024-01-01T00:00:00Z';
137
+ const to = '2024-01-31T23:59:59Z';
138
+ mockStorage.find.mockResolvedValue([]);
139
+ mockStorage.count.mockResolvedValue(0);
140
+ // Act
141
+ await controller.getEntries(undefined, undefined, undefined, undefined, from, to);
142
+ // Assert
143
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({
144
+ from: new Date(from),
145
+ to: new Date(to),
146
+ }));
147
+ });
148
+ });
149
+ describe('getEntriesWithCursor', () => {
150
+ it('should return cursor-paginated entries', async () => {
151
+ // Arrange
152
+ const response = {
153
+ data: [createMockEntry()],
154
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 1 },
155
+ };
156
+ mockStorage.findWithCursor.mockResolvedValue(response);
157
+ // Act
158
+ const result = await controller.getEntriesWithCursor();
159
+ // Assert
160
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith(undefined, {
161
+ limit: 50,
162
+ beforeSequence: undefined,
163
+ afterSequence: undefined,
164
+ filters: undefined,
165
+ });
166
+ expect(result).toEqual(response);
167
+ });
168
+ it('should handle cursor navigation (before)', async () => {
169
+ // Arrange
170
+ mockStorage.findWithCursor.mockResolvedValue({
171
+ data: [],
172
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
173
+ });
174
+ // Act
175
+ await controller.getEntriesWithCursor(undefined, '25', '100');
176
+ // Assert
177
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith(undefined, {
178
+ limit: 25,
179
+ beforeSequence: 100,
180
+ afterSequence: undefined,
181
+ filters: undefined,
182
+ });
183
+ });
184
+ it('should handle cursor navigation (after)', async () => {
185
+ // Arrange
186
+ mockStorage.findWithCursor.mockResolvedValue({
187
+ data: [],
188
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
189
+ });
190
+ // Act
191
+ await controller.getEntriesWithCursor(undefined, '25', undefined, '50');
192
+ // Assert
193
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith(undefined, {
194
+ limit: 25,
195
+ beforeSequence: undefined,
196
+ afterSequence: 50,
197
+ filters: undefined,
198
+ });
199
+ });
200
+ it('should parse levels filter', async () => {
201
+ // Arrange
202
+ mockStorage.findWithCursor.mockResolvedValue({
203
+ data: [],
204
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
205
+ });
206
+ // Act
207
+ await controller.getEntriesWithCursor('log', undefined, undefined, undefined, 'error,warn,info' // levels
208
+ );
209
+ // Assert
210
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('log', {
211
+ limit: 50,
212
+ beforeSequence: undefined,
213
+ afterSequence: undefined,
214
+ filters: expect.objectContaining({
215
+ levels: ['error', 'warn', 'info'],
216
+ }),
217
+ });
218
+ });
219
+ it('should parse boolean slow filter', async () => {
220
+ // Arrange
221
+ mockStorage.findWithCursor.mockResolvedValue({
222
+ data: [],
223
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
224
+ });
225
+ // Act
226
+ await controller.getEntriesWithCursor('query', undefined, undefined, undefined, undefined, undefined, undefined, undefined, 'true' // slow
227
+ );
228
+ // Assert
229
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('query', {
230
+ limit: 50,
231
+ beforeSequence: undefined,
232
+ afterSequence: undefined,
233
+ filters: expect.objectContaining({
234
+ slow: true,
235
+ }),
236
+ });
237
+ });
238
+ it('should parse boolean resolved filter', async () => {
239
+ // Arrange
240
+ mockStorage.findWithCursor.mockResolvedValue({
241
+ data: [],
242
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
243
+ });
244
+ // Act
245
+ await controller.getEntriesWithCursor('exception', undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 'false' // resolved
246
+ );
247
+ // Assert
248
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('exception', {
249
+ limit: 50,
250
+ beforeSequence: undefined,
251
+ afterSequence: undefined,
252
+ filters: expect.objectContaining({
253
+ resolved: false,
254
+ }),
255
+ });
256
+ });
257
+ it('should parse statuses filter with ERR', async () => {
258
+ // Arrange
259
+ mockStorage.findWithCursor.mockResolvedValue({
260
+ data: [],
261
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
262
+ });
263
+ // Act
264
+ await controller.getEntriesWithCursor('request', undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, '200,404,ERR' // statuses
265
+ );
266
+ // Assert
267
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('request', {
268
+ limit: 50,
269
+ beforeSequence: undefined,
270
+ afterSequence: undefined,
271
+ filters: expect.objectContaining({
272
+ statuses: [200, 404, 'ERR'],
273
+ }),
274
+ });
275
+ });
276
+ it('should parse methods filter', async () => {
277
+ // Arrange
278
+ mockStorage.findWithCursor.mockResolvedValue({
279
+ data: [],
280
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
281
+ });
282
+ // Act
283
+ await controller.getEntriesWithCursor('request', undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 'GET,POST' // methods
284
+ );
285
+ // Assert
286
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('request', {
287
+ limit: 50,
288
+ beforeSequence: undefined,
289
+ afterSequence: undefined,
290
+ filters: expect.objectContaining({
291
+ methods: ['GET', 'POST'],
292
+ }),
293
+ });
294
+ });
295
+ it('should handle empty filter values', async () => {
296
+ // Arrange
297
+ mockStorage.findWithCursor.mockResolvedValue({
298
+ data: [],
299
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
300
+ });
301
+ // Act
302
+ await controller.getEntriesWithCursor('request', undefined, undefined, undefined, '' // empty levels
303
+ );
304
+ // Assert
305
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('request', {
306
+ limit: 50,
307
+ beforeSequence: undefined,
308
+ afterSequence: undefined,
309
+ filters: undefined,
310
+ });
311
+ });
312
+ it('should parse search filter', async () => {
313
+ // Arrange
314
+ mockStorage.findWithCursor.mockResolvedValue({
315
+ data: [],
316
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
317
+ });
318
+ // Act - call with all parameters explicitly to reach search at position 41
319
+ await controller.getEntriesWithCursor(undefined, // type (0)
320
+ undefined, // limit (1)
321
+ undefined, // beforeSequence (2)
322
+ undefined, // afterSequence (3)
323
+ undefined, // levels (4)
324
+ undefined, // contexts (5)
325
+ undefined, // queryTypes (6)
326
+ undefined, // sources (7)
327
+ undefined, // slow (8)
328
+ undefined, // names (9)
329
+ undefined, // methods (10)
330
+ undefined, // paths (11)
331
+ undefined, // resolved (12)
332
+ undefined, // statuses (13)
333
+ undefined, // hostnames (14)
334
+ undefined, // controllers (15)
335
+ undefined, // ips (16)
336
+ undefined, // scheduleStatuses (17)
337
+ undefined, // jobStatuses (18)
338
+ undefined, // queues (19)
339
+ undefined, // cacheOperations (20)
340
+ undefined, // mailStatuses (21)
341
+ undefined, // redisStatuses (22)
342
+ undefined, // redisCommands (23)
343
+ undefined, // modelActions (24)
344
+ undefined, // entities (25)
345
+ undefined, // modelSources (26)
346
+ undefined, // notificationTypes (27)
347
+ undefined, // notificationStatuses (28)
348
+ undefined, // viewFormats (29)
349
+ undefined, // viewStatuses (30)
350
+ undefined, // commandStatuses (31)
351
+ undefined, // commandNames (32)
352
+ undefined, // gateNames (33)
353
+ undefined, // gateResults (34)
354
+ undefined, // batchStatuses (35)
355
+ undefined, // batchOperations (36)
356
+ undefined, // dumpStatuses (37)
357
+ undefined, // dumpOperations (38)
358
+ undefined, // dumpFormats (39)
359
+ undefined, // tags (40)
360
+ 'test search' // search (41)
361
+ );
362
+ // Assert
363
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith(undefined, {
364
+ limit: 50,
365
+ beforeSequence: undefined,
366
+ afterSequence: undefined,
367
+ filters: expect.objectContaining({
368
+ search: 'test search',
369
+ }),
370
+ });
371
+ });
372
+ it('should parse tags filter', async () => {
373
+ // Arrange
374
+ mockStorage.findWithCursor.mockResolvedValue({
375
+ data: [],
376
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
377
+ });
378
+ // Act - call with all parameters explicitly to reach tags at position 40
379
+ await controller.getEntriesWithCursor(undefined, // type (0)
380
+ undefined, // limit (1)
381
+ undefined, // beforeSequence (2)
382
+ undefined, // afterSequence (3)
383
+ undefined, // levels (4)
384
+ undefined, // contexts (5)
385
+ undefined, // queryTypes (6)
386
+ undefined, // sources (7)
387
+ undefined, // slow (8)
388
+ undefined, // names (9)
389
+ undefined, // methods (10)
390
+ undefined, // paths (11)
391
+ undefined, // resolved (12)
392
+ undefined, // statuses (13)
393
+ undefined, // hostnames (14)
394
+ undefined, // controllers (15)
395
+ undefined, // ips (16)
396
+ undefined, // scheduleStatuses (17)
397
+ undefined, // jobStatuses (18)
398
+ undefined, // queues (19)
399
+ undefined, // cacheOperations (20)
400
+ undefined, // mailStatuses (21)
401
+ undefined, // redisStatuses (22)
402
+ undefined, // redisCommands (23)
403
+ undefined, // modelActions (24)
404
+ undefined, // entities (25)
405
+ undefined, // modelSources (26)
406
+ undefined, // notificationTypes (27)
407
+ undefined, // notificationStatuses (28)
408
+ undefined, // viewFormats (29)
409
+ undefined, // viewStatuses (30)
410
+ undefined, // commandStatuses (31)
411
+ undefined, // commandNames (32)
412
+ undefined, // gateNames (33)
413
+ undefined, // gateResults (34)
414
+ undefined, // batchStatuses (35)
415
+ undefined, // batchOperations (36)
416
+ undefined, // dumpStatuses (37)
417
+ undefined, // dumpOperations (38)
418
+ undefined, // dumpFormats (39)
419
+ 'important,debug' // tags (40)
420
+ );
421
+ // Assert
422
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith(undefined, {
423
+ limit: 50,
424
+ beforeSequence: undefined,
425
+ afterSequence: undefined,
426
+ filters: expect.objectContaining({
427
+ tags: ['important', 'debug'],
428
+ }),
429
+ });
430
+ });
431
+ });
432
+ describe('getLatestSequence', () => {
433
+ it('should return latest sequence', async () => {
434
+ // Arrange
435
+ mockStorage.getLatestSequence.mockResolvedValue(100);
436
+ // Act
437
+ const result = await controller.getLatestSequence();
438
+ // Assert
439
+ expect(mockStorage.getLatestSequence).toHaveBeenCalledWith(undefined);
440
+ expect(result).toEqual({ data: 100 });
441
+ });
442
+ it('should filter by type', async () => {
443
+ // Arrange
444
+ mockStorage.getLatestSequence.mockResolvedValue(50);
445
+ // Act
446
+ const result = await controller.getLatestSequence('query');
447
+ // Assert
448
+ expect(mockStorage.getLatestSequence).toHaveBeenCalledWith('query');
449
+ expect(result).toEqual({ data: 50 });
450
+ });
451
+ });
452
+ describe('checkNewEntries', () => {
453
+ it('should return count and hasNew true when new entries exist', async () => {
454
+ // Arrange
455
+ mockStorage.hasEntriesAfter.mockResolvedValue(5);
456
+ // Act
457
+ const result = await controller.checkNewEntries('100');
458
+ // Assert
459
+ expect(mockStorage.hasEntriesAfter).toHaveBeenCalledWith(100, undefined);
460
+ expect(result).toEqual({ data: { count: 5, hasNew: true } });
461
+ });
462
+ it('should return hasNew false when no new entries', async () => {
463
+ // Arrange
464
+ mockStorage.hasEntriesAfter.mockResolvedValue(0);
465
+ // Act
466
+ const result = await controller.checkNewEntries('100');
467
+ // Assert
468
+ expect(result).toEqual({ data: { count: 0, hasNew: false } });
469
+ });
470
+ it('should filter by type', async () => {
471
+ // Arrange
472
+ mockStorage.hasEntriesAfter.mockResolvedValue(3);
473
+ // Act
474
+ await controller.checkNewEntries('50', 'exception');
475
+ // Assert
476
+ expect(mockStorage.hasEntriesAfter).toHaveBeenCalledWith(50, 'exception');
477
+ });
478
+ });
479
+ describe('getGroupedEntries', () => {
480
+ it('should return entries grouped by family hash', async () => {
481
+ // Arrange
482
+ const groups = [
483
+ { familyHash: 'abc', count: 5, latestEntry: createMockEntry() },
484
+ ];
485
+ mockStorage.getGroupedByFamilyHash.mockResolvedValue(groups);
486
+ // Act
487
+ const result = await controller.getGroupedEntries();
488
+ // Assert
489
+ expect(mockStorage.getGroupedByFamilyHash).toHaveBeenCalledWith(undefined, 50);
490
+ expect(result).toEqual({ data: groups });
491
+ });
492
+ it('should filter by type and limit', async () => {
493
+ // Arrange
494
+ mockStorage.getGroupedByFamilyHash.mockResolvedValue([]);
495
+ // Act
496
+ await controller.getGroupedEntries('exception', '25');
497
+ // Assert
498
+ expect(mockStorage.getGroupedByFamilyHash).toHaveBeenCalledWith('exception', 25);
499
+ });
500
+ });
501
+ describe('getEntriesByFamilyHash', () => {
502
+ it('should return entries with same family hash', async () => {
503
+ // Arrange
504
+ const entries = [createMockEntry(), createMockEntry({ id: 2 })];
505
+ mockStorage.findByFamilyHash.mockResolvedValue(entries);
506
+ // Act
507
+ const result = await controller.getEntriesByFamilyHash('abc123');
508
+ // Assert
509
+ expect(mockStorage.findByFamilyHash).toHaveBeenCalledWith('abc123', 50);
510
+ expect(result).toEqual({ data: entries });
511
+ });
512
+ it('should respect limit parameter', async () => {
513
+ // Arrange
514
+ mockStorage.findByFamilyHash.mockResolvedValue([]);
515
+ // Act
516
+ await controller.getEntriesByFamilyHash('xyz789', '100');
517
+ // Assert
518
+ expect(mockStorage.findByFamilyHash).toHaveBeenCalledWith('xyz789', 100);
519
+ });
520
+ });
521
+ describe('getEntry', () => {
522
+ it('should return entry by id', async () => {
523
+ // Arrange
524
+ const entry = createMockEntry({ id: 42, type: 'query' });
525
+ mockStorage.findById.mockResolvedValue(entry);
526
+ // Act
527
+ const result = await controller.getEntry(42);
528
+ // Assert
529
+ expect(mockStorage.findById).toHaveBeenCalledWith(42);
530
+ expect(result).toEqual({ data: entry });
531
+ });
532
+ it('should return null and error when entry not found', async () => {
533
+ // Arrange
534
+ mockStorage.findById.mockResolvedValue(null);
535
+ // Act
536
+ const result = await controller.getEntry(999);
537
+ // Assert
538
+ expect(result).toEqual({ data: null, error: 'Entry not found' });
539
+ });
540
+ it('should return related entries for request type', async () => {
541
+ // Arrange
542
+ const entry = createMockEntry({ id: 1, type: 'request', requestId: 'req-123' });
543
+ const related = [
544
+ createMockEntry({ id: 2, type: 'query', requestId: 'req-123' }),
545
+ createMockEntry({ id: 3, type: 'log', requestId: 'req-123' }),
546
+ ];
547
+ mockStorage.findById.mockResolvedValue(entry);
548
+ mockStorage.find.mockResolvedValue([entry, ...related]);
549
+ // Act
550
+ const result = await controller.getEntry(1);
551
+ // Assert
552
+ expect(mockStorage.find).toHaveBeenCalledWith({ requestId: 'req-123', limit: 100 });
553
+ expect(result).toEqual({
554
+ data: entry,
555
+ related,
556
+ });
557
+ });
558
+ it('should not fetch related for non-request types', async () => {
559
+ // Arrange
560
+ const entry = createMockEntry({ id: 1, type: 'query' });
561
+ mockStorage.findById.mockResolvedValue(entry);
562
+ // Act
563
+ const result = await controller.getEntry(1);
564
+ // Assert
565
+ expect(mockStorage.find).not.toHaveBeenCalled();
566
+ expect(result).toEqual({ data: entry });
567
+ });
568
+ });
569
+ describe('getStats', () => {
570
+ it('should return stats from storage', async () => {
571
+ // Arrange
572
+ const stats = {
573
+ total: 360,
574
+ byType: { request: 100, query: 50, exception: 10, log: 200 },
575
+ };
576
+ mockStorage.getStats.mockResolvedValue(stats);
577
+ // Act
578
+ const result = await controller.getStats();
579
+ // Assert
580
+ expect(mockStorage.getStats).toHaveBeenCalled();
581
+ expect(result).toEqual({ data: stats });
582
+ });
583
+ });
584
+ describe('getRequests', () => {
585
+ it('should call getEntries with request type', async () => {
586
+ // Arrange
587
+ const entries = [createMockEntry({ type: 'request' })];
588
+ mockStorage.find.mockResolvedValue(entries);
589
+ mockStorage.count.mockResolvedValue(1);
590
+ // Act
591
+ const result = await controller.getRequests();
592
+ // Assert
593
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ type: 'request' }));
594
+ });
595
+ });
596
+ describe('getQueries', () => {
597
+ it('should return queries without slow filter', async () => {
598
+ // Arrange
599
+ const entries = [
600
+ createMockEntry({ type: 'query', payload: { query: 'SELECT 1', duration: 10, slow: false } }),
601
+ createMockEntry({ type: 'query', payload: { query: 'SELECT 2', duration: 1000, slow: true } }),
602
+ ];
603
+ mockStorage.find.mockResolvedValue(entries);
604
+ mockStorage.count.mockResolvedValue(2);
605
+ // Act
606
+ const result = await controller.getQueries();
607
+ // Assert
608
+ expect(result.data).toHaveLength(2);
609
+ });
610
+ it('should filter slow queries when slow=true', async () => {
611
+ // Arrange
612
+ const entries = [
613
+ createMockEntry({ type: 'query', payload: { query: 'SELECT 1', duration: 10, slow: false } }),
614
+ createMockEntry({ type: 'query', payload: { query: 'SELECT 2', duration: 1000, slow: true } }),
615
+ ];
616
+ mockStorage.find.mockResolvedValue(entries);
617
+ mockStorage.count.mockResolvedValue(2);
618
+ // Act
619
+ const result = await controller.getQueries(undefined, undefined, 'true');
620
+ // Assert
621
+ expect(result.data).toHaveLength(1);
622
+ expect(result.data[0].payload.slow).toBe(true);
623
+ });
624
+ });
625
+ describe('getLogs', () => {
626
+ it('should return logs without level filter', async () => {
627
+ // Arrange
628
+ const entries = [
629
+ createMockEntry({ type: 'log', payload: { level: 'log', message: 'Test log' } }),
630
+ createMockEntry({ type: 'log', payload: { level: 'error', message: 'Test error' } }),
631
+ ];
632
+ mockStorage.find.mockResolvedValue(entries);
633
+ mockStorage.count.mockResolvedValue(2);
634
+ // Act
635
+ const result = await controller.getLogs();
636
+ // Assert
637
+ expect(result.data).toHaveLength(2);
638
+ });
639
+ it('should filter by level', async () => {
640
+ // Arrange
641
+ const entries = [
642
+ createMockEntry({ type: 'log', payload: { level: 'log', message: 'Test log' } }),
643
+ createMockEntry({ type: 'log', payload: { level: 'error', message: 'Test error' } }),
644
+ ];
645
+ mockStorage.find.mockResolvedValue(entries);
646
+ mockStorage.count.mockResolvedValue(2);
647
+ // Act
648
+ const result = await controller.getLogs(undefined, undefined, 'error');
649
+ // Assert
650
+ expect(result.data).toHaveLength(1);
651
+ expect(result.data[0].payload.level).toBe('error');
652
+ });
653
+ });
654
+ describe('getExceptions', () => {
655
+ it('should call getEntries with exception type', async () => {
656
+ // Arrange
657
+ mockStorage.find.mockResolvedValue([]);
658
+ mockStorage.count.mockResolvedValue(0);
659
+ // Act
660
+ await controller.getExceptions();
661
+ // Assert
662
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ type: 'exception' }));
663
+ });
664
+ });
665
+ describe('getStorageStats', () => {
666
+ it('should return storage statistics', async () => {
667
+ // Arrange
668
+ const stats = {
669
+ total: 1000,
670
+ byType: { request: 500, query: 300, exception: 100, log: 100 },
671
+ databaseSize: 5242880,
672
+ oldestEntry: '2024-01-01T00:00:00Z',
673
+ newestEntry: '2024-01-31T23:59:59Z',
674
+ };
675
+ mockStorage.getStorageStats.mockResolvedValue(stats);
676
+ // Act
677
+ const result = await controller.getStorageStats();
678
+ // Assert
679
+ expect(mockStorage.getStorageStats).toHaveBeenCalled();
680
+ expect(result).toEqual({ data: stats });
681
+ });
682
+ });
683
+ describe('getPruningStatus', () => {
684
+ it('should return pruning status', async () => {
685
+ // Arrange
686
+ const storageStats = {
687
+ total: 100,
688
+ byType: {},
689
+ oldestEntry: '2024-01-01T00:00:00Z',
690
+ newestEntry: '2024-01-31T23:59:59Z',
691
+ databaseSize: 1024,
692
+ };
693
+ mockStorage.getStorageStats.mockResolvedValue(storageStats);
694
+ // Act
695
+ const result = await controller.getPruningStatus();
696
+ // Assert
697
+ expect(result.data).toMatchObject({
698
+ enabled: true,
699
+ maxAge: 24,
700
+ interval: 60,
701
+ totalEntries: 100,
702
+ oldestEntry: '2024-01-01T00:00:00Z',
703
+ newestEntry: '2024-01-31T23:59:59Z',
704
+ databaseSize: 1024,
705
+ });
706
+ });
707
+ it('should handle undefined pruning config', async () => {
708
+ // Arrange
709
+ mockConfig.pruning = undefined;
710
+ mockStorage.getStorageStats.mockResolvedValue({
711
+ total: 0,
712
+ byType: {},
713
+ oldestEntry: null,
714
+ newestEntry: null,
715
+ databaseSize: 0,
716
+ });
717
+ // Act
718
+ const result = await controller.getPruningStatus();
719
+ // Assert
720
+ expect(result.data.enabled).toBe(true);
721
+ expect(result.data.maxAge).toBe(24);
722
+ expect(result.data.interval).toBe(60);
723
+ });
724
+ });
725
+ describe('runPruning', () => {
726
+ it('should run pruning and return result', async () => {
727
+ // Arrange
728
+ mockStorage.prune.mockResolvedValue(50);
729
+ // Act
730
+ const result = await controller.runPruning();
731
+ // Assert
732
+ expect(mockStorage.prune).toHaveBeenCalledWith(expect.any(Date));
733
+ expect(result.success).toBe(true);
734
+ expect(result.data.deleted).toBe(50);
735
+ expect(result.data.lastRun).toBeDefined();
736
+ expect(result.data.nextRun).toBeDefined();
737
+ });
738
+ it('should update lastPruneRun and nextPruneRun', async () => {
739
+ // Arrange
740
+ mockStorage.prune.mockResolvedValue(10);
741
+ const beforeRun = Date.now();
742
+ // Act
743
+ await controller.runPruning();
744
+ // Assert
745
+ expect(controller['lastPruneRun'].getTime()).toBeGreaterThanOrEqual(beforeRun);
746
+ expect(controller['nextPruneRun'].getTime()).toBeGreaterThan(controller['lastPruneRun'].getTime());
747
+ });
748
+ it('should calculate prune cutoff based on maxAge config', async () => {
749
+ // Arrange
750
+ mockStorage.prune.mockResolvedValue(0);
751
+ const maxAgeHours = 24;
752
+ const expectedBefore = Date.now() - maxAgeHours * 60 * 60 * 1000;
753
+ // Act
754
+ await controller.runPruning();
755
+ // Assert
756
+ const calledDate = mockStorage.prune.mock.calls[0][0];
757
+ expect(calledDate.getTime()).toBeCloseTo(expectedBefore, -3); // within 1 second
758
+ });
759
+ });
760
+ describe('clearEntries', () => {
761
+ it('should clear all entries', async () => {
762
+ // Arrange
763
+ mockStorage.clear.mockResolvedValue(undefined);
764
+ // Act
765
+ const result = await controller.clearEntries();
766
+ // Assert
767
+ expect(mockStorage.clear).toHaveBeenCalled();
768
+ expect(result).toEqual({ success: true, message: 'All entries cleared' });
769
+ });
770
+ });
771
+ describe('resolveEntry', () => {
772
+ it('should resolve entry and return updated entry', async () => {
773
+ // Arrange
774
+ const entry = createMockEntry({ id: 1, type: 'exception' });
775
+ mockStorage.resolveEntry.mockResolvedValue(undefined);
776
+ mockStorage.findById.mockResolvedValue({ ...entry, resolvedAt: new Date().toISOString() });
777
+ // Act
778
+ const result = await controller.resolveEntry(1);
779
+ // Assert
780
+ expect(mockStorage.resolveEntry).toHaveBeenCalledWith(1);
781
+ expect(mockStorage.findById).toHaveBeenCalledWith(1);
782
+ expect(result.success).toBe(true);
783
+ expect(result.data.resolvedAt).toBeDefined();
784
+ });
785
+ });
786
+ describe('unresolveEntry', () => {
787
+ it('should unresolve entry and return updated entry', async () => {
788
+ // Arrange
789
+ const entry = createMockEntry({ id: 1, type: 'exception' });
790
+ mockStorage.unresolveEntry.mockResolvedValue(undefined);
791
+ mockStorage.findById.mockResolvedValue({ ...entry, resolvedAt: undefined });
792
+ // Act
793
+ const result = await controller.unresolveEntry(1);
794
+ // Assert
795
+ expect(mockStorage.unresolveEntry).toHaveBeenCalledWith(1);
796
+ expect(mockStorage.findById).toHaveBeenCalledWith(1);
797
+ expect(result.success).toBe(true);
798
+ expect(result.data.resolvedAt).toBeUndefined();
799
+ });
800
+ });
801
+ describe('pauseRecording', () => {
802
+ it('should pause recording with reason', async () => {
803
+ // Arrange
804
+ const status = { isPaused: true, pausedAt: new Date(), pauseReason: 'maintenance' };
805
+ mockCollectorService.getRecordingStatus.mockReturnValue(status);
806
+ // Act
807
+ const result = await controller.pauseRecording({ reason: 'maintenance' });
808
+ // Assert
809
+ expect(mockCollectorService.pause).toHaveBeenCalledWith('maintenance');
810
+ expect(result.success).toBe(true);
811
+ expect(result.data).toEqual(status);
812
+ });
813
+ it('should pause recording without reason', async () => {
814
+ // Arrange
815
+ const status = { isPaused: true, pausedAt: new Date() };
816
+ mockCollectorService.getRecordingStatus.mockReturnValue(status);
817
+ // Act
818
+ const result = await controller.pauseRecording({});
819
+ // Assert
820
+ expect(mockCollectorService.pause).toHaveBeenCalledWith(undefined);
821
+ expect(result.success).toBe(true);
822
+ });
823
+ });
824
+ describe('resumeRecording', () => {
825
+ it('should resume recording', async () => {
826
+ // Arrange
827
+ const status = { isPaused: false };
828
+ mockCollectorService.getRecordingStatus.mockReturnValue(status);
829
+ // Act
830
+ const result = await controller.resumeRecording();
831
+ // Assert
832
+ expect(mockCollectorService.resume).toHaveBeenCalled();
833
+ expect(result.success).toBe(true);
834
+ expect(result.data).toEqual(status);
835
+ });
836
+ });
837
+ describe('getRecordingStatus', () => {
838
+ it('should return recording status', async () => {
839
+ // Arrange
840
+ const status = { isPaused: false };
841
+ mockCollectorService.getRecordingStatus.mockReturnValue(status);
842
+ // Act
843
+ const result = await controller.getRecordingStatus();
844
+ // Assert
845
+ expect(mockCollectorService.getRecordingStatus).toHaveBeenCalled();
846
+ expect(result).toEqual({ data: status });
847
+ });
848
+ it('should return paused status with details', async () => {
849
+ // Arrange
850
+ const status = {
851
+ isPaused: true,
852
+ pausedAt: new Date('2024-01-15T10:00:00Z'),
853
+ pauseReason: 'debugging',
854
+ };
855
+ mockCollectorService.getRecordingStatus.mockReturnValue(status);
856
+ // Act
857
+ const result = await controller.getRecordingStatus();
858
+ // Assert
859
+ expect(result.data).toEqual(status);
860
+ });
861
+ });
862
+ describe('Edge Cases', () => {
863
+ describe('getEntries with invalid pagination', () => {
864
+ it('should handle NaN limit by using default', async () => {
865
+ // Arrange
866
+ mockStorage.find.mockResolvedValue([]);
867
+ mockStorage.count.mockResolvedValue(0);
868
+ // Act
869
+ await controller.getEntries(undefined, undefined, 'invalid', undefined);
870
+ // Assert - invalid limit should fall back to default (50)
871
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ limit: 50 }));
872
+ });
873
+ });
874
+ describe('pagination bounds', () => {
875
+ it('should cap limit at MAX_LIMIT (1000)', async () => {
876
+ // Arrange
877
+ mockStorage.find.mockResolvedValue([]);
878
+ mockStorage.count.mockResolvedValue(0);
879
+ // Act
880
+ await controller.getEntries(undefined, undefined, '9999', undefined);
881
+ // Assert - should be capped at 1000
882
+ expect(mockStorage.find).toHaveBeenCalledWith(expect.objectContaining({ limit: 1000 }));
883
+ });
884
+ });
885
+ describe('getEntriesWithCursor with all filters', () => {
886
+ it('should parse all filter types correctly', async () => {
887
+ // Arrange
888
+ mockStorage.findWithCursor.mockResolvedValue({
889
+ data: [],
890
+ meta: { hasMore: false, oldestSequence: null, newestSequence: null, total: 0 },
891
+ });
892
+ // Act
893
+ await controller.getEntriesWithCursor('request', '50', undefined, undefined, 'error,warn', // levels
894
+ 'UserController', // contexts
895
+ 'SELECT,INSERT', // queryTypes
896
+ 'TypeORM', // sources
897
+ 'true', // slow
898
+ 'CreateUser', // names
899
+ 'GET,POST', // methods
900
+ '/api/users', // paths
901
+ 'false', // resolved
902
+ '200,201', // statuses
903
+ 'localhost', // hostnames
904
+ 'UserController', // controllers
905
+ '127.0.0.1', // ips
906
+ 'completed,failed', // scheduleStatuses
907
+ 'active,waiting', // jobStatuses
908
+ 'default', // queues
909
+ 'get,set', // cacheOperations
910
+ 'sent,failed', // mailStatuses
911
+ 'success,error', // redisStatuses
912
+ 'GET,SET', // redisCommands
913
+ 'create,update', // modelActions
914
+ 'User,Post', // entities
915
+ 'TypeORM', // modelSources
916
+ 'email,sms', // notificationTypes
917
+ 'sent', // notificationStatuses
918
+ 'html,json', // viewFormats
919
+ 'rendered', // viewStatuses
920
+ 'completed', // commandStatuses
921
+ 'CreateUser', // commandNames
922
+ 'CanAccess', // gateNames
923
+ 'allowed', // gateResults
924
+ 'completed', // batchStatuses
925
+ 'import', // batchOperations
926
+ 'completed', // dumpStatuses
927
+ 'export', // dumpOperations
928
+ 'sql', // dumpFormats
929
+ 'important', // tags
930
+ 'search term' // search
931
+ );
932
+ // Assert
933
+ expect(mockStorage.findWithCursor).toHaveBeenCalledWith('request', {
934
+ limit: 50,
935
+ beforeSequence: undefined,
936
+ afterSequence: undefined,
937
+ filters: expect.objectContaining({
938
+ levels: ['error', 'warn'],
939
+ contexts: ['UserController'],
940
+ queryTypes: ['SELECT', 'INSERT'],
941
+ sources: ['TypeORM'],
942
+ slow: true,
943
+ names: ['CreateUser'],
944
+ methods: ['GET', 'POST'],
945
+ paths: ['/api/users'],
946
+ resolved: false,
947
+ statuses: [200, 201],
948
+ hostnames: ['localhost'],
949
+ controllers: ['UserController'],
950
+ ips: ['127.0.0.1'],
951
+ scheduleStatuses: ['completed', 'failed'],
952
+ jobStatuses: ['active', 'waiting'],
953
+ queues: ['default'],
954
+ cacheOperations: ['get', 'set'],
955
+ mailStatuses: ['sent', 'failed'],
956
+ redisStatuses: ['success', 'error'],
957
+ redisCommands: ['GET', 'SET'],
958
+ modelActions: ['create', 'update'],
959
+ entities: ['User', 'Post'],
960
+ modelSources: ['TypeORM'],
961
+ notificationTypes: ['email', 'sms'],
962
+ notificationStatuses: ['sent'],
963
+ viewFormats: ['html', 'json'],
964
+ viewStatuses: ['rendered'],
965
+ commandStatuses: ['completed'],
966
+ commandNames: ['CreateUser'],
967
+ gateNames: ['CanAccess'],
968
+ gateResults: ['allowed'],
969
+ batchStatuses: ['completed'],
970
+ batchOperations: ['import'],
971
+ dumpStatuses: ['completed'],
972
+ dumpOperations: ['export'],
973
+ dumpFormats: ['sql'],
974
+ tags: ['important'],
975
+ search: 'search term',
976
+ }),
977
+ });
978
+ });
979
+ });
980
+ });
981
+ });
982
+ //# sourceMappingURL=api.controller.spec.js.map