@talkpilot/core-db 1.3.15 → 1.3.17

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 (90) hide show
  1. package/README.md +20 -10
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +0 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/municipal/index.d.ts +1 -1
  7. package/dist/municipal/index.d.ts.map +1 -1
  8. package/dist/municipal/tickets/tickets.statistics.getters.d.ts.map +1 -1
  9. package/dist/municipal/tickets/tickets.statistics.getters.js +2 -6
  10. package/dist/municipal/tickets/tickets.statistics.getters.js.map +1 -1
  11. package/dist/talkpilot/calls/calls.constants.d.ts +2 -0
  12. package/dist/talkpilot/calls/calls.constants.d.ts.map +1 -1
  13. package/dist/talkpilot/calls/calls.constants.js +3 -1
  14. package/dist/talkpilot/calls/calls.constants.js.map +1 -1
  15. package/dist/talkpilot/calls/calls.getters.d.ts +2 -1
  16. package/dist/talkpilot/calls/calls.getters.d.ts.map +1 -1
  17. package/dist/talkpilot/calls/calls.getters.js +3 -1
  18. package/dist/talkpilot/calls/calls.getters.js.map +1 -1
  19. package/dist/talkpilot/calls/calls.types.d.ts +2 -1
  20. package/dist/talkpilot/calls/calls.types.d.ts.map +1 -1
  21. package/dist/talkpilot/calls/dashboard/calls.dashboard.d.ts.map +1 -1
  22. package/dist/talkpilot/calls/dashboard/calls.dashboard.js +16 -13
  23. package/dist/talkpilot/calls/dashboard/calls.dashboard.js.map +1 -1
  24. package/dist/talkpilot/calls/dashboard/calls.dashboard.types.d.ts +2 -2
  25. package/dist/talkpilot/calls/dashboard/calls.dashboard.types.d.ts.map +1 -1
  26. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts +0 -3
  27. package/dist/talkpilot/clientsConfig/clientsConfig.getters.d.ts.map +1 -1
  28. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js +1 -17
  29. package/dist/talkpilot/clientsConfig/clientsConfig.getters.js.map +1 -1
  30. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts +2 -1
  31. package/dist/talkpilot/clientsConfig/clientsConfig.types.d.ts.map +1 -1
  32. package/dist/test-utils/factories/index.d.ts +0 -1
  33. package/dist/test-utils/factories/index.d.ts.map +1 -1
  34. package/dist/test-utils/factories/index.js +0 -1
  35. package/dist/test-utils/factories/index.js.map +1 -1
  36. package/dist/test-utils/factories/websitalk/scans.d.ts.map +1 -1
  37. package/dist/test-utils/factories/websitalk/scans.js +1 -2
  38. package/dist/test-utils/factories/websitalk/scans.js.map +1 -1
  39. package/dist/websitalk/index.d.ts +0 -1
  40. package/dist/websitalk/index.d.ts.map +1 -1
  41. package/dist/websitalk/index.js +0 -1
  42. package/dist/websitalk/index.js.map +1 -1
  43. package/dist/websitalk/scans/index.d.ts +0 -1
  44. package/dist/websitalk/scans/index.d.ts.map +1 -1
  45. package/dist/websitalk/scans/index.js +0 -1
  46. package/dist/websitalk/scans/index.js.map +1 -1
  47. package/dist/websitalk/scans/scans.constants.d.ts +10 -4
  48. package/dist/websitalk/scans/scans.constants.d.ts.map +1 -1
  49. package/dist/websitalk/scans/scans.constants.js +13 -7
  50. package/dist/websitalk/scans/scans.constants.js.map +1 -1
  51. package/dist/websitalk/scans/scans.getters.d.ts +3 -10
  52. package/dist/websitalk/scans/scans.getters.d.ts.map +1 -1
  53. package/dist/websitalk/scans/scans.getters.js +9 -48
  54. package/dist/websitalk/scans/scans.getters.js.map +1 -1
  55. package/dist/websitalk/scans/scans.types.d.ts +8 -2
  56. package/dist/websitalk/scans/scans.types.d.ts.map +1 -1
  57. package/dist/websitalk/scans/scans.utils.d.ts +3 -0
  58. package/dist/websitalk/scans/scans.utils.d.ts.map +1 -0
  59. package/dist/websitalk/scans/scans.utils.js +7 -0
  60. package/dist/websitalk/scans/scans.utils.js.map +1 -0
  61. package/package.json +1 -1
  62. package/src/index.ts +0 -1
  63. package/src/municipal/index.ts +1 -1
  64. package/src/municipal/tickets/tickets.statistics.getters.ts +3 -16
  65. package/src/talkpilot/calls/__tests__/calls.dashboard.spec.ts +81 -1
  66. package/src/talkpilot/calls/__tests__/calls.spec.ts +13 -0
  67. package/src/talkpilot/calls/__tests__/calls.statistics.spec.ts +4 -6
  68. package/src/talkpilot/calls/calls.constants.ts +3 -0
  69. package/src/talkpilot/calls/calls.getters.ts +11 -1
  70. package/src/talkpilot/calls/calls.types.ts +12 -1
  71. package/src/talkpilot/calls/dashboard/calls.dashboard.ts +16 -13
  72. package/src/talkpilot/calls/dashboard/calls.dashboard.types.ts +2 -2
  73. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.getters.spec.ts +5 -57
  74. package/src/talkpilot/clientsConfig/__tests__/clientsConfig.spec.ts +4 -0
  75. package/src/talkpilot/clientsConfig/clientsConfig.getters.ts +0 -24
  76. package/src/talkpilot/clientsConfig/clientsConfig.types.ts +2 -1
  77. package/src/test-utils/factories/index.ts +0 -1
  78. package/src/test-utils/factories/websitalk/scans.ts +1 -2
  79. package/src/websitalk/index.ts +0 -1
  80. package/src/websitalk/scans/__tests__/scans.spec.ts +26 -121
  81. package/src/websitalk/scans/index.ts +0 -1
  82. package/src/websitalk/scans/scans.getters.ts +17 -67
  83. package/src/websitalk/scans/scans.types.ts +6 -3
  84. package/tsconfig.json +4 -4
  85. package/src/test-utils/factories/websitalk/websiteUrls.ts +0 -17
  86. package/src/websitalk/scans/scans.constants.ts +0 -12
  87. package/src/websitalk/websiteUrls/__tests__/websiteUrls.spec.ts +0 -77
  88. package/src/websitalk/websiteUrls/index.ts +0 -2
  89. package/src/websitalk/websiteUrls/websiteUrls.getters.ts +0 -65
  90. package/src/websitalk/websiteUrls/websiteUrls.types.ts +0 -13
