create-interview-cockpit 0.1.1 → 0.2.0

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.
@@ -1,5 +1,5 @@
1
1
  import { create } from "zustand";
2
- import type { Topic, Question, CodeSnippet } from "./types";
2
+ import type { Topic, Question, CodeSnippet, WorkspaceMeta } from "./types";
3
3
  import * as api from "./api";
4
4
 
5
5
  interface Store {
@@ -14,6 +14,48 @@ interface Store {
14
14
  showSidebar: boolean;
15
15
  viewingFile: string | null;
16
16
 
17
+ // ── Workspaces ───────────────────────────────────────────────
18
+ workspaces: WorkspaceMeta[];
19
+ activeWorkspaceId: string | null;
20
+ driveRootFolders: import("./api").DriveFolder[];
21
+ loadingDriveFolders: boolean;
22
+ fetchWorkspaces: () => Promise<void>;
23
+ createWorkspace: (
24
+ name: string,
25
+ type: "local" | "google_drive",
26
+ ) => Promise<void>;
27
+ activateWorkspace: (id: string) => Promise<void>;
28
+ deleteWorkspace: (id: string) => Promise<void>;
29
+ renameWorkspace: (id: string, name: string) => Promise<void>;
30
+ patchWorkspace: (id: string, data: object) => Promise<void>;
31
+ syncWorkspace: (id: string) => Promise<{
32
+ topicsUpserted: number;
33
+ filesImported: number;
34
+ filesSkipped: number;
35
+ errors: string[];
36
+ }>;
37
+ linkDriveFolder: (
38
+ workspaceId: string,
39
+ url: string,
40
+ ) => Promise<{ folders: import("./api").DriveFolder[] }>;
41
+ selectDriveSubfolder: (
42
+ workspaceId: string,
43
+ subFolderId: string,
44
+ subFolderName: string,
45
+ ) => Promise<void>;
46
+ clearDriveSubfolder: (workspaceId: string) => Promise<void>;
47
+ fetchDriveRootFolders: (workspaceId: string) => Promise<void>;
48
+ attachDriveFolder: (workspaceId: string, url: string) => Promise<void>;
49
+ exportWorkspace: (
50
+ id: string,
51
+ targetFolderId?: string,
52
+ ) => Promise<import("./api").ExportWorkspaceResult>;
53
+ fetchDriveSubfolders: (id: string) => Promise<import("./api").DriveFolder[]>;
54
+ createDriveSubfolder: (
55
+ id: string,
56
+ name: string,
57
+ ) => Promise<import("./api").DriveFolder>;
58
+
17
59
  fetchTopics: () => Promise<void>;
18
60
  fetchQuestions: (topicId: string) => Promise<void>;
19
61
  addTopic: (name: string) => Promise<void>;
@@ -74,6 +116,151 @@ export const useStore = create<Store>((set, get) => ({
74
116
  viewingFile: null,
75
117
  codeSnippets: [],
76
118
 
119
+ // ── Workspaces ───────────────────────────────────────────────
120
+ workspaces: [],
121
+ activeWorkspaceId: null,
122
+ driveRootFolders: [],
123
+ loadingDriveFolders: false,
124
+
125
+ fetchWorkspaces: async () => {
126
+ const registry = await api.fetchWorkspaces();
127
+ set({
128
+ workspaces: registry.workspaces,
129
+ activeWorkspaceId: registry.activeWorkspaceId,
130
+ });
131
+ },
132
+
133
+ createWorkspace: async (name, type) => {
134
+ const registry = await api.createWorkspace(name, type);
135
+ set({
136
+ workspaces: registry.workspaces,
137
+ activeWorkspaceId: registry.activeWorkspaceId,
138
+ });
139
+ },
140
+
141
+ activateWorkspace: async (id) => {
142
+ const registry = await api.activateWorkspaceApi(id);
143
+ set({
144
+ workspaces: registry.workspaces,
145
+ activeWorkspaceId: registry.activeWorkspaceId,
146
+ // Reset all topic/question state for the newly active workspace
147
+ topics: [],
148
+ questionsByTopic: {},
149
+ selectedTopicId: null,
150
+ selectedQuestionId: null,
151
+ currentQuestion: null,
152
+ expandedTopics: [],
153
+ codeSnippets: [],
154
+ });
155
+ const topics = await api.fetchTopics();
156
+ set({ topics });
157
+ },
158
+
159
+ deleteWorkspace: async (id) => {
160
+ const wasActive = get().activeWorkspaceId === id;
161
+ const registry = await api.deleteWorkspaceApi(id);
162
+ set({
163
+ workspaces: registry.workspaces,
164
+ activeWorkspaceId: registry.activeWorkspaceId,
165
+ });
166
+ if (wasActive) {
167
+ set({
168
+ topics: [],
169
+ questionsByTopic: {},
170
+ selectedTopicId: null,
171
+ selectedQuestionId: null,
172
+ currentQuestion: null,
173
+ expandedTopics: [],
174
+ codeSnippets: [],
175
+ });
176
+ const topics = await api.fetchTopics();
177
+ set({ topics });
178
+ }
179
+ },
180
+
181
+ renameWorkspace: async (id, name) => {
182
+ const registry = await api.renameWorkspace(id, name);
183
+ set({ workspaces: registry.workspaces });
184
+ },
185
+
186
+ patchWorkspace: async (id, data) => {
187
+ const registry = await api.patchWorkspace(id, data);
188
+ set({ workspaces: registry.workspaces });
189
+ },
190
+
191
+ syncWorkspace: async (id) => {
192
+ const result = await api.syncWorkspaceApi(id);
193
+ if (id === get().activeWorkspaceId) {
194
+ const topics = await api.fetchTopics();
195
+ set({ topics, questionsByTopic: {} });
196
+ }
197
+ const registry = await api.fetchWorkspaces();
198
+ set({ workspaces: registry.workspaces });
199
+ return result;
200
+ },
201
+
202
+ linkDriveFolder: async (workspaceId, url) => {
203
+ const { registry, folders } = await api.linkDriveFolder(workspaceId, url);
204
+ set({ workspaces: registry.workspaces, driveRootFolders: folders });
205
+ return { folders };
206
+ },
207
+
208
+ selectDriveSubfolder: async (workspaceId, subFolderId, subFolderName) => {
209
+ // Persist the selected subfolder on the workspace
210
+ await api.selectDriveSubfolder(workspaceId, subFolderId, subFolderName);
211
+ const registry = await api.fetchWorkspaces();
212
+ set({ workspaces: registry.workspaces });
213
+ // Sync so the topics update to reflect the chosen subfolder
214
+ if (workspaceId === get().activeWorkspaceId) {
215
+ set({ topics: [], questionsByTopic: {} });
216
+ const result = await api.syncWorkspaceApi(workspaceId);
217
+ const topics = await api.fetchTopics();
218
+ set({ topics, questionsByTopic: {} });
219
+ const reg2 = await api.fetchWorkspaces();
220
+ set({ workspaces: reg2.workspaces });
221
+ }
222
+ },
223
+
224
+ clearDriveSubfolder: async (workspaceId) => {
225
+ await api.selectDriveSubfolder(workspaceId, null, null);
226
+ const registry = await api.fetchWorkspaces();
227
+ set({
228
+ workspaces: registry.workspaces,
229
+ topics: [],
230
+ questionsByTopic: {},
231
+ selectedTopicId: null,
232
+ selectedQuestionId: null,
233
+ currentQuestion: null,
234
+ });
235
+ },
236
+
237
+ fetchDriveRootFolders: async (workspaceId) => {
238
+ set({ loadingDriveFolders: true });
239
+ try {
240
+ const folders = await api.fetchDriveSubfolders(workspaceId);
241
+ set({ driveRootFolders: folders });
242
+ } finally {
243
+ set({ loadingDriveFolders: false });
244
+ }
245
+ },
246
+
247
+ attachDriveFolder: async (workspaceId, url) => {
248
+ const registry = await api.attachDriveFolder(workspaceId, url);
249
+ set({ workspaces: registry.workspaces });
250
+ },
251
+
252
+ exportWorkspace: async (id, targetFolderId) => {
253
+ return api.exportWorkspaceToDrive(id, targetFolderId);
254
+ },
255
+
256
+ fetchDriveSubfolders: async (id) => {
257
+ return api.fetchDriveSubfolders(id);
258
+ },
259
+
260
+ createDriveSubfolder: async (id, name) => {
261
+ return api.createDriveSubfolder(id, name);
262
+ },
263
+
77
264
  fetchTopics: async () => {
78
265
  const topics = await api.fetchTopics();
79
266
  set({ topics });
@@ -2,9 +2,29 @@ export interface ContextFile {
2
2
  id: string;
3
3
  name: string;
4
4
  originalName: string;
5
+ driveFileId?: string;
5
6
  createdAt: string;
6
7
  }
7
8
 
9
+ export interface WorkspaceMeta {
10
+ id: string;
11
+ name: string;
12
+ type: "local" | "google_drive";
13
+ driveConfig?: {
14
+ folderId: string;
15
+ folderName: string;
16
+ lastSyncedAt?: string;
17
+ subFolderId?: string;
18
+ subFolderName?: string;
19
+ };
20
+ createdAt: string;
21
+ }
22
+
23
+ export interface WorkspacesRegistry {
24
+ activeWorkspaceId: string;
25
+ workspaces: WorkspaceMeta[];
26
+ }
27
+
8
28
  export interface Topic {
9
29
  id: string;
10
30
  name: string;
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.1.0"
2
+ "version": "0.2.0"
3
3
  }
@@ -13,6 +13,7 @@
13
13
  "cors": "^2.8.5",
14
14
  "dotenv": "^16.4.0",
15
15
  "express": "^4.21.0",
16
+ "googleapis": "^171.4.0",
16
17
  "mammoth": "^1.12.0",
17
18
  "multer": "^2.1.1",
18
19
  "pdf-parse": "^2.4.5",
@@ -922,6 +923,15 @@
922
923
  "node": ">= 0.6"
923
924
  }
924
925
  },
926
+ "node_modules/agent-base": {
927
+ "version": "7.1.4",
928
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
929
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
930
+ "license": "MIT",
931
+ "engines": {
932
+ "node": ">= 14"
933
+ }
934
+ },
925
935
  "node_modules/ai": {
926
936
  "version": "6.0.168",
927
937
  "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.168.tgz",
@@ -981,6 +991,15 @@
981
991
  ],
982
992
  "license": "MIT"
983
993
  },
994
+ "node_modules/bignumber.js": {
995
+ "version": "9.3.1",
996
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
997
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
998
+ "license": "MIT",
999
+ "engines": {
1000
+ "node": "*"
1001
+ }
1002
+ },
984
1003
  "node_modules/bluebird": {
985
1004
  "version": "3.4.7",
986
1005
  "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
@@ -1011,6 +1030,12 @@
1011
1030
  "npm": "1.2.8000 || >= 1.4.16"
1012
1031
  }
1013
1032
  },
1033
+ "node_modules/buffer-equal-constant-time": {
1034
+ "version": "1.0.1",
1035
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
1036
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
1037
+ "license": "BSD-3-Clause"
1038
+ },
1014
1039
  "node_modules/buffer-from": {
1015
1040
  "version": "1.1.2",
1016
1041
  "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -1140,6 +1165,15 @@
1140
1165
  "url": "https://opencollective.com/express"
1141
1166
  }
1142
1167
  },
1168
+ "node_modules/data-uri-to-buffer": {
1169
+ "version": "4.0.1",
1170
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
1171
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
1172
+ "license": "MIT",
1173
+ "engines": {
1174
+ "node": ">= 12"
1175
+ }
1176
+ },
1143
1177
  "node_modules/debug": {
1144
1178
  "version": "2.6.9",
1145
1179
  "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -1209,6 +1243,15 @@
1209
1243
  "node": ">= 0.4"
1210
1244
  }
1211
1245
  },
