@talkpilot/core-db 1.3.89 → 1.3.91

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 (121) hide show
  1. package/README.md +12 -65
  2. package/dist/configuration/gptLive.seed.d.ts +2 -0
  3. package/dist/configuration/gptLive.seed.d.ts.map +1 -0
  4. package/dist/configuration/gptLive.seed.js +59 -0
  5. package/dist/configuration/gptLive.seed.js.map +1 -0
  6. package/dist/talkpilot/calls/calls.constants.d.ts +1 -11
  7. package/dist/talkpilot/calls/calls.constants.d.ts.map +1 -1
  8. package/dist/talkpilot/calls/calls.constants.js +1 -11
  9. package/dist/talkpilot/calls/calls.constants.js.map +1 -1
  10. package/dist/talkpilot/calls/calls.getters.d.ts +1 -8
  11. package/dist/talkpilot/calls/calls.getters.d.ts.map +1 -1
  12. package/dist/talkpilot/calls/calls.getters.js +1 -216
  13. package/dist/talkpilot/calls/calls.getters.js.map +1 -1
  14. package/dist/talkpilot/calls/calls.types.d.ts +0 -45
  15. package/dist/talkpilot/calls/calls.types.d.ts.map +1 -1
  16. package/dist/talkpilot/clients/clients.getters.d.ts +0 -6
  17. package/dist/talkpilot/clients/clients.getters.d.ts.map +1 -1
  18. package/dist/talkpilot/clients/clients.getters.js +1 -62
  19. package/dist/talkpilot/clients/clients.getters.js.map +1 -1
  20. package/dist/talkpilot/clients/clients.quota.constants.d.ts +2 -0
  21. package/dist/talkpilot/clients/clients.quota.constants.d.ts.map +1 -0
  22. package/dist/talkpilot/clients/clients.quota.constants.js +5 -0
  23. package/dist/talkpilot/clients/clients.quota.constants.js.map +1 -0
  24. package/dist/talkpilot/clients/clients.quota.utils.d.ts +8 -0
  25. package/dist/talkpilot/clients/clients.quota.utils.d.ts.map +1 -0
  26. package/dist/talkpilot/clients/clients.quota.utils.js +45 -0
  27. package/dist/talkpilot/clients/clients.quota.utils.js.map +1 -0
  28. package/dist/talkpilot/clients/clients.types.d.ts +0 -53
  29. package/dist/talkpilot/clients/clients.types.d.ts.map +1 -1
  30. package/dist/talkpilot/clients/index.d.ts +0 -2
  31. package/dist/talkpilot/clients/index.d.ts.map +1 -1
  32. package/dist/talkpilot/clients/index.js +0 -2
  33. package/dist/talkpilot/clients/index.js.map +1 -1
  34. package/dist/talkpilot/contextNotes/contextNotes.getters.d.ts +7 -1
  35. package/dist/talkpilot/contextNotes/contextNotes.getters.d.ts.map +1 -1
  36. package/dist/talkpilot/contextNotes/contextNotes.getters.js +37 -1
  37. package/dist/talkpilot/contextNotes/contextNotes.getters.js.map +1 -1
  38. package/dist/talkpilot/contextNotes/contextNotes.types.d.ts +6 -0
  39. package/dist/talkpilot/contextNotes/contextNotes.types.d.ts.map +1 -1
  40. package/dist/talkpilot/index.d.ts +0 -1
  41. package/dist/talkpilot/index.d.ts.map +1 -1
  42. package/dist/talkpilot/index.js +0 -1
  43. package/dist/talkpilot/index.js.map +1 -1
  44. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts +1 -9
  45. package/dist/talkpilot/phone_numbers/phone_numbers.getter.d.ts.map +1 -1
  46. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js +1 -70
  47. package/dist/talkpilot/phone_numbers/phone_numbers.getter.js.map +1 -1
  48. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts +0 -5
  49. package/dist/talkpilot/phone_numbers/phone_numbers.types.d.ts.map +1 -1
  50. package/dist/test-utils/factories/index.d.ts +0 -2
  51. package/dist/test-utils/factories/index.d.ts.map +1 -1
  52. package/dist/test-utils/factories/index.js +0 -2
  53. package/dist/test-utils/factories/index.js.map +1 -1
  54. package/dist/websitalk/scanResources/scanResources.getters.d.ts.map +1 -1
  55. package/dist/websitalk/scanResources/scanResources.getters.js +1 -2
  56. package/dist/websitalk/scanResources/scanResources.getters.js.map +1 -1
  57. package/dist/websitalk/scanResources/scanResources.utils.d.ts +1 -1
  58. package/dist/websitalk/scanResources/scanResources.utils.d.ts.map +1 -1
  59. package/dist/websitalk/scanResources/scanResources.utils.js +3 -3
  60. package/dist/websitalk/scanResources/scanResources.utils.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/talkpilot/calls/calls.constants.ts +0 -14
  63. package/src/talkpilot/calls/calls.getters.ts +0 -320
  64. package/src/talkpilot/calls/calls.types.ts +0 -52
  65. package/src/talkpilot/clients/clients.getters.ts +2 -91
  66. package/src/talkpilot/clients/clients.types.ts +0 -58
  67. package/src/talkpilot/clients/index.ts +0 -2
  68. package/src/talkpilot/contextNotes/__tests__/contextNotes.getters.spec.ts +141 -0
  69. package/src/talkpilot/contextNotes/contextNotes.getters.ts +75 -1
  70. package/src/talkpilot/contextNotes/contextNotes.types.ts +7 -0
  71. package/src/talkpilot/index.ts +0 -1
  72. package/src/talkpilot/phone_numbers/__tests__/phone_numbers.spec.ts +13 -284
  73. package/src/talkpilot/phone_numbers/phone_numbers.getter.ts +1 -89
  74. package/src/talkpilot/phone_numbers/phone_numbers.types.ts +0 -6
  75. package/src/test-utils/factories/index.ts +0 -2
  76. package/src/websitalk/scanResources/scanResources.getters.ts +6 -2
  77. package/src/websitalk/scanResources/scanResources.utils.ts +3 -2
  78. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts +0 -8
  79. package/dist/talkpilot/auditLogs/auditLogs.getters.d.ts.map +0 -1
  80. package/dist/talkpilot/auditLogs/auditLogs.getters.js +0 -26
  81. package/dist/talkpilot/auditLogs/auditLogs.getters.js.map +0 -1
  82. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts +0 -11
  83. package/dist/talkpilot/auditLogs/auditLogs.types.d.ts.map +0 -1
  84. package/dist/talkpilot/auditLogs/auditLogs.types.js +0 -3
  85. package/dist/talkpilot/auditLogs/auditLogs.types.js.map +0 -1
  86. package/dist/talkpilot/auditLogs/index.d.ts +0 -3
  87. package/dist/talkpilot/auditLogs/index.d.ts.map +0 -1
  88. package/dist/talkpilot/auditLogs/index.js +0 -19
  89. package/dist/talkpilot/auditLogs/index.js.map +0 -1
  90. package/dist/talkpilot/clients/clients.constants.d.ts +0 -4
  91. package/dist/talkpilot/clients/clients.constants.d.ts.map +0 -1
  92. package/dist/talkpilot/clients/clients.constants.js +0 -7
  93. package/dist/talkpilot/clients/clients.constants.js.map +0 -1
  94. package/dist/talkpilot/clients/clients.lifecycle.d.ts +0 -10
  95. package/dist/talkpilot/clients/clients.lifecycle.d.ts.map +0 -1
  96. package/dist/talkpilot/clients/clients.lifecycle.js +0 -109
  97. package/dist/talkpilot/clients/clients.lifecycle.js.map +0 -1
  98. package/dist/test-utils/factories/talkpilot/clients.d.ts +0 -14
  99. package/dist/test-utils/factories/talkpilot/clients.d.ts.map +0 -1
  100. package/dist/test-utils/factories/talkpilot/clients.js +0 -19
  101. package/dist/test-utils/factories/talkpilot/clients.js.map +0 -1
  102. package/dist/test-utils/factories/talkpilot/results.d.ts +0 -16
  103. package/dist/test-utils/factories/talkpilot/results.d.ts.map +0 -1
  104. package/dist/test-utils/factories/talkpilot/results.js +0 -40
  105. package/dist/test-utils/factories/talkpilot/results.js.map +0 -1
  106. package/dist/utils/regex.utils.d.ts +0 -2
  107. package/dist/utils/regex.utils.d.ts.map +0 -1
  108. package/dist/utils/regex.utils.js +0 -6
  109. package/dist/utils/regex.utils.js.map +0 -1
  110. package/src/talkpilot/auditLogs/__tests__/auditLogs.spec.ts +0 -91
  111. package/src/talkpilot/auditLogs/auditLogs.getters.ts +0 -26
  112. package/src/talkpilot/auditLogs/auditLogs.types.ts +0 -12
  113. package/src/talkpilot/auditLogs/index.ts +0 -2
  114. package/src/talkpilot/calls/__tests__/calls.statistics.getters.spec.ts +0 -559
  115. package/src/talkpilot/clients/__tests__/clients.getters.spec.ts +0 -224
  116. package/src/talkpilot/clients/__tests__/clients.lifecycle.spec.ts +0 -194
  117. package/src/talkpilot/clients/clients.constants.ts +0 -4
  118. package/src/talkpilot/clients/clients.lifecycle.ts +0 -132
  119. package/src/test-utils/factories/talkpilot/clients.ts +0 -21
  120. package/src/test-utils/factories/talkpilot/results.ts +0 -43
  121. package/src/utils/regex.utils.ts +0 -2