@@ -21,7 +21,7 @@ export type DashboardSummaryMetrics = {
21
21
  avgDurationSeconds: number;
22
22
  timeSavedMinutes: number;
23
23
  completedCount: number;
24
- busyCount: number;
24
+ inCallCount: number;
25
25
  };
26
26
 
27
27
  export type DashboardVisualData = {
@@ -42,7 +42,7 @@ export type DashboardReportResponse = {
42
42
  };
43
43
  type RawKpiResult = {
44
44
  completedCount: number;
45
- busyCount: number;
45
+ inCallCount: number;
46
46
  answeredDuration: number | null;
47
47
  };
48
48
 
@@ -1,9 +1,6 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from "@jest/globals";
2
2
  import {
3
3
  getClientsConfigCollection,
4
- getActiveScanId,
5
- updateActiveScanId,
6
- clearActiveScanId,
7
4
  updateProductConfig,
8
5
  } from "../clientsConfig.getters";
9
6
 
@@ -26,6 +23,8 @@ describe("updateProductConfig", () => {
26
23
  websiteTalk: {
27
24
  language: "English",
28
25
  companyName: "OldCorp",
26
+ defaultBaseUrl: "https://old-url.com",
27
+ logoUrl: "",
29
28
  timezone: "UTC",
30
29
  },
31
30
  },
@@ -39,7 +38,9 @@ describe("updateProductConfig", () => {
39
38
  expect(updatedDoc).toBeDefined();
40
39
  expect(updatedDoc?.products.websiteTalk?.language).toBe("Hebrew");
41
40
  expect(updatedDoc?.products.websiteTalk?.companyName).toBe("TestCorp");
42
- expect(updatedDoc?.products.websiteTalk?.timezone).toBe("UTC");
41
+ expect(updatedDoc?.products.websiteTalk?.defaultBaseUrl).toBe(
42
+ "https://old-url.com",
43
+ );
43
44
  });
44
45
 
45
46
  it("should throw an error if no client config is found", async () => {
@@ -50,56 +51,3 @@ describe("updateProductConfig", () => {
50
51
  ).rejects.toThrow("No client config found for clientId: invalid-client");
51
52
  });
52
53
  });
53
-
54
- describe("activeScanId", () => {
55
- beforeEach(async () => {
56
- await getClientsConfigCollection().deleteMany({});
57
- });
58
-
59
- afterEach(async () => {
60
- await getClientsConfigCollection().deleteMany({});
61
- });
62
-
63
- it("should return undefined when activeScanId is not set", async () => {
64
- const clientId = "client-active";
65
- await getClientsConfigCollection().insertOne({
66
- clientId,
67
- products: {
68
- websiteTalk: { companyName: "X", timezone: "UTC", language: "he" },
69
- },
70
- } as any);
71
-
72
- expect(await getActiveScanId(clientId)).toBeUndefined();
73
- });
74
-
75
- it("should persist activeScanId and return it from getActiveScanId", async () => {
76
- const clientId = "client-active-2";
77
- await getClientsConfigCollection().insertOne({
78
- clientId,
79
- products: {
80
- websiteTalk: { companyName: "X", timezone: "UTC", language: "he" },
81
- },
82
- } as any);
83
-
84
- await updateActiveScanId(clientId, "scan-abc");
85
- expect(await getActiveScanId(clientId)).toBe("scan-abc");
86
- });
87
-
88
- it("should clear activeScanId and return undefined from getActiveScanId", async () => {
89
- const clientId = "client-active-3";
90
- await getClientsConfigCollection().insertOne({
91
- clientId,
92
- products: {
93
- websiteTalk: {
94
- companyName: "X",
95
- timezone: "UTC",
96
- language: "he",
97
- activeScanId: "scan-old",
98
- },
99
- },
100
- } as any);
101
-
102
- await clearActiveScanId(clientId);
103
- expect(await getActiveScanId(clientId)).toBeUndefined();
104
- });
105
- });
@@ -31,9 +31,11 @@ describe("db.clientsConfig", () => {
31
31
  clientId,
32
32
  products: {
33
33
  websiteTalk: {
34
+ logoUrl: "https://cdn.example.com/branding/acme/logo.png",
34
35
  companyName: "Acme Ltd",
35
36
  timezone: "Asia/Jerusalem",
36
37
  language: "he",
38
+ defaultBaseUrl: "https://acme.example",
37
39
  },
38
40
  },
39
41
  });
@@ -46,9 +48,11 @@ describe("db.clientsConfig", () => {
46
48
  clientId,
47
49
  products: {
48
50
  websiteTalk: {
51
+ logoUrl: "https://cdn.example.com/branding/acme/logo.png",
49
52
  companyName: "Acme Ltd",
50
53
  timezone: "Asia/Jerusalem",
51
54
  language: "he",
55
+ defaultBaseUrl: "https://acme.example",
52
56
  },
53
57
  },
54
58
  });
@@ -53,27 +53,3 @@ export async function updateProductConfig<K extends KnownProductKey>(
53
53
  throw new Error(`No client config found for clientId: ${clientId}`);
54
54
  }
55
55
  }
