@talkpilot/core-db 1.3.52 → 1.3.54

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 (156) hide show
  1. package/README.md +2 -21
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/talkpilot/calls/calls.constants.d.ts +1 -1
  7. package/dist/talkpilot/clients/clients.getters.d.ts +0 -1
  8. package/dist/talkpilot/clients/clients.getters.d.ts.map +1 -1
  9. package/dist/talkpilot/clients/clients.getters.js +1 -8
  10. package/dist/talkpilot/clients/clients.getters.js.map +1 -1
  11. package/dist/talkpilot/clients/clients.types.d.ts +0 -21
  12. package/dist/talkpilot/clients/clients.types.d.ts.map +1 -1
  13. package/dist/talkpilot/clients/index.d.ts +0 -2
  14. package/dist/talkpilot/clients/index.d.ts.map +1 -1
  15. package/dist/talkpilot/clients/index.js +0 -2
  16. package/dist/talkpilot/clients/index.js.map +1 -1
  17. package/dist/talkpilot/flows/flows.getter.d.ts +4 -1
  18. package/dist/talkpilot/flows/flows.getter.d.ts.map +1 -1
  19. package/dist/talkpilot/flows/flows.getter.js +12 -1
  20. package/dist/talkpilot/flows/flows.getter.js.map +1 -1
  21. package/dist/talkpilot/flows/flows.schema.d.ts +31 -0
  22. package/dist/talkpilot/flows/flows.schema.d.ts.map +1 -1
  23. package/dist/talkpilot/flows/flows.schema.js +25 -0
  24. package/dist/talkpilot/flows/flows.schema.js.map +1 -1
  25. package/dist/talkpilot/flows/flows.types.d.ts +14 -0
  26. package/dist/talkpilot/flows/flows.types.d.ts.map +1 -1
  27. package/dist/talkpilot/flows/index.d.ts +1 -1
  28. package/dist/talkpilot/flows/index.d.ts.map +1 -1
  29. package/dist/talkpilot/flows/index.js +3 -1
  30. package/dist/talkpilot/flows/index.js.map +1 -1
  31. package/dist/talkpilot/index.d.ts +0 -1
  32. package/dist/talkpilot/index.d.ts.map +1 -1
  33. package/dist/talkpilot/index.js +0 -1
  34. package/dist/talkpilot/index.js.map +1 -1
  35. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +0 -11
  36. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -1
  37. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +1 -60
  38. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -1
  39. package/dist/talkpilot/results/index.d.ts +0 -3
  40. package/dist/talkpilot/results/index.d.ts.map +1 -1
  41. package/dist/talkpilot/results/index.js +1 -22
  42. package/dist/talkpilot/results/index.js.map +1 -1
  43. package/dist/talkpilot/results/results.getter.d.ts.map +1 -1
  44. package/dist/talkpilot/results/results.getter.js +2 -3
  45. package/dist/talkpilot/results/results.getter.js.map +1 -1
  46. package/dist/test-utils/factories/index.d.ts +0 -2
  47. package/dist/test-utils/factories/index.d.ts.map +1 -1
  48. package/dist/test-utils/factories/index.js +0 -2
  49. package/dist/test-utils/factories/index.js.map +1 -1
  50. package/dist/websitalk/scanResources/scanResources.getters.d.ts +1 -0
  51. package/dist/websitalk/scanResources/scanResources.getters.d.ts.map +1 -1
  52. package/dist/websitalk/scanResources/scanResources.getters.js +6 -1
  53. package/dist/websitalk/scanResources/scanResources.getters.js.map +1 -1
  54. package/dist/websitalk/scans/scans.constants.d.ts +3 -1
  55. package/dist/websitalk/scans/scans.constants.d.ts.map +1 -1
  56. package/dist/websitalk/scans/scans.constants.js +3 -0
  57. package/dist/websitalk/scans/scans.constants.js.map +1 -1
  58. package/dist/websitalk/scans/scans.getters.d.ts +1 -0
  59. package/dist/websitalk/scans/scans.getters.d.ts.map +1 -1
  60. package/dist/websitalk/scans/scans.getters.js +6 -1
  61. package/dist/websitalk/scans/scans.getters.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/index.ts +1 -0
  64. package/src/talkpilot/clients/clients.getters.ts +0 -7
  65. package/src/talkpilot/clients/clients.types.ts +0 -19
  66. package/src/talkpilot/clients/index.ts +0 -2
  67. package/src/talkpilot/flows/__tests__/flows.schema.spec.ts +25 -0
  68. package/src/talkpilot/flows/flows.getter.ts +22 -2
  69. package/src/talkpilot/flows/flows.schema.ts +25 -0
  70. package/src/talkpilot/flows/flows.types.ts +22 -0
  71. package/src/talkpilot/flows/index.ts +6 -1
  72. package/src/talkpilot/index.ts +0 -1
  73. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +13 -227
  74. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +1 -76
  75. package/src/talkpilot/results/index.ts +0 -9
  76. package/src/talkpilot/results/results.getter.ts +2 -3
  77. package/src/test-utils/factories/index.ts +0 -2
  78. package/src/websitalk/scanResources/__tests__/scanResources.spec.ts +19 -0
  79. package/src/websitalk/scanResources/scanResources.getters.ts +7 -0
  80. package/src/websitalk/scans/__tests__/scans.spec.ts +28 -0
  81. package/src/websitalk/scans/scans.constants.ts +3 -0
  82. package/src/websitalk/scans/scans.getters.ts +5 -0
  83. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts +0 -8
  84. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts.map +0 -1
  85. package/dist/talkpilot/auditLogs/auditLogs.getters.js +0 -26
  86. package/dist/talkpilot/auditLogs/auditLogs.getters.js.map +0 -1
  87. package/dist/talkpilot/auditLogs/auditLogs.setters.d.ts +0 -3
  88. package/dist/talkpilot/auditLogs/auditLogs.setters.d.ts.map +0 -1
  89. package/dist/talkpilot/auditLogs/auditLogs.setters.js +0 -9
  90. package/dist/talkpilot/auditLogs/auditLogs.setters.js.map +0 -1
  91. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts +0 -12
  92. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts.map +0 -1
  93. package/dist/talkpilot/auditLogs/auditLogs.types.js +0 -3
  94. package/dist/talkpilot/auditLogs/auditLogs.types.js.map +0 -1
  95. package/dist/talkpilot/auditLogs/index.d.ts +0 -3
  96. package/dist/talkpilot/auditLogs/index.d.ts.map +0 -1
  97. package/dist/talkpilot/auditLogs/index.js +0 -19
  98. package/dist/talkpilot/auditLogs/index.js.map +0 -1
  99. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.d.ts +0 -4
  100. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.d.ts.map +0 -1
  101. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.js +0 -9
  102. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.getters.js.map +0 -1
  103. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.d.ts +0 -3
  104. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.d.ts.map +0 -1
  105. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.js +0 -9
  106. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.setters.js.map +0 -1
  107. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.d.ts +0 -10
  108. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.d.ts.map +0 -1
  109. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.js +0 -3
  110. package/dist/talkpilot/clientDeletionLogs/clientDeletionLogs.types.js.map +0 -1
  111. package/dist/talkpilot/clientDeletionLogs/index.d.ts +0 -4
  112. package/dist/talkpilot/clientDeletionLogs/index.d.ts.map +0 -1
  113. package/dist/talkpilot/clientDeletionLogs/index.js +0 -20
  114. package/dist/talkpilot/clientDeletionLogs/index.js.map +0 -1
  115. package/dist/talkpilot/clients/clients.constants.d.ts +0 -3
  116. package/dist/talkpilot/clients/clients.constants.d.ts.map +0 -1
  117. package/dist/talkpilot/clients/clients.constants.js +0 -6
  118. package/dist/talkpilot/clients/clients.constants.js.map +0 -1
  119. package/dist/talkpilot/clients/clients.lifecycle.d.ts +0 -10
  120. package/dist/talkpilot/clients/clients.lifecycle.d.ts.map +0 -1
  121. package/dist/talkpilot/clients/clients.lifecycle.js +0 -95
  122. package/dist/talkpilot/clients/clients.lifecycle.js.map +0 -1
  123. package/dist/talkpilot/results/results.constants.d.ts +0 -9
  124. package/dist/talkpilot/results/results.constants.d.ts.map +0 -1
  125. package/dist/talkpilot/results/results.constants.js +0 -12
  126. package/dist/talkpilot/results/results.constants.js.map +0 -1
  127. package/dist/talkpilot/results/results.statistics.getters.d.ts +0 -7
  128. package/dist/talkpilot/results/results.statistics.getters.d.ts.map +0 -1
  129. package/dist/talkpilot/results/results.statistics.getters.js +0 -244
  130. package/dist/talkpilot/results/results.statistics.getters.js.map +0 -1
  131. package/dist/talkpilot/results/results.statistics.types.d.ts +0 -42
  132. package/dist/talkpilot/results/results.statistics.types.d.ts.map +0 -1
  133. package/dist/talkpilot/results/results.statistics.types.js +0 -3
  134. package/dist/talkpilot/results/results.statistics.types.js.map +0 -1
  135. package/dist/test-utils/factories/talkpilot/clients.d.ts +0 -14
  136. package/dist/test-utils/factories/talkpilot/clients.d.ts.map +0 -1
  137. package/dist/test-utils/factories/talkpilot/clients.js +0 -19
  138. package/dist/test-utils/factories/talkpilot/clients.js.map +0 -1
  139. package/dist/test-utils/factories/talkpilot/results.d.ts +0 -16
  140. package/dist/test-utils/factories/talkpilot/results.d.ts.map +0 -1
  141. package/dist/test-utils/factories/talkpilot/results.js +0 -40
  142. package/dist/test-utils/factories/talkpilot/results.js.map +0 -1
  143. package/src/talkpilot/auditLogs/__tests__/auditLogs.spec.ts +0 -92
  144. package/src/talkpilot/auditLogs/auditLogs.getters.ts +0 -26
  145. package/src/talkpilot/auditLogs/auditLogs.types.ts +0 -13
  146. package/src/talkpilot/auditLogs/index.ts +0 -2
  147. package/src/talkpilot/clients/__tests__/clients.getters.spec.ts +0 -33
  148. package/src/talkpilot/clients/__tests__/clients.lifecycle.spec.ts +0 -166
  149. package/src/talkpilot/clients/clients.constants.ts +0 -2
  150. package/src/talkpilot/clients/clients.lifecycle.ts +0 -116
  151. package/src/talkpilot/results/__tests__/results.statistics.spec.ts +0 -226
  152. package/src/talkpilot/results/results.constants.ts +0 -11
  153. package/src/talkpilot/results/results.statistics.getters.ts +0 -329
  154. package/src/talkpilot/results/results.statistics.types.ts +0 -45
  155. package/src/test-utils/factories/talkpilot/clients.ts +0 -21
  156. package/src/test-utils/factories/talkpilot/results.ts +0 -43
