@talkpilot/core-db 1.0.1

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 (410) hide show
  1. package/.cursor/rules/development.mdc +65 -0
  2. package/DEVELOPMENT.md +98 -0
  3. package/README.md +140 -0
  4. package/dist/index.d.ts +7 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +29 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/municipal/cities/cities.getters.d.ts +9 -0
  9. package/dist/municipal/cities/cities.getters.d.ts.map +1 -0
  10. package/dist/municipal/cities/cities.getters.js +38 -0
  11. package/dist/municipal/cities/cities.getters.js.map +1 -0
  12. package/dist/municipal/cities/cities.types.d.ts +10 -0
  13. package/dist/municipal/cities/cities.types.d.ts.map +1 -0
  14. package/dist/municipal/cities/cities.types.js +3 -0
  15. package/dist/municipal/cities/cities.types.js.map +1 -0
  16. package/dist/municipal/cities/index.d.ts +3 -0
  17. package/dist/municipal/cities/index.d.ts.map +1 -0
  18. package/dist/municipal/cities/index.js +18 -0
  19. package/dist/municipal/cities/index.js.map +1 -0
  20. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.d.ts +62 -0
  21. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.d.ts.map +1 -0
  22. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.js +180 -0
  23. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.js.map +1 -0
  24. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.d.ts +69 -0
  25. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.d.ts.map +1 -0
  26. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.js +3 -0
  27. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.js.map +1 -0
  28. package/dist/municipal/departmentsSubjects/index.d.ts +3 -0
  29. package/dist/municipal/departmentsSubjects/index.d.ts.map +1 -0
  30. package/dist/municipal/departmentsSubjects/index.js +18 -0
  31. package/dist/municipal/departmentsSubjects/index.js.map +1 -0
  32. package/dist/municipal/index.d.ts +10 -0
  33. package/dist/municipal/index.d.ts.map +1 -0
  34. package/dist/municipal/index.js +37 -0
  35. package/dist/municipal/index.js.map +1 -0
  36. package/dist/municipal/mongodb-client.d.ts +13 -0
  37. package/dist/municipal/mongodb-client.d.ts.map +1 -0
  38. package/dist/municipal/mongodb-client.js +56 -0
  39. package/dist/municipal/mongodb-client.js.map +1 -0
  40. package/dist/municipal/streets/index.d.ts +3 -0
  41. package/dist/municipal/streets/index.d.ts.map +1 -0
  42. package/dist/municipal/streets/index.js +18 -0
  43. package/dist/municipal/streets/index.js.map +1 -0
  44. package/dist/municipal/streets/streets.getters.d.ts +21 -0
  45. package/dist/municipal/streets/streets.getters.d.ts.map +1 -0
  46. package/dist/municipal/streets/streets.getters.js +85 -0
  47. package/dist/municipal/streets/streets.getters.js.map +1 -0
  48. package/dist/municipal/streets/streets.types.d.ts +16 -0
  49. package/dist/municipal/streets/streets.types.d.ts.map +1 -0
  50. package/dist/municipal/streets/streets.types.js +3 -0
  51. package/dist/municipal/streets/streets.types.js.map +1 -0
  52. package/dist/municipal/tickets/index.d.ts +3 -0
  53. package/dist/municipal/tickets/index.d.ts.map +1 -0
  54. package/dist/municipal/tickets/index.js +18 -0
  55. package/dist/municipal/tickets/index.js.map +1 -0
  56. package/dist/municipal/tickets/tickets.getters.d.ts +44 -0
  57. package/dist/municipal/tickets/tickets.getters.d.ts.map +1 -0
  58. package/dist/municipal/tickets/tickets.getters.js +199 -0
  59. package/dist/municipal/tickets/tickets.getters.js.map +1 -0
  60. package/dist/municipal/tickets/tickets.types.d.ts +35 -0
  61. package/dist/municipal/tickets/tickets.types.d.ts.map +1 -0
  62. package/dist/municipal/tickets/tickets.types.js +3 -0
  63. package/dist/municipal/tickets/tickets.types.js.map +1 -0
  64. package/dist/talkpilot/agents/agents.getters.d.ts +9 -0
  65. package/dist/talkpilot/agents/agents.getters.d.ts.map +1 -0
  66. package/dist/talkpilot/agents/agents.getters.js +34 -0
  67. package/dist/talkpilot/agents/agents.getters.js.map +1 -0
  68. package/dist/talkpilot/agents/agents.types.d.ts +13 -0
  69. package/dist/talkpilot/agents/agents.types.d.ts.map +1 -0
  70. package/dist/talkpilot/agents/agents.types.js +3 -0
  71. package/dist/talkpilot/agents/agents.types.js.map +1 -0
  72. package/dist/talkpilot/agents/index.d.ts +3 -0
  73. package/dist/talkpilot/agents/index.d.ts.map +1 -0
  74. package/dist/talkpilot/agents/index.js +19 -0
  75. package/dist/talkpilot/agents/index.js.map +1 -0
  76. package/dist/talkpilot/calls/calls.getters.d.ts +24 -0
  77. package/dist/talkpilot/calls/calls.getters.d.ts.map +1 -0
  78. package/dist/talkpilot/calls/calls.getters.js +151 -0
  79. package/dist/talkpilot/calls/calls.getters.js.map +1 -0
  80. package/dist/talkpilot/calls/calls.types.d.ts +32 -0
  81. package/dist/talkpilot/calls/calls.types.d.ts.map +1 -0
  82. package/dist/talkpilot/calls/calls.types.js +3 -0
  83. package/dist/talkpilot/calls/calls.types.js.map +1 -0
  84. package/dist/talkpilot/calls/index.d.ts +3 -0
  85. package/dist/talkpilot/calls/index.d.ts.map +1 -0
  86. package/dist/talkpilot/calls/index.js +19 -0
  87. package/dist/talkpilot/calls/index.js.map +1 -0
  88. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.d.ts +9 -0
  89. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.d.ts.map +1 -0
  90. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.js +76 -0
  91. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.js.map +1 -0
  92. package/dist/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.d.ts +23 -0
  93. package/dist/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.d.ts.map +1 -0
  94. package/dist/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.js +3 -0
  95. package/dist/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.js.map +1 -0
  96. package/dist/talkpilot/clients/clients.getters.d.ts +5 -0
  97. package/dist/talkpilot/clients/clients.getters.d.ts.map +1 -0
  98. package/dist/talkpilot/clients/clients.getters.js +14 -0
  99. package/dist/talkpilot/clients/clients.getters.js.map +1 -0
  100. package/dist/talkpilot/clients/clients.types.d.ts +12 -0
  101. package/dist/talkpilot/clients/clients.types.d.ts.map +1 -0
  102. package/dist/talkpilot/clients/clients.types.js +3 -0
  103. package/dist/talkpilot/clients/clients.types.js.map +1 -0
  104. package/dist/talkpilot/clients/index.d.ts +3 -0
  105. package/dist/talkpilot/clients/index.d.ts.map +1 -0
  106. package/dist/talkpilot/clients/index.js +18 -0
  107. package/dist/talkpilot/clients/index.js.map +1 -0
  108. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts +7 -0
  109. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts.map +1 -0
  110. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js +21 -0
  111. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js.map +1 -0
  112. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts +53 -0
  113. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts.map +1 -0
  114. package/dist/talkpilot/clientsConfig/clientsConfig.types.js +3 -0
  115. package/dist/talkpilot/clientsConfig/clientsConfig.types.js.map +1 -0
  116. package/dist/talkpilot/clientsConfig/index.d.ts +3 -0
  117. package/dist/talkpilot/clientsConfig/index.d.ts.map +1 -0
  118. package/dist/talkpilot/clientsConfig/index.js +19 -0
  119. package/dist/talkpilot/clientsConfig/index.js.map +1 -0
  120. package/dist/talkpilot/flows/flows.getter.d.ts +5 -0
  121. package/dist/talkpilot/flows/flows.getter.d.ts.map +1 -0
  122. package/dist/talkpilot/flows/flows.getter.js +13 -0
  123. package/dist/talkpilot/flows/flows.getter.js.map +1 -0
  124. package/dist/talkpilot/flows/flows.schema.d.ts +154 -0
  125. package/dist/talkpilot/flows/flows.schema.d.ts.map +1 -0
  126. package/dist/talkpilot/flows/flows.schema.js +94 -0
  127. package/dist/talkpilot/flows/flows.schema.js.map +1 -0
  128. package/dist/talkpilot/flows/flows.types.d.ts +116 -0
  129. package/dist/talkpilot/flows/flows.types.d.ts.map +1 -0
  130. package/dist/talkpilot/flows/flows.types.js +3 -0
  131. package/dist/talkpilot/flows/flows.types.js.map +1 -0
  132. package/dist/talkpilot/flows/index.d.ts +3 -0
  133. package/dist/talkpilot/flows/index.d.ts.map +1 -0
  134. package/dist/talkpilot/flows/index.js +6 -0
  135. package/dist/talkpilot/flows/index.js.map +1 -0
  136. package/dist/talkpilot/groups/groups.getters.d.ts +8 -0
  137. package/dist/talkpilot/groups/groups.getters.d.ts.map +1 -0
  138. package/dist/talkpilot/groups/groups.getters.js +26 -0
  139. package/dist/talkpilot/groups/groups.getters.js.map +1 -0
  140. package/dist/talkpilot/groups/groups.types.d.ts +26 -0
  141. package/dist/talkpilot/groups/groups.types.d.ts.map +1 -0
  142. package/dist/talkpilot/groups/groups.types.js +3 -0
  143. package/dist/talkpilot/groups/groups.types.js.map +1 -0
  144. package/dist/talkpilot/groups/index.d.ts +3 -0
  145. package/dist/talkpilot/groups/index.d.ts.map +1 -0
  146. package/dist/talkpilot/groups/index.js +19 -0
  147. package/dist/talkpilot/groups/index.js.map +1 -0
  148. package/dist/talkpilot/groups/phone.utils.d.ts +4 -0
  149. package/dist/talkpilot/groups/phone.utils.d.ts.map +1 -0
  150. package/dist/talkpilot/groups/phone.utils.js +42 -0
  151. package/dist/talkpilot/groups/phone.utils.js.map +1 -0
  152. package/dist/talkpilot/index.d.ts +19 -0
  153. package/dist/talkpilot/index.d.ts.map +1 -0
  154. package/dist/talkpilot/index.js +46 -0
  155. package/dist/talkpilot/index.js.map +1 -0
  156. package/dist/talkpilot/leads/index.d.ts +3 -0
  157. package/dist/talkpilot/leads/index.d.ts.map +1 -0
  158. package/dist/talkpilot/leads/index.js +6 -0
  159. package/dist/talkpilot/leads/index.js.map +1 -0
  160. package/dist/talkpilot/leads/leads.getter.d.ts +4 -0
  161. package/dist/talkpilot/leads/leads.getter.d.ts.map +1 -0
  162. package/dist/talkpilot/leads/leads.getter.js +7 -0
  163. package/dist/talkpilot/leads/leads.getter.js.map +1 -0
  164. package/dist/talkpilot/leads/leads.schema.d.ts +50 -0
  165. package/dist/talkpilot/leads/leads.schema.d.ts.map +1 -0
  166. package/dist/talkpilot/leads/leads.schema.js +37 -0
  167. package/dist/talkpilot/leads/leads.schema.js.map +1 -0
  168. package/dist/talkpilot/leads/leads.types.d.ts +18 -0
  169. package/dist/talkpilot/leads/leads.types.d.ts.map +1 -0
  170. package/dist/talkpilot/leads/leads.types.js +3 -0
  171. package/dist/talkpilot/leads/leads.types.js.map +1 -0
  172. package/dist/talkpilot/mongodb-client.d.ts +13 -0
  173. package/dist/talkpilot/mongodb-client.d.ts.map +1 -0
  174. package/dist/talkpilot/mongodb-client.js +71 -0
  175. package/dist/talkpilot/mongodb-client.js.map +1 -0
  176. package/dist/talkpilot/phone_numbers/index.d.ts +3 -0
  177. package/dist/talkpilot/phone_numbers/index.d.ts.map +1 -0
  178. package/dist/talkpilot/phone_numbers/index.js +18 -0
  179. package/dist/talkpilot/phone_numbers/index.js.map +1 -0
  180. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +8 -0
  181. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -0
  182. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +44 -0
  183. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -0
  184. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts +29 -0
  185. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts.map +1 -0
  186. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js +18 -0
  187. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js.map +1 -0
  188. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts +16 -0
  189. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts.map +1 -0
  190. package/dist/talkpilot/phone_numbers/phone_numbers.types.js +3 -0
  191. package/dist/talkpilot/phone_numbers/phone_numbers.types.js.map +1 -0
  192. package/dist/talkpilot/plans/index.d.ts +3 -0
  193. package/dist/talkpilot/plans/index.d.ts.map +1 -0
  194. package/dist/talkpilot/plans/index.js +19 -0
  195. package/dist/talkpilot/plans/index.js.map +1 -0
  196. package/dist/talkpilot/plans/plans.getters.d.ts +10 -0
  197. package/dist/talkpilot/plans/plans.getters.d.ts.map +1 -0
  198. package/dist/talkpilot/plans/plans.getters.js +103 -0
  199. package/dist/talkpilot/plans/plans.getters.js.map +1 -0
  200. package/dist/talkpilot/plans/plans.types.d.ts +53 -0
  201. package/dist/talkpilot/plans/plans.types.d.ts.map +1 -0
  202. package/dist/talkpilot/plans/plans.types.js +29 -0
  203. package/dist/talkpilot/plans/plans.types.js.map +1 -0
  204. package/dist/talkpilot/results/index.d.ts +3 -0
  205. package/dist/talkpilot/results/index.d.ts.map +1 -0
  206. package/dist/talkpilot/results/index.js +6 -0
  207. package/dist/talkpilot/results/index.js.map +1 -0
  208. package/dist/talkpilot/results/results.getter.d.ts +7 -0
  209. package/dist/talkpilot/results/results.getter.d.ts.map +1 -0
  210. package/dist/talkpilot/results/results.getter.js +26 -0
  211. package/dist/talkpilot/results/results.getter.js.map +1 -0
  212. package/dist/talkpilot/results/results.schema.d.ts +35 -0
  213. package/dist/talkpilot/results/results.schema.d.ts.map +1 -0
  214. package/dist/talkpilot/results/results.schema.js +29 -0
  215. package/dist/talkpilot/results/results.schema.js.map +1 -0
  216. package/dist/talkpilot/results/results.types.d.ts +34 -0
  217. package/dist/talkpilot/results/results.types.d.ts.map +1 -0
  218. package/dist/talkpilot/results/results.types.js +3 -0
  219. package/dist/talkpilot/results/results.types.js.map +1 -0
  220. package/dist/talkpilot/sessions/index.d.ts +3 -0
  221. package/dist/talkpilot/sessions/index.d.ts.map +1 -0
  222. package/dist/talkpilot/sessions/index.js +6 -0
  223. package/dist/talkpilot/sessions/index.js.map +1 -0
  224. package/dist/talkpilot/sessions/sessions.getter.d.ts +7 -0
  225. package/dist/talkpilot/sessions/sessions.getter.d.ts.map +1 -0
  226. package/dist/talkpilot/sessions/sessions.getter.js +26 -0
  227. package/dist/talkpilot/sessions/sessions.getter.js.map +1 -0
  228. package/dist/talkpilot/sessions/sessions.schema.d.ts +53 -0
  229. package/dist/talkpilot/sessions/sessions.schema.d.ts.map +1 -0
  230. package/dist/talkpilot/sessions/sessions.schema.js +38 -0
  231. package/dist/talkpilot/sessions/sessions.schema.js.map +1 -0
  232. package/dist/talkpilot/sessions/sessions.types.d.ts +22 -0
  233. package/dist/talkpilot/sessions/sessions.types.d.ts.map +1 -0
  234. package/dist/talkpilot/sessions/sessions.types.js +3 -0
  235. package/dist/talkpilot/sessions/sessions.types.js.map +1 -0
  236. package/dist/talkpilot/subscriptions/index.d.ts +4 -0
  237. package/dist/talkpilot/subscriptions/index.d.ts.map +1 -0
  238. package/dist/talkpilot/subscriptions/index.js +20 -0
  239. package/dist/talkpilot/subscriptions/index.js.map +1 -0
  240. package/dist/talkpilot/subscriptions/subscriptions.getters.d.ts +13 -0
  241. package/dist/talkpilot/subscriptions/subscriptions.getters.d.ts.map +1 -0
  242. package/dist/talkpilot/subscriptions/subscriptions.getters.js +105 -0
  243. package/dist/talkpilot/subscriptions/subscriptions.getters.js.map +1 -0
  244. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.d.ts +8 -0
  245. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.d.ts.map +1 -0
  246. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.js +27 -0
  247. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.js.map +1 -0
  248. package/dist/talkpilot/subscriptions/subscriptions.types.d.ts +50 -0
  249. package/dist/talkpilot/subscriptions/subscriptions.types.d.ts.map +1 -0
  250. package/dist/talkpilot/subscriptions/subscriptions.types.js +14 -0
  251. package/dist/talkpilot/subscriptions/subscriptions.types.js.map +1 -0
  252. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts +4 -0
  253. package/dist/talkpilot/subscriptions/subscriptions.utils.d.ts.map +1 -0
  254. package/dist/talkpilot/subscriptions/subscriptions.utils.js +20 -0
  255. package/dist/talkpilot/subscriptions/subscriptions.utils.js.map +1 -0
  256. package/dist/test-utils/db-utils.d.ts +4 -0
  257. package/dist/test-utils/db-utils.d.ts.map +1 -0
  258. package/dist/test-utils/db-utils.js +28 -0
  259. package/dist/test-utils/db-utils.js.map +1 -0
  260. package/dist/test-utils/factories/index.d.ts +13 -0
  261. package/dist/test-utils/factories/index.d.ts.map +1 -0
  262. package/dist/test-utils/factories/index.js +29 -0
  263. package/dist/test-utils/factories/index.js.map +1 -0
  264. package/dist/test-utils/factories/municipal/cities.d.ts +5 -0
  265. package/dist/test-utils/factories/municipal/cities.d.ts.map +1 -0
  266. package/dist/test-utils/factories/municipal/cities.js +18 -0
  267. package/dist/test-utils/factories/municipal/cities.js.map +1 -0
  268. package/dist/test-utils/factories/municipal/departmentsSubjects.d.ts +5 -0
  269. package/dist/test-utils/factories/municipal/departmentsSubjects.d.ts.map +1 -0
  270. package/dist/test-utils/factories/municipal/departmentsSubjects.js +27 -0
  271. package/dist/test-utils/factories/municipal/departmentsSubjects.js.map +1 -0
  272. package/dist/test-utils/factories/municipal/streets.d.ts +5 -0
  273. package/dist/test-utils/factories/municipal/streets.d.ts.map +1 -0
  274. package/dist/test-utils/factories/municipal/streets.js +19 -0
  275. package/dist/test-utils/factories/municipal/streets.js.map +1 -0
  276. package/dist/test-utils/factories/municipal/tickets.d.ts +5 -0
  277. package/dist/test-utils/factories/municipal/tickets.d.ts.map +1 -0
  278. package/dist/test-utils/factories/municipal/tickets.js +27 -0
  279. package/dist/test-utils/factories/municipal/tickets.js.map +1 -0
  280. package/dist/test-utils/factories/talkpilot/agents.d.ts +5 -0
  281. package/dist/test-utils/factories/talkpilot/agents.d.ts.map +1 -0
  282. package/dist/test-utils/factories/talkpilot/agents.js +21 -0
  283. package/dist/test-utils/factories/talkpilot/agents.js.map +1 -0
  284. package/dist/test-utils/factories/talkpilot/calls.d.ts +6 -0
  285. package/dist/test-utils/factories/talkpilot/calls.d.ts.map +1 -0
  286. package/dist/test-utils/factories/talkpilot/calls.js +39 -0
  287. package/dist/test-utils/factories/talkpilot/calls.js.map +1 -0
  288. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.d.ts +5 -0
  289. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.d.ts.map +1 -0
  290. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.js +18 -0
  291. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.js.map +1 -0
  292. package/dist/test-utils/factories/talkpilot/clientsConfig.d.ts +5 -0
  293. package/dist/test-utils/factories/talkpilot/clientsConfig.d.ts.map +1 -0
  294. package/dist/test-utils/factories/talkpilot/clientsConfig.js +18 -0
  295. package/dist/test-utils/factories/talkpilot/clientsConfig.js.map +1 -0
  296. package/dist/test-utils/factories/talkpilot/flows.d.ts +14 -0
  297. package/dist/test-utils/factories/talkpilot/flows.d.ts.map +1 -0
  298. package/dist/test-utils/factories/talkpilot/flows.js +33 -0
  299. package/dist/test-utils/factories/talkpilot/flows.js.map +1 -0
  300. package/dist/test-utils/factories/talkpilot/groups.d.ts +6 -0
  301. package/dist/test-utils/factories/talkpilot/groups.d.ts.map +1 -0
  302. package/dist/test-utils/factories/talkpilot/groups.js +34 -0
  303. package/dist/test-utils/factories/talkpilot/groups.js.map +1 -0
  304. package/dist/test-utils/factories/talkpilot/phone_numbers.d.ts +16 -0
  305. package/dist/test-utils/factories/talkpilot/phone_numbers.d.ts.map +1 -0
  306. package/dist/test-utils/factories/talkpilot/phone_numbers.js +20 -0
  307. package/dist/test-utils/factories/talkpilot/phone_numbers.js.map +1 -0
  308. package/dist/test-utils/factories/talkpilot/sessions.d.ts +5 -0
  309. package/dist/test-utils/factories/talkpilot/sessions.d.ts.map +1 -0
  310. package/dist/test-utils/factories/talkpilot/sessions.js +37 -0
  311. package/dist/test-utils/factories/talkpilot/sessions.js.map +1 -0
  312. package/dist/utils/validation.d.ts +7 -0
  313. package/dist/utils/validation.d.ts.map +1 -0
  314. package/dist/utils/validation.js +23 -0
  315. package/dist/utils/validation.js.map +1 -0
  316. package/jest.config.js +22 -0
  317. package/package.json +43 -0
  318. package/src/__tests__/setup.ts +20 -0
  319. package/src/index.ts +13 -0
  320. package/src/municipal/__tests__/validation.spec.ts +50 -0
  321. package/src/municipal/cities/cities.getters.ts +44 -0
  322. package/src/municipal/cities/cities.types.ts +11 -0
  323. package/src/municipal/cities/index.ts +2 -0
  324. package/src/municipal/departmentsSubjects/departmentsSubjects.getters.ts +273 -0
  325. package/src/municipal/departmentsSubjects/departmentsSubjects.types.ts +76 -0
  326. package/src/municipal/departmentsSubjects/index.ts +11 -0
  327. package/src/municipal/index.ts +18 -0
  328. package/src/municipal/mongodb-client.ts +58 -0
  329. package/src/municipal/streets/index.ts +2 -0
  330. package/src/municipal/streets/streets.getters.ts +105 -0
  331. package/src/municipal/streets/streets.types.ts +18 -0
  332. package/src/municipal/tickets/__tests__/tickets.getters.spec.ts +30 -0
  333. package/src/municipal/tickets/index.ts +2 -0
  334. package/src/municipal/tickets/tickets.getters.ts +234 -0
  335. package/src/municipal/tickets/tickets.types.ts +39 -0
  336. package/src/talkpilot/__tests__/db.spec.ts +38 -0
  337. package/src/talkpilot/__tests__/mongodb-client.spec.ts +19 -0
  338. package/src/talkpilot/__tests__/validation.spec.ts +62 -0
  339. package/src/talkpilot/agents/__tests__/agents.getters.spec.ts +29 -0
  340. package/src/talkpilot/agents/agents.getters.ts +34 -0
  341. package/src/talkpilot/agents/agents.types.ts +14 -0
  342. package/src/talkpilot/agents/index.ts +2 -0
  343. package/src/talkpilot/calls/__tests__/calls.spec.ts +56 -0
  344. package/src/talkpilot/calls/calls.getters.ts +134 -0
  345. package/src/talkpilot/calls/calls.types.ts +45 -0
  346. package/src/talkpilot/calls/index.ts +2 -0
  347. package/src/talkpilot/clientAudioBuffers/__tests__/clientAudioBuffer.getters.spec.ts +78 -0
  348. package/src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts +101 -0
  349. package/src/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.ts +25 -0
  350. package/src/talkpilot/clients/clients.getters.ts +11 -0
  351. package/src/talkpilot/clients/clients.types.ts +12 -0
  352. package/src/talkpilot/clients/index.ts +2 -0
  353. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.spec.ts +28 -0
  354. package/src/talkpilot/clientsConfig/clientsConfig.getters.ts +20 -0
  355. package/src/talkpilot/clientsConfig/clientsConfig.types.ts +55 -0
  356. package/src/talkpilot/clientsConfig/index.ts +2 -0
  357. package/src/talkpilot/flows/flows.getter.ts +11 -0
  358. package/src/talkpilot/flows/flows.schema.ts +90 -0
  359. package/src/talkpilot/flows/flows.types.ts +151 -0
  360. package/src/talkpilot/flows/index.ts +2 -0
  361. package/src/talkpilot/groups/__tests__/groups.spec.ts +83 -0
  362. package/src/talkpilot/groups/__tests__/phone.utils.spec.ts +32 -0
  363. package/src/talkpilot/groups/groups.getters.ts +27 -0
  364. package/src/talkpilot/groups/groups.types.ts +29 -0
  365. package/src/talkpilot/groups/index.ts +2 -0
  366. package/src/talkpilot/groups/phone.utils.ts +40 -0
  367. package/src/talkpilot/index.ts +27 -0
  368. package/src/talkpilot/leads/index.ts +2 -0
  369. package/src/talkpilot/leads/leads.getter.ts +5 -0
  370. package/src/talkpilot/leads/leads.schema.ts +33 -0
  371. package/src/talkpilot/leads/leads.types.ts +20 -0
  372. package/src/talkpilot/mongodb-client.ts +78 -0
  373. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +43 -0
  374. package/src/talkpilot/phone_numbers/index.ts +2 -0
  375. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +47 -0
  376. package/src/talkpilot/phone_numbers/phone_numbers.schema.ts +14 -0
  377. package/src/talkpilot/phone_numbers/phone_numbers.types.ts +15 -0
  378. package/src/talkpilot/plans/index.ts +2 -0
  379. package/src/talkpilot/plans/plans.getters.ts +121 -0
  380. package/src/talkpilot/plans/plans.types.ts +84 -0
  381. package/src/talkpilot/results/index.ts +2 -0
  382. package/src/talkpilot/results/results.getter.ts +26 -0
  383. package/src/talkpilot/results/results.schema.ts +25 -0
  384. package/src/talkpilot/results/results.types.ts +32 -0
  385. package/src/talkpilot/sessions/__tests__/sessions.spec.ts +43 -0
  386. package/src/talkpilot/sessions/index.ts +2 -0
  387. package/src/talkpilot/sessions/sessions.getter.ts +28 -0
  388. package/src/talkpilot/sessions/sessions.schema.ts +34 -0
  389. package/src/talkpilot/sessions/sessions.types.ts +28 -0
  390. package/src/talkpilot/subscriptions/__tests__/subscriptions.getters.utils.spec.ts +42 -0
  391. package/src/talkpilot/subscriptions/index.ts +3 -0
  392. package/src/talkpilot/subscriptions/subscriptions.getters.ts +147 -0
  393. package/src/talkpilot/subscriptions/subscriptions.getters.utils.ts +26 -0
  394. package/src/talkpilot/subscriptions/subscriptions.types.ts +65 -0
  395. package/src/test-utils/db-utils.ts +24 -0
  396. package/src/test-utils/factories/index.ts +12 -0
  397. package/src/test-utils/factories/municipal/cities.ts +16 -0
  398. package/src/test-utils/factories/municipal/departmentsSubjects.ts +29 -0
  399. package/src/test-utils/factories/municipal/streets.ts +17 -0
  400. package/src/test-utils/factories/municipal/tickets.ts +27 -0
  401. package/src/test-utils/factories/talkpilot/agents.ts +19 -0
  402. package/src/test-utils/factories/talkpilot/calls.ts +37 -0
  403. package/src/test-utils/factories/talkpilot/clientAudioBuffers.ts +18 -0
  404. package/src/test-utils/factories/talkpilot/clientsConfig.ts +19 -0
  405. package/src/test-utils/factories/talkpilot/flows.ts +31 -0
  406. package/src/test-utils/factories/talkpilot/groups.ts +33 -0
  407. package/src/test-utils/factories/talkpilot/phone_numbers.ts +20 -0
  408. package/src/test-utils/factories/talkpilot/sessions.ts +35 -0
  409. package/src/utils/validation.ts +23 -0
  410. package/tsconfig.json +27 -0