@@ -7,11 +7,6 @@ import {
7
7
  createPhoneNumberEntity,
8
8
  createPurchasedPhoneNumber,
9
9
  getPrimaryPhoneFlowId,
10
- getClientPhones,
11
- findPhonesByClientIds,
12
- getDistinctClientPhonePairs,
13
- findClientsByPhoneNumbers,
14
- deletePhoneNumberRecords,
15
10
  findPhoneNumbersByClientId,
16
11
  getOwnedPhoneNumber,
17
12
  getPhoneNumberByClientAndFlow,
@@ -25,7 +20,7 @@ import { ObjectId } from "mongodb";
25
20
 
26
21
  describe("db.phoneNumbers", () => {
27
22
  describe("getPhoneDataByPhoneNumber", () => {
28
- it("should return phone number data with flow", async () => {
23
+ it("return phone number data with flow", async () => {
29
24
  const flow = createFlow({
30
25
  clientId: "test-client-id",
31
26
  conversationSettings: {
@@ -73,7 +68,7 @@ describe("db.phoneNumbers", () => {
73
68
  });
74
69
 
75
70
  describe("getClientPhoneNumber", () => {
76
- it("should return phone number by client id", async () => {
71
+ it("return phone number by client id", async () => {
77
72
  const flow = createFlow();
78
73
  const phoneData = createPhoneNumber({
79
74
  flow_id: flow._id,
@@ -89,7 +84,7 @@ describe("db.phoneNumbers", () => {
89
84
  });
90
85
 
91
86
  describe("getClientPhoneData", () => {
92
- it("should return primary phone data by default", async () => {
87
+ it("returns primary phone data by default", async () => {
93
88
  const clientId = "multiPhoneClient";
94
89
  const phone1 = createPhoneNumber({
95
90
  client_id: clientId,
@@ -111,7 +106,7 @@ describe("db.phoneNumbers", () => {
111
106
  expect(result?.phone_number).toBe("2");
112
107
  });
113
108
 
114
- it("should return most recent non-primary phone data if isPrimary is false", async () => {
109
+ it("returns most recent non-primary phone data if isPrimary is false", async () => {
115
110
  const clientId = "multiPhoneClient2";
116
111
  const phone1 = createPhoneNumber({
117
112
  client_id: clientId,
@@ -142,7 +137,7 @@ describe("db.phoneNumbers", () => {
142
137
  });
143
138
 
144
139
  describe("getPhoneNumbersForFlows", () => {
145
- it("should return all phone numbers for the client with flow ObjectIds, newest first", async () => {
140
+ it("returns all phone numbers for the client with flow ObjectIds, newest first", async () => {
146
141
  const clientId = "flowsClient";
147
142
  const flow1 = createFlow({ clientId });
148
143
  const flow2 = createFlow({ clientId });
@@ -180,12 +175,12 @@ describe("db.phoneNumbers", () => {
180
175
  });
181
176
  });
182
177
 
183
- it("should return an empty array when the client has no phone numbers", async () => {
178
+ it("returns an empty array when the client has no phone numbers", async () => {
184
179
  const result = await getPhoneNumbersForFlows("noSuchClient");
185
180
  expect(result).toEqual([]);
186
181
  });
187
182
 
188
- it("should not include phone numbers for other clients", async () => {
183
+ it("does not include phone numbers for other clients", async () => {
189
184
  const clientA = "clientA";
190
185
  const clientB = "clientB";
191
186
  const flow = createFlow();
@@ -202,7 +197,7 @@ describe("db.phoneNumbers", () => {
202
197
  });
203
198
 
204
199
  describe("createPhoneNumberEntity", () => {
205
- it("should create first phone number as primary", async () => {
200
+ it("creates first phone number as primary", async () => {
206
201
  const clientId = "newClient";
207
202
  const flowId = new ObjectId().toHexString();
208
203
  const phoneNumber = "+123456789";
@@ -216,7 +211,7 @@ describe("db.phoneNumbers", () => {
216
211
  expect(result.is_primary).toBe(true);
217
212
  });
218
213
 
219
- it("should create subsequent phone number as non-primary", async () => {
214
+ it("creates subsequent phone number as non-primary", async () => {
220
215
  const clientId = "existingClient";
221
216
  const flowId = new ObjectId().toHexString();
222
217
 
@@ -231,7 +226,7 @@ describe("db.phoneNumbers", () => {
231
226
  });
232
227
 
233
228
  describe("createPurchasedPhoneNumber", () => {
234
- it("should persist a phone_numbers document with provider payload and flow", async () => {
229
+ it("persists a phone_numbers document with provider payload and flow", async () => {
235
230
  const clientId = "purchasedClientDb";
236
231
  const flowId = new ObjectId().toHexString();
237
232
  const phoneNumber = "+15551234567";
@@ -263,7 +258,7 @@ describe("db.phoneNumbers", () => {
263
258
  });
264
259
 
265
260
  describe("getPrimaryPhoneFlowId", () => {
266
- it("should return flow_id from primary phone as string", async () => {
261
+ it("returns flow_id from primary phone as string", async () => {
267
262
  const clientId = "primaryFlowClient";
268
263
  const flowId = new ObjectId();
269
264
  await getPhoneNumbersCollection().insertOne(
@@ -277,11 +272,11 @@ describe("db.phoneNumbers", () => {
277
272
  expect(await getPrimaryPhoneFlowId(clientId)).toBe(flowId.toHexString());
278
273
  });
279
274
 
280
- it("should return null when client has no primary phone", async () => {
275
+ it("returns null when client has no primary phone", async () => {
281
276
  expect(await getPrimaryPhoneFlowId("no-phone-client")).toBeNull();
282
277
  });
283
278
 
284
- it("should return null when primary phone has no flow_id", async () => {
279
+ it("returns null when primary phone has no flow_id", async () => {
285
280
  const clientId = "phoneNoFlow";
286
281
  const phone = createPhoneNumber({
287
282
  client_id: clientId,
@@ -294,272 +289,6 @@ describe("db.phoneNumbers", () => {
294
289
  });
295
290
  });
296
291
 
297
- describe("getClientPhones", () => {
298
- it("should return all phone numbers for the given client, projected to phoneNumber only", async () => {
299
- const clientId = "phonesClientA";
300
- await getPhoneNumbersCollection().insertMany([
301
- createPhoneNumber({ client_id: clientId, phone_number: "+100" }),
302
- createPhoneNumber({ client_id: clientId, phone_number: "+200" }),
303
- ]);
304
-
305
- const result = await getClientPhones(clientId);
306
-
307
- expect(result).toHaveLength(2);
308
- expect(result).toEqual(
309
- expect.arrayContaining([
310
- { phoneNumber: "+100" },
311
- { phoneNumber: "+200" },
312
- ]),
313
- );
314
- });
315
-
316
- it("should not include phone numbers belonging to other clients", async () => {
317
- await getPhoneNumbersCollection().insertOne(
318
- createPhoneNumber({ client_id: "someOtherClient" }),
319
- );
320
-
321
- const result = await getClientPhones("phonesClientB");
322
- expect(result).toEqual([]);
323
- });
324
-
325
- it("should remove exact duplicate phone records for the same client", async () => {
326
- const clientId = "phonesClientDup";
327
- await getPhoneNumbersCollection().insertMany([
328
- createPhoneNumber({ client_id: clientId, phone_number: "+300" }),
329
- createPhoneNumber({ client_id: clientId, phone_number: "+300" }),
330
- createPhoneNumber({ client_id: clientId, phone_number: "+400" }),
331
- ]);
332
-
333
- const result = await getClientPhones(clientId);
334
-
335
- expect(result).toHaveLength(2);
336
- expect(result).toEqual(
337
- expect.arrayContaining([
338
- { phoneNumber: "+300" },
339
- { phoneNumber: "+400" },
340
- ]),
341
- );
342
- });
343
- });
344
-
345
- describe("findPhonesByClientIds", () => {
346
- it("should return a Map of clientId to phone number for the requested clients only", async () => {
347
- await getPhoneNumbersCollection().insertMany([
348
- createPhoneNumber({ client_id: "mapClientA", phone_number: "+111" }),
349
- createPhoneNumber({ client_id: "mapClientB", phone_number: "+222" }),
350
- createPhoneNumber({ client_id: "mapClientC", phone_number: "+333" }),
351
- ]);
352
-
353
- const result = await findPhonesByClientIds(["mapClientA", "mapClientB"]);
354
-
355
- expect(result).toBeInstanceOf(Map);
356
- expect(result.get("mapClientA")).toBe("+111");
357
- expect(result.get("mapClientB")).toBe("+222");
358
- expect(result.has("mapClientC")).toBe(false);
359
- });
360
-
361
- it("should return an empty Map for an empty list of clients", async () => {
362
- await getPhoneNumbersCollection().insertOne(
363
- createPhoneNumber({ client_id: "mapClientA", phone_number: "+111" }),
364
- );
365
-
366
- const result = await findPhonesByClientIds([]);
367
-
368
- expect(result.size).toBe(0);
369
- });
370
-
371
- it("should skip clients that have no phone number", async () => {
372
- const result = await findPhonesByClientIds(["clientWithoutPhone"]);
373
- expect(result.size).toBe(0);
374
- });
375
-
376
- it("should return the most recently updated phone number when a client has several", async () => {
377
- const clientId = "mapClientRecent";
378
- await getPhoneNumbersCollection().insertMany([
379
- createPhoneNumber({
380
- client_id: clientId,
381
- phone_number: "+old",
382
- updatedAt: new Date("2023-01-01"),
383
- }),
384
- createPhoneNumber({
385
- client_id: clientId,
386
- phone_number: "+new",
387
- updatedAt: new Date("2023-06-01"),
388
- }),
389
- ]);
390
-
391
- const result = await findPhonesByClientIds([clientId]);
392
-
393
- expect(result.get(clientId)).toBe("+new");
394
- });
395
-
396
- it("should prefer the is_primary number over a more recently updated non-primary one", async () => {
397
- const clientId = "mapClientPrimary";
398
- await getPhoneNumbersCollection().insertMany([
399
- createPhoneNumber({
400
- client_id: clientId,
401
- phone_number: "+primary",
402
- is_primary: true,
403
- updatedAt: new Date("2023-01-01"),
404
- }),
405
- createPhoneNumber({
406
- client_id: clientId,
407
- phone_number: "+secondary",
408
- is_primary: false,
409
- updatedAt: new Date("2023-06-01"),
410
- }),
411
- ]);
412
-
413
- const result = await findPhonesByClientIds([clientId]);
414
-
415
- expect(result.get(clientId)).toBe("+primary");
416
- });
417
- });
418
-
419
- describe("getDistinctClientPhonePairs", () => {
420
- it("should return unique client+phone pairs, collapsing exact duplicates", async () => {
421
- await getPhoneNumbersCollection().insertMany([
422
- createPhoneNumber({ client_id: "pairClientA", phone_number: "+500" }),
423
- createPhoneNumber({ client_id: "pairClientA", phone_number: "+500" }),
424
- createPhoneNumber({ client_id: "pairClientB", phone_number: "+600" }),
425
- ]);
426
-
427
- const result = await getDistinctClientPhonePairs();
428
-
429
- expect(result).toEqual(
430
- expect.arrayContaining([
431
- { clientId: "pairClientA", phoneNumber: "+500", isPrimary: true },
432
- { clientId: "pairClientB", phoneNumber: "+600", isPrimary: true },
433
- ]),
434
- );
435
- expect(
436
- result.filter(
437
- (p) => p.clientId === "pairClientA" && p.phoneNumber === "+500",
438
- ),
439
- ).toHaveLength(1);
440
- });
441
-
442
- it("should keep separate pairs when the same number is shared by different clients", async () => {
443
- await getPhoneNumbersCollection().insertMany([
444
- createPhoneNumber({ client_id: "sharedClientA", phone_number: "+700" }),
445
- createPhoneNumber({ client_id: "sharedClientB", phone_number: "+700" }),
446
- ]);
447
-
448
- const result = await getDistinctClientPhonePairs();
449
-
450
- expect(result).toEqual(
451
- expect.arrayContaining([
452
- { clientId: "sharedClientA", phoneNumber: "+700", isPrimary: true },
453
- { clientId: "sharedClientB", phoneNumber: "+700", isPrimary: true },
454
- ]),
455
- );
456
- });
457
-
458
- it("should report isPrimary: false for a non-primary number", async () => {
459
- await getPhoneNumbersCollection().insertMany([
460
- createPhoneNumber({ client_id: "mixedClient", phone_number: "+900", is_primary: true }),
461
- createPhoneNumber({ client_id: "mixedClient", phone_number: "+901", is_primary: false }),
462
- ]);
463
-
464
- const result = await getDistinctClientPhonePairs();
465
-
466
- expect(result).toEqual(
467
- expect.arrayContaining([
468
- { clientId: "mixedClient", phoneNumber: "+900", isPrimary: true },
469
- { clientId: "mixedClient", phoneNumber: "+901", isPrimary: false },
470
- ]),
471
- );
472
- });
473
-
474
- it("should report isPrimary: false when no phone_numbers document for that client is marked primary", async () => {
475
- await getPhoneNumbersCollection().insertOne(
476
- createPhoneNumber({ client_id: "noPrimaryClient", phone_number: "+902", is_primary: false }),
477
- );
478
-
479
- const result = await getDistinctClientPhonePairs();
480
-
481
- expect(result).toContainEqual({
482
- clientId: "noPrimaryClient",
483
- phoneNumber: "+902",
484
- isPrimary: false,
485
- });
486
- });
487
- });
488
-
489
- describe("getDistinctClientPhonePairs with clientIds", () => {
490
- it("should return only the pairs of the given clients", async () => {
491
- await getPhoneNumbersCollection().insertMany([
492
- createPhoneNumber({ client_id: "wantedPairClient", phone_number: "+111" }),
493
- createPhoneNumber({ client_id: "otherPairClient", phone_number: "+222" }),
494
- ]);
495
-
496
- const result = await getDistinctClientPhonePairs(["wantedPairClient"]);
497
-
498
- expect(result).toEqual([
499
- { clientId: "wantedPairClient", phoneNumber: "+111", isPrimary: true },
500
- ]);
501
- });
502
- });
503
-
504
- describe("findClientsByPhoneNumbers", () => {
505
- it("should return other clients sharing each phone number, excluding the given client", async () => {
506
- await getPhoneNumbersCollection().insertMany([
507
- createPhoneNumber({ client_id: "excludeMe", phone_number: "+800" }),
508
- createPhoneNumber({ client_id: "otherClient1", phone_number: "+800" }),
509
- createPhoneNumber({ client_id: "otherClient2", phone_number: "+800" }),
510
- ]);
511
-
512
- const result = await findClientsByPhoneNumbers(["+800"], "excludeMe");
513
-
514
- expect(result.get("+800")).toEqual(
515
- expect.arrayContaining(["otherClient1", "otherClient2"]),
516
- );
517
- expect(result.get("+800")).not.toContain("excludeMe");
518
- });
519
-
520
- it("should return an empty array for a phone number with no other clients", async () => {
521
- await getPhoneNumbersCollection().insertOne(
522
- createPhoneNumber({ client_id: "soleOwner", phone_number: "+900" }),
523
- );
524
-
525
- const result = await findClientsByPhoneNumbers(["+900"], "soleOwner");
526
-
527
- expect(result.get("+900")).toEqual([]);
528
- });
529
-
530
- it("should return an empty map immediately when given no phone numbers", async () => {
531
- const result = await findClientsByPhoneNumbers([]);
532
- expect(result.size).toBe(0);
533
- });
534
- });
535
-
536
- describe("deletePhoneNumberRecords", () => {
537
- it("should delete every record for the given phone number across all clients", async () => {
538
- await getPhoneNumbersCollection().insertMany([
539
- createPhoneNumber({ client_id: "delClientA", phone_number: "+1000" }),
540
- createPhoneNumber({ client_id: "delClientB", phone_number: "+1000" }),
541
- createPhoneNumber({ client_id: "delClientC", phone_number: "+2000" }),
542
- ]);
543
-
544
- const deletedCount = await deletePhoneNumberRecords("+1000");
545
-
546
- expect(deletedCount).toBe(2);
547
- const remaining = await getPhoneNumbersCollection()
548
- .find({ phone_number: "+1000" })
549
- .toArray();
550
- expect(remaining).toHaveLength(0);
551
- const untouched = await getPhoneNumbersCollection().findOne({
552
- phone_number: "+2000",
553
- });
554
- expect(untouched?.client_id).toBe("delClientC");
555
- });
556
-
557
- it("should return 0 when no records match the phone number", async () => {
558
- const deletedCount = await deletePhoneNumberRecords("+9999999");
559
- expect(deletedCount).toBe(0);
560
- });
561
- });
562
-
563
292
  describe("findPhoneNumbersByClientId", () => {
564
293
  it("returns only that client's numbers", async () => {
565
294
  const clientId = "list-client";
@@ -9,7 +9,6 @@ import {
9
9
  } from "../index";
10
10
  import {
11
11
  ClientPhoneNumberForFlow,
12
- ClientPhonePair,
13
12
  PhoneNumber,
14
13
  PhoneNumberWithFlow,
15
14
  PurchasedPhoneProviderPayload,
@@ -159,9 +158,7 @@ export const findClientByPhoneNumber = async (
159
158
  return client;
160
159
  };
161
160
 
162
- export const getPrimaryPhoneFlowId = async (
163
- clientId: string,
164
- ): Promise<string | null> => {
161
+ export const getPrimaryPhoneFlowId = async (clientId: string): Promise<string | null> => {
165
162
  const phone = await getClientPhoneData(clientId);
166
163
  return phone?.flow_id ? String(phone.flow_id) : null;
167
164
  };
@@ -179,91 +176,6 @@ export const bindClientPhoneToFlow = async (
179
176
  }
180
177
  };
181
178
 
182
- export const getClientPhones = async (
183
- clientId: string,
184
- ): Promise<{ phoneNumber: string }[]> => {
185
- const docs = await getPhoneNumbersCollection()
186
- .aggregate<{ _id: string }>([
187
- { $match: { client_id: clientId } },
188
- { $group: { _id: "$phone_number" } },
189
- ])
190
- .toArray();
191
- return docs.map((d) => ({ phoneNumber: d._id }));
192
- };
193
-
194
- export const findPhonesByClientIds = async (
195
- clientIds: string[],
196
- ): Promise<Map<string, string>> => {
197
- if (clientIds.length === 0) return new Map();
198
-
199
- const docs = await getPhoneNumbersCollection()
200
- .aggregate<{ _id: string; phone_number: string }>([
201
- { $match: { client_id: { $in: clientIds } } },
202
- { $sort: { is_primary: -1, updatedAt: -1 } },
203
- { $group: { _id: "$client_id", phone_number: { $first: "$phone_number" } } },
204
- ])
205
- .toArray();
206
- return new Map(docs.map((d) => [d._id, d.phone_number]));
207
- };
208
-
209
- export const getDistinctClientPhonePairs = async (
210
- clientIds?: string[],
211
- ): Promise<ClientPhonePair[]> => {
212
- const docs = await getPhoneNumbersCollection()
213
- .aggregate<{
214
- _id: { client_id: string; phone_number: string };
215
- isPrimary: boolean;
216
- }>([
217
- ...(clientIds ? [{ $match: { client_id: { $in: clientIds } } }] : []),
218
- {
219
- $group: {
220
- _id: { client_id: "$client_id", phone_number: "$phone_number" },
221
- isPrimary: { $max: "$is_primary" },
222
- },
223
- },
224
- ])
225
- .toArray();
226
- return docs.map((d) => ({
227
- clientId: d._id.client_id,
228
- phoneNumber: d._id.phone_number,
229
- isPrimary: Boolean(d.isPrimary),
230
- }));
231
- };
232
-
233
- export const findClientsByPhoneNumbers = async (
234
- phoneNumbers: string[],
235
- excludeClientId?: string,
236
- ): Promise<Map<string, string[]>> => {
237
- const result = new Map<string, string[]>(
238
- phoneNumbers.map((p) => [p, [] as string[]]),
239
- );
240
- if (phoneNumbers.length === 0) return result;
241
-
242
- const docs = await getPhoneNumbersCollection()
243
- .aggregate<{ _id: string; clientIds: string[] }>([
244
- {
245
- $match: {
246
- phone_number: { $in: phoneNumbers },
247
- ...(excludeClientId ? { client_id: { $ne: excludeClientId } } : {}),
248
- },
249
- },
250
- { $group: { _id: "$phone_number", clientIds: { $addToSet: "$client_id" } } },
251
- ])
252
- .toArray();
253
-
254
- docs.forEach((d) => result.set(d._id, d.clientIds));
255
- return result;
256
- };
257
-
258
- /** Deletes this number's record for every client that references it. Check `findClientsByPhoneNumbers` first to see who's affected. */
259
- export const deletePhoneNumberRecords = async (
260
- phoneNumber: string,
261
- ): Promise<number> => {
262
- const result = await getPhoneNumbersCollection().deleteMany({
263
- phone_number: phoneNumber,
264
- });
265
- return result.deletedCount;
266
- };
267
179
  export const findPhoneNumbersByClientId = (
268
180
  clientId: string,
269
181
  ): Promise<PhoneNumber[]> =>
@@ -28,9 +28,3 @@ export type ClientPhoneNumberForFlow = {
28
28
  phoneNumber: string;
29
29
  isPrimary: boolean;
30
30
  };
31
-
32
- export type ClientPhonePair = {
33
- clientId: string;
34
- phoneNumber: string;
35
- isPrimary: boolean;
36
- };
@@ -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";
@@ -17,8 +17,12 @@ import type {
17
17
  ScanResourcePageSummary,
18
18
  UrlTaskStatus,
19
19
  } from "./scanResources.types";
20
- import { decodeCursor, encodeCursor, statusesForColumn } from "./scanResources.utils";
21
- import { escapeRegex } from "../../utils/regex.utils";
20
+ import {
21
+ decodeCursor,
22
+ encodeCursor,
23
+ escapeRegex,
24
+ statusesForColumn,
25
+ } from "./scanResources.utils";
22
26
 
23
27
  export const getScanResourcesCollection = (): Collection<ScanResource> =>
24
28
  getDb().collection<ScanResource>(SCAN_RESOURCES_COLLECTION);
@@ -2,8 +2,6 @@ import { ObjectId } from "mongodb";
2
2
  import { BOARD_COLUMN_STATUSES } from "./scanResources.constants";
3
3
  import type { BoardColumn, UrlTaskStatus } from "./scanResources.types";
4
4
 
5
- export { escapeRegex } from "../../utils/regex.utils";
6
-
7
5
  const STATUS_TO_COLUMN: Record<UrlTaskStatus, BoardColumn> = Object.entries(
8
6
  BOARD_COLUMN_STATUSES,
9
7
  ).reduce(
@@ -28,3 +26,6 @@ export const encodeCursor = (id: ObjectId): string =>
28
26
 
29
27
  export const decodeCursor = (cursor: string): ObjectId =>
30
28
  new ObjectId(Buffer.from(cursor, "base64").toString("utf-8"));
29
+
30
+ export const escapeRegex = (text: string): string =>
31
+ text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -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,11 +0,0 @@
1
- import { WithId } from "mongodb";
2
- export type AuditLogEntry = {
3
- clientId: string;
4
- adminEmail: string;
5
- action: "delete";
6
- timestamp: Date;
7
- allSucceeded?: boolean;
8
- failedCollections?: string[];
9
- };
10
- export type AuditLogDoc = WithId<AuditLogEntry>;
11
- //# 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,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
@@ -1 +0,0 @@
1
- {"version":3,"file":"auditLogs.types.js","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/auditLogs.types.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- export * from "./auditLogs.types";
2
- export * from "./auditLogs.getters";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC"}
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./auditLogs.types"), exports);
18
- __exportStar(require("./auditLogs.getters"), exports);
19
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/talkpilot/auditLogs/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,sDAAoC"}
@@ -1,4 +0,0 @@
1
- /** Collections to always skip during client deletion — e.g. auditLogs, which must survive it. */
2
- export declare const DELETE_DENYLIST: string[];
3
- export declare const BACKOFFICE_ROLES: readonly ["admin", "viewer"];
4
- //# sourceMappingURL=clients.constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clients.constants.d.ts","sourceRoot":"","sources":["../../../src/talkpilot/clients/clients.constants.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,eAAe,EAAE,MAAM,EAAkB,CAAC;AAEvD,eAAO,MAAM,gBAAgB,8BAA+B,CAAC"}