1246
+ "node_modules/ecdsa-sig-formatter": {
1247
+ "version": "1.0.11",
1248
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
1249
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
1250
+ "license": "Apache-2.0",
1251
+ "dependencies": {
1252
+ "safe-buffer": "^5.0.1"
1253
+ }
1254
+ },
1212
1255
  "node_modules/ee-first": {
1213
1256
  "version": "1.1.1",
1214
1257
  "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1366,6 +1409,35 @@
1366
1409
  "url": "https://opencollective.com/express"
1367
1410
  }
1368
1411
  },
1412
+ "node_modules/extend": {
1413
+ "version": "3.0.2",
1414
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
1415
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
1416
+ "license": "MIT"
1417
+ },
1418
+ "node_modules/fetch-blob": {
1419
+ "version": "3.2.0",
1420
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
1421
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
1422
+ "funding": [
1423
+ {
1424
+ "type": "github",
1425
+ "url": "https://github.com/sponsors/jimmywarting"
1426
+ },
1427
+ {
1428
+ "type": "paypal",
1429
+ "url": "https://paypal.me/jimmywarting"
1430
+ }
1431
+ ],
1432
+ "license": "MIT",
1433
+ "dependencies": {
1434
+ "node-domexception": "^1.0.0",
1435
+ "web-streams-polyfill": "^3.0.3"
1436
+ },
1437
+ "engines": {
1438
+ "node": "^12.20 || >= 14.13"
1439
+ }
1440
+ },
1369
1441
  "node_modules/finalhandler": {
1370
1442
  "version": "1.3.2",
1371
1443
  "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
@@ -1384,6 +1456,18 @@
1384
1456
  "node": ">= 0.8"
1385
1457
  }