@@ -0,0 +1,273 @@
1
+ import { getDb, DepartmentSubject } from '../index';
2
+ import { Collection, Filter } from 'mongodb';
3
+ import { CityName, VectorSearchResult } from './departmentsSubjects.types';
4
+
5
+ export const getDepartmentsSubjectsCollection = (): Collection<DepartmentSubject> => {
6
+ return getDb().collection<DepartmentSubject>('departmentsSubjects');
7
+ };
8
+
9
+ /**
10
+ * Get all departments subjects for a given city.
11
+ * No DB sort; tree build does not depend on order. Callers that need alphabetical order
12
+ * sort in memory (e.g. sortTreeAlphabetically in full-tree-subjects.service).
13
+ * @param cityName - City name to filter subjects
14
+ * @param withEmbeddings - Whether to include embedding and embedding_model fields (default: false)
15
+ * @returns Array of all department subjects for the city
16
+ */
17
+ export const getAllDepartmentsSubjectsByCity = async (
18
+ cityName: CityName,
19
+ withEmbeddings: boolean = false
20
+ ): Promise<DepartmentSubject[]> => {
21
+ const collection = getDepartmentsSubjectsCollection();
22
+ const query = collection.find({ cityName });
23
+
24
+ if (!withEmbeddings) {
25
+ return (await query
26
+ .project({ embedding: 0, embedding_model: 0 })
27
+ .toArray()) as DepartmentSubject[];
28
+ }
29
+
30
+ return await query.toArray();
31
+ };
32
+
33
+ /**
34
+ * Perform vector search on departmentsSubjects collection
35
+ * @param queryVector - The embedding vector to search with
36
+ * @param cityName - City name to filter results
37
+ * @param limit - Maximum number of results (default: 5)
38
+ * @param numCandidates - Number of candidates to consider (default: 800)
39
+ * @returns Array of vector search results
40
+ */
41
+ export const vectorSearchDepartmentsSubjects = async (
42
+ queryVector: number[],
43
+ cityName: CityName,
44
+ limit: number = 5,
45
+ numCandidates: number = 800
46
+ ): Promise<VectorSearchResult[]> => {
47
+ const collection = getDepartmentsSubjectsCollection();
48
+ const indexName = 'subjectTreesIndex';
49
+
50
+ const results = await collection
51
+ .aggregate<VectorSearchResult>([
52
+ {
53
+ $vectorSearch: {
54
+ index: indexName,
55
+ path: 'embedding',
56
+ queryVector,
57
+ numCandidates,
58
+ limit,
59
+ filter: { cityName },
60
+ },
61
+ },
62
+ {
63
+ $project: {
64
+ _id: 0,
65
+ subjectName: 1,
66
+ subject_id: { $toInt: '$subject_id' }, // Convert string to number
67
+ sub_subject_name: 1,
68
+ sub_subject_id: 1,
69
+ descriptions: 1,
70
+ guidelines: 1,
71
+ score: { $meta: 'vectorSearchScore' },
72
+ },
73
+ },
74
+ ])
75
+ .toArray();
76
+
77
+ return results;
78
+ };
79
+
80
+ export const addDepartmentSubjectInstruction = async (
81
+ filter: Filter<DepartmentSubject>,
82
+ instructionText: string
83
+ ): Promise<DepartmentSubject | null> => {
84
+ const newInstruction = {
85
+ id: Date.now(),
86
+ instruction: instructionText,
87
+ };
88
+
89
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
90
+ filter,
91
+ {
92
+ $push: { instructions: newInstruction },
93
+ $set: { updatedAt: new Date() },
94
+ },
95
+ { returnDocument: 'after' }
96
+ );
97
+
98
+ return result || null;
99
+ };
100
+
101
+ export const updateDepartmentSubjectInstruction = async (
102
+ filter: Filter<DepartmentSubject>,
103
+ instructionId: number,
104
+ newInstructionText: string
105
+ ): Promise<DepartmentSubject | null> => {
106
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
107
+ { ...filter, 'instructions.id': instructionId },
108
+ { $set: { 'instructions.$.instruction': newInstructionText, updatedAt: new Date() } },
109
+ { returnDocument: 'after' }
110
+ );
111
+
112
+ return result || null;
113
+ };
114
+
115
+ export const removeDepartmentSubjectInstruction = async (
116
+ filter: Filter<DepartmentSubject>,
117
+ instructionId: number
118
+ ): Promise<DepartmentSubject | null> => {
119
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
120
+ filter,
121
+ {
122
+ $pull: { instructions: { id: instructionId } },
123
+ $set: { updatedAt: new Date() },
124
+ },
125
+ { returnDocument: 'after' }
126
+ );
127
+
128
+ return result || null;
129
+ };
130
+
131
+ export const addDepartmentSubjectCommunication = async (
132
+ filter: Filter<DepartmentSubject>,
133
+ communication: {
134
+ type: 'free_text_sms' | 'upload_url_sms';
135
+ message_text?: string;
136
+ template_id?: string;
137
+ to?: string;
138
+ }
139
+ ): Promise<DepartmentSubject | null> => {
140
+ const newCommunication = {
141
+ id: Date.now(),
142
+ type: communication.type,
143
+ ...(communication.message_text !== undefined && { message_text: communication.message_text }),
144
+ is_deleted: false,
145
+ ...(communication.template_id !== undefined && { template_id: communication.template_id }),
146
+ ...(communication.to !== undefined && { to: communication.to }),
147
+ };
148
+
149
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
150
+ filter,
151
+ {
152
+ $push: { communications: newCommunication },
153
+ $set: { updatedAt: new Date() },
154
+ },
155
+ { returnDocument: 'after' }
156
+ );
157
+
158
+ return result || null;
159
+ };
160
+
161
+ export const updateDepartmentSubjectCommunication = async (
162
+ filter: Filter<DepartmentSubject>,
163
+ communicationId: number,
164
+ updates: {
165
+ type?: 'free_text_sms' | 'upload_url_sms';
166
+ message_text?: string | null;
167
+ template_id?: string | null;
168
+ to?: string | null;
169
+ is_deleted?: boolean | null;
170
+ }
171
+ ): Promise<DepartmentSubject | null> => {
172
+ const setFields: Record<string, unknown> = { updatedAt: new Date() };
173
+ if (updates.type !== undefined) setFields['communications.$.type'] = updates.type;
174
+ if (updates.message_text !== undefined)
175
+ setFields['communications.$.message_text'] = updates.message_text;
176
+ if (updates.template_id !== undefined)
177
+ setFields['communications.$.template_id'] = updates.template_id;
178
+ if (updates.to !== undefined) setFields['communications.$.to'] = updates.to;
179
+ if (updates.is_deleted !== undefined)
180
+ setFields['communications.$.is_deleted'] = updates.is_deleted;
181
+
182
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
183
+ { ...filter, 'communications.id': communicationId },
184
+ { $set: setFields },
185
+ { returnDocument: 'after' }
186
+ );
187
+
188
+ return result || null;
189
+ };
190
+
191
+ export const removeDepartmentSubjectCommunication = async (
192
+ filter: Filter<DepartmentSubject>,
193
+ communicationId: number
194
+ ): Promise<DepartmentSubject | null> => {
195
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
196
+ filter,
197
+ {
198
+ $pull: { communications: { id: communicationId } },
199
+ $set: { updatedAt: new Date() },
200
+ },
201
+ { returnDocument: 'after' }
202
+ );
203
+
204
+ return result || null;
205
+ };
206
+
207
+ /**
208
+ * Get department subject by subject_id, sub_subject_id, and cityName
209
+ * @param subjectId - Subject ID (from event_subject_id)
210
+ * @param subSubjectId - Sub-subject ID (from event_sub_subject_id, optional)
211
+ * @param cityName - City name to filter results
212
+ * @returns DepartmentSubject document or null if not found
213
+ */
214
+ export const getDepartmentSubjectBySubjectIds = async (
215
+ subjectId: string,
216
+ subSubjectId: string,
217
+ cityName: CityName
218
+ ): Promise<DepartmentSubject | null> => {
219
+ const collection = getDepartmentsSubjectsCollection();
220
+
221
+ const filter: Filter<DepartmentSubject> = {
222
+ subject_id: subjectId,
223
+ cityName,
224
+ };
225
+
226
+ if (subSubjectId) {
227
+ filter.sub_subject_id = subSubjectId;
228
+ }
229
+
230
+ const result = await collection.findOne(filter);
231
+
232
+ return result || null;
233
+ };
234
+
235
+ /**
236
+ * Update or create guidelines field for a department subject
237
+ * @param filter - MongoDB filter to find the document
238
+ * @param guidelines - Guidelines text to set
239
+ * @returns Updated DepartmentSubject document or null if not found
240
+ */
241
+ export const updateDepartmentSubjectGuidelines = async (
242
+ filter: Filter<DepartmentSubject>,
243
+ guidelines: string
244
+ ): Promise<DepartmentSubject | null> => {
245
+ // $set will create the field if it doesn't exist
246
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
247
+ filter,
248
+ { $set: { guidelines, updatedAt: new Date() } },
249
+ { returnDocument: 'after' }
250
+ );
251
+ return result || null;
252
+ };
253
+
254
+ /**
255
+ * Clear guidelines field from a department subject document (sets it to null)
256
+ * @param filter - MongoDB filter to find the document
257
+ * @returns Updated DepartmentSubject document or null if not found
258
+ */
259
+ export const deleteDepartmentSubjectGuidelines = async (
260
+ filter: Filter<DepartmentSubject>
261
+ ): Promise<DepartmentSubject | null> => {
262
+ // $set clears the field by setting it to null (keeps the field in the document)
263
+ const result = await getDepartmentsSubjectsCollection().findOneAndUpdate(
264
+ filter,
265
+ { $set: { guidelines: null, updatedAt: new Date() } },
266
+ { returnDocument: 'after' }
267
+ );
268
+ return result || null;
269
+ };
270
+
271
+ export const findSubjectByQuery = async (query: Partial<DepartmentSubject>) => {
272
+ return await getDepartmentsSubjectsCollection().findOne(query);
273
+ };
@@ -0,0 +1,76 @@
1
+ import { ObjectId, WithId } from 'mongodb';
2
+ import { Request } from 'express';
3
+ import { ClientConfigDoc, Products } from '../../talkpilot/clientsConfig/clientsConfig.types';
4
+
5
+ export type DepartmentSubject = {
6
+ _id: ObjectId;
7
+ createdAt: Date;
8
+ updatedAt: Date;
9
+ subjectName: string; // e.g. "אחזקה- איטום"
10
+ subject_id: string; // e.g. "6121"
11
+ sub_subject_name: string; // e.g. "איטום"
12
+ sub_subject_id: string; // e.g. "6123"
13
+ sub_subject_name2?: string; // e.g. "ניקיון באגם" (level 3 - grandchild)
14
+ sub_subject_id2?: string; // e.g. "2898" (level 3 - grandchild)
15
+ descriptions: string[]; // array of guideline / example descriptions
16
+ embedding_text?: string; // the text used to create the embedding
17
+ embedding?: number[]; // length should match embedding_dims (e.g. 1536)
18
+ embedding_model?: string; // e.g. "text-embedding-3-small"
19
+ embedding_dims?: number; // e.g. 1536
20
+ cityName: CityName;
21
+ guidelines?: string | null;
22
+ instructions?: Instruction[];
23
+ communications?: Communication[];
24
+ sla?: number;
25
+ };
26
+
27
+ export interface Instruction {
28
+ id: number;
29
+ instruction: string;
30
+ }
31
+
32
+ export interface Communication {
33
+ id: number;
34
+ type: CommunicationType;
35
+ message_text?: string;
36
+ template_id?: string;
37
+ to?: string;
38
+ is_deleted?: boolean;
39
+ }
40
+
41
+ export type DepartmentSubjectDoc = WithId<DepartmentSubject>;
42
+
43
+ /**
44
+ * Vector search result from MongoDB
45
+ */
46
+ export type VectorSearchResult = {
47
+ subjectName: string;
48
+ subject_id: number;
49
+ sub_subject_id: string;
50
+ sub_subject_id2?: string | null;
51
+ sub_subject_name: string;
52
+ sub_subject_name2?: string | null;
53
+ descriptions?: string[];
54
+ guidelines?: string | null;
55
+ instructions?: string | null;
56
+ score?: number;
57
+ };
58
+
59
+ /**
60
+ * City name type for municipal data
61
+ */
62
+ // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
63
+ export type CityName = 'ashdod' | 'maltar' | 'billit' | 'hashkelon' | 'eilat' | 'tests' | string;
64
+ export type CommunicationType = 'free_text_sms' | 'upload_url_sms';
65
+
66
+ /**
67
+ * Extended Express Request type with client configuration
68
+ */
69
+ export type RequestWithClientConfig = Request & {
70
+ uid: string;
71
+ clientConfig: ClientConfigDoc<Products>;
72
+ isGuest: boolean;
73
+ claims: Record<string, unknown>;
74
+ crmName?: string;
75
+ callSid?: string;
76
+ };
@@ -0,0 +1,11 @@
1
+ export * from './departmentsSubjects.getters';
2
+ export type {
3
+ DepartmentSubject,
4
+ DepartmentSubjectDoc,
5
+ VectorSearchResult,
6
+ CityName,
7
+ RequestWithClientConfig,
8
+ Communication,
9
+ Instruction,
10
+ } from './departmentsSubjects.types';
11
+
@@ -0,0 +1,18 @@
1
+ import { Db, ObjectId as MongoObjectId } from 'mongodb';
2
+
3
+ export * from './cities';
4
+ export * from './streets';
5
+ export * from './departmentsSubjects';
6
+ export * from './tickets';
7
+ export { municipalDataMongodbClient } from './mongodb-client';
8
+
9
+ let db: Db;
10
+ export const setDb = (d: Db) => {
11
+ db = d;
12
+ };
13
+ export const getDb = (): Db => {
14
+ if (!db) throw new Error('Municipal Data DB not initialised');
15
+ return db;
16
+ };
17
+
18
+ export const ObjectId = MongoObjectId;
@@ -0,0 +1,58 @@
1
+ import { MongoClient, Db } from 'mongodb';
2
+ import { setDb } from './index';
3
+ import { validateConfig, validateMongoUri } from '../utils/validation';
4
+
5
+ class MunicipalDataMongoDBClient {
6
+ private client: MongoClient | null = null;
7
+ private db: Db | null = null;
8
+ private readonly defaultDbName = 'municipal-data';
9
+
10
+ async connect(uri?: string, dbName?: string): Promise<void> {
11
+ if (this.client) {
12
+ return;
13
+ }
14
+
15
+ const mongodbUri = uri || process.env.MONGO_URI || process.env.MONGODB_URI;
16
+ validateConfig('MONGO_URI', mongodbUri);
17
+ validateMongoUri(mongodbUri!);
18
+
19
+ try {
20
+ this.client = new MongoClient(mongodbUri!);
21
+ await this.client.connect();
22
+ const targetDbName = dbName || this.defaultDbName;
23
+ this.db = this.client.db(targetDbName);
24
+ setDb(this.db);
25
+ console.info(`[core-db] Municipal MongoDB connected: ${targetDbName}`);
26
+ } catch (error) {
27
+ console.error('[core-db] Municipal connection failed', error as Error);
28
+ throw error;
29
+ }
30
+ }
31
+
32
+ async disconnect(): Promise<void> {
33
+ if (this.client) {
34
+ try {
35
+ await this.client.close();
36
+ this.client = null;
37
+ this.db = null;
38
+ console.info('Municipal Data MongoDB disconnected successfully');
39
+ } catch (error) {
40
+ console.error('Error disconnecting from Municipal Data MongoDB', error as Error);
41
+ throw error;
42
+ }
43
+ }
44
+ }
45
+
46
+ getDb(): Db {
47
+ if (!this.db) {
48
+ throw new Error('Municipal Data database not initialized. Call connect() first.');
49
+ }
50
+ return this.db;
51
+ }
52
+
53
+ isConnected(): boolean {
54
+ return this.client !== null && this.client !== undefined;
55
+ }
56
+ }
57
+
58
+ export const municipalDataMongodbClient = new MunicipalDataMongoDBClient();
@@ -0,0 +1,2 @@
1
+ export * from './streets.getters';
2
+ export type { Street, StreetDoc, StreetHint } from './streets.types';
@@ -0,0 +1,105 @@
1
+ import { CityName, getDb, ObjectId, Street } from '../index';
2
+ import type { StreetHint } from './streets.types';
3
+ import { Collection, Filter, ObjectId as MongoObjectId } from 'mongodb';
4
+
5
+ export const getStreetsCollection = (): Collection<Street> => {
6
+ return getDb().collection<Street>('streets');
7
+ };
8
+
9
+ export const findStreets = async (filter: Filter<Street> = {}): Promise<Street[]> => {
10
+ return await getStreetsCollection().find(filter).toArray();
11
+ };
12
+
13
+ export const getStreetById = async (streetId: string): Promise<Street | null> => {
14
+ const street = await getStreetsCollection().findOne({ _id: new ObjectId(streetId) });
15
+ return street ? street : null;
16
+ };
17
+
18
+ export const getStreetsByCityName = async (cityName: CityName): Promise<Street[]> => {
19
+ return await getStreetsCollection().find({ cityName }).sort({ name: 1 }).toArray();
20
+ };
21
+
22
+ export const getStreetByStreetId = async (streetId: string): Promise<Street | null> => {
23
+ const street = await getStreetsCollection().findOne({ id: streetId });
24
+ return street ? street : null;
25
+ };
26
+
27
+ /** Get street by business id and city. Use this when the client's city is known so the same id in another city is not returned. */
28
+ export const getStreetByStreetIdAndCity = async (
29
+ streetId: string,
30
+ cityName: CityName
31
+ ): Promise<Street | null> => {
32
+ const street = await getStreetsCollection().findOne({ id: streetId, cityName });
33
+ return street ? street : null;
34
+ };
35
+
36
+ export const createStreet = async (
37
+ streetData: Omit<Street, '_id' | 'createdAt' | 'updatedAt'>
38
+ ): Promise<MongoObjectId> => {
39
+ const street: Omit<Street, '_id'> = {
40
+ ...streetData,
41
+ createdAt: new Date(),
42
+ updatedAt: new Date(),
43
+ };
44
+ const { insertedId } = await getStreetsCollection().insertOne(street as Street);
45
+ return insertedId;
46
+ };
47
+
48
+ export const updateStreet = async (
49
+ streetId: string,
50
+ data: Partial<Omit<Street, '_id' | 'createdAt' | 'updatedAt'>>
51
+ ): Promise<Street | null> => {
52
+ const result = await getStreetsCollection().findOneAndUpdate(
53
+ { _id: new ObjectId(streetId) },
54
+ { $set: { ...data, updatedAt: new Date() } },
55
+ { returnDocument: 'after' }
56
+ );
57
+ return result || null;
58
+ };
59
+
60
+ /**
61
+ * Add or update a street hint on an already-fetched street.
62
+ * Only place that creates a new hint id (Date.getTime().toString()). Returns null if hint.id provided but not found, or text empty.
63
+ */
64
+ export const upsertStreetHintOnStreet = async (
65
+ street: Street,
66
+ hint: Partial<StreetHint> & Pick<StreetHint, 'text'>
67
+ ): Promise<Street | null> => {
68
+ const text = hint.text.trim();
69
+ if (!text) return null;
70
+
71
+ const hints = street.hints || [];
72
+ let updatedHints: StreetHint[];
73
+
74
+ if (hint.id != null && hint.id !== '') {
75
+ const hintIndex = hints.findIndex((h) => String(h.id) === String(hint.id));
76
+ if (hintIndex === -1) return null;
77
+ updatedHints = [...hints];
78
+ updatedHints[hintIndex] = { id: String(hint.id), text };
79
+ } else {
80
+ updatedHints = [...hints, { id: new Date().getTime().toString(), text }];
81
+ }
82
+
83
+ return updateStreet(street._id.toString(), { hints: updatedHints });
84
+ };
85
+
86
+ /** Remove a hint from a street. streetId is the street business id (e.g. "703"). Updates document updatedAt. */
87
+ export const deleteStreetHint = async (
88
+ streetId: string,
89
+ hintId: string
90
+ ): Promise<Street | null> => {
91
+ const result = await getStreetsCollection().findOneAndUpdate(
92
+ { id: streetId },
93
+ { $pull: { hints: { id: hintId } }, $set: { updatedAt: new Date() } },
94
+ { returnDocument: 'after' }
95
+ );
96
+ if (result) {
97
+ console.info('Street hint deleted', { streetId, hintId });
98
+ }
99
+ return result || null;
100
+ };
101
+
102
+ export const deleteStreet = async (streetId: string): Promise<boolean> => {
103
+ const result = await getStreetsCollection().deleteOne({ _id: new ObjectId(streetId) });
104
+ return result.deletedCount > 0;
105
+ };
@@ -0,0 +1,18 @@
1
+ import { ObjectId, WithId } from 'mongodb';
2
+
3
+ export type StreetHint = {
4
+ id: string;
5
+ text: string;
6
+ };
7
+
8
+ export type Street = {
9
+ _id: ObjectId;
10
+ createdAt: Date;
11
+ updatedAt: Date;
12
+ id: string;
13
+ name: string;
14
+ cityName: string;
15
+ hints?: StreetHint[];
16
+ };
17
+
18
+ export type StreetDoc = WithId<Street>;
@@ -0,0 +1,30 @@
1
+ import { findTicketsByCallSid } from '../tickets.getters';
2
+ import { setDb } from '../../index';
3
+ import { Db, Collection } from 'mongodb';
4
+ import { createTicket } from '../../../test-utils/factories';
5
+
6
+ describe('tickets getters', () => {
7
+ let mockDb: Partial<Db>;
8
+ let mockCollection: Partial<Collection>;
9
+
10
+ beforeEach(() => {
11
+ const mockTicket = createTicket({ callSid: '123' });
12
+ mockCollection = {
13
+ find: jest.fn().mockReturnValue({
14
+ toArray: jest.fn().mockResolvedValue([mockTicket]),
15
+ }),
16
+ };
17
+ mockDb = {
18
+ collection: jest.fn().mockReturnValue(mockCollection),
19
+ };
20
+ setDb(mockDb as Db);
21
+ });
22
+
23
+ it('findTicketsByCallSid should return tickets for the given callSid', async () => {
24
+ const result = await findTicketsByCallSid('123');
25
+
26
+ expect(mockDb.collection).toHaveBeenCalledWith('tickets');
27
+ expect(mockCollection.find).toHaveBeenCalledWith({ callSid: '123' });
28
+ expect(result[0].callSid).toBe('123');
29
+ });
30
+ });
@@ -0,0 +1,2 @@
1
+ export * from './tickets.getters';
2
+ export type { Ticket, TicketDoc, SubjectStatsItem } from './tickets.types';