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,888 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * HttpClientWatcher Tests
5
+ *
6
+ * Tests for the HTTP client watcher that monitors outgoing HTTP requests.
7
+ * Follows AAA (Arrange-Act-Assert) pattern.
8
+ */
9
+ const testing_1 = require("@nestjs/testing");
10
+ const collector_service_1 = require("../../core/collector.service");
11
+ const nestlens_config_1 = require("../../nestlens.config");
12
+ const http_client_watcher_1 = require("../../watchers/http-client.watcher");
13
+ describe('HttpClientWatcher', () => {
14
+ let watcher;
15
+ let mockCollector;
16
+ let mockConfig;
17
+ let requestInterceptor;
18
+ let responseInterceptor;
19
+ const createAxiosInstance = () => {
20
+ const interceptors = {
21
+ request: {
22
+ use: jest.fn((onFulfilled, onRejected) => {
23
+ requestInterceptor = { onFulfilled, onRejected };
24
+ return 0;
25
+ }),
26
+ },
27
+ response: {
28
+ use: jest.fn((onFulfilled, onRejected) => {
29
+ responseInterceptor = { onFulfilled, onRejected };
30
+ return 0;
31
+ }),
32
+ },
33
+ };
34
+ return { interceptors };
35
+ };
36
+ const createWatcher = async (config, axiosInstance) => {
37
+ const providers = [
38
+ http_client_watcher_1.HttpClientWatcher,
39
+ { provide: collector_service_1.CollectorService, useValue: mockCollector },
40
+ { provide: nestlens_config_1.NESTLENS_CONFIG, useValue: config },
41
+ ];
42
+ if (axiosInstance !== undefined) {
43
+ providers.push({ provide: http_client_watcher_1.NESTLENS_HTTP_CLIENT, useValue: axiosInstance });
44
+ }
45
+ const module = await testing_1.Test.createTestingModule({
46
+ providers,
47
+ }).compile();
48
+ return module.get(http_client_watcher_1.HttpClientWatcher);
49
+ };
50
+ beforeEach(() => {
51
+ jest.clearAllMocks();
52
+ mockCollector = {
53
+ collect: jest.fn(),
54
+ collectImmediate: jest.fn(),
55
+ };
56
+ mockConfig = {
57
+ enabled: true,
58
+ watchers: {
59
+ httpClient: { enabled: true },
60
+ },
61
+ };
62
+ });
63
+ // ============================================================================
64
+ // Config Handling
65
+ // ============================================================================
66
+ describe('Config Handling', () => {
67
+ it('should be enabled when httpClient watcher config is true', async () => {
68
+ // Arrange
69
+ mockConfig.watchers = { httpClient: true };
70
+ const axios = createAxiosInstance();
71
+ watcher = await createWatcher(mockConfig, axios);
72
+ // Assert
73
+ expect(watcher.config.enabled).toBe(true);
74
+ });
75
+ it('should be disabled when httpClient watcher config is false', async () => {
76
+ // Arrange
77
+ mockConfig.watchers = { httpClient: false };
78
+ const axios = createAxiosInstance();
79
+ watcher = await createWatcher(mockConfig, axios);
80
+ // Act
81
+ watcher.onModuleInit();
82
+ // Assert - should not setup interceptors
83
+ expect(axios.interceptors.request.use).not.toHaveBeenCalled();
84
+ });
85
+ it('should use default maxBodySize of 64KB', async () => {
86
+ // Arrange
87
+ mockConfig.watchers = { httpClient: true };
88
+ const axios = createAxiosInstance();
89
+ watcher = await createWatcher(mockConfig, axios);
90
+ // Assert
91
+ expect(watcher.maxBodySize).toBe(64 * 1024);
92
+ });
93
+ it('should use custom maxBodySize from config', async () => {
94
+ // Arrange
95
+ mockConfig.watchers = { httpClient: { enabled: true, maxBodySize: 1024 } };
96
+ const axios = createAxiosInstance();
97
+ watcher = await createWatcher(mockConfig, axios);
98
+ // Assert
99
+ expect(watcher.maxBodySize).toBe(1024);
100
+ });
101
+ });
102
+ // ============================================================================
103
+ // Module Initialization
104
+ // ============================================================================
105
+ describe('Module Initialization', () => {
106
+ it('should handle missing axios instance gracefully', async () => {
107
+ // Arrange
108
+ watcher = await createWatcher(mockConfig, undefined);
109
+ // Act & Assert - should not throw
110
+ expect(() => watcher.onModuleInit()).not.toThrow();
111
+ });
112
+ it('should setup interceptors when axios is available', async () => {
113
+ // Arrange
114
+ const axios = createAxiosInstance();
115
+ watcher = await createWatcher(mockConfig, axios);
116
+ // Act
117
+ watcher.onModuleInit();
118
+ // Assert
119
+ expect(axios.interceptors.request.use).toHaveBeenCalled();
120
+ expect(axios.interceptors.response.use).toHaveBeenCalled();
121
+ });
122
+ it('should handle invalid axios instance', async () => {
123
+ // Arrange
124
+ const invalidAxios = {};
125
+ watcher = await createWatcher(mockConfig, invalidAxios);
126
+ // Act & Assert - should not throw
127
+ expect(() => watcher.onModuleInit()).not.toThrow();
128
+ });
129
+ });
130
+ // ============================================================================
131
+ // Request Interceptor
132
+ // ============================================================================
133
+ describe('Request Interceptor', () => {
134
+ it('should add start time metadata to request', async () => {
135
+ // Arrange
136
+ const axios = createAxiosInstance();
137
+ watcher = await createWatcher(mockConfig, axios);
138
+ watcher.onModuleInit();
139
+ const config = { url: 'https://api.example.com/users' };
140
+ // Act
141
+ const result = requestInterceptor.onFulfilled(config);
142
+ // Assert
143
+ expect(result.metadata.nestlensStartTime).toBeDefined();
144
+ expect(typeof result.metadata.nestlensStartTime).toBe('number');
145
+ });
146
+ it('should preserve existing metadata', async () => {
147
+ // Arrange
148
+ const axios = createAxiosInstance();
149
+ watcher = await createWatcher(mockConfig, axios);
150
+ watcher.onModuleInit();
151
+ const config = {
152
+ url: 'https://api.example.com/users',
153
+ metadata: { existingKey: 'existingValue' },
154
+ };
155
+ // Act
156
+ const result = requestInterceptor.onFulfilled(config);
157
+ // Assert
158
+ expect(result.metadata.existingKey).toBe('existingValue');
159
+ expect(result.metadata.nestlensStartTime).toBeDefined();
160
+ });
161
+ it('should reject errors in request interceptor', async () => {
162
+ // Arrange
163
+ const axios = createAxiosInstance();
164
+ watcher = await createWatcher(mockConfig, axios);
165
+ watcher.onModuleInit();
166
+ const error = new Error('Request setup failed');
167
+ // Act & Assert
168
+ await expect(requestInterceptor.onRejected(error)).rejects.toThrow('Request setup failed');
169
+ });
170
+ });
171
+ // ============================================================================
172
+ // Response Interceptor - Success
173
+ // ============================================================================
174
+ describe('Response Interceptor - Success', () => {
175
+ it('should collect successful response', async () => {
176
+ // Arrange
177
+ const axios = createAxiosInstance();
178
+ watcher = await createWatcher(mockConfig, axios);
179
+ watcher.onModuleInit();
180
+ const response = {
181
+ config: {
182
+ method: 'GET',
183
+ url: 'https://api.example.com/users',
184
+ metadata: { nestlensStartTime: Date.now() - 100 },
185
+ },
186
+ status: 200,
187
+ headers: { 'content-type': 'application/json' },
188
+ data: { users: [] },
189
+ };
190
+ // Act
191
+ const result = responseInterceptor.onFulfilled(response);
192
+ // Assert
193
+ expect(result).toBe(response);
194
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
195
+ method: 'GET',
196
+ url: 'https://api.example.com/users',
197
+ statusCode: 200,
198
+ }));
199
+ });
200
+ it('should parse URL hostname and path', async () => {
201
+ // Arrange
202
+ const axios = createAxiosInstance();
203
+ watcher = await createWatcher(mockConfig, axios);
204
+ watcher.onModuleInit();
205
+ const response = {
206
+ config: {
207
+ method: 'POST',
208
+ url: 'https://api.example.com/v1/users?page=1',
209
+ metadata: { nestlensStartTime: Date.now() },
210
+ },
211
+ status: 201,
212
+ headers: {},
213
+ data: {},
214
+ };
215
+ // Act
216
+ responseInterceptor.onFulfilled(response);
217
+ // Assert
218
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
219
+ hostname: 'api.example.com',
220
+ path: '/v1/users?page=1',
221
+ }));
222
+ });
223
+ it('should calculate request duration', async () => {
224
+ // Arrange
225
+ const axios = createAxiosInstance();
226
+ watcher = await createWatcher(mockConfig, axios);
227
+ watcher.onModuleInit();
228
+ const response = {
229
+ config: {
230
+ method: 'GET',
231
+ url: 'https://api.example.com/users',
232
+ metadata: { nestlensStartTime: Date.now() - 150 },
233
+ },
234
+ status: 200,
235
+ headers: {},
236
+ data: {},
237
+ };
238
+ // Act
239
+ responseInterceptor.onFulfilled(response);
240
+ // Assert
241
+ const call = mockCollector.collect.mock.calls[0][1];
242
+ expect(call.duration).toBeGreaterThanOrEqual(0);
243
+ });
244
+ });
245
+ // ============================================================================
246
+ // Response Interceptor - Error
247
+ // ============================================================================
248
+ describe('Response Interceptor - Error', () => {
249
+ it('should collect failed response', async () => {
250
+ // Arrange
251
+ const axios = createAxiosInstance();
252
+ watcher = await createWatcher(mockConfig, axios);
253
+ watcher.onModuleInit();
254
+ const error = {
255
+ config: {
256
+ method: 'POST',
257
+ url: 'https://api.example.com/users',
258
+ metadata: { nestlensStartTime: Date.now() },
259
+ },
260
+ response: {
261
+ status: 500,
262
+ headers: {},
263
+ data: { error: 'Internal Server Error' },
264
+ },
265
+ message: 'Request failed with status code 500',
266
+ };
267
+ // Act
268
+ try {
269
+ await responseInterceptor.onRejected(error);
270
+ }
271
+ catch {
272
+ // Expected
273
+ }
274
+ // Assert
275
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
276
+ statusCode: 500,
277
+ error: 'Request failed with status code 500',
278
+ }));
279
+ });
280
+ it('should handle network errors (no response)', async () => {
281
+ // Arrange
282
+ const axios = createAxiosInstance();
283
+ watcher = await createWatcher(mockConfig, axios);
284
+ watcher.onModuleInit();
285
+ const error = {
286
+ config: {
287
+ method: 'GET',
288
+ url: 'https://api.example.com/users',
289
+ metadata: { nestlensStartTime: Date.now() },
290
+ },
291
+ message: 'Network Error',
292
+ };
293
+ // Act
294
+ try {
295
+ await responseInterceptor.onRejected(error);
296
+ }
297
+ catch {
298
+ // Expected
299
+ }
300
+ // Assert
301
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
302
+ error: 'Network Error',
303
+ statusCode: undefined,
304
+ }));
305
+ });
306
+ it('should re-throw the error', async () => {
307
+ // Arrange
308
+ const axios = createAxiosInstance();
309
+ watcher = await createWatcher(mockConfig, axios);
310
+ watcher.onModuleInit();
311
+ const error = new Error('Connection refused');
312
+ error.config = { url: 'https://api.example.com' };
313
+ // Act & Assert
314
+ await expect(responseInterceptor.onRejected(error)).rejects.toThrow('Connection refused');
315
+ });
316
+ });
317
+ // ============================================================================
318
+ // Ignored Hosts
319
+ // ============================================================================
320
+ describe('Ignored Hosts', () => {
321
+ it('should skip ignored hosts', async () => {
322
+ // Arrange
323
+ mockConfig.watchers = {
324
+ httpClient: { enabled: true, ignoreHosts: ['localhost', 'internal.service'] },
325
+ };
326
+ const axios = createAxiosInstance();
327
+ watcher = await createWatcher(mockConfig, axios);
328
+ watcher.onModuleInit();
329
+ const response = {
330
+ config: {
331
+ method: 'GET',
332
+ url: 'http://localhost:3000/api/health',
333
+ metadata: { nestlensStartTime: Date.now() },
334
+ },
335
+ status: 200,
336
+ headers: {},
337
+ data: {},
338
+ };
339
+ // Act
340
+ responseInterceptor.onFulfilled(response);
341
+ // Assert
342
+ expect(mockCollector.collect).not.toHaveBeenCalled();
343
+ });
344
+ it('should collect non-ignored hosts', async () => {
345
+ // Arrange
346
+ mockConfig.watchers = {
347
+ httpClient: { enabled: true, ignoreHosts: ['localhost'] },
348
+ };
349
+ const axios = createAxiosInstance();
350
+ watcher = await createWatcher(mockConfig, axios);
351
+ watcher.onModuleInit();
352
+ const response = {
353
+ config: {
354
+ method: 'GET',
355
+ url: 'https://api.example.com/users',
356
+ metadata: { nestlensStartTime: Date.now() },
357
+ },
358
+ status: 200,
359
+ headers: {},
360
+ data: {},
361
+ };
362
+ // Act
363
+ responseInterceptor.onFulfilled(response);
364
+ // Assert
365
+ expect(mockCollector.collect).toHaveBeenCalled();
366
+ });
367
+ });
368
+ // ============================================================================
369
+ // Header Masking
370
+ // ============================================================================
371
+ describe('Header Masking', () => {
372
+ it('should mask sensitive headers', async () => {
373
+ // Arrange
374
+ const axios = createAxiosInstance();
375
+ watcher = await createWatcher(mockConfig, axios);
376
+ watcher.onModuleInit();
377
+ const response = {
378
+ config: {
379
+ method: 'GET',
380
+ url: 'https://api.example.com/users',
381
+ headers: {
382
+ Authorization: 'Bearer secret-token',
383
+ Cookie: 'session=abc123',
384
+ 'Content-Type': 'application/json',
385
+ },
386
+ metadata: { nestlensStartTime: Date.now() },
387
+ },
388
+ status: 200,
389
+ headers: {},
390
+ data: {},
391
+ };
392
+ // Act
393
+ responseInterceptor.onFulfilled(response);
394
+ // Assert
395
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
396
+ requestHeaders: expect.objectContaining({
397
+ Authorization: '********',
398
+ Cookie: '********',
399
+ 'Content-Type': 'application/json',
400
+ }),
401
+ }));
402
+ });
403
+ it('should mask custom sensitive headers', async () => {
404
+ // Arrange
405
+ mockConfig.watchers = {
406
+ httpClient: { enabled: true, sensitiveHeaders: ['X-Custom-Secret'] },
407
+ };
408
+ const axios = createAxiosInstance();
409
+ watcher = await createWatcher(mockConfig, axios);
410
+ watcher.onModuleInit();
411
+ const response = {
412
+ config: {
413
+ method: 'GET',
414
+ url: 'https://api.example.com/users',
415
+ headers: {
416
+ 'X-Custom-Secret': 'my-secret',
417
+ 'X-Request-Id': '123',
418
+ },
419
+ metadata: { nestlensStartTime: Date.now() },
420
+ },
421
+ status: 200,
422
+ headers: {},
423
+ data: {},
424
+ };
425
+ // Act
426
+ responseInterceptor.onFulfilled(response);
427
+ // Assert
428
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
429
+ requestHeaders: expect.objectContaining({
430
+ 'X-Custom-Secret': '********',
431
+ 'X-Request-Id': '123',
432
+ }),
433
+ }));
434
+ });
435
+ });
436
+ // ============================================================================
437
+ // Body Masking
438
+ // ============================================================================
439
+ describe('Body Masking', () => {
440
+ it('should mask sensitive request params', async () => {
441
+ // Arrange
442
+ const axios = createAxiosInstance();
443
+ watcher = await createWatcher(mockConfig, axios);
444
+ watcher.onModuleInit();
445
+ const response = {
446
+ config: {
447
+ method: 'POST',
448
+ url: 'https://api.example.com/login',
449
+ data: {
450
+ username: 'testuser',
451
+ password: 'secret123',
452
+ },
453
+ metadata: { nestlensStartTime: Date.now() },
454
+ },
455
+ status: 200,
456
+ headers: {},
457
+ data: {},
458
+ };
459
+ // Act
460
+ responseInterceptor.onFulfilled(response);
461
+ // Assert
462
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
463
+ requestBody: expect.objectContaining({
464
+ username: 'testuser',
465
+ password: '********',
466
+ }),
467
+ }));
468
+ });
469
+ it('should mask sensitive response params', async () => {
470
+ // Arrange
471
+ const axios = createAxiosInstance();
472
+ watcher = await createWatcher(mockConfig, axios);
473
+ watcher.onModuleInit();
474
+ const response = {
475
+ config: {
476
+ method: 'POST',
477
+ url: 'https://api.example.com/oauth/token',
478
+ metadata: { nestlensStartTime: Date.now() },
479
+ },
480
+ status: 200,
481
+ headers: {},
482
+ data: {
483
+ access_token: 'eyJhbGc...',
484
+ refresh_token: 'dGhpcyBpcyBhIHNlY3JldA==',
485
+ expires_in: 3600,
486
+ },
487
+ };
488
+ // Act
489
+ responseInterceptor.onFulfilled(response);
490
+ // Assert
491
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
492
+ responseBody: expect.objectContaining({
493
+ access_token: '********',
494
+ refresh_token: '********',
495
+ expires_in: 3600,
496
+ }),
497
+ }));
498
+ });
499
+ it('should handle nested sensitive data', async () => {
500
+ // Arrange
501
+ const axios = createAxiosInstance();
502
+ watcher = await createWatcher(mockConfig, axios);
503
+ watcher.onModuleInit();
504
+ const response = {
505
+ config: {
506
+ method: 'POST',
507
+ url: 'https://api.example.com/users',
508
+ data: {
509
+ user: {
510
+ name: 'Test',
511
+ credentials: {
512
+ password: 'secret',
513
+ },
514
+ },
515
+ },
516
+ metadata: { nestlensStartTime: Date.now() },
517
+ },
518
+ status: 200,
519
+ headers: {},
520
+ data: {},
521
+ };
522
+ // Act
523
+ responseInterceptor.onFulfilled(response);
524
+ // Assert
525
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
526
+ requestBody: expect.objectContaining({
527
+ user: expect.objectContaining({
528
+ name: 'Test',
529
+ credentials: expect.objectContaining({
530
+ password: '********',
531
+ }),
532
+ }),
533
+ }),
534
+ }));
535
+ });
536
+ });
537
+ // ============================================================================
538
+ // Body Capture Configuration
539
+ // ============================================================================
540
+ describe('Body Capture Configuration', () => {
541
+ it('should skip request body when captureRequestBody is false', async () => {
542
+ // Arrange
543
+ mockConfig.watchers = {
544
+ httpClient: { enabled: true, captureRequestBody: false },
545
+ };
546
+ const axios = createAxiosInstance();
547
+ watcher = await createWatcher(mockConfig, axios);
548
+ watcher.onModuleInit();
549
+ const response = {
550
+ config: {
551
+ method: 'POST',
552
+ url: 'https://api.example.com/users',
553
+ data: { name: 'Test' },
554
+ metadata: { nestlensStartTime: Date.now() },
555
+ },
556
+ status: 200,
557
+ headers: {},
558
+ data: {},
559
+ };
560
+ // Act
561
+ responseInterceptor.onFulfilled(response);
562
+ // Assert
563
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
564
+ requestBody: undefined,
565
+ }));
566
+ });
567
+ it('should skip response body when captureResponseBody is false', async () => {
568
+ // Arrange
569
+ mockConfig.watchers = {
570
+ httpClient: { enabled: true, captureResponseBody: false },
571
+ };
572
+ const axios = createAxiosInstance();
573
+ watcher = await createWatcher(mockConfig, axios);
574
+ watcher.onModuleInit();
575
+ const response = {
576
+ config: {
577
+ method: 'GET',
578
+ url: 'https://api.example.com/users',
579
+ metadata: { nestlensStartTime: Date.now() },
580
+ },
581
+ status: 200,
582
+ headers: {},
583
+ data: { users: [] },
584
+ };
585
+ // Act
586
+ responseInterceptor.onFulfilled(response);
587
+ // Assert
588
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
589
+ responseBody: undefined,
590
+ }));
591
+ });
592
+ });
593
+ // ============================================================================
594
+ // Large Body Handling
595
+ // ============================================================================
596
+ describe('Large Body Handling', () => {
597
+ it('should truncate large request bodies', async () => {
598
+ // Arrange
599
+ mockConfig.watchers = { httpClient: { enabled: true, maxBodySize: 100 } };
600
+ const axios = createAxiosInstance();
601
+ watcher = await createWatcher(mockConfig, axios);
602
+ watcher.onModuleInit();
603
+ const response = {
604
+ config: {
605
+ method: 'POST',
606
+ url: 'https://api.example.com/users',
607
+ data: { largeField: 'x'.repeat(200) },
608
+ metadata: { nestlensStartTime: Date.now() },
609
+ },
610
+ status: 200,
611
+ headers: {},
612
+ data: {},
613
+ };
614
+ // Act
615
+ responseInterceptor.onFulfilled(response);
616
+ // Assert
617
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
618
+ requestBody: expect.objectContaining({
619
+ _truncated: true,
620
+ _size: expect.any(Number),
621
+ }),
622
+ }));
623
+ });
624
+ it('should handle deeply nested objects with max depth', async () => {
625
+ // Arrange
626
+ const axios = createAxiosInstance();
627
+ watcher = await createWatcher(mockConfig, axios);
628
+ watcher.onModuleInit();
629
+ // Create a deeply nested object that exceeds MAX_MASK_DEPTH
630
+ let deeplyNested = { value: 'deep' };
631
+ for (let i = 0; i < 15; i++) {
632
+ deeplyNested = { nested: deeplyNested };
633
+ }
634
+ const response = {
635
+ config: {
636
+ method: 'POST',
637
+ url: 'https://api.example.com/users',
638
+ data: deeplyNested,
639
+ metadata: { nestlensStartTime: Date.now() },
640
+ },
641
+ status: 200,
642
+ headers: {},
643
+ data: {},
644
+ };
645
+ // Act
646
+ responseInterceptor.onFulfilled(response);
647
+ // Assert - deeply nested object should be truncated at max depth
648
+ expect(mockCollector.collect).toHaveBeenCalled();
649
+ });
650
+ });
651
+ // ============================================================================
652
+ // setupInterceptors (Manual Setup)
653
+ // ============================================================================
654
+ describe('setupInterceptors (Manual Setup)', () => {
655
+ it('should setup interceptors on custom axios instance', async () => {
656
+ // Arrange
657
+ watcher = await createWatcher(mockConfig, undefined);
658
+ const customAxios = createAxiosInstance();
659
+ // Act
660
+ watcher.setupInterceptors(customAxios);
661
+ // Assert
662
+ expect(customAxios.interceptors.request.use).toHaveBeenCalled();
663
+ expect(customAxios.interceptors.response.use).toHaveBeenCalled();
664
+ });
665
+ it('should handle HttpService with axiosRef', async () => {
666
+ // Arrange
667
+ watcher = await createWatcher(mockConfig, undefined);
668
+ const innerAxios = createAxiosInstance();
669
+ const httpService = {
670
+ interceptors: {}, // Invalid
671
+ axiosRef: innerAxios,
672
+ };
673
+ // Act
674
+ watcher.setupInterceptors(httpService);
675
+ // Assert
676
+ expect(innerAxios.interceptors.request.use).toHaveBeenCalled();
677
+ });
678
+ });
679
+ // ============================================================================
680
+ // Relative URLs
681
+ // ============================================================================
682
+ describe('Relative URLs', () => {
683
+ it('should handle relative URLs', async () => {
684
+ // Arrange
685
+ const axios = createAxiosInstance();
686
+ watcher = await createWatcher(mockConfig, axios);
687
+ watcher.onModuleInit();
688
+ const response = {
689
+ config: {
690
+ method: 'GET',
691
+ url: '/api/users',
692
+ metadata: { nestlensStartTime: Date.now() },
693
+ },
694
+ status: 200,
695
+ headers: {},
696
+ data: {},
697
+ };
698
+ // Act
699
+ responseInterceptor.onFulfilled(response);
700
+ // Assert
701
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
702
+ url: '/api/users',
703
+ path: '/api/users',
704
+ hostname: undefined,
705
+ }));
706
+ });
707
+ });
708
+ // ============================================================================
709
+ // Missing Config
710
+ // ============================================================================
711
+ describe('Missing Config', () => {
712
+ it('should handle missing config in response', async () => {
713
+ // Arrange
714
+ const axios = createAxiosInstance();
715
+ watcher = await createWatcher(mockConfig, axios);
716
+ watcher.onModuleInit();
717
+ const response = {
718
+ config: undefined,
719
+ status: 200,
720
+ headers: {},
721
+ data: {},
722
+ };
723
+ // Act
724
+ responseInterceptor.onFulfilled(response);
725
+ // Assert - should not throw, should not collect
726
+ expect(mockCollector.collect).not.toHaveBeenCalled();
727
+ });
728
+ });
729
+ // ============================================================================
730
+ // Header Value Types
731
+ // ============================================================================
732
+ describe('Header Value Types', () => {
733
+ it('should handle numeric header values', async () => {
734
+ // Arrange
735
+ const axios = createAxiosInstance();
736
+ watcher = await createWatcher(mockConfig, axios);
737
+ watcher.onModuleInit();
738
+ const response = {
739
+ config: { url: 'https://api.example.com/test', method: 'get', headers: {} },
740
+ status: 200,
741
+ headers: { 'content-length': 1234 },
742
+ data: {},
743
+ };
744
+ // Act
745
+ responseInterceptor.onFulfilled(response);
746
+ // Assert
747
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
748
+ responseHeaders: expect.objectContaining({
749
+ 'content-length': '1234',
750
+ }),
751
+ }));
752
+ });
753
+ it('should handle boolean header values', async () => {
754
+ // Arrange
755
+ const axios = createAxiosInstance();
756
+ watcher = await createWatcher(mockConfig, axios);
757
+ watcher.onModuleInit();
758
+ const response = {
759
+ config: { url: 'https://api.example.com/test', method: 'get', headers: {} },
760
+ status: 200,
761
+ headers: { 'x-cached': true },
762
+ data: {},
763
+ };
764
+ // Act
765
+ responseInterceptor.onFulfilled(response);
766
+ // Assert
767
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
768
+ responseHeaders: expect.objectContaining({
769
+ 'x-cached': 'true',
770
+ }),
771
+ }));
772
+ });
773
+ it('should handle array header values', async () => {
774
+ // Arrange
775
+ const axios = createAxiosInstance();
776
+ watcher = await createWatcher(mockConfig, axios);
777
+ watcher.onModuleInit();
778
+ const response = {
779
+ config: { url: 'https://api.example.com/test', method: 'get', headers: {} },
780
+ status: 200,
781
+ headers: { 'x-custom-values': ['value1', 'value2'] },
782
+ data: {},
783
+ };
784
+ // Act
785
+ responseInterceptor.onFulfilled(response);
786
+ // Assert - array values should be joined with comma
787
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
788
+ responseHeaders: expect.objectContaining({
789
+ 'x-custom-values': 'value1, value2',
790
+ }),
791
+ }));
792
+ });
793
+ });
794
+ // ============================================================================
795
+ // Sensitive Data Masking Edge Cases
796
+ // ============================================================================
797
+ describe('Sensitive Data Masking', () => {
798
+ it('should mask sensitive data in nested arrays', async () => {
799
+ // Arrange
800
+ const axios = createAxiosInstance();
801
+ watcher = await createWatcher(mockConfig, axios);
802
+ watcher.onModuleInit();
803
+ const response = {
804
+ config: {
805
+ url: 'https://api.example.com/test',
806
+ method: 'post',
807
+ headers: {},
808
+ data: {
809
+ users: [
810
+ { name: 'John', password: 'secret1' },
811
+ { name: 'Jane', password: 'secret2' },
812
+ ],
813
+ },
814
+ },
815
+ status: 200,
816
+ headers: {},
817
+ data: {},
818
+ };
819
+ // Act
820
+ responseInterceptor.onFulfilled(response);
821
+ // Assert
822
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
823
+ requestBody: expect.objectContaining({
824
+ users: expect.arrayContaining([
825
+ expect.objectContaining({ password: '********' }),
826
+ ]),
827
+ }),
828
+ }));
829
+ });
830
+ it('should handle circular reference in body via max depth truncation', async () => {
831
+ // Arrange
832
+ const axios = createAxiosInstance();
833
+ watcher = await createWatcher(mockConfig, axios);
834
+ watcher.onModuleInit();
835
+ const circularObj = { name: 'test' };
836
+ circularObj.self = circularObj;
837
+ const response = {
838
+ config: {
839
+ url: 'https://api.example.com/test',
840
+ method: 'post',
841
+ headers: {},
842
+ data: circularObj,
843
+ },
844
+ status: 200,
845
+ headers: {},
846
+ data: {},
847
+ };
848
+ // Act
849
+ responseInterceptor.onFulfilled(response);
850
+ // Assert - circular reference is handled via max depth limit
851
+ // The implementation traverses until MAX_MASK_DEPTH (10) and truncates
852
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
853
+ requestBody: expect.objectContaining({
854
+ name: 'test',
855
+ self: expect.any(Object),
856
+ }),
857
+ }));
858
+ });
859
+ it('should return error for truly unserializable body', async () => {
860
+ // Arrange
861
+ const axios = createAxiosInstance();
862
+ watcher = await createWatcher(mockConfig, axios);
863
+ watcher.onModuleInit();
864
+ // Create an object with BigInt which cannot be JSON.stringify'd
865
+ const unserializableObj = { value: BigInt(123) };
866
+ const response = {
867
+ config: {
868
+ url: 'https://api.example.com/test',
869
+ method: 'post',
870
+ headers: {},
871
+ data: unserializableObj,
872
+ },
873
+ status: 200,
874
+ headers: {},
875
+ data: {},
876
+ };
877
+ // Act
878
+ responseInterceptor.onFulfilled(response);
879
+ // Assert - BigInt causes JSON.stringify to fail
880
+ expect(mockCollector.collect).toHaveBeenCalledWith('http-client', expect.objectContaining({
881
+ requestBody: expect.objectContaining({
882
+ _error: 'Unable to serialize body',
883
+ }),
884
+ }));
885
+ });
886
+ });
887
+ });
888
+ //# sourceMappingURL=http-client.watcher.spec.js.map