1386
1458
  },
1459
+ "node_modules/formdata-polyfill": {
1460
+ "version": "4.0.10",
1461
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
1462
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
1463
+ "license": "MIT",
1464
+ "dependencies": {
1465
+ "fetch-blob": "^3.1.2"
1466
+ },
1467
+ "engines": {
1468
+ "node": ">=12.20.0"
1469
+ }
1470
+ },
1387
1471
  "node_modules/forwarded": {
1388
1472
  "version": "0.2.0",
1389
1473
  "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -1426,6 +1510,34 @@
1426
1510
  "url": "https://github.com/sponsors/ljharb"
1427
1511
  }
1428
1512
  },
1513
+ "node_modules/gaxios": {
1514
+ "version": "7.1.4",
1515
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz",
1516
+ "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==",
1517
+ "license": "Apache-2.0",
1518
+ "dependencies": {
1519
+ "extend": "^3.0.2",
1520
+ "https-proxy-agent": "^7.0.1",
1521
+ "node-fetch": "^3.3.2"
1522
+ },
1523
+ "engines": {
1524
+ "node": ">=18"
1525
+ }
1526
+ },
1527
+ "node_modules/gcp-metadata": {
1528
+ "version": "8.1.2",
1529
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz",
1530
+ "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==",
1531
+ "license": "Apache-2.0",
1532
+ "dependencies": {
1533
+ "gaxios": "^7.0.0",
1534
+ "google-logging-utils": "^1.0.0",
1535
+ "json-bigint": "^1.0.0"
1536
+ },
1537
+ "engines": {
1538
+ "node": ">=18"
1539
+ }
1540
+ },
1429
1541
  "node_modules/get-intrinsic": {
1430
1542
  "version": "1.3.0",
1431
1543
  "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -1476,6 +1588,61 @@
1476
1588
  "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
1477
1589
  }
