@talkpilot/core-db 1.3.66 → 1.3.68

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 (356) hide show
  1. package/.cursor/rules/development.mdc +65 -65
  2. package/AGENTS.md +49 -49
  3. package/DEVELOPMENT.md +141 -141
  4. package/README.md +1 -48
  5. package/dist/configuration/models/models.constants.d.ts +1 -1
  6. package/dist/configuration/models/models.constants.d.ts.map +1 -1
  7. package/dist/configuration/models/models.constants.js +6 -1
  8. package/dist/configuration/models/models.constants.js.map +1 -1
  9. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.d.ts +10 -0
  10. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.d.ts.map +1 -0
  11. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.js +15 -0
  12. package/dist/municipal/departmentsSubjects/departmentsSubjects.setters.js.map +1 -0
  13. package/dist/municipal/streets/streets.setters.d.ts +10 -0
  14. package/dist/municipal/streets/streets.setters.d.ts.map +1 -0
  15. package/dist/municipal/streets/streets.setters.js +15 -0
  16. package/dist/municipal/streets/streets.setters.js.map +1 -0
  17. package/dist/reconcile/index.d.ts +5 -0
  18. package/dist/reconcile/index.d.ts.map +1 -0
  19. package/dist/{talkpilot/clientDeletionLogs → reconcile}/index.js +4 -3
  20. package/dist/reconcile/index.js.map +1 -0
  21. package/dist/reconcile/reconcile.diff.d.ts +4 -0
  22. package/dist/reconcile/reconcile.diff.d.ts.map +1 -0
  23. package/dist/reconcile/reconcile.diff.js +36 -0
  24. package/dist/reconcile/reconcile.diff.js.map +1 -0
  25. package/dist/reconcile/reconcile.execute.d.ts +7 -0
  26. package/dist/reconcile/reconcile.execute.d.ts.map +1 -0
  27. package/dist/reconcile/reconcile.execute.js +20 -0
  28. package/dist/reconcile/reconcile.execute.js.map +1 -0
  29. package/dist/reconcile/reconcile.ops.d.ts +12 -0
  30. package/dist/reconcile/reconcile.ops.d.ts.map +1 -0
  31. package/dist/reconcile/reconcile.ops.js +24 -0
  32. package/dist/reconcile/reconcile.ops.js.map +1 -0
  33. package/dist/reconcile/reconcile.types.d.ts +32 -0
  34. package/dist/reconcile/reconcile.types.d.ts.map +1 -0
  35. package/dist/{talkpilot/auditLogs/auditLogs.types.js → reconcile/reconcile.types.js} +1 -1
  36. package/dist/reconcile/reconcile.types.js.map +1 -0
  37. package/dist/talkpilot/callTokenUsage/callTokenUsage.getters.d.ts +4 -0
  38. package/dist/talkpilot/callTokenUsage/callTokenUsage.getters.d.ts.map +1 -0
  39. package/dist/talkpilot/callTokenUsage/callTokenUsage.getters.js +30 -0
  40. package/dist/talkpilot/callTokenUsage/callTokenUsage.getters.js.map +1 -0
  41. package/dist/talkpilot/callTokenUsage/callTokenUsage.types.d.ts +28 -0
  42. package/dist/talkpilot/callTokenUsage/callTokenUsage.types.d.ts.map +1 -0
  43. package/dist/talkpilot/{clientDeletionLogs/clientDeletionLogs.types.js → callTokenUsage/callTokenUsage.types.js} +1 -1
  44. package/dist/talkpilot/callTokenUsage/callTokenUsage.types.js.map +1 -0
  45. package/dist/talkpilot/callTokenUsage/index.d.ts +3 -0
  46. package/dist/talkpilot/callTokenUsage/index.d.ts.map +1 -0
  47. package/dist/talkpilot/{auditLogs → callTokenUsage}/index.js +1 -2
  48. package/dist/talkpilot/callTokenUsage/index.js.map +1 -0
  49. package/dist/talkpilot/calls/calls.constants.d.ts +1 -9
  50. package/dist/talkpilot/calls/calls.constants.d.ts.map +1 -1
  51. package/dist/talkpilot/calls/calls.constants.js +1 -9
  52. package/dist/talkpilot/calls/calls.constants.js.map +1 -1
  53. package/dist/talkpilot/calls/calls.getters.d.ts +1 -7
  54. package/dist/talkpilot/calls/calls.getters.d.ts.map +1 -1
  55. package/dist/talkpilot/calls/calls.getters.js +1 -181
  56. package/dist/talkpilot/calls/calls.getters.js.map +1 -1
  57. package/dist/talkpilot/calls/calls.types.d.ts +2 -35
  58. package/dist/talkpilot/calls/calls.types.d.ts.map +1 -1
  59. package/dist/talkpilot/clients/clients.getters.d.ts +0 -2
  60. package/dist/talkpilot/clients/clients.getters.d.ts.map +1 -1
  61. package/dist/talkpilot/clients/clients.getters.js +1 -15
  62. package/dist/talkpilot/clients/clients.getters.js.map +1 -1
  63. package/dist/talkpilot/clients/clients.types.d.ts +0 -21
  64. package/dist/talkpilot/clients/clients.types.d.ts.map +1 -1
  65. package/dist/talkpilot/clients/index.d.ts +0 -2
  66. package/dist/talkpilot/clients/index.d.ts.map +1 -1
  67. package/dist/talkpilot/clients/index.js +0 -2
  68. package/dist/talkpilot/clients/index.js.map +1 -1
  69. package/dist/talkpilot/index.d.ts +1 -1
  70. package/dist/talkpilot/index.d.ts.map +1 -1
  71. package/dist/talkpilot/index.js +1 -1
  72. package/dist/talkpilot/index.js.map +1 -1
  73. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +1 -9
  74. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -1
  75. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +1 -66
  76. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -1
  77. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts +0 -5
  78. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts.map +1 -1
  79. package/dist/test-utils/factories/index.d.ts +0 -2
  80. package/dist/test-utils/factories/index.d.ts.map +1 -1
  81. package/dist/test-utils/factories/index.js +0 -2
  82. package/dist/test-utils/factories/index.js.map +1 -1
  83. package/jest.config.js +20 -20
  84. package/package.json +46 -46
  85. package/src/__tests__/setup.ts +20 -20
  86. package/src/bulkWrite/__tests__/bulkWrite.spec.ts +65 -65
  87. package/src/bulkWrite/bulkWrite.ops.ts +45 -45
  88. package/src/bulkWrite/bulkWrite.types.ts +4 -4
  89. package/src/bulkWrite/index.ts +2 -2
  90. package/src/config.ts +9 -9
  91. package/src/configuration/index.ts +17 -17
  92. package/src/configuration/internalModels/index.ts +3 -3
  93. package/src/configuration/internalModels/internalModels.constants.ts +1 -1
  94. package/src/configuration/internalModels/internalModels.getters.ts +33 -33
  95. package/src/configuration/internalModels/internalModels.types.ts +12 -12
  96. package/src/configuration/models/__tests__/models.getters.spec.ts +67 -67
  97. package/src/configuration/models/index.ts +27 -27
  98. package/src/configuration/models/models.constants.ts +20 -15
  99. package/src/configuration/models/models.getters.ts +71 -71
  100. package/src/configuration/models/models.types.ts +80 -80
  101. package/src/configuration/mongodb-client.ts +62 -62
  102. package/src/configuration/prompts/index.ts +2 -2
  103. package/src/configuration/prompts/prompts.getters.ts +49 -49
  104. package/src/configuration/prompts/prompts.types.ts +11 -11
  105. package/src/connection.ts +81 -81
  106. package/src/index.ts +47 -47
  107. package/src/municipal/__tests__/validation.spec.ts +62 -62
  108. package/src/municipal/cities/cities.getters.ts +50 -50
  109. package/src/municipal/cities/cities.types.ts +11 -11
  110. package/src/municipal/cities/index.ts +2 -2
  111. package/src/municipal/departmentsSubjects/__tests__/departmentsSubjects.spec.ts +272 -272
  112. package/src/municipal/departmentsSubjects/departmentsSubjects.getters.ts +317 -317
  113. package/src/municipal/departmentsSubjects/departmentsSubjects.types.ts +73 -73
  114. package/src/municipal/departmentsSubjects/index.ts +9 -9
  115. package/src/municipal/index.ts +22 -22
  116. package/src/municipal/mongodb-client.ts +61 -61
  117. package/src/municipal/muniIssues/__tests__/muniIssues.setters.spec.ts +94 -94
  118. package/src/municipal/muniIssues/__tests__/muniIssues.setup.spec.ts +92 -92
  119. package/src/municipal/muniIssues/index.ts +17 -17
  120. package/src/municipal/muniIssues/muniIssues.constants.ts +18 -18
  121. package/src/municipal/muniIssues/muniIssues.getters.ts +24 -24
  122. package/src/municipal/muniIssues/muniIssues.schema.ts +66 -66
  123. package/src/municipal/muniIssues/muniIssues.setters.ts +24 -24
  124. package/src/municipal/muniIssues/muniIssues.setup.ts +65 -65
  125. package/src/municipal/muniIssues/muniIssues.types.ts +37 -37
  126. package/src/municipal/streets/__tests__/streets.spec.ts +253 -253
  127. package/src/municipal/streets/index.ts +2 -2
  128. package/src/municipal/streets/streets.getters.ts +140 -140
  129. package/src/municipal/streets/streets.types.ts +19 -19
  130. package/src/municipal/systemInstructions/__tests__/getters.spec.ts +113 -113
  131. package/src/municipal/systemInstructions/__tests__/setters.spec.ts +274 -274
  132. package/src/municipal/systemInstructions/index.ts +7 -7
  133. package/src/municipal/systemInstructions/instructions.getters.ts +57 -57
  134. package/src/municipal/systemInstructions/instructions.setters.ts +119 -119
  135. package/src/municipal/systemInstructions/instructions.types.ts +30 -30
  136. package/src/municipal/tickets/__tests__/tickets.getters.spec.ts +30 -30
  137. package/src/municipal/tickets/__tests__/tickets.statistics.spec.ts +99 -99
  138. package/src/municipal/tickets/index.ts +9 -9
  139. package/src/municipal/tickets/tickets.constants.ts +8 -8
  140. package/src/municipal/tickets/tickets.getters.ts +121 -121
  141. package/src/municipal/tickets/tickets.statistics.aggregation.ts +110 -110
  142. package/src/municipal/tickets/tickets.statistics.getters.ts +145 -145
  143. package/src/municipal/tickets/tickets.types.ts +54 -54
  144. package/src/municipal/utils/types.ts +11 -11
  145. package/src/talkpilot/__tests__/db.spec.ts +38 -38
  146. package/src/talkpilot/__tests__/mongodb-client.spec.ts +18 -18
  147. package/src/talkpilot/__tests__/validation.spec.ts +68 -68
  148. package/src/talkpilot/agents/__tests__/agents.getters.spec.ts +29 -29
  149. package/src/talkpilot/agents/agents.getters.ts +34 -34
  150. package/src/talkpilot/agents/agents.types.ts +14 -14
  151. package/src/talkpilot/agents/index.ts +2 -2
  152. package/src/talkpilot/backgroundToolResults/__tests__/backgroundToolResults.getters.spec.ts +147 -147
  153. package/src/talkpilot/backgroundToolResults/backgroundToolResults.getters.ts +65 -65
  154. package/src/talkpilot/backgroundToolResults/backgroundToolResults.types.ts +23 -23
  155. package/src/talkpilot/backgroundToolResults/index.ts +2 -2
  156. package/src/talkpilot/callTokenUsage/__tests__/callTokenUsage.getters.spec.ts +57 -0
  157. package/src/talkpilot/callTokenUsage/callTokenUsage.getters.ts +42 -0
  158. package/src/talkpilot/callTokenUsage/callTokenUsage.types.ts +28 -0
  159. package/src/talkpilot/callTokenUsage/index.ts +2 -0
  160. package/src/talkpilot/calls/__tests__/callStats.utils.spec.ts +128 -128
  161. package/src/talkpilot/calls/__tests__/calls.dashboard.spec.ts +229 -229
  162. package/src/talkpilot/calls/__tests__/calls.spec.ts +471 -471
  163. package/src/talkpilot/calls/__tests__/calls.statistics.spec.ts +483 -483
  164. package/src/talkpilot/calls/calls.constants.ts +49 -61
  165. package/src/talkpilot/calls/calls.getters.ts +1 -270
  166. package/src/talkpilot/calls/calls.statistics.getters.ts +668 -668
  167. package/src/talkpilot/calls/calls.statistics.types.ts +48 -48
  168. package/src/talkpilot/calls/calls.types.ts +2 -40
  169. package/src/talkpilot/calls/dashboard/calls.dashboard.ts +295 -295
  170. package/src/talkpilot/calls/dashboard/calls.dashboard.types.ts +57 -57
  171. package/src/talkpilot/calls/index.ts +6 -6
  172. package/src/talkpilot/clientAudioBuffers/__tests__/clientAudioBuffer.getters.spec.ts +160 -160
  173. package/src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts +117 -117
  174. package/src/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.ts +25 -25
  175. package/src/talkpilot/clientAudioBuffers/index.ts +2 -2
  176. package/src/talkpilot/clients/__tests__/clients.quota.spec.ts +123 -123
  177. package/src/talkpilot/clients/clients.getters.ts +19 -32
  178. package/src/talkpilot/clients/clients.quota.getters.ts +119 -119
  179. package/src/talkpilot/clients/clients.quota.types.ts +27 -27
  180. package/src/talkpilot/clients/clients.types.ts +18 -37
  181. package/src/talkpilot/clients/index.ts +4 -6
  182. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.getters.spec.ts +423 -423
  183. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.spec.ts +212 -212
  184. package/src/talkpilot/clientsConfig/clientsConfig.constants.ts +2 -2
  185. package/src/talkpilot/clientsConfig/clientsConfig.getters.ts +247 -247
  186. package/src/talkpilot/clientsConfig/clientsConfig.types.ts +137 -137
  187. package/src/talkpilot/clientsConfig/index.ts +3 -3
  188. package/src/talkpilot/contextNotes/__tests__/contextNotes.getters.spec.ts +217 -217
  189. package/src/talkpilot/contextNotes/contextNotes.getters.ts +85 -85
  190. package/src/talkpilot/contextNotes/contextNotes.types.ts +20 -20
  191. package/src/talkpilot/contextNotes/index.ts +2 -2
  192. package/src/talkpilot/flows/__tests__/flows.schema.spec.ts +124 -124
  193. package/src/talkpilot/flows/flows.getter.ts +34 -34
  194. package/src/talkpilot/flows/flows.schema.ts +180 -180
  195. package/src/talkpilot/flows/flows.types.ts +211 -211
  196. package/src/talkpilot/flows/index.ts +7 -7
  197. package/src/talkpilot/groups/__tests__/groups.spec.ts +90 -90
  198. package/src/talkpilot/groups/__tests__/phone.utils.spec.ts +32 -32
  199. package/src/talkpilot/groups/groups.getters.ts +30 -30
  200. package/src/talkpilot/groups/groups.types.ts +29 -29
  201. package/src/talkpilot/groups/index.ts +3 -3
  202. package/src/talkpilot/groups/phone.utils.ts +46 -46
  203. package/src/talkpilot/index.ts +32 -32
  204. package/src/talkpilot/leads/index.ts +2 -2
  205. package/src/talkpilot/leads/leads.getter.ts +6 -6
  206. package/src/talkpilot/leads/leads.schema.ts +33 -33
  207. package/src/talkpilot/leads/leads.types.ts +20 -20
  208. package/src/talkpilot/mongodb-client.ts +78 -78
  209. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +530 -774
  210. package/src/talkpilot/phone_numbers/index.ts +2 -2
  211. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +240 -324
  212. package/src/talkpilot/phone_numbers/phone_numbers.schema.ts +17 -17
  213. package/src/talkpilot/phone_numbers/phone_numbers.types.ts +30 -36
  214. package/src/talkpilot/phone_numbers/phone_numbers.utils.ts +9 -9
  215. package/src/talkpilot/plans/__tests__/plans.spec.ts +70 -70
  216. package/src/talkpilot/plans/index.ts +2 -2
  217. package/src/talkpilot/plans/plans.getters.ts +132 -132
  218. package/src/talkpilot/plans/plans.types.ts +89 -89
  219. package/src/talkpilot/products/__tests__/products.getters.spec.ts +44 -44
  220. package/src/talkpilot/products/index.ts +2 -2
  221. package/src/talkpilot/products/products.getters.ts +12 -12
  222. package/src/talkpilot/products/products.types.ts +9 -9
  223. package/src/talkpilot/results/index.ts +7 -7
  224. package/src/talkpilot/results/results.getter.ts +39 -39
  225. package/src/talkpilot/results/results.schema.ts +25 -25
  226. package/src/talkpilot/results/results.types.ts +34 -34
  227. package/src/talkpilot/retry_analyze/__tests__/retryAnalyze.getters.spec.ts +156 -156
  228. package/src/talkpilot/retry_analyze/index.ts +2 -2
  229. package/src/talkpilot/retry_analyze/retryAnalyze.getters.ts +84 -84
  230. package/src/talkpilot/retry_analyze/retryAnalyze.types.ts +13 -13
  231. package/src/talkpilot/sessions/__tests__/sessions.spec.ts +147 -147
  232. package/src/talkpilot/sessions/index.ts +2 -2
  233. package/src/talkpilot/sessions/sessions.getter.ts +92 -92
  234. package/src/talkpilot/sessions/sessions.schema.ts +34 -34
  235. package/src/talkpilot/sessions/sessions.types.ts +30 -30
  236. package/src/talkpilot/subscriptions/__tests__/subscriptions.getters.utils.spec.ts +45 -45
  237. package/src/talkpilot/subscriptions/index.ts +3 -3
  238. package/src/talkpilot/subscriptions/subscriptions.getters.ts +146 -146
  239. package/src/talkpilot/subscriptions/subscriptions.getters.utils.ts +33 -33
  240. package/src/talkpilot/subscriptions/subscriptions.types.ts +66 -66
  241. package/src/talkpilot/utils/__tests__/query.utils.spec.ts +49 -49
  242. package/src/talkpilot/utils/query.utils.ts +21 -21
  243. package/src/test-utils/db-utils.ts +33 -33
  244. package/src/test-utils/factories/index.ts +18 -20
  245. package/src/test-utils/factories/municipal/cities.ts +16 -16
  246. package/src/test-utils/factories/municipal/departmentsSubjects.ts +37 -37
  247. package/src/test-utils/factories/municipal/muniIssues.ts +32 -32
  248. package/src/test-utils/factories/municipal/streets.ts +22 -22
  249. package/src/test-utils/factories/municipal/tickets.ts +39 -39
  250. package/src/test-utils/factories/talkpilot/agents.ts +19 -19
  251. package/src/test-utils/factories/talkpilot/calls.ts +37 -37
  252. package/src/test-utils/factories/talkpilot/clientAudioBuffers.ts +20 -20
  253. package/src/test-utils/factories/talkpilot/clientsConfig.ts +18 -18
  254. package/src/test-utils/factories/talkpilot/contextNotes.ts +40 -40
  255. package/src/test-utils/factories/talkpilot/flows.ts +33 -33
  256. package/src/test-utils/factories/talkpilot/groups.ts +33 -33
  257. package/src/test-utils/factories/talkpilot/phone_numbers.ts +22 -22
  258. package/src/test-utils/factories/talkpilot/sessions.ts +35 -35
  259. package/src/test-utils/factories/websitalk/knowledgeDocuments.ts +29 -29
  260. package/src/test-utils/factories/websitalk/scanResources.ts +26 -26
  261. package/src/test-utils/factories/websitalk/scans.ts +30 -30
  262. package/src/test-utils/factories/websitalk/websiteUrls.ts +17 -17
  263. package/src/utils/date.utils.ts +126 -126
  264. package/src/utils/shared.types.ts +4 -4
  265. package/src/utils/validation.ts +23 -23
  266. package/src/websitalk/index.ts +18 -18
  267. package/src/websitalk/knowledgeDocuments/__tests__/knowledgeDocuments.spec.ts +238 -238
  268. package/src/websitalk/knowledgeDocuments/index.ts +3 -3
  269. package/src/websitalk/knowledgeDocuments/knowledgeDocuments.constants.ts +26 -26
  270. package/src/websitalk/knowledgeDocuments/knowledgeDocuments.getters.ts +95 -95
  271. package/src/websitalk/knowledgeDocuments/knowledgeDocuments.types.ts +75 -75
  272. package/src/websitalk/mongodb-client.ts +61 -61
  273. package/src/websitalk/scanResources/__tests__/scanResources.spec.ts +267 -267
  274. package/src/websitalk/scanResources/index.ts +4 -4
  275. package/src/websitalk/scanResources/scanResources.constants.ts +60 -60
  276. package/src/websitalk/scanResources/scanResources.getters.ts +128 -128
  277. package/src/websitalk/scanResources/scanResources.types.ts +105 -105
  278. package/src/websitalk/scanResources/scanResources.utils.ts +31 -31
  279. package/src/websitalk/scans/__tests__/scans.spec.ts +362 -362
  280. package/src/websitalk/scans/index.ts +4 -4
  281. package/src/websitalk/scans/scans.constants.ts +18 -18
  282. package/src/websitalk/scans/scans.getters.ts +172 -172
  283. package/src/websitalk/scans/scans.types.ts +58 -58
  284. package/src/websitalk/scans/scans.utils.ts +5 -5
  285. package/src/websitalk/websiteUrls/__tests__/websiteUrls.spec.ts +77 -77
  286. package/src/websitalk/websiteUrls/index.ts +2 -2
  287. package/src/websitalk/websiteUrls/websiteUrls.getters.ts +65 -65
  288. package/src/websitalk/websiteUrls/websiteUrls.types.ts +13 -13
  289. package/tsconfig.json +23 -23
  290. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts +0 -8
  291. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts.map +0 -1
  292. package/dist/talkpilot/auditLogs/auditLogs.getters.js +0 -26
  293. package/dist/talkpilot/auditLogs/auditLogs.getters.js.map +0 -1
  294. package/dist/talkpilot/auditLogs/auditLogs.setters.d.ts +0 -3
  295. package/dist/talkpilot/auditLogs/auditLogs.setters.d.ts.map +0 -1
  296. package/dist/talkpilot/auditLogs/auditLogs.setters.js +0 -9
  297. package/dist/talkpilot/auditLogs/auditLogs.setters.js.map +0 -1
  298. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts +0 -11
  299. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts.map +0 -1
  300. package/dist/talkpilot/auditLogs/auditLogs.types.js.map +0 -1
  301. package/dist/talkpilot/auditLogs/index.d.ts +0 -3
  302. package/dist/talkpilot/auditLogs/index.d.ts.map +0 -1
  303. package/dist/talkpilot/auditLogs/index.js.map +0 -1
  304. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.d.ts +0 -4
  305. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.d.ts.map +0 -1
  306. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.js +0 -9
  307. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.js.map +0 -1
  308. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.d.ts +0 -3
  309. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.d.ts.map +0 -1
  310. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.js +0 -9
  311. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.js.map +0 -1
  312. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.d.ts +0 -10
  313. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.d.ts.map +0 -1
  314. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.js.map +0 -1
  315. package/dist/talkpilot/clientDeletionLogs/index.d.ts +0 -4
  316. package/dist/talkpilot/clientDeletionLogs/index.d.ts.map +0 -1
  317. package/dist/talkpilot/clientDeletionLogs/index.js.map +0 -1
  318. package/dist/talkpilot/clients/clients.constants.d.ts +0 -3
  319. package/dist/talkpilot/clients/clients.constants.d.ts.map +0 -1
  320. package/dist/talkpilot/clients/clients.constants.js +0 -6
  321. package/dist/talkpilot/clients/clients.constants.js.map +0 -1
  322. package/dist/talkpilot/clients/clients.lifecycle.d.ts +0 -10
  323. package/dist/talkpilot/clients/clients.lifecycle.d.ts.map +0 -1
  324. package/dist/talkpilot/clients/clients.lifecycle.js +0 -95
  325. package/dist/talkpilot/clients/clients.lifecycle.js.map +0 -1
  326. package/dist/talkpilot/results/results.constants.d.ts +0 -4
  327. package/dist/talkpilot/results/results.constants.d.ts.map +0 -1
  328. package/dist/talkpilot/results/results.constants.js +0 -10
  329. package/dist/talkpilot/results/results.constants.js.map +0 -1
  330. package/dist/talkpilot/results/results.statistics.getters.d.ts +0 -12
  331. package/dist/talkpilot/results/results.statistics.getters.d.ts.map +0 -1
  332. package/dist/talkpilot/results/results.statistics.getters.js +0 -258
  333. package/dist/talkpilot/results/results.statistics.getters.js.map +0 -1
  334. package/dist/talkpilot/results/results.statistics.types.d.ts +0 -22
  335. package/dist/talkpilot/results/results.statistics.types.d.ts.map +0 -1
  336. package/dist/talkpilot/results/results.statistics.types.js +0 -3
  337. package/dist/talkpilot/results/results.statistics.types.js.map +0 -1
  338. package/dist/test-utils/factories/talkpilot/clients.d.ts +0 -14
  339. package/dist/test-utils/factories/talkpilot/clients.d.ts.map +0 -1
  340. package/dist/test-utils/factories/talkpilot/clients.js +0 -19
  341. package/dist/test-utils/factories/talkpilot/clients.js.map +0 -1
  342. package/dist/test-utils/factories/talkpilot/results.d.ts +0 -16
  343. package/dist/test-utils/factories/talkpilot/results.d.ts.map +0 -1
  344. package/dist/test-utils/factories/talkpilot/results.js +0 -40
  345. package/dist/test-utils/factories/talkpilot/results.js.map +0 -1
  346. package/src/talkpilot/auditLogs/__tests__/auditLogs.spec.ts +0 -91
  347. package/src/talkpilot/auditLogs/auditLogs.getters.ts +0 -26
  348. package/src/talkpilot/auditLogs/auditLogs.types.ts +0 -12
  349. package/src/talkpilot/auditLogs/index.ts +0 -2
  350. package/src/talkpilot/calls/__tests__/calls.statistics.getters.spec.ts +0 -374
  351. package/src/talkpilot/clients/__tests__/clients.getters.spec.ts +0 -51
  352. package/src/talkpilot/clients/__tests__/clients.lifecycle.spec.ts +0 -166
  353. package/src/talkpilot/clients/clients.constants.ts +0 -2
  354. package/src/talkpilot/clients/clients.lifecycle.ts +0 -116
  355. package/src/test-utils/factories/talkpilot/clients.ts +0 -21
  356. package/src/test-utils/factories/talkpilot/results.ts +0 -43
