@talkpilot/core-db 1.1.8 → 1.1.10

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 (331) hide show
  1. package/README.md +7 -0
  2. package/dist/connection.d.ts +1 -1
  3. package/dist/connection.d.ts.map +1 -1
  4. package/dist/connection.js +21 -24
  5. package/dist/connection.js.map +1 -1
  6. package/dist/index.d.ts +9 -9
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/municipal/cities/cities.getters.d.ts +2 -2
  10. package/dist/municipal/cities/cities.getters.d.ts.map +1 -1
  11. package/dist/municipal/cities/cities.getters.js +8 -4
  12. package/dist/municipal/cities/cities.getters.js.map +1 -1
  13. package/dist/municipal/cities/cities.types.d.ts +1 -1
  14. package/dist/municipal/cities/index.d.ts +2 -2
  15. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.d.ts +3 -3
  16. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.d.ts.map +1 -1
  17. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.js +30 -22
  18. package/dist/municipal/departmentsSubjects/departmentsSubjects.getters.js.map +1 -1
  19. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.d.ts +4 -4
  20. package/dist/municipal/departmentsSubjects/departmentsSubjects.types.d.ts.map +1 -1
  21. package/dist/municipal/departmentsSubjects/index.d.ts +2 -2
  22. package/dist/municipal/index.d.ts +8 -8
  23. package/dist/municipal/index.d.ts.map +1 -1
  24. package/dist/municipal/index.js +1 -1
  25. package/dist/municipal/mongodb-client.d.ts +1 -1
  26. package/dist/municipal/mongodb-client.d.ts.map +1 -1
  27. package/dist/municipal/mongodb-client.js +7 -7
  28. package/dist/municipal/mongodb-client.js.map +1 -1
  29. package/dist/municipal/streets/index.d.ts +2 -2
  30. package/dist/municipal/streets/streets.getters.d.ts +3 -3
  31. package/dist/municipal/streets/streets.getters.d.ts.map +1 -1
  32. package/dist/municipal/streets/streets.getters.js +19 -9
  33. package/dist/municipal/streets/streets.getters.js.map +1 -1
  34. package/dist/municipal/streets/streets.types.d.ts +1 -1
  35. package/dist/municipal/systemInstructions/index.d.ts +3 -3
  36. package/dist/municipal/systemInstructions/index.d.ts.map +1 -1
  37. package/dist/municipal/systemInstructions/instructions.getters.d.ts +3 -3
  38. package/dist/municipal/systemInstructions/instructions.getters.d.ts.map +1 -1
  39. package/dist/municipal/systemInstructions/instructions.getters.js +10 -4
  40. package/dist/municipal/systemInstructions/instructions.getters.js.map +1 -1
  41. package/dist/municipal/systemInstructions/instructions.setters.d.ts +2 -2
  42. package/dist/municipal/systemInstructions/instructions.setters.d.ts.map +1 -1
  43. package/dist/municipal/systemInstructions/instructions.setters.js +13 -8
  44. package/dist/municipal/systemInstructions/instructions.setters.js.map +1 -1
  45. package/dist/municipal/systemInstructions/instructions.types.d.ts +3 -3
  46. package/dist/municipal/systemInstructions/instructions.types.d.ts.map +1 -1
  47. package/dist/municipal/systemInstructions/instructions.types.js +6 -6
  48. package/dist/municipal/tickets/index.d.ts +2 -2
  49. package/dist/municipal/tickets/tickets.getters.d.ts +3 -3
  50. package/dist/municipal/tickets/tickets.getters.d.ts.map +1 -1
  51. package/dist/municipal/tickets/tickets.getters.js +50 -29
  52. package/dist/municipal/tickets/tickets.getters.js.map +1 -1
  53. package/dist/municipal/tickets/tickets.types.d.ts +1 -1
  54. package/dist/municipal/tickets/tickets.types.d.ts.map +1 -1
  55. package/dist/municipal/utils/types.d.ts +1 -1
  56. package/dist/municipal/utils/types.d.ts.map +1 -1
  57. package/dist/talkpilot/agents/agents.getters.d.ts +1 -1
  58. package/dist/talkpilot/agents/agents.getters.js +2 -2
  59. package/dist/talkpilot/agents/agents.types.d.ts +2 -2
  60. package/dist/talkpilot/agents/index.d.ts +2 -2
  61. package/dist/talkpilot/backgroundToolResults/backgroundToolResults.getters.d.ts +2 -2
  62. package/dist/talkpilot/backgroundToolResults/backgroundToolResults.getters.d.ts.map +1 -1
  63. package/dist/talkpilot/backgroundToolResults/backgroundToolResults.getters.js +1 -1
  64. package/dist/talkpilot/backgroundToolResults/backgroundToolResults.getters.js.map +1 -1
  65. package/dist/talkpilot/backgroundToolResults/backgroundToolResults.types.d.ts +2 -2
  66. package/dist/talkpilot/backgroundToolResults/index.d.ts +2 -2
  67. package/dist/talkpilot/calls/calls.getters.d.ts +4 -3
  68. package/dist/talkpilot/calls/calls.getters.d.ts.map +1 -1
  69. package/dist/talkpilot/calls/calls.getters.js +24 -16
  70. package/dist/talkpilot/calls/calls.getters.js.map +1 -1
  71. package/dist/talkpilot/calls/calls.types.d.ts +26 -3
  72. package/dist/talkpilot/calls/calls.types.d.ts.map +1 -1
  73. package/dist/talkpilot/calls/calls.types.js +2 -2
  74. package/dist/talkpilot/calls/index.d.ts +2 -2
  75. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.d.ts +2 -2
  76. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.d.ts.map +1 -1
  77. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.js +2 -2
  78. package/dist/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.js.map +1 -1
  79. package/dist/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.d.ts +2 -2
  80. package/dist/talkpilot/clientAudioBuffers/index.d.ts +2 -2
  81. package/dist/talkpilot/clients/clients.getters.d.ts +2 -2
  82. package/dist/talkpilot/clients/clients.getters.d.ts.map +1 -1
  83. package/dist/talkpilot/clients/clients.getters.js +5 -2
  84. package/dist/talkpilot/clients/clients.getters.js.map +1 -1
  85. package/dist/talkpilot/clients/clients.types.d.ts +1 -1
  86. package/dist/talkpilot/clients/index.d.ts +2 -2
  87. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts +2 -2
  88. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts.map +1 -1
  89. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js +1 -1
  90. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js.map +1 -1
  91. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts +3 -3
  92. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts.map +1 -1
  93. package/dist/talkpilot/clientsConfig/index.d.ts +2 -2
  94. package/dist/talkpilot/flows/flows.getter.d.ts +2 -2
  95. package/dist/talkpilot/flows/flows.getter.d.ts.map +1 -1
  96. package/dist/talkpilot/flows/flows.getter.js +1 -1
  97. package/dist/talkpilot/flows/flows.getter.js.map +1 -1
  98. package/dist/talkpilot/flows/flows.schema.d.ts +0 -3
  99. package/dist/talkpilot/flows/flows.schema.d.ts.map +1 -1
  100. package/dist/talkpilot/flows/flows.schema.js +87 -80
  101. package/dist/talkpilot/flows/flows.schema.js.map +1 -1
  102. package/dist/talkpilot/flows/flows.types.d.ts +16 -17
  103. package/dist/talkpilot/flows/flows.types.d.ts.map +1 -1
  104. package/dist/talkpilot/flows/index.d.ts +2 -2
  105. package/dist/talkpilot/groups/groups.getters.d.ts +2 -2
  106. package/dist/talkpilot/groups/groups.getters.d.ts.map +1 -1
  107. package/dist/talkpilot/groups/groups.getters.js +2 -2
  108. package/dist/talkpilot/groups/groups.getters.js.map +1 -1
  109. package/dist/talkpilot/groups/groups.types.d.ts +1 -1
  110. package/dist/talkpilot/groups/index.d.ts +3 -3
  111. package/dist/talkpilot/groups/phone.utils.d.ts +1 -1
  112. package/dist/talkpilot/groups/phone.utils.d.ts.map +1 -1
  113. package/dist/talkpilot/groups/phone.utils.js +2 -2
  114. package/dist/talkpilot/groups/phone.utils.js.map +1 -1
  115. package/dist/talkpilot/index.d.ts +16 -16
  116. package/dist/talkpilot/index.js +1 -1
  117. package/dist/talkpilot/leads/index.d.ts +2 -2
  118. package/dist/talkpilot/leads/leads.getter.d.ts +2 -2
  119. package/dist/talkpilot/leads/leads.getter.d.ts.map +1 -1
  120. package/dist/talkpilot/leads/leads.getter.js +1 -1
  121. package/dist/talkpilot/leads/leads.getter.js.map +1 -1
  122. package/dist/talkpilot/leads/leads.schema.js +16 -16
  123. package/dist/talkpilot/leads/leads.types.d.ts +1 -1
  124. package/dist/talkpilot/mongodb-client.d.ts +1 -1
  125. package/dist/talkpilot/mongodb-client.js +8 -9
  126. package/dist/talkpilot/mongodb-client.js.map +1 -1
  127. package/dist/talkpilot/phone_numbers/index.d.ts +1 -1
  128. package/dist/talkpilot/phone_numbers/index.d.ts.map +1 -1
  129. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +5 -2
  130. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -1
  131. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +66 -12
  132. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -1
  133. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts +11 -2
  134. package/dist/talkpilot/phone_numbers/phone_numbers.schema.d.ts.map +1 -1
  135. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js +5 -2
  136. package/dist/talkpilot/phone_numbers/phone_numbers.schema.js.map +1 -1
  137. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts +16 -3
  138. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts.map +1 -1
  139. package/dist/talkpilot/plans/index.d.ts +2 -2
  140. package/dist/talkpilot/plans/plans.getters.d.ts +2 -2
  141. package/dist/talkpilot/plans/plans.getters.d.ts.map +1 -1
  142. package/dist/talkpilot/plans/plans.getters.js +3 -3
  143. package/dist/talkpilot/plans/plans.getters.js.map +1 -1
  144. package/dist/talkpilot/plans/plans.types.d.ts +4 -4
  145. package/dist/talkpilot/plans/plans.types.d.ts.map +1 -1
  146. package/dist/talkpilot/plans/plans.types.js +19 -19
  147. package/dist/talkpilot/results/index.d.ts +2 -2
  148. package/dist/talkpilot/results/index.d.ts.map +1 -1
  149. package/dist/talkpilot/results/index.js.map +1 -1
  150. package/dist/talkpilot/results/results.getter.d.ts +3 -3
  151. package/dist/talkpilot/results/results.getter.d.ts.map +1 -1
  152. package/dist/talkpilot/results/results.getter.js +4 -4
  153. package/dist/talkpilot/results/results.getter.js.map +1 -1
  154. package/dist/talkpilot/results/results.schema.js +18 -18
  155. package/dist/talkpilot/results/results.types.d.ts +1 -1
  156. package/dist/talkpilot/sessions/index.d.ts +2 -2
  157. package/dist/talkpilot/sessions/sessions.getter.d.ts +3 -3
  158. package/dist/talkpilot/sessions/sessions.getter.d.ts.map +1 -1
  159. package/dist/talkpilot/sessions/sessions.getter.js +13 -10
  160. package/dist/talkpilot/sessions/sessions.getter.js.map +1 -1
  161. package/dist/talkpilot/sessions/sessions.schema.js +17 -17
  162. package/dist/talkpilot/sessions/sessions.types.d.ts +2 -2
  163. package/dist/talkpilot/subscriptions/index.d.ts +3 -3
  164. package/dist/talkpilot/subscriptions/subscriptions.getters.d.ts +2 -2
  165. package/dist/talkpilot/subscriptions/subscriptions.getters.d.ts.map +1 -1
  166. package/dist/talkpilot/subscriptions/subscriptions.getters.js +11 -11
  167. package/dist/talkpilot/subscriptions/subscriptions.getters.js.map +1 -1
  168. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.d.ts +2 -2
  169. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.d.ts.map +1 -1
  170. package/dist/talkpilot/subscriptions/subscriptions.getters.utils.js.map +1 -1
  171. package/dist/talkpilot/subscriptions/subscriptions.types.d.ts +2 -2
  172. package/dist/talkpilot/subscriptions/subscriptions.types.d.ts.map +1 -1
  173. package/dist/talkpilot/subscriptions/subscriptions.types.js +7 -7
  174. package/dist/talkpilot/utils/query.utils.d.ts +1 -1
  175. package/dist/test-utils/db-utils.d.ts +1 -1
  176. package/dist/test-utils/db-utils.js +2 -2
  177. package/dist/test-utils/factories/index.d.ts +12 -12
  178. package/dist/test-utils/factories/municipal/cities.d.ts +2 -2
  179. package/dist/test-utils/factories/municipal/cities.d.ts.map +1 -1
  180. package/dist/test-utils/factories/municipal/cities.js +1 -1
  181. package/dist/test-utils/factories/municipal/departmentsSubjects.d.ts +2 -2
  182. package/dist/test-utils/factories/municipal/departmentsSubjects.d.ts.map +1 -1
  183. package/dist/test-utils/factories/municipal/departmentsSubjects.js +7 -1
  184. package/dist/test-utils/factories/municipal/departmentsSubjects.js.map +1 -1
  185. package/dist/test-utils/factories/municipal/streets.d.ts +2 -2
  186. package/dist/test-utils/factories/municipal/streets.d.ts.map +1 -1
  187. package/dist/test-utils/factories/municipal/streets.js +6 -1
  188. package/dist/test-utils/factories/municipal/streets.js.map +1 -1
  189. package/dist/test-utils/factories/municipal/tickets.d.ts +2 -2
  190. package/dist/test-utils/factories/municipal/tickets.d.ts.map +1 -1
  191. package/dist/test-utils/factories/municipal/tickets.js +7 -1
  192. package/dist/test-utils/factories/municipal/tickets.js.map +1 -1
  193. package/dist/test-utils/factories/talkpilot/agents.d.ts +2 -2
  194. package/dist/test-utils/factories/talkpilot/agents.d.ts.map +1 -1
  195. package/dist/test-utils/factories/talkpilot/agents.js +4 -4
  196. package/dist/test-utils/factories/talkpilot/calls.d.ts +2 -2
  197. package/dist/test-utils/factories/talkpilot/calls.d.ts.map +1 -1
  198. package/dist/test-utils/factories/talkpilot/calls.js +1 -1
  199. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.d.ts +2 -2
  200. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.d.ts.map +1 -1
  201. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.js +1 -1
  202. package/dist/test-utils/factories/talkpilot/clientAudioBuffers.js.map +1 -1
  203. package/dist/test-utils/factories/talkpilot/clientsConfig.d.ts +2 -2
  204. package/dist/test-utils/factories/talkpilot/clientsConfig.d.ts.map +1 -1
  205. package/dist/test-utils/factories/talkpilot/clientsConfig.js.map +1 -1
  206. package/dist/test-utils/factories/talkpilot/flows.d.ts +3 -3
  207. package/dist/test-utils/factories/talkpilot/flows.d.ts.map +1 -1
  208. package/dist/test-utils/factories/talkpilot/flows.js.map +1 -1
  209. package/dist/test-utils/factories/talkpilot/groups.d.ts +2 -2
  210. package/dist/test-utils/factories/talkpilot/groups.d.ts.map +1 -1
  211. package/dist/test-utils/factories/talkpilot/groups.js +9 -9
  212. package/dist/test-utils/factories/talkpilot/groups.js.map +1 -1
  213. package/dist/test-utils/factories/talkpilot/phone_numbers.d.ts +3 -3
  214. package/dist/test-utils/factories/talkpilot/phone_numbers.d.ts.map +1 -1
  215. package/dist/test-utils/factories/talkpilot/phone_numbers.js.map +1 -1
  216. package/dist/test-utils/factories/talkpilot/sessions.d.ts +2 -2
  217. package/dist/test-utils/factories/talkpilot/sessions.d.ts.map +1 -1
  218. package/dist/test-utils/factories/talkpilot/sessions.js +1 -1
  219. package/dist/utils/validation.js +2 -2
  220. package/dist/utils/validation.js.map +1 -1
  221. package/package.json +3 -1
  222. package/src/__tests__/setup.ts +3 -3
  223. package/src/connection.ts +27 -25
  224. package/src/index.ts +9 -9
  225. package/src/municipal/__tests__/validation.spec.ts +35 -23
  226. package/src/municipal/cities/cities.getters.ts +16 -10
  227. package/src/municipal/cities/cities.types.ts +1 -1
  228. package/src/municipal/cities/index.ts +2 -2
  229. package/src/municipal/departmentsSubjects/departmentsSubjects.getters.ts +53 -44
  230. package/src/municipal/departmentsSubjects/departmentsSubjects.types.ts +5 -5
  231. package/src/municipal/departmentsSubjects/index.ts +2 -3
  232. package/src/municipal/index.ts +10 -10
  233. package/src/municipal/mongodb-client.ts +13 -10
  234. package/src/municipal/streets/index.ts +2 -2
  235. package/src/municipal/streets/streets.getters.ts +43 -23
  236. package/src/municipal/streets/streets.types.ts +1 -1
  237. package/src/municipal/systemInstructions/__tests__/getters.spec.ts +67 -52
  238. package/src/municipal/systemInstructions/__tests__/setters.spec.ts +271 -238
  239. package/src/municipal/systemInstructions/index.ts +7 -3
  240. package/src/municipal/systemInstructions/instructions.getters.ts +30 -18
  241. package/src/municipal/systemInstructions/instructions.setters.ts +43 -19
  242. package/src/municipal/systemInstructions/instructions.types.ts +10 -10
  243. package/src/municipal/tickets/__tests__/tickets.getters.spec.ts +12 -12
  244. package/src/municipal/tickets/index.ts +2 -2
  245. package/src/municipal/tickets/tickets.getters.ts +69 -42
  246. package/src/municipal/tickets/tickets.types.ts +2 -2
  247. package/src/municipal/utils/types.ts +8 -3
  248. package/src/talkpilot/__tests__/db.spec.ts +12 -12
  249. package/src/talkpilot/__tests__/mongodb-client.spec.ts +7 -8
  250. package/src/talkpilot/__tests__/validation.spec.ts +30 -24
  251. package/src/talkpilot/agents/__tests__/agents.getters.spec.ts +10 -10
  252. package/src/talkpilot/agents/agents.getters.ts +3 -3
  253. package/src/talkpilot/agents/agents.types.ts +2 -2
  254. package/src/talkpilot/agents/index.ts +2 -2
  255. package/src/talkpilot/backgroundToolResults/__tests__/backgroundToolResults.getters.spec.ts +42 -31
  256. package/src/talkpilot/backgroundToolResults/backgroundToolResults.getters.ts +11 -11
  257. package/src/talkpilot/backgroundToolResults/backgroundToolResults.types.ts +2 -3
  258. package/src/talkpilot/backgroundToolResults/index.ts +2 -2
  259. package/src/talkpilot/calls/__tests__/callStats.utils.spec.ts +27 -27
  260. package/src/talkpilot/calls/__tests__/calls.spec.ts +178 -40
  261. package/src/talkpilot/calls/calls.getters.ts +57 -27
  262. package/src/talkpilot/calls/calls.types.ts +39 -16
  263. package/src/talkpilot/calls/index.ts +2 -2
  264. package/src/talkpilot/clientAudioBuffers/__tests__/clientAudioBuffer.getters.spec.ts +73 -39
  265. package/src/talkpilot/clientAudioBuffers/clientAudioBuffer.getters.ts +18 -11
  266. package/src/talkpilot/clientAudioBuffers/clientsAudioBuffers.types.ts +2 -2
  267. package/src/talkpilot/clientAudioBuffers/index.ts +2 -2
  268. package/src/talkpilot/clients/clients.getters.ts +10 -5
  269. package/src/talkpilot/clients/clients.types.ts +1 -1
  270. package/src/talkpilot/clients/index.ts +2 -2
  271. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.spec.ts +21 -18
  272. package/src/talkpilot/clientsConfig/clientsConfig.getters.ts +6 -4
  273. package/src/talkpilot/clientsConfig/clientsConfig.types.ts +10 -8
  274. package/src/talkpilot/clientsConfig/index.ts +2 -2
  275. package/src/talkpilot/flows/__tests__/flows.schema.spec.ts +38 -37
  276. package/src/talkpilot/flows/flows.getter.ts +8 -5
  277. package/src/talkpilot/flows/flows.schema.ts +87 -80
  278. package/src/talkpilot/flows/flows.types.ts +23 -24
  279. package/src/talkpilot/flows/index.ts +2 -2
  280. package/src/talkpilot/groups/__tests__/groups.spec.ts +34 -27
  281. package/src/talkpilot/groups/__tests__/phone.utils.spec.ts +20 -20
  282. package/src/talkpilot/groups/groups.getters.ts +8 -5
  283. package/src/talkpilot/groups/groups.types.ts +1 -1
  284. package/src/talkpilot/groups/index.ts +3 -3
  285. package/src/talkpilot/groups/phone.utils.ts +12 -6
  286. package/src/talkpilot/index.ts +17 -17
  287. package/src/talkpilot/leads/index.ts +2 -2
  288. package/src/talkpilot/leads/leads.getter.ts +5 -4
  289. package/src/talkpilot/leads/leads.schema.ts +16 -16
  290. package/src/talkpilot/leads/leads.types.ts +1 -1
  291. package/src/talkpilot/mongodb-client.ts +12 -12
  292. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +162 -33
  293. package/src/talkpilot/phone_numbers/index.ts +1 -1
  294. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +94 -18
  295. package/src/talkpilot/phone_numbers/phone_numbers.schema.ts +5 -2
  296. package/src/talkpilot/phone_numbers/phone_numbers.types.ts +18 -3
  297. package/src/talkpilot/plans/__tests__/plans.spec.ts +30 -26
  298. package/src/talkpilot/plans/index.ts +2 -2
  299. package/src/talkpilot/plans/plans.getters.ts +25 -18
  300. package/src/talkpilot/plans/plans.types.ts +27 -23
  301. package/src/talkpilot/results/index.ts +5 -2
  302. package/src/talkpilot/results/results.getter.ts +9 -8
  303. package/src/talkpilot/results/results.schema.ts +18 -18
  304. package/src/talkpilot/results/results.types.ts +1 -1
  305. package/src/talkpilot/sessions/__tests__/sessions.spec.ts +65 -41
  306. package/src/talkpilot/sessions/index.ts +2 -2
  307. package/src/talkpilot/sessions/sessions.getter.ts +21 -16
  308. package/src/talkpilot/sessions/sessions.schema.ts +17 -17
  309. package/src/talkpilot/sessions/sessions.types.ts +2 -2
  310. package/src/talkpilot/subscriptions/__tests__/subscriptions.getters.utils.spec.ts +18 -15
  311. package/src/talkpilot/subscriptions/index.ts +3 -3
  312. package/src/talkpilot/subscriptions/subscriptions.getters.ts +36 -33
  313. package/src/talkpilot/subscriptions/subscriptions.getters.utils.ts +10 -3
  314. package/src/talkpilot/subscriptions/subscriptions.types.ts +9 -9
  315. package/src/talkpilot/utils/__tests__/query.utils.spec.ts +8 -8
  316. package/src/talkpilot/utils/query.utils.ts +2 -2
  317. package/src/test-utils/db-utils.ts +5 -5
  318. package/src/test-utils/factories/index.ts +12 -12
  319. package/src/test-utils/factories/municipal/cities.ts +5 -5
  320. package/src/test-utils/factories/municipal/departmentsSubjects.ts +32 -25
  321. package/src/test-utils/factories/municipal/streets.ts +10 -5
  322. package/src/test-utils/factories/municipal/tickets.ts +12 -6
  323. package/src/test-utils/factories/talkpilot/agents.ts +8 -8
  324. package/src/test-utils/factories/talkpilot/calls.ts +5 -5
  325. package/src/test-utils/factories/talkpilot/clientAudioBuffers.ts +14 -12
  326. package/src/test-utils/factories/talkpilot/clientsConfig.ts +7 -8
  327. package/src/test-utils/factories/talkpilot/flows.ts +7 -5
  328. package/src/test-utils/factories/talkpilot/groups.ts +13 -13
  329. package/src/test-utils/factories/talkpilot/phone_numbers.ts +8 -6
  330. package/src/test-utils/factories/talkpilot/sessions.ts +5 -5
  331. package/src/utils/validation.ts +4 -4