1478
1590
  },
1591
+ "node_modules/google-auth-library": {
1592
+ "version": "10.6.2",
1593
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz",
1594
+ "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==",
1595
+ "license": "Apache-2.0",
1596
+ "dependencies": {
1597
+ "base64-js": "^1.3.0",
1598
+ "ecdsa-sig-formatter": "^1.0.11",
1599
+ "gaxios": "^7.1.4",
1600
+ "gcp-metadata": "8.1.2",
1601
+ "google-logging-utils": "1.1.3",
1602
+ "jws": "^4.0.0"
1603
+ },
1604
+ "engines": {
1605
+ "node": ">=18"
1606
+ }
1607
+ },
1608
+ "node_modules/google-logging-utils": {
1609
+ "version": "1.1.3",
1610
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
1611
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
1612
+ "license": "Apache-2.0",
1613
+ "engines": {
1614
+ "node": ">=14"
1615
+ }
1616
+ },
1617
+ "node_modules/googleapis": {
1618
+ "version": "171.4.0",
1619
+ "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-171.4.0.tgz",
1620
+ "integrity": "sha512-xybFL2SmmUgIifgsbsRQYRdNrSAYwxWZDmkZTGjUIaRnX5jPqR8el/cEvo6rCqh7iaZx6MfEPS/lrDgZ0bymkg==",
1621
+ "license": "Apache-2.0",
1622
+ "dependencies": {
1623
+ "google-auth-library": "^10.2.0",
1624
+ "googleapis-common": "^8.0.0"
1625
+ },
1626
+ "engines": {
1627
+ "node": ">=18"
1628
+ }
1629
+ },
1630
+ "node_modules/googleapis-common": {
1631
+ "version": "8.0.1",
1632
+ "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.1.tgz",
1633
+ "integrity": "sha512-eCzNACUXPb1PW5l0ULTzMHaL/ltPRADoPgjBlT8jWsTbxkCp6siv+qKJ/1ldaybCthGwsYFYallF7u9AkU4L+A==",
1634
+ "license": "Apache-2.0",
1635
+ "dependencies": {
1636
+ "extend": "^3.0.2",
1637
+ "gaxios": "^7.0.0-rc.4",
1638
+ "google-auth-library": "^10.1.0",
1639
+ "qs": "^6.7.0",
1640
+ "url-template": "^2.0.8"
1641
+ },
1642
+ "engines": {
1643
+ "node": ">=18.0.0"
1644
+ }
1645
+ },
1479
1646
  "node_modules/gopd": {
1480
1647
  "version": "1.2.0",
1481
1648
  "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -1532,6 +1699,42 @@
1532
1699
  "url": "https://opencollective.com/express"
1533
1700
  }