56
-
57
- export const getActiveScanId = async (
58
- clientId: string,
59
- ): Promise<string | undefined> => {
60
- const cfg = await getClientConfig(clientId);
61
- return cfg?.products?.websiteTalk?.activeScanId;
62
- };
63
-
64
- export const updateActiveScanId = async (
65
- clientId: string,
66
- scanId: string,
67
- ): Promise<void> => {
68
- await updateProductConfig(clientId, "websiteTalk", { activeScanId: scanId });
69
- };
70
-
71
- export const clearActiveScanId = async (clientId: string): Promise<void> => {
72
- const result = await getClientsConfigCollection().updateOne(
73
- { clientId },
74
- { $unset: { "products.websiteTalk.activeScanId": "" } },
75
- );
76
- if (result.matchedCount === 0) {
77
- throw new Error(`No client config found for clientId: ${clientId}`);
78
- }
79
- };
@@ -58,10 +58,11 @@ export type WebsiteTalkScheduler = {
58
58
 
59
59
  /** Product config for the websiteTalk */
60
60
  export type WebsiteTalkProduct = {
61
+ logoUrl: string;
61
62
  companyName: string;
62
63
  timezone: string;
63
64
  language: string;
64
- activeScanId?: string;
65
+ defaultBaseUrl: string;
65
66
  };
66
67
 
67
68
  // ---------------------------------------------------------------------------
@@ -13,4 +13,3 @@ export * from "./municipal/muniIssues";
13
13
  export * from "./municipal/streets";
14
14
  export * from "./municipal/tickets";
15
15
  export * from "./websitalk/scans";
16
- export * from "./websitalk/websiteUrls";
@@ -1,11 +1,10 @@
1
1
  import { Factory } from "fishery";
2
2
  import { faker } from "@faker-js/faker";
3
- import { ObjectId } from "mongodb";
4
3
  import type { Scan } from "../../../websitalk";
5
4
 
6
5
  export const scanFactory = Factory.define<Scan>(() => ({
7
6
  clientId: faker.string.uuid(),
8
- websiteUrlId: new ObjectId().toString(),
7
+ baseUrl: faker.internet.url(),
9
8
  status: "CHECKING",
10
9
  activeTasksCount: 0,
11
10
  pagesScanned: 0,
@@ -1,7 +1,6 @@
1
1
  import { Db, ObjectId as MongoObjectId } from "mongodb";
2
2
 
3
3
  export * from "./scans";
4
- export * from "./websiteUrls";
5
4
  export { websitalkMongodbClient } from "./mongodb-client";
6
5
 
7
6
  let db: Db;
@@ -6,12 +6,7 @@ import {
6
6
  countScans,
7
7
  createScanDoc,
8
8
  updateScanDoc,
9
- findInProgressScansByClient,
10
- getScansByWebsiteUrl,
11
- getLatestScanByWebsiteUrl,
12
- getInProgressScanByWebsiteUrl,
13
- getLatestCompletedScanByWebsiteUrl,
14
- deleteScansByWebsiteUrl,
9
+ getActiveScanStatus,
15
10
  } from "../scans.getters";
16
11
  import { createScanFixture } from "../../../test-utils/factories";
17
12
  import { ObjectId } from "mongodb";
@@ -42,7 +37,7 @@ describe("db.websitalk.scans", () => {
42
37
  expect(result.length).toBe(1);
43
38
  expect(result[0]).toMatchObject({
44
39
  clientId,
45
- websiteUrlId: scanInside.websiteUrlId,
40
+ baseUrl: scanInside.baseUrl,
46
41
  status: "COMPLETED",
47
42
  });
48
43
  expect(result[0]).toHaveProperty("siteChrome");
@@ -88,12 +83,12 @@ describe("db.websitalk.scans", () => {
88
83
  clientId,
89
84
  new Date("2023-05-01"),
90
85
  new Date("2023-05-31"),
91
- ["clientId", "websiteUrlId", "status"],
86
+ ["clientId", "baseUrl", "status"],
92
87
  );
93
88
 
94
89
  expect(result).toMatchObject({
95
90
  clientId,
96
- websiteUrlId: scan.websiteUrlId,
91
+ baseUrl: scan.baseUrl,
97
92
  status: "COMPLETED",
98
93
  });
99
94
  expect(result).toHaveProperty("_id");
@@ -115,7 +110,7 @@ describe("db.websitalk.scans", () => {
115
110
  const count = await countScans({ clientId });
116
111
 
117
112
  expect(result.length).toBe(1);
118
- expect(result[0].websiteUrlId).toBe(completed.websiteUrlId);
113
+ expect(result[0].baseUrl).toBe(completed.baseUrl);
119
114
  expect(count).toBe(2);
120
115
  });
121
116
  });
@@ -123,15 +118,15 @@ describe("db.websitalk.scans", () => {
123
118
  describe("createScanDoc()", () => {
124
119
  it("should insert a scan with default values for the rest of the fields", async () => {
125
120
  const clientId = "createClient";
126
- const websiteUrlId = new ObjectId().toString();
121
+ const baseUrl = "https://example.com";
127
122
 
128
- const { insertedId } = await createScanDoc({ clientId, websiteUrlId });
123
+ const { insertedId } = await createScanDoc({ clientId, baseUrl });
129
124
 
130
125
  const result = await getScansCollection().findOne({ _id: insertedId });
131
126
 
132
127
  expect(result).toMatchObject({
133
128
  clientId,
134
- websiteUrlId,
129
+ baseUrl,
135
130
  status: "CHECKING",
136
131
  activeTasksCount: 0,
137
132
  pagesScanned: 0,
@@ -171,143 +166,53 @@ describe("db.websitalk.scans", () => {
171
166
  });
172
167
  });
173
168
 
174
- describe("in-progress scan helpers", () => {
175
- const websiteUrlId = "website-123";
169
+ describe("getActiveScanStatus()", () => {
170
+ it("should return isActive: true with the status when the latest scan is still in progress", async () => {
171
+ const clientId = "activeClient";
176
172
 
177
- it("should return website scan history newest first", async () => {
178
173
  await getScansCollection().insertMany([
179
174
  createScanFixture({
180
- websiteUrlId,
181
- status: "COMPLETED",
182
- createdAt: new Date("2023-05-01"),
183
- }),
184
- createScanFixture({
185
- websiteUrlId,
186
- status: "COMPLETED",
187
- createdAt: new Date("2023-05-15"),
188
- }),
189
- ]);
190
-
191
- const scans = await getScansByWebsiteUrl(websiteUrlId);
192
- expect(scans).toHaveLength(2);
193
- expect(scans[0].createdAt.getTime()).toBeGreaterThan(
194
- scans[1].createdAt.getTime(),
195
- );
196
- });
197
-
198
- it("should return the newest scan for a website", async () => {
199
- await getScansCollection().insertMany([
200
- createScanFixture({
201
- websiteUrlId,
202
- status: "COMPLETED",
203
- createdAt: new Date("2023-05-01"),
204
- }),
205
- createScanFixture({
206
- websiteUrlId,
207
- status: "FAILED",
208
- createdAt: new Date("2023-05-15"),
209
- }),
210
- ]);
211
-
212
- const latest = await getLatestScanByWebsiteUrl(websiteUrlId);
213
- expect(latest?.status).toBe("FAILED");
214
- });
215
-
216
- it("should return in-progress scan and return null when only completed exists", async () => {
217
- await getScansCollection().insertMany([
218
- createScanFixture({
219
- websiteUrlId,
175
+ clientId,
220
176
  status: "COMPLETED",
221
177
  createdAt: new Date("2023-05-01"),
222
178
  }),
223
179
  createScanFixture({
224
- websiteUrlId,
180
+ clientId,
225
181
  status: "SCANNING",
226
182
  createdAt: new Date("2023-05-15"),
227
183
  }),
228
184
  ]);
229
185
 
230
- const inProgressScan = await getInProgressScanByWebsiteUrl(websiteUrlId);
231
- expect(inProgressScan?.status).toBe("SCANNING");
186
+ const result = await getActiveScanStatus(clientId);
232
187
 
233
- await getScansCollection().deleteMany({ websiteUrlId });
234
- await getScansCollection().insertOne(
235
- createScanFixture({
236
- websiteUrlId,
237
- status: "COMPLETED",
238
- createdAt: new Date("2023-05-20"),
239
- }),
240
- );
241
-
242
- expect(await getInProgressScanByWebsiteUrl(websiteUrlId)).toBeNull();
188
+ expect(result).toEqual({ isActive: true, status: "SCANNING" });
243
189
  });
244
190
 
245
- it("should return all in-progress scans across websites for a client", async () => {
246
- const clientId = "multiScanClient";
191
+ it("should return isActive: false when the latest scan finished (COMPLETED / FAILED)", async () => {
192
+ const clientId = "finishedClient";
193
+
247
194
  await getScansCollection().insertMany([
248
195
  createScanFixture({
249
196
  clientId,
250
- websiteUrlId: "website-a",
251
197
  status: "SCANNING",
198
+ createdAt: new Date("2023-05-01"),
252
199
  }),
253
200
  createScanFixture({
254
201
  clientId,
255
- websiteUrlId: "website-b",
256
- status: "PROCESSING",
257
- }),
258
- createScanFixture({
259
- clientId,
260
- websiteUrlId: "website-c",
261
- status: "COMPLETED",
262
- }),
263
- ]);
264
-
265
- const scans = await findInProgressScansByClient(clientId);
266
- expect(scans).toHaveLength(2);
267
- expect(scans.map((s) => s.websiteUrlId).sort()).toEqual([
268
- "website-a",
269
- "website-b",
270
- ]);
271
- });
272
- });
273
-
274
- describe("website delete helpers", () => {
275
- it("should return the newest completed scan only", async () => {
276
- const websiteUrlId = new ObjectId().toString();
277
- await getScansCollection().insertMany([
278
- createScanFixture({
279
- websiteUrlId,
280
202
  status: "FAILED",
281
- createdAt: new Date("2023-05-25"),
282
- }),
283
- createScanFixture({
284
- websiteUrlId,
285
- status: "COMPLETED",
286
- createdAt: new Date("2023-05-20"),
287
- }),
288
- createScanFixture({
289
- websiteUrlId,
290
- status: "COMPLETED",
291
- createdAt: new Date("2023-05-22"),
203
+ createdAt: new Date("2023-05-15"),
292
204
  }),
293
205
  ]);
294
206
 
295
- const latest = await getLatestCompletedScanByWebsiteUrl(websiteUrlId);
296
- expect(latest?.status).toBe("COMPLETED");
297
- expect(latest?.createdAt).toEqual(new Date("2023-05-22"));
207
+ const result = await getActiveScanStatus(clientId);
208
+
209
+ expect(result).toEqual({ isActive: false });
298
210
  });
299
211
 
300
- it("should delete all scans for the website and return count", async () => {
301
- const websiteUrlId = new ObjectId().toString();
302
- await getScansCollection().insertMany([
303
- createScanFixture({ websiteUrlId }),
304
- createScanFixture({ websiteUrlId }),
305
- createScanFixture({ websiteUrlId: new ObjectId().toString() }),
306
- ]);
212
+ it("should return isActive: false when the client has no scans", async () => {
213
+ const result = await getActiveScanStatus("noScansClient");
307
214
 
308
- const deleted = await deleteScansByWebsiteUrl(websiteUrlId);
309
- expect(deleted).toBe(2);
310
- expect(await countScans({ websiteUrlId })).toBe(0);
215
+ expect(result).toEqual({ isActive: false });
311
216
  });
312
217
  });
313
218
  });
@@ -1,3 +1,2 @@
1
- export * from "./scans.constants";
2
1
  export * from "./scans.getters";
3
2
  export * from "./scans.types";
@@ -4,12 +4,12 @@ import {
4
4
  applyQueryOptions,
5
5
  QueryOptions,
6
6
  } from "../../talkpilot/utils/query.utils";
7
- import type { Scan, ScanDoc } from "./scans.types";
8
- import {
9
- FINISHED_SCAN_STATUSES,
10
- INITIAL_SCAN_STATUS,
11
- isInProgressScan,
12
- } from "./scans.constants";
7
+ import type {
8
+ ActiveScanStatus,
9
+ Scan,
10
+ ScanDoc,
11
+ ScanStatus,
12
+ } from "./scans.types";
13
13
 
14
14
  export const getScansCollection = (): Collection<Scan> => {
15
15
  return getDb().collection<Scan>("scans");
@@ -57,12 +57,11 @@ export const getScanFieldsByClientAndDateRange = <K extends keyof Scan>(
57
57
  };
58
58
 
59
59
  export const createScanDoc = (
60
- scan: Pick<Scan, "clientId" | "websiteUrlId"> &
61
- Partial<Pick<Scan, "notifyPhoneNumber">>,
60
+ scan: Pick<Scan, "clientId" | "baseUrl" | "notifyPhoneNumber">,
62
61
  ) => {
63
62
  return getScansCollection().insertOne({
64
63
  ...scan,
65
- status: INITIAL_SCAN_STATUS,
64
+ status: "CHECKING",
66
65
  activeTasksCount: 0,
67
66
  pagesScanned: 0,
68
67
  pagesSkipped: 0,
@@ -73,48 +72,21 @@ export const createScanDoc = (
73
72
  });
74
73
  };
75
74
 
76
- export const getScanById = async (id: string): Promise<ScanDoc | null> => {
77
- return getScansCollection().findOne({ _id: new ObjectId(id) });
78
- };
79
-
80
- export const getScansByWebsiteUrl = async (
81
- websiteUrlId: string,
82
- ): Promise<ScanDoc[]> => {
83
- return getScansCollection()
84
- .find({ websiteUrlId })
85
- .sort({ createdAt: -1 })
86
- .toArray();
87
- };
75
+ const FINISHED_SCAN_STATUSES: ScanStatus[] = ["COMPLETED", "FAILED"];
88
76
 
89
- export const getLatestScanByWebsiteUrl = async (
90
- websiteUrlId: string,
91
- ): Promise<ScanDoc | null> => {
92
- return getScansCollection().findOne(
93
- { websiteUrlId },
77
+ export const getActiveScanStatus = async (
78
+ clientId: string,
79
+ ): Promise<ActiveScanStatus> => {
80
+ const latestScan = await getScansCollection().findOne(
81
+ { clientId },
94
82
  { sort: { createdAt: -1 } },
95
83
  );
96
- };
97
84
 
98
- export const getInProgressScanByWebsiteUrl = async (
99
- websiteUrlId: string,
100
- ): Promise<ScanDoc | null> => {
101
- const latestScan = await getLatestScanByWebsiteUrl(websiteUrlId);
102
- if (!latestScan || !isInProgressScan(latestScan)) {
103
- return null;
85
+ if (!latestScan || FINISHED_SCAN_STATUSES.includes(latestScan.status)) {
86
+ return { isActive: false };
104
87
  }
105
- return latestScan;
106
- };
107
88
 
108
- export const findInProgressScansByClient = async (
109
- clientId: string,
110
- ): Promise<ScanDoc[]> => {
111
- return getScansCollection()
112
- .find({
113
- clientId,
114
- status: { $nin: FINISHED_SCAN_STATUSES },
115
- })
116
- .sort({ createdAt: -1 })
117
- .toArray();
89
+ return { isActive: true, status: latestScan.status };
118
90
  };
119
91
 
120
92
  export const updateScanDoc = async (
@@ -139,25 +111,3 @@ export const findScansByQuery = async (
139
111
  export const countScans = async (query: Filter<Scan>): Promise<number> => {
140
112
  return getScansCollection().countDocuments(query);
141
113
  };
142
-
143
- export const hasScansForWebsiteUrl = async (
144
- websiteUrlId: string,
145
- ): Promise<boolean> => {
146
- return (await countScans({ websiteUrlId })) > 0;
147
- };
148
-
149
- export const getLatestCompletedScanByWebsiteUrl = async (
150
- websiteUrlId: string,
151
- ): Promise<ScanDoc | null> => {
152
- return getScansCollection().findOne(
153
- { websiteUrlId, status: "COMPLETED" },
154
- { sort: { createdAt: -1 } },
155
- );
156
- };
157
-
158
- export const deleteScansByWebsiteUrl = async (
159
- websiteUrlId: string,
160
- ): Promise<number> => {
161
- const result = await getScansCollection().deleteMany({ websiteUrlId });
162
- return result.deletedCount;
163
- };
@@ -6,8 +6,11 @@ export type ScanStatus =
6
6
  | "SCANNING"
7
7
  | "PROCESSING"
8
8
  | "COMPLETED"
9
- | "FAILED"
10
- | "OVERWRITTEN";
9
+ | "FAILED";
10
+
11
+ export type ActiveScanStatus =
12
+ | { isActive: true; status: ScanStatus }
13
+ | { isActive: false };
11
14
 
12
15
  export type SiteChromeEntry = {
13
16
  url: string;
@@ -35,7 +38,7 @@ export type SkippedEntry = {
35
38
 
36
39
  export type Scan = {
37
40
  clientId: string;
38
- websiteUrlId: string;
41
+ baseUrl: string;
39
42
  notifyPhoneNumber?: string | null;
40
43
  status: ScanStatus;
41
44
  activeTasksCount: number;
package/tsconfig.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "node16",
6
- "isolatedModules": true,
4
+ "module": "CommonJS",
5
+ "moduleResolution": "node",
7
6
  "lib": ["ES2022"],
8
7
  "declaration": true,
9
8
  "declarationMap": true,
@@ -16,7 +15,8 @@
16
15
  "skipLibCheck": true,
17
16
  "resolveJsonModule": true,
18
17
  "experimentalDecorators": true,
19
- "emitDecoratorMetadata": true
18
+ "emitDecoratorMetadata": true,
19
+ "baseUrl": "."
20
20
  },
21
21
  "include": ["src/**/*"],
22
22
  "exclude": ["node_modules", "dist", "test", "**/*.test.ts", "**/__tests__/*", "**/*.spec.ts"]
@@ -1,17 +0,0 @@
1
- import { Factory } from "fishery";
2
- import { faker } from "@faker-js/faker";
3
- import type { WebsiteUrl } from "../../../websitalk/websiteUrls";
4
-
5
- export const websiteUrlFactory = Factory.define<WebsiteUrl>(() => ({
6
- clientId: faker.string.uuid(),
7
- name: faker.company.name(),
8
- baseUrl: faker.internet.url(),
9
- createdAt: new Date(),
10
- updatedAt: new Date(),
11
- }));
12
-
13
- export function createWebsiteUrlFixture(
14
- overrides?: Partial<WebsiteUrl>,
15
- ): WebsiteUrl {
16
- return websiteUrlFactory.build(overrides);
17
- }
@@ -1,12 +0,0 @@
1
- import type { Scan, ScanStatus } from "./scans.types";
2
-
3
- export const INITIAL_SCAN_STATUS = "CHECKING" as const satisfies ScanStatus;
4
-
5
- export const FINISHED_SCAN_STATUSES: ScanStatus[] = [
6
- "COMPLETED",
7
- "FAILED",
8
- "OVERWRITTEN",
9
- ];
10
-
11
- export const isInProgressScan = (scan: Scan): boolean =>
12
- !FINISHED_SCAN_STATUSES.includes(scan.status);