@@ -1,2 +1,2 @@
1
- export { getLeadsCollection } from './leads.getter';
2
- export type { Lead, LeadItem, LeadProperty } from './leads.types';
1
+ export { getLeadsCollection } from "./leads.getter";
2
+ export type { Lead, LeadItem, LeadProperty } from "./leads.types";
@@ -1,5 +1,6 @@
1
- import type { Collection } from 'mongodb';
2
- import { getDb } from '../index';
3
- import type { Lead } from './leads.types';
1
+ import type { Collection } from "mongodb";
2
+ import { getDb } from "../index";
3
+ import type { Lead } from "./leads.types";
4
4
 
5
- export const getLeadsCollection = (): Collection<Lead> => getDb().collection<Lead>('leads');
5
+ export const getLeadsCollection = (): Collection<Lead> =>
6
+ getDb().collection<Lead>("leads");
@@ -1,27 +1,27 @@
1
1
  export const leadsMongoSchema = {
2
- bsonType: 'object',
3
- required: ['flowId', 'clientId', 'createdAt', 'leads'],
2
+ bsonType: "object",
3
+ required: ["flowId", "clientId", "createdAt", "leads"],
4
4
  properties: {
5
- _id: { bsonType: 'objectId' },
6
- flowId: { bsonType: 'string' },
7
- clientId: { bsonType: 'string' },
8
- createdAt: { bsonType: 'date' },
5
+ _id: { bsonType: "objectId" },
6
+ flowId: { bsonType: "string" },
7
+ clientId: { bsonType: "string" },
8
+ createdAt: { bsonType: "date" },
9
9
  leads: {
10
- bsonType: 'array',
10
+ bsonType: "array",
11
11
  items: {
12
- bsonType: 'object',
13
- required: ['callSid', 'timestamp'],
12
+ bsonType: "object",
13
+ required: ["callSid", "timestamp"],
14
14
  properties: {
15
- callSid: { bsonType: 'string' },
16
- timestamp: { bsonType: 'date' },
15
+ callSid: { bsonType: "string" },
16
+ timestamp: { bsonType: "date" },
17
17
  properties: {
18
- bsonType: 'array',
18
+ bsonType: "array",
19
19
  items: {
20
- bsonType: 'object',
21
- required: ['name', 'value'],
20
+ bsonType: "object",
21
+ required: ["name", "value"],
22
22
  properties: {
23
- name: { bsonType: 'string' },
24
- value: { bsonType: 'string' },
23
+ name: { bsonType: "string" },
24
+ value: { bsonType: "string" },
25
25
  },
26
26
  },
27
27
  },
@@ -1,4 +1,4 @@
1
- import { ObjectId } from 'mongodb';
1
+ import { ObjectId } from "mongodb";
2
2
 
3
3
  export interface LeadProperty {
4
4
  name: string;
@@ -1,6 +1,6 @@
1
- import { MongoClient, Db } from 'mongodb';
2
- import { setDb } from './index';
3
- import { validateConfig, validateMongoUri } from '../utils/validation';
1
+ import { MongoClient, Db } from "mongodb";
2
+ import { setDb } from "./index";
3
+ import { validateConfig, validateMongoUri } from "../utils/validation";
4
4
 
5
5
  class MongoDBClient {
6
6
  private client: MongoClient | null = null;
@@ -22,7 +22,7 @@ class MongoDBClient {
22
22
  }
23
23
 
24
24
  const mongodbUri = uri || process.env.MONGO_URI || process.env.MONGODB_URI;
25
- validateConfig('MONGO_URI', mongodbUri);
25
+ validateConfig("MONGO_URI", mongodbUri);
26
26
  validateMongoUri(mongodbUri!);
27
27
 
28
28
  try {
@@ -30,13 +30,13 @@ class MongoDBClient {
30
30
  await this.client.connect();
31
31
 
32
32
  const dbNameFromUri = this.extractDatabaseName(mongodbUri!);
33
- const dbNameFromEnv = process.env.MONGODB_DB_NAME;
34
- const dbName = databaseName || dbNameFromUri || dbNameFromEnv;
33
+ const dbName =
34
+ databaseName || process.env.TALKPILOT_DB_NAME || dbNameFromUri;
35
35
 
36
36
  if (!dbName) {
37
37
  throw new Error(
38
- '[core-db] Database name not specified. Please pass databaseName to connect(), ' +
39
- 'add it to the URI, or set MONGODB_DB_NAME.'
38
+ "[core-db] Database name not specified. Please pass databaseName to connect(), " +
39
+ "add it to the URI, or set TALKPILOT_DB_NAME.",
40
40
  );
41
41
  }
42
42
 
@@ -44,7 +44,7 @@ class MongoDBClient {
44
44
  setDb(this.db);
45
45
  console.info(`[core-db] TalkPilot MongoDB connected: ${dbName}`);
46
46
  } catch (error) {
47
- console.error('[core-db] TalkPilot connection failed', error as Error);
47
+ console.error("[core-db] TalkPilot connection failed", error);
48
48
  throw error;
49
49
  }
50
50
  }
@@ -55,9 +55,9 @@ class MongoDBClient {
55
55
  await this.client.close();
56
56
  this.client = null;
57
57
  this.db = null;
58
- console.info('MongoDB disconnected successfully');
58
+ console.info("MongoDB disconnected successfully");
59
59
  } catch (error) {
60
- console.error('Error disconnecting from MongoDB', error as Error);
60
+ console.error("[core-db] Disconnection failed", error);
61
61
  throw error;
62
62
  }
63
63
  }
@@ -65,7 +65,7 @@ class MongoDBClient {
65
65
 
66
66
  getDb(): Db {
67
67
  if (!this.db) {
68
- throw new Error('Database not initialized. Call connect() first.');
68
+ throw new Error("Database not initialized. Call connect() first.");
69
69
  }
70
70
  return this.db;
71
71
  }
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  getPhoneDataByPhoneNumber,
3
3
  getPhoneNumbersCollection,
4
+ getPhoneNumbersForFlows,
4
5
  getClientPhoneNumber,
5
6
  getClientPhoneData,
6
7
  createPhoneNumberEntity,
8
+ createPurchasedPhoneNumber,
7
9
  } from '../phone_numbers.getter';
8
10
  import { getFlowsCollection } from '../../flows/flows.getter';
9
11
  import { createFlow, createPhoneNumber } from '../../../test-utils/factories';
@@ -13,31 +15,37 @@ describe('db.phoneNumbers', () => {
13
15
  describe('getPhoneDataByPhoneNumber', () => {
14
16
  it('return phone number data with flow', async () => {
15
17
  const flow = createFlow({
16
- clientId: 'test-client-id',
18
+ clientId: "test-client-id",
17
19
  conversationSettings: {
18
20
  interruptions: {
19
21
  enableInterruptionDetection: true,
20
22
  interruptionWindowSeconds: 60,
21
23
  interruptionThresholdSeconds: 10,
22
- interruptionInstruction: 'I am hearing background noise that makes it hard for me to focus on what you are saying. Please try to move to a quieter place or reduce the noise so I can better assist you.',
24
+ interruptionInstruction:
25
+ "I am hearing background noise that makes it hard for me to focus on what you are saying. Please try to move to a quieter place or reduce the noise so I can better assist you.",
23
26
  },
24
27
  silence: {
25
28
  enableSilenceDetection: true,
26
29
  firstWarningSilenceSeconds: 5,
27
- firstWarningInstruction: 'I have not heard you for a few seconds. If you are still on the line, please say something so we can continue.',
30
+ firstWarningInstruction:
31
+ "I have not heard you for a few seconds. If you are still on the line, please say something so we can continue.",
28
32
  secondWarningSilenceSeconds: 10,
29
- secondWarningInstruction: 'I still have not heard anything from you. If you do not respond in the next few seconds, I will have to end this call.',
33
+ secondWarningInstruction:
34
+ "I still have not heard anything from you. If you do not respond in the next few seconds, I will have to end this call.",
30
35
  disconnectSilenceSeconds: 30,
31
36
  },
32
37
  },
33
38
  });
34
- const phoneData = createPhoneNumber({ flow_id: flow._id, client_id: 'test-client-id' });
35
-
39
+ const phoneData = createPhoneNumber({
40
+ flow_id: flow._id,
41
+ client_id: "test-client-id",
42
+ });
43
+
36
44
  await getFlowsCollection().insertOne(flow);
37
45
  await getPhoneNumbersCollection().insertOne(phoneData);
38
46
 
39
47
  const result = await getPhoneDataByPhoneNumber(phoneData.phone_number);
40
-
48
+
41
49
  expect(result).toBeDefined();
42
50
  expect(result).toMatchObject({
43
51
  client_id: phoneData.client_id,
@@ -46,15 +54,20 @@ describe('db.phoneNumbers', () => {
46
54
  });
47
55
  // Specifically check if the flow was joined correctly
48
56
  expect(result?.flow.flowName).toBe(flow.flowName);
49
- expect(result?.flow.conversationSettings?.silence?.firstWarningSilenceSeconds).toBe(5);
57
+ expect(
58
+ result?.flow.conversationSettings?.silence?.firstWarningSilenceSeconds,
59
+ ).toBe(5);
50
60
  });
51
61
  });
52
62
 
53
- describe('getClientPhoneNumber', () => {
54
- it('return phone number by client id', async () => {
63
+ describe("getClientPhoneNumber", () => {
64
+ it("return phone number by client id", async () => {
55
65
  const flow = createFlow();
56
- const phoneData = createPhoneNumber({ flow_id: flow._id, is_primary: true });
57
-
66
+ const phoneData = createPhoneNumber({
67
+ flow_id: flow._id,
68
+ is_primary: true,
69
+ });
70
+
58
71
  await getFlowsCollection().insertOne(flow);
59
72
  await getPhoneNumbersCollection().insertOne(phoneData);
60
73
 
@@ -63,31 +76,113 @@ describe('db.phoneNumbers', () => {
63
76
  });
64
77
  });
65
78
 
66
- describe('getClientPhoneData', () => {
67
- it('returns primary phone data by default', async () => {
68
- const clientId = 'multiPhoneClient';
69
- const phone1 = createPhoneNumber({ client_id: clientId, is_primary: false, phone_number: '1', createdAt: new Date('2023-01-01') });
70
- const phone2 = createPhoneNumber({ client_id: clientId, is_primary: true, phone_number: '2', createdAt: new Date('2023-01-02') });
79
+ describe("getClientPhoneData", () => {
80
+ it("returns primary phone data by default", async () => {
81
+ const clientId = "multiPhoneClient";
82
+ const phone1 = createPhoneNumber({
83
+ client_id: clientId,
84
+ is_primary: false,
85
+ phone_number: "1",
86
+ createdAt: new Date("2023-01-01"),
87
+ });
88
+ const phone2 = createPhoneNumber({
89
+ client_id: clientId,
90
+ is_primary: true,
91
+ phone_number: "2",
92
+ createdAt: new Date("2023-01-02"),
93
+ });
71
94
 
72
95
  await getPhoneNumbersCollection().insertOne(phone1);
73
96
  await getPhoneNumbersCollection().insertOne(phone2);
74
97
 
75
98
  const result = await getClientPhoneData(clientId);
76
- expect(result?.phone_number).toBe('2');
99
+ expect(result?.phone_number).toBe("2");
77
100
  });
78
101
 
79
- it('returns most recent non-primary phone data if isPrimary is false', async () => {
80
- const clientId = 'multiPhoneClient2';
81
- const phone1 = createPhoneNumber({ client_id: clientId, is_primary: false, phone_number: '1', createdAt: new Date('2023-01-01') });
82
- const phone2 = createPhoneNumber({ client_id: clientId, is_primary: false, phone_number: '2', createdAt: new Date('2023-01-02') });
83
- const phone3 = createPhoneNumber({ client_id: clientId, is_primary: true, phone_number: '3', createdAt: new Date('2023-01-03') });
102
+ it("returns most recent non-primary phone data if isPrimary is false", async () => {
103
+ const clientId = "multiPhoneClient2";
104
+ const phone1 = createPhoneNumber({
105
+ client_id: clientId,
106
+ is_primary: false,
107
+ phone_number: "1",
108
+ createdAt: new Date("2023-01-01"),
109
+ });
110
+ const phone2 = createPhoneNumber({
111
+ client_id: clientId,
112
+ is_primary: false,
113
+ phone_number: "2",
114
+ createdAt: new Date("2023-01-02"),
115
+ });
116
+ const phone3 = createPhoneNumber({
117
+ client_id: clientId,
118
+ is_primary: true,
119
+ phone_number: "3",
120
+ createdAt: new Date("2023-01-03"),
121
+ });
84
122
 
85
123
  await getPhoneNumbersCollection().insertOne(phone1);
86
124
  await getPhoneNumbersCollection().insertOne(phone2);
87
125
  await getPhoneNumbersCollection().insertOne(phone3);
88
126
 
89
127
  const result = await getClientPhoneData(clientId, false);
90
- expect(result?.phone_number).toBe('2');
128
+ expect(result?.phone_number).toBe("2");
129
+ });
130
+ });
131
+
132
+ describe('getPhoneNumbersForFlows', () => {
133
+ it('returns all phone numbers for the client with flow ObjectIds, newest first', async () => {
134
+ const clientId = 'flowsClient';
135
+ const flow1 = createFlow({ clientId });
136
+ const flow2 = createFlow({ clientId });
137
+ await getFlowsCollection().insertMany([flow1, flow2]);
138
+
139
+ const older = createPhoneNumber({
140
+ client_id: clientId,
141
+ flow_id: flow1._id,
142
+ phone_number: '+100',
143
+ is_primary: true,
144
+ createdAt: new Date('2023-01-01'),
145
+ });
146
+ const newer = createPhoneNumber({
147
+ client_id: clientId,
148
+ flow_id: flow2._id,
149
+ phone_number: '+200',
150
+ is_primary: false,
151
+ createdAt: new Date('2023-06-01'),
152
+ });
153
+
154
+ await getPhoneNumbersCollection().insertMany([older, newer]);
155
+
156
+ const result = await getPhoneNumbersForFlows(clientId);
157
+
158
+ expect(result).toHaveLength(2);
159
+ expect(result[0]).toEqual({
160
+ flowId: String(flow2._id),
161
+ phoneNumber: '+200',
162
+ isPrimary: false,
163
+ });
164
+ expect(result[1]).toEqual({
165
+ flowId: String(flow1._id),
166
+ phoneNumber: '+100',
167
+ isPrimary: true,
168
+ });
169
+ });
170
+
171
+ it('returns an empty array when the client has no phone numbers', async () => {
172
+ const result = await getPhoneNumbersForFlows('noSuchClient');
173
+ expect(result).toEqual([]);
174
+ });
175
+
176
+ it('does not include phone numbers for other clients', async () => {
177
+ const clientA = 'clientA';
178
+ const clientB = 'clientB';
179
+ const flow = createFlow();
180
+ await getFlowsCollection().insertOne(flow);
181
+ const phone = createPhoneNumber({ client_id: clientA, flow_id: flow._id });
182
+ await getPhoneNumbersCollection().insertOne(phone);
183
+
184
+ const result = await getPhoneNumbersForFlows(clientB);
185
+ expect(result).toEqual([]);
91
186
  });
92
187
  });
93
188
 
@@ -95,24 +190,58 @@ describe('db.phoneNumbers', () => {
95
190
  it('creates first phone number as primary', async () => {
96
191
  const clientId = 'newClient';
97
192
  const flowId = new ObjectId().toHexString();
98
- const phoneNumber = '+123456789';
193
+ const phoneNumber = "+123456789";
99
194
 
100
- const result = await createPhoneNumberEntity(phoneNumber, flowId, clientId);
195
+ const result = await createPhoneNumberEntity(
196
+ phoneNumber,
197
+ flowId,
198
+ clientId,
199
+ );
101
200
  expect(result.phone_number).toBe(phoneNumber);
102
201
  expect(result.is_primary).toBe(true);
103
202
  });
104
203
 
105
- it('creates subsequent phone number as non-primary', async () => {
106
- const clientId = 'existingClient';
204
+ it("creates subsequent phone number as non-primary", async () => {
205
+ const clientId = "existingClient";
107
206
  const flowId = new ObjectId().toHexString();
108
-
207
+
109
208
  // Create first one
110
- await createPhoneNumberEntity('+111', flowId, clientId);
111
-
209
+ await createPhoneNumberEntity("+111", flowId, clientId);
210
+
112
211
  // Create second one
113
- const result = await createPhoneNumberEntity('+222', flowId, clientId);
114
- expect(result.phone_number).toBe('+222');
212
+ const result = await createPhoneNumberEntity("+222", flowId, clientId);
213
+ expect(result.phone_number).toBe("+222");
115
214
  expect(result.is_primary).toBe(false);
116
215
  });
117
216
  });
217
+
218
+ describe('createPurchasedPhoneNumber', () => {
219
+ it('persists a phone_numbers document with provider payload and flow', async () => {
220
+ const clientId = 'purchasedClientDb';
221
+ const flowId = new ObjectId().toHexString();
222
+ const phoneNumber = '+15551234567';
223
+ const providerPayload = {
224
+ provider: 'twilio' as const,
225
+ provider_sid: 'PNxxxxxxxx',
226
+ };
227
+
228
+ await createPurchasedPhoneNumber(
229
+ phoneNumber,
230
+ providerPayload,
231
+ clientId,
232
+ flowId,
233
+ );
234
+
235
+ // Re-read from Mongo to confirm insert succeeded (not only the function return value).
236
+ const stored = await getPhoneNumbersCollection().findOne({ phone_number: phoneNumber });
237
+ expect(stored).not.toBeNull();
238
+ expect(stored).toMatchObject({
239
+ phone_number: phoneNumber,
240
+ client_id: clientId,
241
+ provider: 'twilio',
242
+ provider_sid: 'PNxxxxxxxx',
243
+ flow_id: new ObjectId(flowId),
244
+ });
245
+ });
246
+ });
118
247
  });
@@ -1,2 +1,2 @@
1
1
  export * from './phone_numbers.getter';
2
- export type { PhoneNumber } from './phone_numbers.types';
2
+ export type * from './phone_numbers.types';
@@ -1,4 +1,4 @@
1
- import type { Collection } from 'mongodb';
1
+ import type { Collection } from "mongodb";
2
2
  import {
3
3
  Client,
4
4
  getClientsCollection,
@@ -7,32 +7,54 @@ import {
7
7
  ObjectId,
8
8
  findSubscriptions,
9
9
  } from '../index';
10
- import { PhoneNumber, PhoneNumberWithFlow } from './phone_numbers.types';
10
+ import {
11
+ ClientPhoneNumberForFlow,
12
+ PhoneNumber,
13
+ PhoneNumberWithFlow,
14
+ PurchasedPhoneProviderPayload
15
+ } from "./phone_numbers.types";
11
16
 
12
17
  export const getPhoneNumbersCollection = (): Collection<PhoneNumber> =>
13
- getDb().collection<PhoneNumber>('phone_numbers');
18
+ getDb().collection<PhoneNumber>("phone_numbers");
14
19
 
15
20
  export const getPhoneDataByPhoneNumber = async (
16
- phoneNumber: string
21
+ phoneNumber: string,
17
22
  ): Promise<PhoneNumberWithFlow | null> => {
18
- const phoneCallData = await getPhoneNumbersCollection().findOne({ phone_number: phoneNumber });
23
+ const phoneCallData = await getPhoneNumbersCollection().findOne({
24
+ phone_number: phoneNumber,
25
+ });
19
26
  if (!phoneCallData) {
20
- throw new Error('PhoneNumber not found');
27
+ throw new Error("PhoneNumber not found");
21
28
  }
22
- const flow = await getFlowsCollection().findOne({ _id: new ObjectId(phoneCallData.flow_id) });
29
+ const flow = await getFlowsCollection().findOne({
30
+ _id: new ObjectId(phoneCallData.flow_id),
31
+ });
23
32
  if (!flow) {
24
- throw new Error('Flow not found');
33
+ throw new Error("Flow not found");
25
34
  }
26
35
  const [subscription] =
27
- (await findSubscriptions({ clientId: phoneCallData.client_id, isActive: true })) || [];
36
+ (await findSubscriptions({
37
+ clientId: phoneCallData.client_id,
38
+ isActive: true,
39
+ })) || [];
28
40
 
29
- return { ...phoneCallData, flow, subscriptionId: subscription?._id?.toString() ?? undefined };
41
+ return {
42
+ ...phoneCallData,
43
+ flow,
44
+ subscriptionId: subscription?._id?.toString() ?? undefined,
45
+ };
30
46
  };
31
47
 
32
- export const getClientPrimaryPhoneNumber = async (clientId: string): Promise<string | null> => {
48
+ export const getClientPrimaryPhoneNumber = async (
49
+ clientId: string,
50
+ ): Promise<string | null> => {
33
51
  return (
34
- (await getPhoneNumbersCollection().findOne({ client_id: clientId, is_primary: true }))
35
- ?.phone_number ?? null
52
+ (
53
+ await getPhoneNumbersCollection().findOne({
54
+ client_id: clientId,
55
+ is_primary: true,
56
+ })
57
+ )?.phone_number ?? null
36
58
  );
37
59
  };
38
60
 
@@ -40,17 +62,37 @@ export const getClientPhoneNumber = getClientPrimaryPhoneNumber;
40
62
 
41
63
  export const getClientPhoneData = async (
42
64
  clientId: string,
43
- isPrimary?: boolean
65
+ isPrimary?: boolean,
44
66
  ): Promise<PhoneNumber | null> => {
45
67
  const filter = { client_id: clientId, is_primary: isPrimary !== false };
46
- const options = isPrimary === false ? { sort: { createdAt: -1 } as const } : {};
68
+ const options =
69
+ isPrimary === false ? { sort: { createdAt: -1 } as const } : {};
47
70
  return getPhoneNumbersCollection().findOne(filter, options);
48
71
  };
49
72
 
73
+ export const getPhoneNumbersForFlows = async (
74
+ clientId: string,
75
+ ): Promise<ClientPhoneNumberForFlow[]> => {
76
+ const docs = await getPhoneNumbersCollection()
77
+ .find({
78
+ client_id: clientId,
79
+ flow_id: { $exists: true, $type: "objectId" },
80
+ })
81
+ .project({ _id: 0, flow_id: 1, phone_number: 1, is_primary: 1 })
82
+ .sort({ createdAt: -1 })
83
+ .toArray();
84
+
85
+ return docs.map((doc) => ({
86
+ flowId: String(doc.flow_id),
87
+ phoneNumber: doc.phone_number,
88
+ isPrimary: doc.is_primary,
89
+ }));
90
+ };
91
+
50
92
  export const createPhoneNumberEntity = async (
51
93
  phoneNumber: string,
52
94
  flowId: string,
53
- clientId: string
95
+ clientId: string,
54
96
  ): Promise<PhoneNumber> => {
55
97
  const existing = await getClientPhoneData(clientId);
56
98
  const isPrimary = !existing;
@@ -64,15 +106,49 @@ export const createPhoneNumberEntity = async (
64
106
  updatedAt: new Date(),
65
107
  });
66
108
  const phoneNumberData = await getClientPhoneData(clientId, isPrimary);
67
- if (!phoneNumberData) throw new Error('Failed to create phoneNumber');
109
+ if (!phoneNumberData) throw new Error("Failed to create phoneNumber");
68
110
  return phoneNumberData;
69
111
  };
70
112
 
113
+ /** API-purchased number; `flowId` may be omitted until the number is bound to a flow. */
114
+ export const createPurchasedPhoneNumber = async (
115
+ phoneNumber: string,
116
+ providerPayload: PurchasedPhoneProviderPayload,
117
+ clientId: string,
118
+ flowId?: string | null,
119
+ ): Promise<PhoneNumber> => {
120
+ const existingPhoneForClient = await getClientPhoneData(clientId);
121
+ const isPrimary = !existingPhoneForClient;
122
+
123
+ const now = new Date();
124
+ const trimmedFlowId = flowId?.trim();
125
+ const flowObjectId = trimmedFlowId ? new ObjectId(trimmedFlowId) : undefined;
126
+
127
+ const doc: PhoneNumber = {
128
+ phone_number: phoneNumber,
129
+ client_id: clientId,
130
+ is_primary: isPrimary,
131
+ ...providerPayload,
132
+ createdAt: now,
133
+ updatedAt: now,
134
+ };
135
+
136
+ if (flowObjectId) {
137
+ doc.flow_id = flowObjectId;
138
+ }
139
+
140
+ await getPhoneNumbersCollection().insertOne(doc);
141
+
142
+ const created = await getClientPhoneData(clientId, isPrimary);
143
+ if (!created) throw new Error('Failed to create phoneNumber');
144
+ return created;
145
+ };
146
+
71
147
  export const findClientByPhoneNumber = async (phoneNumber: string): Promise<Client> => {
72
148
  const phoneData = await getPhoneNumbersCollection().findOne({ phone_number: phoneNumber });
73
149
  if (!phoneData) throw new Error('Failed to get phone data');
74
150
  const clientId = phoneData.client_id;
75
151
  const client = await getClientsCollection().findOne({ clientId });
76
- if (!client) throw new Error('Failed to get client');
152
+ if (!client) throw new Error("Failed to get client");
77
153
  return client;
78
154
  };
@@ -1,12 +1,15 @@
1
1
  export const phoneNumbersMongoSchema = {
2
2
  bsonType: 'object',
3
- required: ['client_id', 'flow_id', 'phone_number'],
3
+ required: ['client_id', 'phone_number'],
4
4
  properties: {
5
5
  _id: { bsonType: 'objectId' },
6
6
  client_id: { bsonType: 'string' },
7
- flow_id: { bsonType: 'string' },
7
+ flow_id: { bsonType: ['objectId', 'string'] },
8
8
  phone_number: { bsonType: 'string' },
9
9
  is_primary: { bsonType: 'bool' },
10
+ provider: { bsonType: 'string' },
11
+ provider_sid: { bsonType: 'string' },
12
+ friendly_name: { bsonType: 'string' },
10
13
  createdAt: { bsonType: 'date' },
11
14
  updatedAt: { bsonType: 'date' },
12
15
  },
@@ -1,15 +1,30 @@
1
- import { ObjectId, WithId } from "mongodb";
2
- import { Flow } from "../flows/flows.types";
1
+ import { ObjectId, WithId } from 'mongodb';
2
+ import { Flow } from '../flows/flows.types';
3
+
4
+ export type PurchasedPhoneProviderPayload = {
5
+ provider: 'twilio' | 'telnyx';
6
+ provider_sid: string;
7
+ friendly_name?: string;
8
+ };
3
9
 
4
10
  export type PhoneNumber = {
5
11
  _id?: ObjectId;
6
12
  client_id: string;
7
- flow_id: ObjectId;
13
+ flow_id?: ObjectId;
8
14
  phone_number: string;
9
15
  subscriptionId?: string;
10
16
  is_primary: boolean;
17
+ provider?: 'twilio' | 'telnyx';
18
+ provider_sid?: string;
19
+ friendly_name?: string;
11
20
  createdAt: Date;
12
21
  updatedAt: Date;
13
22
  };
14
23
 
15
24
  export type PhoneNumberWithFlow = WithId<PhoneNumber> & { flow: Flow };
25
+
26
+ export type ClientPhoneNumberForFlow = {
27
+ flowId: string;
28
+ phoneNumber: string;
29
+ isPrimary: boolean;
30
+ };