1534
1701
  },
1702
+ "node_modules/https-proxy-agent": {
1703
+ "version": "7.0.6",
1704
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
1705
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
1706
+ "license": "MIT",
1707
+ "dependencies": {
1708
+ "agent-base": "^7.1.2",
1709
+ "debug": "4"
1710
+ },
1711
+ "engines": {
1712
+ "node": ">= 14"
1713
+ }
1714
+ },
1715
+ "node_modules/https-proxy-agent/node_modules/debug": {
1716
+ "version": "4.4.3",
1717
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1718
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1719
+ "license": "MIT",
1720
+ "dependencies": {
1721
+ "ms": "^2.1.3"
1722
+ },
1723
+ "engines": {
1724
+ "node": ">=6.0"
1725
+ },
1726
+ "peerDependenciesMeta": {
1727
+ "supports-color": {
1728
+ "optional": true
1729
+ }
1730
+ }
1731
+ },
1732
+ "node_modules/https-proxy-agent/node_modules/ms": {
1733
+ "version": "2.1.3",
1734
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1735
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1736
+ "license": "MIT"
1737
+ },
1535
1738
  "node_modules/iconv-lite": {
1536
1739
  "version": "0.4.24",
1537
1740
  "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1571,6 +1774,15 @@
1571
1774
  "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
1572
1775
  "license": "MIT"
1573
1776
  },
