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,853 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * SqliteStorage Tests
5
+ *
6
+ * Tests for SQLite-based entry storage.
7
+ * Follows AAA (Arrange-Act-Assert) pattern.
8
+ */
9
+ const sqlite_storage_1 = require("../../../core/storage/sqlite.storage");
10
+ describe('SqliteStorage', () => {
11
+ let storage;
12
+ beforeEach(() => {
13
+ // Create storage with in-memory database for testing
14
+ storage = new sqlite_storage_1.SqliteStorage(':memory:');
15
+ });
16
+ afterEach(async () => {
17
+ if (storage) {
18
+ await storage.onModuleDestroy();
19
+ }
20
+ });
21
+ // ============================================================================
22
+ // save
23
+ // ============================================================================
24
+ describe('save', () => {
25
+ it('should save a request entry', async () => {
26
+ // Arrange
27
+ const entry = {
28
+ type: 'request',
29
+ requestId: 'req-123',
30
+ payload: {
31
+ method: 'GET',
32
+ url: '/api/users',
33
+ path: '/api/users',
34
+ query: {},
35
+ params: {},
36
+ headers: {},
37
+ statusCode: 200,
38
+ duration: 50,
39
+ memory: 1024,
40
+ },
41
+ };
42
+ // Act
43
+ const result = await storage.save(entry);
44
+ // Assert
45
+ expect(result.id).toBeDefined();
46
+ expect(result.type).toBe('request');
47
+ expect(result.createdAt).toBeDefined();
48
+ });
49
+ it('should save a query entry', async () => {
50
+ // Arrange
51
+ const entry = {
52
+ type: 'query',
53
+ requestId: 'req-123',
54
+ payload: {
55
+ query: 'SELECT * FROM users',
56
+ duration: 10,
57
+ slow: false,
58
+ },
59
+ };
60
+ // Act
61
+ const result = await storage.save(entry);
62
+ // Assert
63
+ expect(result.id).toBeDefined();
64
+ expect(result.type).toBe('query');
65
+ });
66
+ it('should save an exception entry', async () => {
67
+ // Arrange
68
+ const entry = {
69
+ type: 'exception',
70
+ requestId: 'req-123',
71
+ payload: {
72
+ name: 'Error',
73
+ message: 'Something went wrong',
74
+ stack: 'Error: Something went wrong\n at test.ts:10',
75
+ },
76
+ };
77
+ // Act
78
+ const result = await storage.save(entry);
79
+ // Assert
80
+ expect(result.id).toBeDefined();
81
+ expect(result.type).toBe('exception');
82
+ });
83
+ });
84
+ // ============================================================================
85
+ // saveBatch
86
+ // ============================================================================
87
+ describe('saveBatch', () => {
88
+ it('should save multiple entries in a batch', async () => {
89
+ // Arrange
90
+ const entries = [
91
+ {
92
+ type: 'request',
93
+ requestId: 'req-1',
94
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
95
+ },
96
+ {
97
+ type: 'request',
98
+ requestId: 'req-2',
99
+ payload: { method: 'POST', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 201, duration: 100, memory: 2048 },
100
+ },
101
+ ];
102
+ // Act
103
+ const result = await storage.saveBatch(entries);
104
+ // Assert
105
+ expect(result).toHaveLength(2);
106
+ expect(result[0].id).toBeDefined();
107
+ expect(result[1].id).toBeDefined();
108
+ expect(result[0].id).not.toBe(result[1].id);
109
+ });
110
+ it('should handle empty batch', async () => {
111
+ // Arrange
112
+ const entries = [];
113
+ // Act
114
+ const result = await storage.saveBatch(entries);
115
+ // Assert
116
+ expect(result).toHaveLength(0);
117
+ });
118
+ });
119
+ // ============================================================================
120
+ // find
121
+ // ============================================================================
122
+ describe('find', () => {
123
+ it('should find entries by type', async () => {
124
+ // Arrange
125
+ await storage.save({
126
+ type: 'request',
127
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
128
+ });
129
+ await storage.save({
130
+ type: 'query',
131
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
132
+ });
133
+ // Act
134
+ const result = await storage.find({ type: 'request' });
135
+ // Assert
136
+ expect(result).toHaveLength(1);
137
+ expect(result[0].type).toBe('request');
138
+ });
139
+ it('should find entries by requestId', async () => {
140
+ // Arrange
141
+ await storage.save({
142
+ type: 'request',
143
+ requestId: 'req-123',
144
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
145
+ });
146
+ await storage.save({
147
+ type: 'request',
148
+ requestId: 'req-456',
149
+ payload: { method: 'POST', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
150
+ });
151
+ // Act
152
+ const result = await storage.find({ requestId: 'req-123' });
153
+ // Assert
154
+ expect(result).toHaveLength(1);
155
+ expect(result[0].requestId).toBe('req-123');
156
+ });
157
+ it('should find entries with limit', async () => {
158
+ // Arrange
159
+ for (let i = 0; i < 5; i++) {
160
+ await storage.save({
161
+ type: 'request',
162
+ payload: { method: 'GET', url: `/api/${i}`, path: `/api/${i}`, query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
163
+ });
164
+ }
165
+ // Act
166
+ const result = await storage.find({ limit: 3 });
167
+ // Assert
168
+ expect(result).toHaveLength(3);
169
+ });
170
+ it('should find entries with limit and offset', async () => {
171
+ // Arrange
172
+ for (let i = 0; i < 5; i++) {
173
+ await storage.save({
174
+ type: 'request',
175
+ payload: { method: 'GET', url: `/api/${i}`, path: `/api/${i}`, query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
176
+ });
177
+ }
178
+ // Act - SQLite requires LIMIT when using OFFSET
179
+ const result = await storage.find({ limit: 100, offset: 2 });
180
+ // Assert
181
+ expect(result).toHaveLength(3);
182
+ });
183
+ it('should find entries by date range', async () => {
184
+ // Arrange
185
+ await storage.save({
186
+ type: 'request',
187
+ payload: { method: 'GET', url: '/old', path: '/old', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
188
+ });
189
+ // Act - use wide date range to ensure entry is included
190
+ const from = new Date(Date.now() - 24 * 60 * 60 * 1000); // 1 day ago
191
+ const to = new Date(Date.now() + 24 * 60 * 60 * 1000); // 1 day from now
192
+ const result = await storage.find({ from, to });
193
+ // Assert
194
+ expect(result).toHaveLength(1);
195
+ });
196
+ });
197
+ // ============================================================================
198
+ // findById
199
+ // ============================================================================
200
+ describe('findById', () => {
201
+ it('should find entry by id', async () => {
202
+ // Arrange
203
+ const saved = await storage.save({
204
+ type: 'request',
205
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
206
+ });
207
+ // Act
208
+ const result = await storage.findById(saved.id);
209
+ // Assert
210
+ expect(result).not.toBeNull();
211
+ expect(result?.id).toBe(saved.id);
212
+ });
213
+ it('should return null for non-existent id', async () => {
214
+ // Act
215
+ const result = await storage.findById(99999);
216
+ // Assert
217
+ expect(result).toBeNull();
218
+ });
219
+ });
220
+ // ============================================================================
221
+ // count
222
+ // ============================================================================
223
+ describe('count', () => {
224
+ it('should count all entries', async () => {
225
+ // Arrange
226
+ await storage.save({ type: 'request', payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 } });
227
+ await storage.save({ type: 'query', payload: { query: 'SELECT 1', duration: 5, slow: false } });
228
+ // Act
229
+ const result = await storage.count();
230
+ // Assert
231
+ expect(result).toBe(2);
232
+ });
233
+ it('should count entries by type', async () => {
234
+ // Arrange
235
+ await storage.save({ type: 'request', payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 } });
236
+ await storage.save({ type: 'request', payload: { method: 'POST', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 201, duration: 100, memory: 2048 } });
237
+ await storage.save({ type: 'query', payload: { query: 'SELECT 1', duration: 5, slow: false } });
238
+ // Act
239
+ const result = await storage.count('request');
240
+ // Assert
241
+ expect(result).toBe(2);
242
+ });
243
+ });
244
+ // ============================================================================
245
+ // getStats
246
+ // ============================================================================
247
+ describe('getStats', () => {
248
+ it('should return stats for empty database', async () => {
249
+ // Act
250
+ const result = await storage.getStats();
251
+ // Assert
252
+ expect(result.total).toBe(0);
253
+ expect(result.byType).toEqual({});
254
+ expect(result.slowQueries).toBe(0);
255
+ expect(result.exceptions).toBe(0);
256
+ });
257
+ it('should return correct stats', async () => {
258
+ // Arrange
259
+ await storage.save({
260
+ type: 'request',
261
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 100, memory: 1024 },
262
+ });
263
+ await storage.save({
264
+ type: 'request',
265
+ payload: { method: 'POST', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 200, memory: 2048 },
266
+ });
267
+ await storage.save({
268
+ type: 'query',
269
+ payload: { query: 'SELECT 1', duration: 5, slow: true },
270
+ });
271
+ await storage.save({
272
+ type: 'exception',
273
+ payload: { name: 'Error', message: 'Test error', stack: '' },
274
+ });
275
+ // Act
276
+ const result = await storage.getStats();
277
+ // Assert
278
+ expect(result.total).toBe(4);
279
+ expect(result.byType.request).toBe(2);
280
+ expect(result.byType.query).toBe(1);
281
+ expect(result.byType.exception).toBe(1);
282
+ expect(result.slowQueries).toBe(1);
283
+ expect(result.exceptions).toBe(1);
284
+ expect(result.avgResponseTime).toBeDefined();
285
+ });
286
+ });
287
+ // ============================================================================
288
+ // prune
289
+ // ============================================================================
290
+ describe('prune', () => {
291
+ it('should prune entries before date', async () => {
292
+ // Arrange
293
+ await storage.save({
294
+ type: 'request',
295
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
296
+ });
297
+ // Act
298
+ const before = new Date(Date.now() + 10000); // Future date to delete all
299
+ const deleted = await storage.prune(before);
300
+ // Assert
301
+ expect(deleted).toBe(1);
302
+ const count = await storage.count();
303
+ expect(count).toBe(0);
304
+ });
305
+ it('should not prune entries after date', async () => {
306
+ // Arrange
307
+ await storage.save({
308
+ type: 'request',
309
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
310
+ });
311
+ // Act - use a date from yesterday to ensure entry is definitely after it
312
+ const before = new Date(Date.now() - 24 * 60 * 60 * 1000); // 1 day ago
313
+ const deleted = await storage.prune(before);
314
+ // Assert
315
+ expect(deleted).toBe(0);
316
+ const count = await storage.count();
317
+ expect(count).toBe(1);
318
+ });
319
+ });
320
+ // ============================================================================
321
+ // pruneByType
322
+ // ============================================================================
323
+ describe('pruneByType', () => {
324
+ it('should prune entries by type', async () => {
325
+ // Arrange
326
+ await storage.save({
327
+ type: 'request',
328
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
329
+ });
330
+ await storage.save({
331
+ type: 'query',
332
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
333
+ });
334
+ // Act
335
+ const before = new Date(Date.now() + 10000);
336
+ const deleted = await storage.pruneByType('request', before);
337
+ // Assert
338
+ expect(deleted).toBe(1);
339
+ const requestCount = await storage.count('request');
340
+ const queryCount = await storage.count('query');
341
+ expect(requestCount).toBe(0);
342
+ expect(queryCount).toBe(1);
343
+ });
344
+ });
345
+ // ============================================================================
346
+ // clear
347
+ // ============================================================================
348
+ describe('clear', () => {
349
+ it('should clear all entries', async () => {
350
+ // Arrange
351
+ await storage.save({ type: 'request', payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 } });
352
+ await storage.save({ type: 'query', payload: { query: 'SELECT 1', duration: 5, slow: false } });
353
+ // Act
354
+ await storage.clear();
355
+ // Assert
356
+ const count = await storage.count();
357
+ expect(count).toBe(0);
358
+ });
359
+ });
360
+ // ============================================================================
361
+ // updateFamilyHash
362
+ // ============================================================================
363
+ describe('updateFamilyHash', () => {
364
+ it('should update family hash', async () => {
365
+ // Arrange
366
+ const saved = await storage.save({
367
+ type: 'exception',
368
+ payload: { name: 'Error', message: 'Test', stack: '' },
369
+ });
370
+ // Act
371
+ await storage.updateFamilyHash(saved.id, 'hash-123');
372
+ const result = await storage.findById(saved.id);
373
+ // Assert
374
+ expect(result?.familyHash).toBe('hash-123');
375
+ });
376
+ });
377
+ // ============================================================================
378
+ // resolveException
379
+ // ============================================================================
380
+ describe('resolveEntry', () => {
381
+ it('should mark entry as resolved', async () => {
382
+ // Arrange
383
+ const saved = await storage.save({
384
+ type: 'exception',
385
+ payload: { name: 'Error', message: 'Test', stack: '' },
386
+ });
387
+ // Act
388
+ await storage.resolveEntry(saved.id);
389
+ const result = await storage.findById(saved.id);
390
+ // Assert
391
+ expect(result?.resolvedAt).toBeDefined();
392
+ });
393
+ });
394
+ // ============================================================================
395
+ // Tags
396
+ // ============================================================================
397
+ describe('tags', () => {
398
+ it('should add tags to entry', async () => {
399
+ // Arrange
400
+ const saved = await storage.save({
401
+ type: 'request',
402
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
403
+ });
404
+ // Act
405
+ await storage.addTags(saved.id, ['tag1', 'tag2']);
406
+ const result = await storage.findById(saved.id);
407
+ // Assert
408
+ expect(result?.tags).toContain('tag1');
409
+ expect(result?.tags).toContain('tag2');
410
+ });
411
+ it('should remove tags from entry', async () => {
412
+ // Arrange
413
+ const saved = await storage.save({
414
+ type: 'request',
415
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
416
+ });
417
+ await storage.addTags(saved.id, ['tag1', 'tag2', 'tag3']);
418
+ // Act
419
+ await storage.removeTags(saved.id, ['tag2']);
420
+ const result = await storage.findById(saved.id);
421
+ // Assert
422
+ expect(result?.tags).toContain('tag1');
423
+ expect(result?.tags).not.toContain('tag2');
424
+ expect(result?.tags).toContain('tag3');
425
+ });
426
+ it('should get tags for entry', async () => {
427
+ // Arrange
428
+ const saved = await storage.save({
429
+ type: 'request',
430
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
431
+ });
432
+ await storage.addTags(saved.id, ['alpha', 'beta']);
433
+ // Act
434
+ const tags = await storage.getEntryTags(saved.id);
435
+ // Assert
436
+ expect(tags).toContain('alpha');
437
+ expect(tags).toContain('beta');
438
+ });
439
+ it('should get all unique tags with counts', async () => {
440
+ // Arrange
441
+ const entry1 = await storage.save({
442
+ type: 'request',
443
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
444
+ });
445
+ const entry2 = await storage.save({
446
+ type: 'request',
447
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
448
+ });
449
+ await storage.addTags(entry1.id, ['common', 'unique1']);
450
+ await storage.addTags(entry2.id, ['common', 'unique2']);
451
+ // Act
452
+ const allTags = await storage.getAllTags();
453
+ // Assert - returns TagWithCount objects
454
+ const tagNames = allTags.map((t) => t.tag);
455
+ expect(tagNames).toContain('common');
456
+ expect(tagNames).toContain('unique1');
457
+ expect(tagNames).toContain('unique2');
458
+ // 'common' should have count of 2
459
+ const commonTag = allTags.find((t) => t.tag === 'common');
460
+ expect(commonTag?.count).toBe(2);
461
+ });
462
+ it('should find entries by tags', async () => {
463
+ // Arrange
464
+ const entry1 = await storage.save({
465
+ type: 'request',
466
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
467
+ });
468
+ const entry2 = await storage.save({
469
+ type: 'request',
470
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
471
+ });
472
+ await storage.addTags(entry1.id, ['important']);
473
+ await storage.addTags(entry2.id, ['normal']);
474
+ // Act
475
+ const results = await storage.findByTags(['important']);
476
+ // Assert
477
+ expect(results).toHaveLength(1);
478
+ expect(results[0].id).toBe(entry1.id);
479
+ });
480
+ });
481
+ // ============================================================================
482
+ // Pagination
483
+ // ============================================================================
484
+ describe('pagination', () => {
485
+ it('should get entries with cursor pagination', async () => {
486
+ // Arrange
487
+ for (let i = 0; i < 10; i++) {
488
+ await storage.save({
489
+ type: 'request',
490
+ payload: { method: 'GET', url: `/api/${i}`, path: `/api/${i}`, query: {}, params: {}, headers: {}, statusCode: 200, duration: 50 + i, memory: 1024 },
491
+ });
492
+ }
493
+ // Act
494
+ const result = await storage.findWithCursor('request', { limit: 5 });
495
+ // Assert
496
+ expect(result.data).toHaveLength(5);
497
+ expect(result.meta.hasMore).toBe(true);
498
+ expect(result.meta.total).toBe(10);
499
+ });
500
+ it('should get next page with cursor', async () => {
501
+ // Arrange
502
+ for (let i = 0; i < 10; i++) {
503
+ await storage.save({
504
+ type: 'request',
505
+ payload: { method: 'GET', url: `/api/${i}`, path: `/api/${i}`, query: {}, params: {}, headers: {}, statusCode: 200, duration: 50 + i, memory: 1024 },
506
+ });
507
+ }
508
+ // Act
509
+ const firstPage = await storage.findWithCursor('request', { limit: 5 });
510
+ const secondPage = await storage.findWithCursor('request', {
511
+ limit: 5,
512
+ beforeSequence: firstPage.meta.oldestSequence ?? undefined,
513
+ });
514
+ // Assert
515
+ expect(secondPage.data).toHaveLength(5);
516
+ expect(secondPage.meta.hasMore).toBe(false);
517
+ });
518
+ });
519
+ // ============================================================================
520
+ // getLatestSequence
521
+ // ============================================================================
522
+ describe('getLatestSequence', () => {
523
+ it('should return null for empty database', async () => {
524
+ // Act
525
+ const result = await storage.getLatestSequence();
526
+ // Assert
527
+ expect(result).toBeNull();
528
+ });
529
+ it('should return latest sequence id', async () => {
530
+ // Arrange
531
+ await storage.save({
532
+ type: 'request',
533
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
534
+ });
535
+ const second = await storage.save({
536
+ type: 'request',
537
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
538
+ });
539
+ // Act
540
+ const result = await storage.getLatestSequence();
541
+ // Assert
542
+ expect(result).toBe(second.id);
543
+ });
544
+ it('should return latest sequence by type', async () => {
545
+ // Arrange
546
+ await storage.save({
547
+ type: 'request',
548
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
549
+ });
550
+ const query = await storage.save({
551
+ type: 'query',
552
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
553
+ });
554
+ // Act
555
+ const result = await storage.getLatestSequence('query');
556
+ // Assert
557
+ expect(result).toBe(query.id);
558
+ });
559
+ });
560
+ // ============================================================================
561
+ // hasEntriesAfter
562
+ // ============================================================================
563
+ describe('hasEntriesAfter', () => {
564
+ it('should return 0 when no entries after sequence', async () => {
565
+ // Arrange
566
+ const entry = await storage.save({
567
+ type: 'request',
568
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
569
+ });
570
+ // Act
571
+ const result = await storage.hasEntriesAfter(entry.id);
572
+ // Assert
573
+ expect(result).toBe(0);
574
+ });
575
+ it('should return count of entries after sequence', async () => {
576
+ // Arrange
577
+ const first = await storage.save({
578
+ type: 'request',
579
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
580
+ });
581
+ await storage.save({
582
+ type: 'request',
583
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
584
+ });
585
+ await storage.save({
586
+ type: 'request',
587
+ payload: { method: 'GET', url: '/api/3', path: '/api/3', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
588
+ });
589
+ // Act
590
+ const result = await storage.hasEntriesAfter(first.id);
591
+ // Assert
592
+ expect(result).toBe(2);
593
+ });
594
+ it('should filter by type when counting entries after', async () => {
595
+ // Arrange
596
+ const first = await storage.save({
597
+ type: 'request',
598
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
599
+ });
600
+ await storage.save({
601
+ type: 'query',
602
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
603
+ });
604
+ await storage.save({
605
+ type: 'request',
606
+ payload: { method: 'POST', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 201, duration: 100, memory: 2048 },
607
+ });
608
+ // Act
609
+ const result = await storage.hasEntriesAfter(first.id, 'request');
610
+ // Assert
611
+ expect(result).toBe(1);
612
+ });
613
+ });
614
+ // ============================================================================
615
+ // getStorageStats
616
+ // ============================================================================
617
+ describe('getStorageStats', () => {
618
+ it('should return stats for empty database', async () => {
619
+ // Act
620
+ const result = await storage.getStorageStats();
621
+ // Assert
622
+ expect(result.total).toBe(0);
623
+ expect(result.byType).toEqual({});
624
+ expect(result.oldestEntry).toBeNull();
625
+ expect(result.newestEntry).toBeNull();
626
+ });
627
+ it('should return correct storage stats', async () => {
628
+ // Arrange
629
+ await storage.save({
630
+ type: 'request',
631
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
632
+ });
633
+ await storage.save({
634
+ type: 'query',
635
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
636
+ });
637
+ // Act
638
+ const result = await storage.getStorageStats();
639
+ // Assert
640
+ expect(result.total).toBe(2);
641
+ expect(result.byType.request).toBe(1);
642
+ expect(result.byType.query).toBe(1);
643
+ expect(result.oldestEntry).toBeDefined();
644
+ expect(result.newestEntry).toBeDefined();
645
+ });
646
+ });
647
+ // ============================================================================
648
+ // Monitored Tags
649
+ // ============================================================================
650
+ describe('monitored tags', () => {
651
+ it('should add monitored tag', async () => {
652
+ // Act
653
+ const result = await storage.addMonitoredTag('important');
654
+ // Assert
655
+ expect(result.id).toBeDefined();
656
+ expect(result.tag).toBe('important');
657
+ expect(result.createdAt).toBeDefined();
658
+ });
659
+ it('should get all monitored tags', async () => {
660
+ // Arrange
661
+ await storage.addMonitoredTag('alpha');
662
+ await storage.addMonitoredTag('beta');
663
+ // Act
664
+ const result = await storage.getMonitoredTags();
665
+ // Assert
666
+ expect(result).toHaveLength(2);
667
+ expect(result.map(t => t.tag)).toContain('alpha');
668
+ expect(result.map(t => t.tag)).toContain('beta');
669
+ });
670
+ it('should remove monitored tag', async () => {
671
+ // Arrange
672
+ await storage.addMonitoredTag('temp');
673
+ await storage.addMonitoredTag('keep');
674
+ // Act
675
+ await storage.removeMonitoredTag('temp');
676
+ const result = await storage.getMonitoredTags();
677
+ // Assert
678
+ expect(result).toHaveLength(1);
679
+ expect(result[0].tag).toBe('keep');
680
+ });
681
+ it('should handle duplicate monitored tags', async () => {
682
+ // Arrange & Act
683
+ await storage.addMonitoredTag('duplicate');
684
+ await storage.addMonitoredTag('duplicate');
685
+ const result = await storage.getMonitoredTags();
686
+ // Assert - should only have one
687
+ expect(result).toHaveLength(1);
688
+ });
689
+ });
690
+ // ============================================================================
691
+ // unresolveEntry
692
+ // ============================================================================
693
+ describe('unresolveEntry', () => {
694
+ it('should unresolve a resolved entry', async () => {
695
+ // Arrange
696
+ const saved = await storage.save({
697
+ type: 'exception',
698
+ payload: { name: 'Error', message: 'Test', stack: '' },
699
+ });
700
+ await storage.resolveEntry(saved.id);
701
+ // Act
702
+ await storage.unresolveEntry(saved.id);
703
+ const result = await storage.findById(saved.id);
704
+ // Assert
705
+ expect(result?.resolvedAt).toBeUndefined();
706
+ });
707
+ });
708
+ // ============================================================================
709
+ // findByFamilyHash
710
+ // ============================================================================
711
+ describe('findByFamilyHash', () => {
712
+ it('should find entries by family hash', async () => {
713
+ // Arrange
714
+ const entry1 = await storage.save({
715
+ type: 'exception',
716
+ payload: { name: 'Error', message: 'Test 1', stack: '' },
717
+ });
718
+ const entry2 = await storage.save({
719
+ type: 'exception',
720
+ payload: { name: 'Error', message: 'Test 2', stack: '' },
721
+ });
722
+ await storage.save({
723
+ type: 'exception',
724
+ payload: { name: 'Error', message: 'Different', stack: '' },
725
+ });
726
+ await storage.updateFamilyHash(entry1.id, 'hash-abc');
727
+ await storage.updateFamilyHash(entry2.id, 'hash-abc');
728
+ // Act
729
+ const result = await storage.findByFamilyHash('hash-abc');
730
+ // Assert
731
+ expect(result).toHaveLength(2);
732
+ });
733
+ it('should return empty array for non-existent hash', async () => {
734
+ // Act
735
+ const result = await storage.findByFamilyHash('non-existent');
736
+ // Assert
737
+ expect(result).toHaveLength(0);
738
+ });
739
+ });
740
+ // ============================================================================
741
+ // getGroupedByFamilyHash
742
+ // ============================================================================
743
+ describe('getGroupedByFamilyHash', () => {
744
+ it('should return empty array when no family hashes', async () => {
745
+ // Arrange
746
+ await storage.save({
747
+ type: 'exception',
748
+ payload: { name: 'Error', message: 'Test', stack: '' },
749
+ });
750
+ // Act
751
+ const result = await storage.getGroupedByFamilyHash();
752
+ // Assert
753
+ expect(result).toHaveLength(0);
754
+ });
755
+ it('should group entries by family hash', async () => {
756
+ // Arrange
757
+ const entry1 = await storage.save({
758
+ type: 'exception',
759
+ payload: { name: 'Error', message: 'Test 1', stack: '' },
760
+ });
761
+ const entry2 = await storage.save({
762
+ type: 'exception',
763
+ payload: { name: 'Error', message: 'Test 2', stack: '' },
764
+ });
765
+ const entry3 = await storage.save({
766
+ type: 'exception',
767
+ payload: { name: 'Error', message: 'Test 3', stack: '' },
768
+ });
769
+ await storage.updateFamilyHash(entry1.id, 'hash-a');
770
+ await storage.updateFamilyHash(entry2.id, 'hash-a');
771
+ await storage.updateFamilyHash(entry3.id, 'hash-b');
772
+ // Act
773
+ const result = await storage.getGroupedByFamilyHash();
774
+ // Assert
775
+ expect(result).toHaveLength(2);
776
+ const hashA = result.find(r => r.familyHash === 'hash-a');
777
+ expect(hashA?.count).toBe(2);
778
+ const hashB = result.find(r => r.familyHash === 'hash-b');
779
+ expect(hashB?.count).toBe(1);
780
+ });
781
+ it('should filter by type when grouping', async () => {
782
+ // Arrange
783
+ const exc = await storage.save({
784
+ type: 'exception',
785
+ payload: { name: 'Error', message: 'Test', stack: '' },
786
+ });
787
+ const query = await storage.save({
788
+ type: 'query',
789
+ payload: { query: 'SELECT 1', duration: 5, slow: false },
790
+ });
791
+ await storage.updateFamilyHash(exc.id, 'hash-exc');
792
+ await storage.updateFamilyHash(query.id, 'hash-query');
793
+ // Act
794
+ const result = await storage.getGroupedByFamilyHash('exception');
795
+ // Assert
796
+ expect(result).toHaveLength(1);
797
+ expect(result[0].familyHash).toBe('hash-exc');
798
+ });
799
+ });
800
+ // ============================================================================
801
+ // findByTags with AND logic
802
+ // ============================================================================
803
+ describe('findByTags advanced', () => {
804
+ it('should return empty array when tags array is empty', async () => {
805
+ // Arrange
806
+ const entry = await storage.save({
807
+ type: 'request',
808
+ payload: { method: 'GET', url: '/api', path: '/api', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
809
+ });
810
+ await storage.addTags(entry.id, ['tag1']);
811
+ // Act
812
+ const result = await storage.findByTags([]);
813
+ // Assert
814
+ expect(result).toHaveLength(0);
815
+ });
816
+ it('should find entries with AND logic (all tags required)', async () => {
817
+ // Arrange
818
+ const entry1 = await storage.save({
819
+ type: 'request',
820
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
821
+ });
822
+ const entry2 = await storage.save({
823
+ type: 'request',
824
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
825
+ });
826
+ await storage.addTags(entry1.id, ['red', 'blue', 'green']);
827
+ await storage.addTags(entry2.id, ['red', 'blue']);
828
+ // Act - find entries with BOTH red and green
829
+ const result = await storage.findByTags(['red', 'green'], 'AND');
830
+ // Assert - only entry1 has both
831
+ expect(result).toHaveLength(1);
832
+ expect(result[0].id).toBe(entry1.id);
833
+ });
834
+ it('should find entries with OR logic (any tag)', async () => {
835
+ // Arrange
836
+ const entry1 = await storage.save({
837
+ type: 'request',
838
+ payload: { method: 'GET', url: '/api/1', path: '/api/1', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
839
+ });
840
+ const entry2 = await storage.save({
841
+ type: 'request',
842
+ payload: { method: 'GET', url: '/api/2', path: '/api/2', query: {}, params: {}, headers: {}, statusCode: 200, duration: 50, memory: 1024 },
843
+ });
844
+ await storage.addTags(entry1.id, ['alpha']);
845
+ await storage.addTags(entry2.id, ['beta']);
846
+ // Act - find entries with alpha OR beta
847
+ const result = await storage.findByTags(['alpha', 'beta'], 'OR');
848
+ // Assert
849
+ expect(result).toHaveLength(2);
850
+ });
851
+ });
852
+ });
853
+ //# sourceMappingURL=sqlite.storage.spec.js.map