@@ -7,11 +7,6 @@ import {
7
7
  createPhoneNumberEntity,
8
8
  createPurchasedPhoneNumber,
9
9
  getPrimaryPhoneFlowId,
10
- getClientPhones,
11
- getAllClientPhoneMappings,
12
- getDistinctClientPhonePairs,
13
- findClientsByPhoneNumbers,
14
- deletePhoneNumberRecords,
15
10
  } from "../phone_numbers.getter";
16
11
  import { getFlowsCollection } from "../../flows/flows.getter";
17
12
  import { createFlow, createPhoneNumber } from "../../../test-utils/factories";
@@ -19,7 +14,7 @@ import { ObjectId } from "mongodb";
19
14
 
20
15
  describe("db.phoneNumbers", () => {
21
16
  describe("getPhoneDataByPhoneNumber", () => {
22
- it("should return phone number data with flow", async () => {
17
+ it("return phone number data with flow", async () => {
23
18
  const flow = createFlow({
24
19
  clientId: "test-client-id",
25
20
  conversationSettings: {
@@ -67,7 +62,7 @@ describe("db.phoneNumbers", () => {
67
62
  });
68
63
 
69
64
  describe("getClientPhoneNumber", () => {
70
- it("should return phone number by client id", async () => {
65
+ it("return phone number by client id", async () => {
71
66
  const flow = createFlow();
72
67
  const phoneData = createPhoneNumber({
73
68
  flow_id: flow._id,
@@ -83,7 +78,7 @@ describe("db.phoneNumbers", () => {
83
78
  });
84
79
 
85
80
  describe("getClientPhoneData", () => {
86
- it("should return primary phone data by default", async () => {
81
+ it("returns primary phone data by default", async () => {
87
82
  const clientId = "multiPhoneClient";
88
83
  const phone1 = createPhoneNumber({
89
84
  client_id: clientId,
@@ -105,7 +100,7 @@ describe("db.phoneNumbers", () => {
105
100
  expect(result?.phone_number).toBe("2");
106
101
  });
107
102
 
108
- it("should return most recent non-primary phone data if isPrimary is false", async () => {
103
+ it("returns most recent non-primary phone data if isPrimary is false", async () => {
109
104
  const clientId = "multiPhoneClient2";
110
105
  const phone1 = createPhoneNumber({
111
106
  client_id: clientId,
@@ -136,7 +131,7 @@ describe("db.phoneNumbers", () => {
136
131
  });
137
132
 
138
133
  describe("getPhoneNumbersForFlows", () => {
139
- it("should return all phone numbers for the client with flow ObjectIds, newest first", async () => {
134
+ it("returns all phone numbers for the client with flow ObjectIds, newest first", async () => {
140
135
  const clientId = "flowsClient";
141
136
  const flow1 = createFlow({ clientId });
142
137
  const flow2 = createFlow({ clientId });
@@ -174,12 +169,12 @@ describe("db.phoneNumbers", () => {
174
169
  });
175
170
  });
176
171
 
177
- it("should return an empty array when the client has no phone numbers", async () => {
172
+ it("returns an empty array when the client has no phone numbers", async () => {
178
173
  const result = await getPhoneNumbersForFlows("noSuchClient");
179
174
  expect(result).toEqual([]);
180
175
  });
181
176
 
182
- it("should not include phone numbers for other clients", async () => {
177
+ it("does not include phone numbers for other clients", async () => {
183
178
  const clientA = "clientA";
184
179
  const clientB = "clientB";
185
180
  const flow = createFlow();
@@ -196,7 +191,7 @@ describe("db.phoneNumbers", () => {
196
191
  });
197
192
 
198
193
  describe("createPhoneNumberEntity", () => {
199
- it("should create first phone number as primary", async () => {
194
+ it("creates first phone number as primary", async () => {
200
195
  const clientId = "newClient";
201
196
  const flowId = new ObjectId().toHexString();
202
197
  const phoneNumber = "+123456789";
@@ -210,7 +205,7 @@ describe("db.phoneNumbers", () => {
210
205
  expect(result.is_primary).toBe(true);
211
206
  });
212
207
 
213
- it("should create subsequent phone number as non-primary", async () => {
208
+ it("creates subsequent phone number as non-primary", async () => {
214
209
  const clientId = "existingClient";
215
210
  const flowId = new ObjectId().toHexString();
216
211
 
@@ -225,7 +220,7 @@ describe("db.phoneNumbers", () => {
225
220
  });
226
221
 
227
222
  describe("createPurchasedPhoneNumber", () => {
228
- it("should persist a phone_numbers document with provider payload and flow", async () => {
223
+ it("persists a phone_numbers document with provider payload and flow", async () => {
229
224
  const clientId = "purchasedClientDb";
230
225
  const flowId = new ObjectId().toHexString();
231
226
  const phoneNumber = "+15551234567";
@@ -257,7 +252,7 @@ describe("db.phoneNumbers", () => {
257
252
  });
258
253
 
259
254
  describe("getPrimaryPhoneFlowId", () => {
260
- it("should return flow_id from primary phone as string", async () => {
255
+ it("returns flow_id from primary phone as string", async () => {
261
256
  const clientId = "primaryFlowClient";
262
257
  const flowId = new ObjectId();
263
258
  await getPhoneNumbersCollection().insertOne(
@@ -271,11 +266,11 @@ describe("db.phoneNumbers", () => {
271
266
  expect(await getPrimaryPhoneFlowId(clientId)).toBe(flowId.toHexString());
272
267
  });
273
268
 
274
- it("should return null when client has no primary phone", async () => {
269
+ it("returns null when client has no primary phone", async () => {
275
270
  expect(await getPrimaryPhoneFlowId("no-phone-client")).toBeNull();
276
271
  });
277
272
 
278
- it("should return null when primary phone has no flow_id", async () => {
273
+ it("returns null when primary phone has no flow_id", async () => {
279
274
  const clientId = "phoneNoFlow";
280
275
  const phone = createPhoneNumber({ client_id: clientId, is_primary: true });
281
276
  delete phone.flow_id;
@@ -284,213 +279,4 @@ describe("db.phoneNumbers", () => {
284
279
  expect(await getPrimaryPhoneFlowId(clientId)).toBeNull();
285
280
  });
286
281
  });
287
-
288
- describe("getClientPhones", () => {
289
- it("should return all phone numbers for the given client, projected to phoneNumber only", async () => {
290
- const clientId = "phonesClientA";
291
- await getPhoneNumbersCollection().insertMany([
292
- createPhoneNumber({ client_id: clientId, phone_number: "+100" }),
293
- createPhoneNumber({ client_id: clientId, phone_number: "+200" }),
294
- ]);
295
-
296
- const result = await getClientPhones(clientId);
297
-
298
- expect(result).toHaveLength(2);
299
- expect(result).toEqual(
300
- expect.arrayContaining([
301
- { phoneNumber: "+100" },
302
- { phoneNumber: "+200" },
303
- ]),
304
- );
305
- });
306
-
307
- it("should not include phone numbers belonging to other clients", async () => {
308
- await getPhoneNumbersCollection().insertOne(
309
- createPhoneNumber({ client_id: "someOtherClient" }),
310
- );
311
-
312
- const result = await getClientPhones("phonesClientB");
313
- expect(result).toEqual([]);
314
- });
315
-
316
- it("should remove exact duplicate phone records for the same client", async () => {
317
- const clientId = "phonesClientDup";
318
- await getPhoneNumbersCollection().insertMany([
319
- createPhoneNumber({ client_id: clientId, phone_number: "+300" }),
320
- createPhoneNumber({ client_id: clientId, phone_number: "+300" }),
321
- createPhoneNumber({ client_id: clientId, phone_number: "+400" }),
322
- ]);
323
-
324
- const result = await getClientPhones(clientId);
325
-
326
- expect(result).toHaveLength(2);
327
- expect(result).toEqual(
328
- expect.arrayContaining([
329
- { phoneNumber: "+300" },
330
- { phoneNumber: "+400" },
331
- ]),
332
- );
333
- });
334
- });
335
-
336
- describe("getAllClientPhoneMappings", () => {
337
- it("should return a Map of clientId to phone number across all clients", async () => {
338
- await getPhoneNumbersCollection().insertMany([
339
- createPhoneNumber({ client_id: "mapClientA", phone_number: "+111" }),
340
- createPhoneNumber({ client_id: "mapClientB", phone_number: "+222" }),
341
- ]);
342
-
343
- const result = await getAllClientPhoneMappings();
344
-
345
- expect(result).toBeInstanceOf(Map);
346
- expect(result.get("mapClientA")).toBe("+111");
347
- expect(result.get("mapClientB")).toBe("+222");
348
- });
349
-
350
- it("should return an empty Map when there are no phone numbers", async () => {
351
- const result = await getAllClientPhoneMappings();
352
- expect(result.size).toBe(0);
353
- });
354
-
355
- it("should return the most recently updated phone number when a client has several", async () => {
356
- const clientId = "mapClientRecent";
357
- await getPhoneNumbersCollection().insertMany([
358
- createPhoneNumber({
359
- client_id: clientId,
360
- phone_number: "+old",
361
- updatedAt: new Date("2023-01-01"),
362
- }),
363
- createPhoneNumber({
364
- client_id: clientId,
365
- phone_number: "+new",
366
- updatedAt: new Date("2023-06-01"),
367
- }),
368
- ]);
369
-
370
- const result = await getAllClientPhoneMappings();
371
-
372
- expect(result.get(clientId)).toBe("+new");
373
- });
374
-
375
- it("should prefer the is_primary number over a more recently updated non-primary one", async () => {
376
- const clientId = "mapClientPrimary";
377
- await getPhoneNumbersCollection().insertMany([
378
- createPhoneNumber({
379
- client_id: clientId,
380
- phone_number: "+primary",
381
- is_primary: true,
382
- updatedAt: new Date("2023-01-01"),
383
- }),
384
- createPhoneNumber({
385
- client_id: clientId,
386
- phone_number: "+secondary",
387
- is_primary: false,
388
- updatedAt: new Date("2023-06-01"),
389
- }),
390
- ]);
391
-
392
- const result = await getAllClientPhoneMappings();
393
-
394
- expect(result.get(clientId)).toBe("+primary");
395
- });
396
- });
397
-
398
- describe("getDistinctClientPhonePairs", () => {
399
- it("should return unique client+phone pairs, collapsing exact duplicates", async () => {
400
- await getPhoneNumbersCollection().insertMany([
401
- createPhoneNumber({ client_id: "pairClientA", phone_number: "+500" }),
402
- createPhoneNumber({ client_id: "pairClientA", phone_number: "+500" }),
403
- createPhoneNumber({ client_id: "pairClientB", phone_number: "+600" }),
404
- ]);
405
-
406
- const result = await getDistinctClientPhonePairs();
407
-
408
- expect(result).toEqual(
409
- expect.arrayContaining([
410
- { clientId: "pairClientA", phoneNumber: "+500" },
411
- { clientId: "pairClientB", phoneNumber: "+600" },
412
- ]),
413
- );
414
- expect(
415
- result.filter(
416
- (p) => p.clientId === "pairClientA" && p.phoneNumber === "+500",
417
- ),
418
- ).toHaveLength(1);
419
- });
420
-
421
- it("should keep separate pairs when the same number is shared by different clients", async () => {
422
- await getPhoneNumbersCollection().insertMany([
423
- createPhoneNumber({ client_id: "sharedClientA", phone_number: "+700" }),
424
- createPhoneNumber({ client_id: "sharedClientB", phone_number: "+700" }),
425
- ]);
426
-
427
- const result = await getDistinctClientPhonePairs();
428
-
429
- expect(result).toEqual(
430
- expect.arrayContaining([
431
- { clientId: "sharedClientA", phoneNumber: "+700" },
432
- { clientId: "sharedClientB", phoneNumber: "+700" },
433
- ]),
434
- );
435
- });
436
- });
437
-
438
- describe("findClientsByPhoneNumbers", () => {
439
- it("should return other clients sharing each phone number, excluding the given client", async () => {
440
- await getPhoneNumbersCollection().insertMany([
441
- createPhoneNumber({ client_id: "excludeMe", phone_number: "+800" }),
442
- createPhoneNumber({ client_id: "otherClient1", phone_number: "+800" }),
443
- createPhoneNumber({ client_id: "otherClient2", phone_number: "+800" }),
444
- ]);
445
-
446
- const result = await findClientsByPhoneNumbers(["+800"], "excludeMe");
447
-
448
- expect(result.get("+800")).toEqual(
449
- expect.arrayContaining(["otherClient1", "otherClient2"]),
450
- );
451
- expect(result.get("+800")).not.toContain("excludeMe");
452
- });
453
-
454
- it("should return an empty array for a phone number with no other clients", async () => {
455
- await getPhoneNumbersCollection().insertOne(
456
- createPhoneNumber({ client_id: "soleOwner", phone_number: "+900" }),
457
- );
458
-
459
- const result = await findClientsByPhoneNumbers(["+900"], "soleOwner");
460
-
461
- expect(result.get("+900")).toEqual([]);
462
- });
463
-
464
- it("should return an empty map immediately when given no phone numbers", async () => {
465
- const result = await findClientsByPhoneNumbers([]);
466
- expect(result.size).toBe(0);
467
- });
468
- });
469
-
470
- describe("deletePhoneNumberRecords", () => {
471
- it("should delete every record for the given phone number across all clients", async () => {
472
- await getPhoneNumbersCollection().insertMany([
473
- createPhoneNumber({ client_id: "delClientA", phone_number: "+1000" }),
474
- createPhoneNumber({ client_id: "delClientB", phone_number: "+1000" }),
475
- createPhoneNumber({ client_id: "delClientC", phone_number: "+2000" }),
476
- ]);
477
-
478
- const deletedCount = await deletePhoneNumberRecords("+1000");
479
-
480
- expect(deletedCount).toBe(2);
481
- const remaining = await getPhoneNumbersCollection()
482
- .find({ phone_number: "+1000" })
483
- .toArray();
484
- expect(remaining).toHaveLength(0);
485
- const untouched = await getPhoneNumbersCollection().findOne({
486
- phone_number: "+2000",
487
- });
488
- expect(untouched?.client_id).toBe("delClientC");
489
- });
490
-
491
- it("should return 0 when no records match the phone number", async () => {
492
- const deletedCount = await deletePhoneNumberRecords("+9999999");
493
- expect(deletedCount).toBe(0);
494
- });
495
- });
496
282
  });
@@ -157,9 +157,7 @@ export const findClientByPhoneNumber = async (
157
157
  return client;
158
158
  };
159
159
 
160
- export const getPrimaryPhoneFlowId = async (
161
- clientId: string,
162
- ): Promise<string | null> => {
160
+ export const getPrimaryPhoneFlowId = async (clientId: string): Promise<string | null> => {
163
161
  const phone = await getClientPhoneData(clientId);
164
162
  return phone?.flow_id ? String(phone.flow_id) : null;
165
163
  };
@@ -176,76 +174,3 @@ export const bindClientPhoneToFlow = async (
176
174
  throw new Error(`No primary phone number found for client: ${clientId}`);
177
175
  }
178
176
  };
179
-
180
- export const getClientPhones = async (
181
- clientId: string,
182
- ): Promise<{ phoneNumber: string }[]> => {
183
- const docs = await getPhoneNumbersCollection()
184
- .aggregate<{ _id: string }>([
185
- { $match: { client_id: clientId } },
186
- { $group: { _id: "$phone_number" } },
187
- ])
188
- .toArray();
189
- return docs.map((d) => ({ phoneNumber: d._id }));
190
- };
191
-
192
- export const getAllClientPhoneMappings = async (): Promise<
193
- Map<string, string>
194
- > => {
195
- const docs = await getPhoneNumbersCollection()
196
- .aggregate<{ _id: string; phone_number: string }>([
197
- { $sort: { is_primary: -1, updatedAt: -1 } },
198
- { $group: { _id: "$client_id", phone_number: { $first: "$phone_number" } } },
199
- ])
200
- .toArray();
201
- return new Map(docs.map((d) => [d._id, d.phone_number]));
202
- };
203
-
204
- export const getDistinctClientPhonePairs = async (): Promise<
205
- { clientId: string; phoneNumber: string }[]
206
- > => {
207
- const docs = await getPhoneNumbersCollection()
208
- .aggregate<{ _id: { client_id: string; phone_number: string } }>([
209
- { $group: { _id: { client_id: "$client_id", phone_number: "$phone_number" } } },
210
- ])
211
- .toArray();
212
- return docs.map((d) => ({
213
- clientId: d._id.client_id,
214
- phoneNumber: d._id.phone_number,
215
- }));
216
- };
217
-
218
- export const findClientsByPhoneNumbers = async (
219
- phoneNumbers: string[],
220
- excludeClientId?: string,
221
- ): Promise<Map<string, string[]>> => {
222
- const result = new Map<string, string[]>(
223
- phoneNumbers.map((p) => [p, [] as string[]]),
224
- );
225
- if (phoneNumbers.length === 0) return result;
226
-
227
- const docs = await getPhoneNumbersCollection()
228
- .aggregate<{ _id: string; clientIds: string[] }>([
229
- {
230
- $match: {
231
- phone_number: { $in: phoneNumbers },
232
- ...(excludeClientId ? { client_id: { $ne: excludeClientId } } : {}),
233
- },
234
- },
235
- { $group: { _id: "$phone_number", clientIds: { $addToSet: "$client_id" } } },
236
- ])
237
- .toArray();
238
-
239
- docs.forEach((d) => result.set(d._id, d.clientIds));
240
- return result;
241
- };
242
-
243
- /** Deletes this number's record for every client that references it. Check `findClientsByPhoneNumbers` first to see who's affected. */
244
- export const deletePhoneNumberRecords = async (
245
- phoneNumber: string,
246
- ): Promise<number> => {
247
- const result = await getPhoneNumbersCollection().deleteMany({
248
- phone_number: phoneNumber,
249
- });
250
- return result.deletedCount;
251
- };
@@ -1,4 +1,3 @@
1
- export * from "./results.constants";
2
1
  export {
3
2
  getResultsCollection,
4
3
  initializeResultDocument,
@@ -6,11 +5,3 @@ export {
6
5
  findResultByCallSid,
7
6
  } from "./results.getter";
8
7
  export type * from "./results.types";
9
- export {
10
- aggregateActiveCallsSummary,
11
- aggregateTodayCallsSummary,
12
- aggregateClientCallStats,
13
- aggregateSessionCallStats,
14
- findClientIdsByCallSids,
15
- } from "./results.statistics.getters";
16
- export type * from "./results.statistics.types";
@@ -1,6 +1,5 @@
1
1
  import { Collection, ObjectId } from "mongodb";
2
2
  import { getDb, Session } from "../index";
3
- import { INCOMING_SESSION_ID } from "./results.constants";
4
3
  import type { Result } from "./results.types";
5
4
 
6
5
  export const getResultsCollection = (): Collection<Result> =>
@@ -18,8 +17,8 @@ export const initializeResultDocument = async (
18
17
  runId: createRunId(),
19
18
  date: new Date(),
20
19
  calls: [],
21
- sessionId: session ? session._id!.toString() : INCOMING_SESSION_ID,
22
- sessionName: session ? session.session_name : INCOMING_SESSION_ID,
20
+ sessionId: session ? session._id!.toString() : "incomingCall",
21
+ sessionName: session ? session.session_name : "incomingCall",
23
22
  clientId,
24
23
  });
25
24
  const result = await getResultsCollection().findOne({ _id: insertedId });
@@ -1,5 +1,4 @@
1
1
  export * from "./talkpilot/agents";
2
- export * from "./talkpilot/clients";
3
2
  export * from "./talkpilot/calls";
4
3
  export * from "./talkpilot/clientAudioBuffers";
5
4
  export * from "./talkpilot/clientsConfig";
@@ -8,7 +7,6 @@ export * from "./talkpilot/contextNotes";
8
7
  export * from "./talkpilot/groups";
9
8
  export * from "./talkpilot/phone_numbers";
10
9
  export * from "./talkpilot/sessions";
11
- export * from "./talkpilot/results";
12
10
  export * from "./municipal/cities";
13
11
  export * from "./municipal/departmentsSubjects";
14
12
  export * from "./municipal/muniIssues";
@@ -5,6 +5,7 @@ import {
5
5
  getScanPages,
6
6
  getScanResourceById,
7
7
  getScanResourceCountsByScanIds,
8
+ deleteScanResourcesByScanId,
8
9
  } from "../scanResources.getters";
9
10
  import { boardColumn } from "../scanResources.utils";
10
11
  import { createScanResourceFixture } from "../../../test-utils/factories";
@@ -190,4 +191,22 @@ describe("db.websitalk.scanResources", () => {
190
191
  expect(result).toBeNull();
191
192
  });
192
193
  });
194
+
195
+ describe("deleteScanResourcesByScanId()", () => {
196
+ it("should delete all resources for the scan and return the count", async () => {
197
+ const scanId = new ObjectId().toString();
198
+ await getScanResourcesCollection().insertMany([
199
+ createScanResourceFixture({ scanId }),
200
+ createScanResourceFixture({ scanId }),
201
+ createScanResourceFixture({ scanId: new ObjectId().toString() }),
202
+ ]);
203
+
204
+ const deleted = await deleteScanResourcesByScanId(scanId);
205
+
206
+ expect(deleted).toBe(2);
207
+ expect(
208
+ await getScanResourcesCollection().countDocuments({ scanId }),
209
+ ).toBe(0);
210
+ });
211
+ });
193
212
  });
@@ -100,3 +100,10 @@ export const getScanResourceById = async (
100
100
  pageId: string,
101
101
  ): Promise<ScanResourceDoc | null> =>
102
102
  getScanResourcesCollection().findOne({ scanId, _id: new ObjectId(pageId) });
103
+
104
+ export const deleteScanResourcesByScanId = async (
105
+ scanId: string,
106
+ ): Promise<number> => {
107
+ const result = await getScanResourcesCollection().deleteMany({ scanId });
108
+ return result.deletedCount;
109
+ };
@@ -12,7 +12,9 @@ import {
12
12
  getInProgressScanByWebsiteUrl,
13
13
  getLatestCompletedScanByWebsiteUrl,
14
14
  deleteScansByWebsiteUrl,
15
+ deleteScanById,
15
16
  } from "../scans.getters";
17
+ import { FINISHED_SCAN_STATUSES, SCAN_STATUSES } from "../scans.constants";
16
18
  import { createScanFixture } from "../../../test-utils/factories";
17
19
  import { ObjectId } from "mongodb";
18
20
 
@@ -310,4 +312,30 @@ describe("db.websitalk.scans", () => {
310
312
  expect(await countScans({ websiteUrlId })).toBe(0);
311
313
  });
312
314
  });
315
+
316
+ describe("deleteScanById()", () => {
317
+ it("should delete the scan and return true", async () => {
318
+ const { insertedId } =
319
+ await getScansCollection().insertOne(createScanFixture());
320
+
321
+ expect(await deleteScanById(insertedId)).toBe(true);
322
+ expect(
323
+ await getScansCollection().findOne({ _id: insertedId }),
324
+ ).toBeNull();
325
+ });
326
+
327
+ it("should return false when the scan does not exist", async () => {
328
+ expect(await deleteScanById(new ObjectId())).toBe(false);
329
+ });
330
+ });
331
+
332
+ describe("FINISHED_SCAN_STATUSES", () => {
333
+ it("should include CANCELED — canceling is final, not resumable", () => {
334
+ expect(FINISHED_SCAN_STATUSES).toContain(SCAN_STATUSES.CANCELED);
335
+ });
336
+
337
+ it("should NOT include PAUSED — pausing is reversible", () => {
338
+ expect(FINISHED_SCAN_STATUSES).not.toContain(SCAN_STATUSES.PAUSED);
339
+ });
340
+ });
313
341
  });
@@ -6,10 +6,13 @@ export const SCAN_STATUSES = {
6
6
  COMPLETED: "COMPLETED",
7
7
  FAILED: "FAILED",
8
8
  OVERWRITTEN: "OVERWRITTEN",
9
+ PAUSED: "PAUSED",
10
+ CANCELED: "CANCELED",
9
11
  } as const;
10
12
 
11
13
  export const FINISHED_SCAN_STATUSES = [
12
14
  SCAN_STATUSES.COMPLETED,
13
15
  SCAN_STATUSES.FAILED,
14
16
  SCAN_STATUSES.OVERWRITTEN,
17
+ SCAN_STATUSES.CANCELED,
15
18
  ] as const;
@@ -164,3 +164,8 @@ export const deleteScansByWebsiteUrl = async (
164
164
  const result = await getScansCollection().deleteMany({ websiteUrlId });
165
165
  return result.deletedCount;
166
166
  };
167
+
168
+ export const deleteScanById = async (scanId: ObjectId): Promise<boolean> => {
169
+ const result = await getScansCollection().deleteOne({ _id: scanId });
170
+ return result.deletedCount > 0;
171
+ };
@@ -1,8 +0,0 @@
1
- import { Collection } from "mongodb";
2
- import { QueryOptions } from "../utils/query.utils";
3
- import { AuditLogDoc, AuditLogEntry } from "./auditLogs.types";
4
- export declare const getAuditLogsCollection: () => Collection<AuditLogEntry>;
5
- export declare const insertAuditLog: (entry: AuditLogEntry) => Promise<void>;
6
- export declare const findAuditLogs: (options: Pick<QueryOptions, "skip"> & Required<Pick<QueryOptions, "limit">>) => Promise<AuditLogDoc[]>;
7
- export declare const countAuditLogs: () => Promise<number>;
8
- //# sourceMappingURL=auditLogs.getters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.getters.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.getters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAqB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE/D,eAAO,MAAM,sBAAsB,QAAO,UAAU,CAAC,aAAa,CAEjE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,OAAO,aAAa,KAAG,OAAO,CAAC,IAAI,CAEvE,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,KAC1E,OAAO,CAAC,WAAW,EAAE,CAMvB,CAAC;AAEF,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,CAErD,CAAC"}
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.countAuditLogs = exports.findAuditLogs = exports.insertAuditLog = exports.getAuditLogsCollection = void 0;
4
- const index_1 = require("../index");
5
- const query_utils_1 = require("../utils/query.utils");
6
- const getAuditLogsCollection = () => {
7
- return (0, index_1.getDb)().collection("auditLogs");
8
- };
9
- exports.getAuditLogsCollection = getAuditLogsCollection;
10
- const insertAuditLog = async (entry) => {
11
- await (0, exports.getAuditLogsCollection)().insertOne(entry);
12
- };
13
- exports.insertAuditLog = insertAuditLog;
14
- const findAuditLogs = async (options) => {
15
- const cursor = (0, exports.getAuditLogsCollection)().find({});
16
- return (0, query_utils_1.applyQueryOptions)(cursor, {
17
- sort: { timestamp: -1 },
18
- ...options,
19
- }).toArray();
20
- };
21
- exports.findAuditLogs = findAuditLogs;
22
- const countAuditLogs = async () => {
23
- return (0, exports.getAuditLogsCollection)().countDocuments({});
24
- };
25
- exports.countAuditLogs = countAuditLogs;
26
- //# sourceMappingURL=auditLogs.getters.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.getters.js","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.getters.ts"],"names":[],"mappings":";;;AACA,oCAAiC;AACjC,sDAAuE;AAGhE,MAAM,sBAAsB,GAAG,GAA8B,EAAE;IACpE,OAAO,IAAA,aAAK,GAAE,CAAC,UAAU,CAAgB,WAAW,CAAC,CAAC;AACxD,CAAC,CAAC;AAFW,QAAA,sBAAsB,0BAEjC;AAEK,MAAM,cAAc,GAAG,KAAK,EAAE,KAAoB,EAAiB,EAAE;IAC1E,MAAM,IAAA,8BAAsB,GAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB;AAEK,MAAM,aAAa,GAAG,KAAK,EAChC,OAA2E,EACnD,EAAE;IAC1B,MAAM,MAAM,GAAG,IAAA,8BAAsB,GAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,OAAO,IAAA,+BAAiB,EAAC,MAAM,EAAE;QAC/B,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE;QACvB,GAAG,OAAO;KACX,CAAC,CAAC,OAAO,EAAE,CAAC;AACf,CAAC,CAAC;AARW,QAAA,aAAa,iBAQxB;AAEK,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACxD,OAAO,IAAA,8BAAsB,GAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB"}
@@ -1,3 +0,0 @@
1
- import { AuditLogEntry } from "./auditLogs.types";
2
- export declare const insertAuditLog: (entry: AuditLogEntry) => Promise<void>;
3
- //# sourceMappingURL=auditLogs.setters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.setters.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.setters.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,eAAO,MAAM,cAAc,GAAU,OAAO,aAAa,KAAG,OAAO,CAAC,IAAI,CAEvE,CAAC"}
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.insertAuditLog = void 0;
4
- const auditLogs_getters_1 = require("./auditLogs.getters");
5
- const insertAuditLog = async (entry) => {
6
- await (0, auditLogs_getters_1.getAuditLogsCollection)().insertOne(entry);
7
- };
8
- exports.insertAuditLog = insertAuditLog;
9
- //# sourceMappingURL=auditLogs.setters.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.setters.js","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.setters.ts"],"names":[],"mappings":";;;AAAA,2DAA6D;AAGtD,MAAM,cAAc,GAAG,KAAK,EAAE,KAAoB,EAAiB,EAAE;IAC1E,MAAM,IAAA,0CAAsB,GAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAClD,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB"}
@@ -1,12 +0,0 @@
1
- import { WithId } from "mongodb";
2
- export type AuditLogEntry = {
3
- clientId: string;
4
- adminEmail: string;
5
- action: "delete";
6
- timestamp: Date;
7
- env?: string;
8
- allSucceeded?: boolean;
9
- failedCollections?: string[];
10
- };
11
- export type AuditLogDoc = WithId<AuditLogEntry>;
12
- //# sourceMappingURL=auditLogs.types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.types.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC"}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=auditLogs.types.js.map