1777
+ "node_modules/json-bigint": {
1778
+ "version": "1.0.0",
1779
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
1780
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
1781
+ "license": "MIT",
1782
+ "dependencies": {
1783
+ "bignumber.js": "^9.0.0"
1784
+ }
1785
+ },
1574
1786
  "node_modules/json-schema": {
1575
1787
  "version": "0.4.0",
1576
1788
  "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
@@ -1619,6 +1831,27 @@
1619
1831
  "safe-buffer": "~5.1.0"
1620
1832
  }
1621
1833
  },
1834
+ "node_modules/jwa": {
1835
+ "version": "2.0.1",
1836
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
1837
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
1838
+ "license": "MIT",
1839
+ "dependencies": {
1840
+ "buffer-equal-constant-time": "^1.0.1",
1841
+ "ecdsa-sig-formatter": "1.0.11",
1842
+ "safe-buffer": "^5.0.1"
1843
+ }
1844
+ },
1845
+ "node_modules/jws": {
1846
+ "version": "4.0.1",
1847
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
1848
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
1849
+ "license": "MIT",
1850
+ "dependencies": {
1851
+ "jwa": "^2.0.1",
1852
+ "safe-buffer": "^5.0.1"
1853
+ }
1854
+ },
1622
1855
  "node_modules/lie": {
1623
1856
  "version": "3.3.0",
1624
1857
  "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
@@ -1766,6 +1999,44 @@
1766
1999
  "node": ">= 0.6"
1767
2000
  }
1768
2001
  },
2002
+ "node_modules/node-domexception": {
2003
+ "version": "1.0.0",
2004
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
2005
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
2006
+ "deprecated": "Use your platform's native DOMException instead",
2007
+ "funding": [
2008
+ {
2009
+ "type": "github",
2010
+ "url": "https://github.com/sponsors/jimmywarting"
2011
+ },
2012
+ {
2013
+ "type": "github",
2014
+ "url": "https://paypal.me/jimmywarting"
2015
+ }
2016
+ ],
2017
+ "license": "MIT",
2018
+ "engines": {
2019
+ "node": ">=10.5.0"
2020
+ }
2021
+ },
2022
+ "node_modules/node-fetch": {
2023
+ "version": "3.3.2",
2024
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
2025
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
2026
+ "license": "MIT",
2027
+ "dependencies": {
2028
+ "data-uri-to-buffer": "^4.0.0",
2029
+ "fetch-blob": "^3.1.4",
2030
+ "formdata-polyfill": "^4.0.10"
2031
+ },
2032
+ "engines": {
2033
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
2034
+ },
2035
+ "funding": {
2036
+ "type": "opencollective",
2037
+ "url": "https://opencollective.com/node-fetch"
2038
+ }
2039
+ },
1769
2040
  "node_modules/object-assign": {
1770
2041
  "version": "4.1.1",
1771
2042
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -2220,6 +2491,12 @@
2220
2491
  "node": ">= 0.8"
2221
2492
  }
2222
2493
  },
2494
+ "node_modules/url-template": {
2495
+ "version": "2.0.8",
2496
+ "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
2497
+ "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==",
2498
+ "license": "BSD"
2499
+ },
2223
2500
  "node_modules/util-deprecate": {
2224
2501
  "version": "1.0.2",
2225
2502
  "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -2244,6 +2521,15 @@
2244
2521
  "node": ">= 0.8"
2245
2522
  }
2246
2523
  },
2524
+ "node_modules/web-streams-polyfill": {
2525
+ "version": "3.3.3",
2526
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
2527
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
2528
+ "license": "MIT",
2529
+ "engines": {
2530
+ "node": ">= 8"
2531
+ }
2532
+ },
2247
2533
  "node_modules/xmlbuilder": {
2248
2534
  "version": "10.1.1",
2249
2535
  "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
@@ -14,6 +14,7 @@
14
14
  "cors": "^2.8.5",
15
15
  "dotenv": "^16.4.0",
16
16
  "express": "^4.21.0",
17
+ "googleapis": "^171.4.0",
17
18
  "mammoth": "^1.12.0",
18
19
  "multer": "^2.1.1",
19
20
  "pdf-parse": "^2.4.5",