@@ -1,374 +0,0 @@
1
- import { ObjectId } from "mongodb";
2
- import {
3
- aggregateActiveCallsSummary,
4
- aggregateTodayCallsSummary,
5
- aggregateClientCallStats,
6
- aggregateSessionCallStats,
7
- getAllClientsLastCallDate,
8
- findClientIdsByCallSids,
9
- getCallsCollection,
10
- } from "../calls.getters";
11
- import { getSessionsCollection } from "../../sessions/sessions.getter";
12
- import type { Call } from "../calls.types";
13
- import {
14
- createOutGoingCallDoc,
15
- createIncomingCallDoc,
16
- createSession,
17
- } from "../../../test-utils/factories";
18
-
19
- const insertCall = (call: Call) =>
20
- getCallsCollection().insertOne({ ...call, env: call.env ?? "test" });
21
-
22
- describe("calls.getters statistics", () => {
23
- describe("aggregateActiveCallsSummary", () => {
24
- it("should count distinct active calls within the last 2 hours, split incoming/outgoing", async () => {
25
- const now = new Date();
26
- await Promise.all([
27
- insertCall(createIncomingCallDoc({ clientId: "clientA", status: "in-progress", updatedAt: now })),
28
- insertCall(createOutGoingCallDoc({ clientId: "clientB", status: "in-progress", updatedAt: now })),
29
- insertCall(createIncomingCallDoc({ clientId: "clientC", status: "completed", updatedAt: now })),
30
- ]);
31
-
32
- const summary = await aggregateActiveCallsSummary();
33
-
34
- expect(summary.total).toBe(2);
35
- expect(summary.incoming).toBe(1);
36
- expect(summary.outgoing).toBe(1);
37
- expect(summary.activeClientIds.sort()).toEqual(["clientA", "clientB"]);
38
- });
39
-
40
- it("should filter by clientId when provided", async () => {
41
- const now = new Date();
42
- await Promise.all([
43
- insertCall(createOutGoingCallDoc({ clientId: "onlyThisClient", status: "in-progress", updatedAt: now })),
44
- insertCall(createOutGoingCallDoc({ clientId: "otherClient", status: "in-progress", updatedAt: now })),
45
- ]);
46
-
47
- const summary = await aggregateActiveCallsSummary("onlyThisClient");
48
- expect(summary.total).toBe(1);
49
- expect(summary.activeClientIds).toEqual(["onlyThisClient"]);
50
- });
51
-
52
- it("should exclude calls whose updatedAt is older than 2 hours", async () => {
53
- const threeHoursAgo = new Date(Date.now() - 3 * 60 * 60 * 1000);
54
- await insertCall(createOutGoingCallDoc({ status: "in-progress", updatedAt: threeHoursAgo }));
55
-
56
- const summary = await aggregateActiveCallsSummary();
57
- expect(summary.total).toBe(0);
58
- });
59
- });
60
-
61
- describe("aggregateTodayCallsSummary", () => {
62
- it("should aggregate status/type counts and total minutes within the given date range", async () => {
63
- const today = new Date().toISOString().slice(0, 10);
64
- await Promise.all([
65
- insertCall(createIncomingCallDoc({ status: "completed", callLength: 120, createdAt: new Date() })),
66
- insertCall(createOutGoingCallDoc({ status: "failed", callLength: 30, createdAt: new Date() })),
67
- ]);
68
-
69
- const summary = await aggregateTodayCallsSummary({ dateFrom: today, dateTo: today });
70
-
71
- expect(summary.total).toBe(2);
72
- expect(summary.incoming).toBe(1);
73
- expect(summary.outgoing).toBe(1);
74
- expect(summary.completed).toBe(1);
75
- expect(summary.failed).toBe(1);
76
- expect(summary.totalMinutes).toBe(3); // ceil(150/60)
77
- });
78
-
79
- it("should respect the given timezone when resolving an explicit date", async () => {
80
- // 23:30 UTC on 2026-01-01 is already 2026-01-02 in Asia/Jerusalem (+2).
81
- const lateUtc = new Date("2026-01-01T23:30:00.000Z");
82
- await insertCall(createOutGoingCallDoc({ status: "completed", createdAt: lateUtc }));
83
-
84
- const summaryUtc = await aggregateTodayCallsSummary({
85
- dateFrom: "2026-01-01",
86
- dateTo: "2026-01-01",
87
- timezone: "UTC",
88
- });
89
- expect(summaryUtc.total).toBe(1);
90
-
91
- const summaryJerusalem = await aggregateTodayCallsSummary({
92
- dateFrom: "2026-01-01",
93
- dateTo: "2026-01-01",
94
- timezone: "Asia/Jerusalem",
95
- });
96
- expect(summaryJerusalem.total).toBe(0);
97
- });
98
-
99
- it("should include a call's full history (not just today) when no date range is given", async () => {
100
- const sixMonthsAgo = new Date(Date.now() - 180 * 24 * 60 * 60 * 1000);
101
- await insertCall(createOutGoingCallDoc({ status: "completed", createdAt: sixMonthsAgo }));
102
-
103
- const summary = await aggregateTodayCallsSummary({});
104
- expect(summary.total).toBe(1);
105
- });
106
- });
107
-
108
- describe("aggregateClientCallStats", () => {
109
- it("should group call counts and minutes by clientId", async () => {
110
- const today = new Date().toISOString().slice(0, 10);
111
- await Promise.all([
112
- insertCall(
113
- createOutGoingCallDoc({ clientId: "clientX", status: "completed", callLength: 60, createdAt: new Date() }),
114
- ),
115
- insertCall(
116
- createOutGoingCallDoc({ clientId: "clientX", status: "failed", callLength: 60, createdAt: new Date() }),
117
- ),
118
- ]);
119
-
120
- const rows = await aggregateClientCallStats({ dateFrom: today, dateTo: today });
121
- const row = rows.find((r) => r.clientId === "clientX");
122
-
123
- expect(row?.totalCalls).toBe(2);
124
- expect(row?.statusCounts).toMatchObject({ completed: 1, failed: 1 });
125
- expect(row?.totalMinutes).toBe(2);
126
- });
127
-
128
- it("should not include other clients when filtered by clientId", async () => {
129
- const today = new Date().toISOString().slice(0, 10);
130
- await Promise.all([
131
- insertCall(createOutGoingCallDoc({ clientId: "wantedClient", status: "completed", createdAt: new Date() })),
132
- insertCall(createOutGoingCallDoc({ clientId: "unwantedClient", status: "completed", createdAt: new Date() })),
133
- ]);
134
-
135
- const rows = await aggregateClientCallStats({
136
- dateFrom: today,
137
- dateTo: today,
138
- clientId: "wantedClient",
139
- });
140
-
141
- expect(rows).toHaveLength(1);
142
- expect(rows[0].clientId).toBe("wantedClient");
143
- });
144
-
145
- it("should include a client's full history when no date range is given", async () => {
146
- const sixMonthsAgo = new Date(Date.now() - 180 * 24 * 60 * 60 * 1000);
147
- await Promise.all([
148
- insertCall(createOutGoingCallDoc({ clientId: "longHistoryClient", status: "completed", createdAt: sixMonthsAgo })),
149
- insertCall(createOutGoingCallDoc({ clientId: "longHistoryClient", status: "completed", createdAt: new Date() })),
150
- ]);
151
-
152
- const rows = await aggregateClientCallStats({});
153
- const row = rows.find((r) => r.clientId === "longHistoryClient");
154
-
155
- expect(row?.totalCalls).toBe(2);
156
- });
157
-
158
- it("should set lastCallDate to the most recent call", async () => {
159
- const earlierCall = new Date("2026-01-01T00:00:00.000Z");
160
- const laterCall = new Date("2026-03-10T00:00:00.000Z");
161
- await Promise.all([
162
- insertCall(createOutGoingCallDoc({ clientId: "lastCallDateClient", status: "completed", createdAt: earlierCall })),
163
- insertCall(createOutGoingCallDoc({ clientId: "lastCallDateClient", status: "completed", createdAt: laterCall })),
164
- ]);
165
-
166
- const rows = await aggregateClientCallStats({});
167
- const row = rows.find((r) => r.clientId === "lastCallDateClient");
168
-
169
- expect(row?.lastCallDate).toEqual(laterCall);
170
- });
171
-
172
- it("should filter by clientId alone when no date range is given", async () => {
173
- await Promise.all([
174
- insertCall(createOutGoingCallDoc({ clientId: "onlyThisClientNoRange", status: "completed", createdAt: new Date() })),
175
- insertCall(createOutGoingCallDoc({ clientId: "otherClientNoRange", status: "completed", createdAt: new Date() })),
176
- ]);
177
-
178
- const rows = await aggregateClientCallStats({ clientId: "onlyThisClientNoRange" });
179
-
180
- expect(rows).toHaveLength(1);
181
- expect(rows[0].clientId).toBe("onlyThisClientNoRange");
182
- });
183
-
184
- it("should count every real status separately, including queued; a missing status only inflates totalCalls", async () => {
185
- const today = new Date().toISOString().slice(0, 10);
186
- await Promise.all([
187
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "completed", createdAt: new Date() })),
188
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "canceled", createdAt: new Date() })),
189
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "queued" as any, createdAt: new Date() })),
190
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "ringing", createdAt: new Date() })),
191
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "initiated", createdAt: new Date() })),
192
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: "answered", createdAt: new Date() })),
193
- insertCall(createOutGoingCallDoc({ clientId: "statusBucketClient", status: undefined, createdAt: new Date() })),
194
- ]);
195
-
196
- const rows = await aggregateClientCallStats({ dateFrom: today, dateTo: today });
197
- const row = rows.find((r) => r.clientId === "statusBucketClient");
198
-
199
- expect(row?.totalCalls).toBe(7);
200
- expect(row?.statusCounts).toMatchObject({
201
- completed: 1,
202
- canceled: 1,
203
- queued: 1,
204
- ringing: 1,
205
- initiated: 1,
206
- answered: 1,
207
- });
208
- });
209
- });
210
-
211
- describe("aggregateSessionCallStats", () => {
212
- it("should group by sessionId and resolve the session's current name via the sessions collection", async () => {
213
- const today = new Date().toISOString().slice(0, 10);
214
- const sessionId = new ObjectId();
215
- await getSessionsCollection().insertOne(createSession({ _id: sessionId, session_name: "My Session" }));
216
- await insertCall(
217
- createOutGoingCallDoc({ sessionId, status: "completed", createdAt: new Date() }),
218
- );
219
-
220
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
221
- const row = rows.find((r) => r.sessionId === sessionId.toString());
222
-
223
- expect(row).toMatchObject({ sessionName: "My Session", totalCalls: 1 });
224
- expect(row?.statusCounts).toMatchObject({ completed: 1 });
225
- });
226
-
227
- it("should always show the session's current name, even if it was renamed after some calls happened", async () => {
228
- const today = new Date().toISOString().slice(0, 10);
229
- const sessionId = new ObjectId();
230
- const earlierCall = new Date(Date.now() - 60 * 60 * 1000);
231
- const laterCall = new Date();
232
-
233
- await getSessionsCollection().insertOne(createSession({ _id: sessionId, session_name: "New Name" }));
234
- await Promise.all([
235
- insertCall(createOutGoingCallDoc({ sessionId, status: "completed", createdAt: earlierCall })),
236
- insertCall(createOutGoingCallDoc({ sessionId, status: "completed", createdAt: laterCall })),
237
- ]);
238
-
239
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
240
- const merged = rows.find((r) => r.sessionId === sessionId.toString());
241
-
242
- expect(merged).toMatchObject({ sessionName: "New Name", totalCalls: 2 });
243
- expect(merged?.statusCounts).toMatchObject({ completed: 2 });
244
- });
245
-
246
- it("should show 'Unknown' when the session no longer exists in the sessions collection", async () => {
247
- const today = new Date().toISOString().slice(0, 10);
248
- const orphanedSessionId = new ObjectId();
249
- await insertCall(createOutGoingCallDoc({ sessionId: orphanedSessionId, status: "completed", createdAt: new Date() }));
250
-
251
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
252
- const row = rows.find((r) => r.sessionId === orphanedSessionId.toString());
253
-
254
- expect(row?.sessionName).toBe("Unknown");
255
- });
256
-
257
- it("should label a null sessionId as 'Incoming Call', not 'Unknown' — a call with no session is expected, not broken data", async () => {
258
- const today = new Date().toISOString().slice(0, 10);
259
- await Promise.all([
260
- insertCall(createIncomingCallDoc({ status: "completed", createdAt: new Date() })),
261
- insertCall(createIncomingCallDoc({ status: "failed", createdAt: new Date() })),
262
- ]);
263
-
264
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
265
- const row = rows.find((r) => r.sessionName === "Incoming Call");
266
-
267
- expect(row).toBeDefined();
268
- expect(row?.totalCalls).toBe(2);
269
- expect(row?.statusCounts).toMatchObject({ completed: 1, failed: 1 });
270
- expect(row?.sessionName).not.toBe("Unknown");
271
- });
272
-
273
- it("should only include the given client's sessions when clientId is provided", async () => {
274
- const today = new Date().toISOString().slice(0, 10);
275
- const sessionA = new ObjectId();
276
- const sessionB = new ObjectId();
277
- await getSessionsCollection().insertMany([
278
- createSession({ _id: sessionA, session_name: "Session A" }),
279
- createSession({ _id: sessionB, session_name: "Session B" }),
280
- ]);
281
- await Promise.all([
282
- insertCall(createOutGoingCallDoc({ clientId: "clientA", sessionId: sessionA, status: "completed", createdAt: new Date() })),
283
- insertCall(createOutGoingCallDoc({ clientId: "clientB", sessionId: sessionB, status: "completed", createdAt: new Date() })),
284
- ]);
285
-
286
- const rows = await aggregateSessionCallStats({
287
- dateFrom: today,
288
- dateTo: today,
289
- clientId: "clientA",
290
- });
291
-
292
- expect(rows).toHaveLength(1);
293
- expect(rows[0]).toMatchObject({ sessionId: sessionA.toString(), sessionName: "Session A" });
294
- });
295
-
296
- it("should exclude a session with no calls in the given date range", async () => {
297
- const today = new Date().toISOString().slice(0, 10);
298
- const longAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
299
- const oldSessionId = new ObjectId();
300
- await getSessionsCollection().insertOne(createSession({ _id: oldSessionId, session_name: "Old Session" }));
301
- await insertCall(createOutGoingCallDoc({ sessionId: oldSessionId, status: "completed", createdAt: longAgo }));
302
-
303
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
304
-
305
- expect(rows.find((r) => r.sessionId === oldSessionId.toString())).toBeUndefined();
306
- });
307
-
308
- it("should include a session's full history when no date range is given", async () => {
309
- const longAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
310
- const sessionId = new ObjectId();
311
- await getSessionsCollection().insertOne(createSession({ _id: sessionId, session_name: "All Time Session" }));
312
- await insertCall(createOutGoingCallDoc({ sessionId, status: "completed", createdAt: longAgo }));
313
-
314
- const rows = await aggregateSessionCallStats({});
315
- const row = rows.find((r) => r.sessionId === sessionId.toString());
316
-
317
- expect(row?.totalCalls).toBe(1);
318
- });
319
-
320
- it("should count each real status separately, including queued", async () => {
321
- const today = new Date().toISOString().slice(0, 10);
322
- const sessionId = new ObjectId();
323
- await getSessionsCollection().insertOne(createSession({ _id: sessionId, session_name: "Bucket Session" }));
324
- await Promise.all([
325
- insertCall(createOutGoingCallDoc({ sessionId, status: "completed", createdAt: new Date() })),
326
- insertCall(createOutGoingCallDoc({ sessionId, status: "canceled", createdAt: new Date() })),
327
- insertCall(createOutGoingCallDoc({ sessionId, status: "queued" as any, createdAt: new Date() })),
328
- ]);
329
-
330
- const rows = await aggregateSessionCallStats({ dateFrom: today, dateTo: today });
331
- const row = rows.find((r) => r.sessionId === sessionId.toString());
332
-
333
- expect(row?.totalCalls).toBe(3);
334
- expect(row?.statusCounts).toMatchObject({ completed: 1, canceled: 1, queued: 1 });
335
- });
336
- });
337
-
338
- describe("getAllClientsLastCallDate", () => {
339
- it("should map each clientId to its most recent call, ignoring any date range", async () => {
340
- const earlierCall = new Date("2026-01-01T00:00:00.000Z");
341
- const laterCall = new Date("2026-03-10T00:00:00.000Z");
342
- await Promise.all([
343
- insertCall(createOutGoingCallDoc({ clientId: "lastCallMapClientA", status: "completed", createdAt: earlierCall })),
344
- insertCall(createOutGoingCallDoc({ clientId: "lastCallMapClientA", status: "completed", createdAt: laterCall })),
345
- insertCall(createOutGoingCallDoc({ clientId: "lastCallMapClientB", status: "completed", createdAt: earlierCall })),
346
- ]);
347
-
348
- const map = await getAllClientsLastCallDate();
349
-
350
- expect(map.get("lastCallMapClientA")).toEqual(laterCall);
351
- expect(map.get("lastCallMapClientB")).toEqual(earlierCall);
352
- });
353
- });
354
-
355
- describe("findClientIdsByCallSids", () => {
356
- it("should map each callSid to the clientId that owns it", async () => {
357
- await Promise.all([
358
- insertCall(createOutGoingCallDoc({ clientId: "clientA", callSid: "CAaaa" })),
359
- insertCall(createOutGoingCallDoc({ clientId: "clientB", callSid: "CAbbb" })),
360
- ]);
361
-
362
- const map = await findClientIdsByCallSids(["CAaaa", "CAbbb", "CAunknown"]);
363
-
364
- expect(map.get("CAaaa")).toBe("clientA");
365
- expect(map.get("CAbbb")).toBe("clientB");
366
- expect(map.has("CAunknown")).toBe(false);
367
- });
368
-
369
- it("should return an empty map when given no callSids", async () => {
370
- const map = await findClientIdsByCallSids([]);
371
- expect(map.size).toBe(0);
372
- });
373
- });
374
- });
@@ -1,51 +0,0 @@
1
- import { getClientsCollection, getAllClientCredits, getAllClientIds } from "../clients.getters";
2
- import { createClient } from "../../../test-utils/factories";
3
-
4
- describe("db.clients", () => {
5
- describe("getAllClientCredits", () => {
6
- it("should return a Map of clientId to credits across all clients", async () => {
7
- await getClientsCollection().insertMany([
8
- createClient({ clientId: "creditsClientA", credits: 100 }),
9
- createClient({ clientId: "creditsClientB", credits: 250 }),
10
- ]);
11
-
12
- const result = await getAllClientCredits();
13
-
14
- expect(result).toBeInstanceOf(Map);
15
- expect(result.get("creditsClientA")).toBe(100);
16
- expect(result.get("creditsClientB")).toBe(250);
17
- });
18
-
19
- it("should default missing credits to 0", async () => {
20
- const client = createClient({ clientId: "noCreditsClient" });
21
- delete (client as { credits?: number }).credits;
22
- await getClientsCollection().insertOne(client);
23
-
24
- const result = await getAllClientCredits();
25
- expect(result.get("noCreditsClient")).toBe(0);
26
- });
27
-
28
- it("should return an empty Map when there are no clients", async () => {
29
- const result = await getAllClientCredits();
30
- expect(result.size).toBe(0);
31
- });
32
- });
33
-
34
- describe("getAllClientIds", () => {
35
- it("should return the ids of all clients", async () => {
36
- await getClientsCollection().insertMany([
37
- createClient({ clientId: "idClientA" }),
38
- createClient({ clientId: "idClientB" }),
39
- ]);
40
-
41
- const result = await getAllClientIds();
42
-
43
- expect(result.sort()).toEqual(["idClientA", "idClientB"]);
44
- });
45
-
46
- it("should return an empty array when there are no clients", async () => {
47
- const result = await getAllClientIds();
48
- expect(result).toEqual([]);
49
- });
50
- });
51
- });
@@ -1,166 +0,0 @@
1
- import {
2
- clientExistsInAnyCollection,
3
- deleteClientDataAcrossDomains,
4
- } from "../clients.lifecycle";
5
- import { getPhoneNumbersCollection } from "../../phone_numbers/phone_numbers.getter";
6
- import {
7
- createMuniIssue,
8
- generateMuniIssueId,
9
- getAuditLogsCollection,
10
- getScansCollection,
11
- } from "../../../index";
12
- import {
13
- createPhoneNumber,
14
- createMuniIssueInput,
15
- createScanFixture,
16
- } from "../../../test-utils/factories";
17
-
18
- describe("db.clients.lifecycle", () => {
19
- describe("clientExistsInAnyCollection", () => {
20
- it("should return true when the client exists only in phone_numbers (client_id field)", async () => {
21
- const clientId = "existsPhoneOnly";
22
- await getPhoneNumbersCollection().insertOne(
23
- createPhoneNumber({ client_id: clientId }),
24
- );
25
-
26
- expect(await clientExistsInAnyCollection(clientId)).toBe(true);
27
- });
28
-
29
- it("should return true when the client exists only in muniIssues (municipal DB)", async () => {
30
- const clientId = "existsMuniOnly";
31
- await createMuniIssue(
32
- createMuniIssueInput({ clientId }),
33
- generateMuniIssueId(),
34
- );
35
-
36
- expect(await clientExistsInAnyCollection(clientId)).toBe(true);
37
- });
38
-
39
- it("should return false when the client does not exist anywhere", async () => {
40
- expect(await clientExistsInAnyCollection("noSuchClientAtAll")).toBe(
41
- false,
42
- );
43
- });
44
-
45
- it("should not consider websitalk data (scans/websiteUrls) at all", async () => {
46
- const clientId = "onlyInWebsitalk";
47
- await getScansCollection().insertOne(createScanFixture({ clientId }));
48
-
49
- expect(await clientExistsInAnyCollection(clientId)).toBe(false);
50
- });
51
-
52
- it("should not be fooled by unrelated collections lacking a clientId/client_id field", async () => {
53
- await global.db
54
- .collection("someUnrelatedCollection")
55
- .insertOne({ someField: "someValue" });
56
-
57
- expect(await clientExistsInAnyCollection("noSuchClientAtAll")).toBe(
58
- false,
59
- );
60
- });
61
- });
62
-
63
- describe("deleteClientDataAcrossDomains", () => {
64
- it("should return deleted:false with a reason and delete nothing when the client does not exist", async () => {
65
- await getPhoneNumbersCollection().insertOne(
66
- createPhoneNumber({ client_id: "unrelatedClient" }),
67
- );
68
-
69
- const summary = await deleteClientDataAcrossDomains(
70
- "missingClient",
71
- "admin@callai.co.il",
72
- );
73
-
74
- expect(summary.deleted).toBe(false);
75
- if (!summary.deleted) {
76
- expect(summary.reason).toBeTruthy();
77
- }
78
- expect(
79
- await getPhoneNumbersCollection().findOne({
80
- client_id: "unrelatedClient",
81
- }),
82
- ).not.toBeNull();
83
- });
84
-
85
- it("should not write an audit log entry when the client does not exist", async () => {
86
- await deleteClientDataAcrossDomains(
87
- "missingClientNoAudit",
88
- "admin@callai.co.il",
89
- );
90
-
91
- expect(
92
- await getAuditLogsCollection().findOne({
93
- clientId: "missingClientNoAudit",
94
- }),
95
- ).toBeNull();
96
- });
97
-
98
- it("should delete the client's data across talkpilot and municipal domains", async () => {
99
- const clientId = "deleteMeEverywhere";
100
- await getPhoneNumbersCollection().insertOne(
101
- createPhoneNumber({ client_id: clientId }),
102
- );
103
- await createMuniIssue(
104
- createMuniIssueInput({ clientId }),
105
- generateMuniIssueId(),
106
- );
107
-
108
- const adminEmail = "admin@callai.co.il";
109
- const summary = await deleteClientDataAcrossDomains(
110
- clientId,
111
- adminEmail,
112
- );
113
-
114
- expect(summary.deleted).toBe(true);
115
- if (summary.deleted) {
116
- expect(summary.allSucceeded).toBe(true);
117
- const byName = (name: string) =>
118
- summary.results.find((r) => r.collectionName === name);
119
- expect(byName("phone_numbers")?.deletedCount).toBe(1);
120
- expect(byName("muniIssues")?.deletedCount).toBe(1);
121
- }
122
-
123
- expect(await clientExistsInAnyCollection(clientId)).toBe(false);
124
-
125
- // The audit entry itself must survive the client's own deletion.
126
- const auditEntry = await getAuditLogsCollection().findOne({ clientId });
127
- expect(auditEntry).toMatchObject({
128
- clientId,
129
- adminEmail,
130
- action: "delete",
131
- });
132
- expect(auditEntry?.timestamp).toBeInstanceOf(Date);
133
- });
134
-
135
- it("should not touch websitalk data (scans/websiteUrls) — callers must call the external website-talk deletion API separately", async () => {
136
- const clientId = "hasWebsitalkData";
137
- await getPhoneNumbersCollection().insertOne(
138
- createPhoneNumber({ client_id: clientId }),
139
- );
140
- await getScansCollection().insertOne(createScanFixture({ clientId }));
141
-
142
- await deleteClientDataAcrossDomains(clientId, "admin@callai.co.il");
143
-
144
- expect(
145
- await getScansCollection().findOne({ clientId }),
146
- ).not.toBeNull();
147
- });
148
-
149
- it("should not delete unrelated clients' data", async () => {
150
- const targetClient = "deleteTarget";
151
- const otherClient = "keepMeClient";
152
- await getPhoneNumbersCollection().insertOne(
153
- createPhoneNumber({ client_id: targetClient }),
154
- );
155
- await getPhoneNumbersCollection().insertOne(
156
- createPhoneNumber({ client_id: otherClient }),
157
- );
158
-
159
- await deleteClientDataAcrossDomains(targetClient, "admin@callai.co.il");
160
-
161
- expect(
162
- await getPhoneNumbersCollection().findOne({ client_id: otherClient }),
163
- ).not.toBeNull();
164
- });
165
- });
166
- });
@@ -1,2 +0,0 @@
1
- /** Collections to always skip during client deletion — e.g. auditLogs, which must survive it. */
2
- export const DELETE_DENYLIST: string[] = ["auditLogs"];