eggi-ai-db-schema-2 0.1.1

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 (188) hide show
  1. package/CHANGELOG.md +750 -0
  2. package/README.md +660 -0
  3. package/dist/config/database.d.ts +28 -0
  4. package/dist/config/database.d.ts.map +1 -0
  5. package/dist/config/database.js +72 -0
  6. package/dist/config/database.js.map +1 -0
  7. package/dist/index.d.ts +28 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +199 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/database-service.d.ts +714 -0
  12. package/dist/lib/database-service.d.ts.map +1 -0
  13. package/dist/lib/database-service.js +1394 -0
  14. package/dist/lib/database-service.js.map +1 -0
  15. package/dist/lib/db-types.d.ts +167 -0
  16. package/dist/lib/db-types.d.ts.map +1 -0
  17. package/dist/lib/db-types.js +28 -0
  18. package/dist/lib/db-types.js.map +1 -0
  19. package/dist/lib/db.d.ts +58 -0
  20. package/dist/lib/db.d.ts.map +1 -0
  21. package/dist/lib/db.js +292 -0
  22. package/dist/lib/db.js.map +1 -0
  23. package/dist/lib/index.d.ts +11 -0
  24. package/dist/lib/index.d.ts.map +1 -0
  25. package/dist/lib/index.js +26 -0
  26. package/dist/lib/index.js.map +1 -0
  27. package/dist/lib/pg-client.d.ts +50 -0
  28. package/dist/lib/pg-client.d.ts.map +1 -0
  29. package/dist/lib/pg-client.js +106 -0
  30. package/dist/lib/pg-client.js.map +1 -0
  31. package/dist/lib/schema.d.ts +298 -0
  32. package/dist/lib/schema.d.ts.map +1 -0
  33. package/dist/lib/schema.js +12 -0
  34. package/dist/lib/schema.js.map +1 -0
  35. package/dist/migration-manager.d.ts +49 -0
  36. package/dist/migration-manager.d.ts.map +1 -0
  37. package/dist/migration-manager.js +282 -0
  38. package/dist/migration-manager.js.map +1 -0
  39. package/dist/queries/minimal-connections.d.ts +31 -0
  40. package/dist/queries/minimal-connections.d.ts.map +1 -0
  41. package/dist/queries/minimal-connections.js +143 -0
  42. package/dist/queries/minimal-connections.js.map +1 -0
  43. package/dist/schema.ts +340 -0
  44. package/dist/seed.d.ts +8 -0
  45. package/dist/seed.d.ts.map +1 -0
  46. package/dist/seed.js +40 -0
  47. package/dist/seed.js.map +1 -0
  48. package/dist/types/index.d.ts +7 -0
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/index.js +23 -0
  51. package/dist/types/index.js.map +1 -0
  52. package/dist/types/types.d.ts +77 -0
  53. package/dist/types/types.d.ts.map +1 -0
  54. package/dist/types/types.js +3 -0
  55. package/dist/types/types.js.map +1 -0
  56. package/dist/utils/authenticated-user-operations.d.ts +110 -0
  57. package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
  58. package/dist/utils/authenticated-user-operations.js +292 -0
  59. package/dist/utils/authenticated-user-operations.js.map +1 -0
  60. package/dist/utils/authentication-operations.d.ts +48 -0
  61. package/dist/utils/authentication-operations.d.ts.map +1 -0
  62. package/dist/utils/authentication-operations.js +172 -0
  63. package/dist/utils/authentication-operations.js.map +1 -0
  64. package/dist/utils/company-mapping-job-operations.d.ts +103 -0
  65. package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
  66. package/dist/utils/company-mapping-job-operations.js +413 -0
  67. package/dist/utils/company-mapping-job-operations.js.map +1 -0
  68. package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
  69. package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
  70. package/dist/utils/company-sheet-upload-operations.js +135 -0
  71. package/dist/utils/company-sheet-upload-operations.js.map +1 -0
  72. package/dist/utils/contact-operations.d.ts +70 -0
  73. package/dist/utils/contact-operations.d.ts.map +1 -0
  74. package/dist/utils/contact-operations.js +294 -0
  75. package/dist/utils/contact-operations.js.map +1 -0
  76. package/dist/utils/forager-linkedin-operations.d.ts +74 -0
  77. package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
  78. package/dist/utils/forager-linkedin-operations.js +778 -0
  79. package/dist/utils/forager-linkedin-operations.js.map +1 -0
  80. package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
  81. package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
  82. package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
  83. package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
  84. package/dist/utils/index.d.ts +29 -0
  85. package/dist/utils/index.d.ts.map +1 -0
  86. package/dist/utils/index.js +77 -0
  87. package/dist/utils/index.js.map +1 -0
  88. package/dist/utils/introduction-request-operations.d.ts +160 -0
  89. package/dist/utils/introduction-request-operations.d.ts.map +1 -0
  90. package/dist/utils/introduction-request-operations.js +492 -0
  91. package/dist/utils/introduction-request-operations.js.map +1 -0
  92. package/dist/utils/invitation-operations.d.ts +141 -0
  93. package/dist/utils/invitation-operations.d.ts.map +1 -0
  94. package/dist/utils/invitation-operations.js +749 -0
  95. package/dist/utils/invitation-operations.js.map +1 -0
  96. package/dist/utils/linkedin-account-operations.d.ts +45 -0
  97. package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
  98. package/dist/utils/linkedin-account-operations.js +279 -0
  99. package/dist/utils/linkedin-account-operations.js.map +1 -0
  100. package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
  101. package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
  102. package/dist/utils/linkedin-account-relationship-operations.js +274 -0
  103. package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
  104. package/dist/utils/linkedin-data-operations.d.ts +102 -0
  105. package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
  106. package/dist/utils/linkedin-data-operations.js +613 -0
  107. package/dist/utils/linkedin-data-operations.js.map +1 -0
  108. package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
  109. package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
  110. package/dist/utils/linkedin-identifier-utils.js +63 -0
  111. package/dist/utils/linkedin-identifier-utils.js.map +1 -0
  112. package/dist/utils/linkedin-profile-cache.d.ts +131 -0
  113. package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
  114. package/dist/utils/linkedin-profile-cache.js +418 -0
  115. package/dist/utils/linkedin-profile-cache.js.map +1 -0
  116. package/dist/utils/llm-inference-job-operations.d.ts +116 -0
  117. package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
  118. package/dist/utils/llm-inference-job-operations.js +267 -0
  119. package/dist/utils/llm-inference-job-operations.js.map +1 -0
  120. package/dist/utils/mapping-job-operations.d.ts +272 -0
  121. package/dist/utils/mapping-job-operations.d.ts.map +1 -0
  122. package/dist/utils/mapping-job-operations.js +833 -0
  123. package/dist/utils/mapping-job-operations.js.map +1 -0
  124. package/dist/utils/mapping-operations.d.ts +80 -0
  125. package/dist/utils/mapping-operations.d.ts.map +1 -0
  126. package/dist/utils/mapping-operations.js +318 -0
  127. package/dist/utils/mapping-operations.js.map +1 -0
  128. package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
  129. package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
  130. package/dist/utils/on-demand-mapping-operations.js +728 -0
  131. package/dist/utils/on-demand-mapping-operations.js.map +1 -0
  132. package/dist/utils/onboarding-operations.d.ts +53 -0
  133. package/dist/utils/onboarding-operations.d.ts.map +1 -0
  134. package/dist/utils/onboarding-operations.js +223 -0
  135. package/dist/utils/onboarding-operations.js.map +1 -0
  136. package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
  137. package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
  138. package/dist/utils/organization-assignment-job-operations.js +881 -0
  139. package/dist/utils/organization-assignment-job-operations.js.map +1 -0
  140. package/dist/utils/organization-assignment-operations.d.ts +59 -0
  141. package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
  142. package/dist/utils/organization-assignment-operations.js +130 -0
  143. package/dist/utils/organization-assignment-operations.js.map +1 -0
  144. package/dist/utils/organization-operations.d.ts +284 -0
  145. package/dist/utils/organization-operations.d.ts.map +1 -0
  146. package/dist/utils/organization-operations.js +1030 -0
  147. package/dist/utils/organization-operations.js.map +1 -0
  148. package/dist/utils/organization-relationship-operations.d.ts +79 -0
  149. package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
  150. package/dist/utils/organization-relationship-operations.js +294 -0
  151. package/dist/utils/organization-relationship-operations.js.map +1 -0
  152. package/dist/utils/quota-operations.d.ts +107 -0
  153. package/dist/utils/quota-operations.d.ts.map +1 -0
  154. package/dist/utils/quota-operations.js +692 -0
  155. package/dist/utils/quota-operations.js.map +1 -0
  156. package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
  157. package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
  158. package/dist/utils/recursive-mapping-job-operations.js +169 -0
  159. package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
  160. package/dist/utils/relationship-operations.d.ts +130 -0
  161. package/dist/utils/relationship-operations.d.ts.map +1 -0
  162. package/dist/utils/relationship-operations.js +329 -0
  163. package/dist/utils/relationship-operations.js.map +1 -0
  164. package/dist/utils/sales-pipeline-operations.d.ts +163 -0
  165. package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
  166. package/dist/utils/sales-pipeline-operations.js +725 -0
  167. package/dist/utils/sales-pipeline-operations.js.map +1 -0
  168. package/dist/utils/skills-operations.d.ts +117 -0
  169. package/dist/utils/skills-operations.d.ts.map +1 -0
  170. package/dist/utils/skills-operations.js +487 -0
  171. package/dist/utils/skills-operations.js.map +1 -0
  172. package/dist/utils/subscription-operations.d.ts +123 -0
  173. package/dist/utils/subscription-operations.d.ts.map +1 -0
  174. package/dist/utils/subscription-operations.js +391 -0
  175. package/dist/utils/subscription-operations.js.map +1 -0
  176. package/dist/utils/unipile-account-operations.d.ts +96 -0
  177. package/dist/utils/unipile-account-operations.d.ts.map +1 -0
  178. package/dist/utils/unipile-account-operations.js +255 -0
  179. package/dist/utils/unipile-account-operations.js.map +1 -0
  180. package/dist/utils/user-industry-operations.d.ts +80 -0
  181. package/dist/utils/user-industry-operations.d.ts.map +1 -0
  182. package/dist/utils/user-industry-operations.js +237 -0
  183. package/dist/utils/user-industry-operations.js.map +1 -0
  184. package/dist/utils/user-operations.d.ts +87 -0
  185. package/dist/utils/user-operations.d.ts.map +1 -0
  186. package/dist/utils/user-operations.js +212 -0
  187. package/dist/utils/user-operations.js.map +1 -0
  188. package/package.json +98 -0
@@ -0,0 +1,728 @@
1
+ "use strict";
2
+ /**
3
+ * =============================================================================
4
+ * ON-DEMAND MAPPING OPERATIONS UTILITIES - CONSOLIDATED SCHEMA
5
+ * =============================================================================
6
+ * Utility functions for creating and managing on-demand mapping jobs from Chrome extension
7
+ * Updated to work with the new consolidated linkedin.accounts schema
8
+ *
9
+ * USAGE EXAMPLES:
10
+ *
11
+ * 1. CREATE ON-DEMAND REQUEST:
12
+ * ```typescript
13
+ * const request = await createOnDemandMappingJob({
14
+ * requesterLinkedinAccountId: 123,
15
+ * internalIdentifierAcoa: "ACoAABCDEFG...", // Target ACoA identifier
16
+ * metadata: {
17
+ * source: "chrome_extension",
18
+ * user_agent: "Mozilla/5.0...",
19
+ * requested_by: "user_456"
20
+ * }
21
+ * });
22
+ * ```
23
+ *
24
+ * 2. GET REQUEST WITH STATUS:
25
+ * ```typescript
26
+ * const requestWithStatus = await getOnDemandMappingJobWithStatus(123, "ACoAABCDEFG...");
27
+ * // Returns: { id, mappingJobId, status: "completed", progress: 100, ... }
28
+ * ```
29
+ *
30
+ * 3. UPDATE MAPPING JOB ASSOCIATION:
31
+ * ```typescript
32
+ * await updateOnDemandMappingJobId(123, "ACoAABCDEFG...", 789);
33
+ * ```
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createOnDemandMappingJob = createOnDemandMappingJob;
37
+ exports.getOnDemandMappingJob = getOnDemandMappingJob;
38
+ exports.getOnDemandMappingJobById = getOnDemandMappingJobById;
39
+ exports.getOnDemandMappingJobWithStatus = getOnDemandMappingJobWithStatus;
40
+ exports.updateOnDemandMappingJobId = updateOnDemandMappingJobId;
41
+ exports.getOnDemandMappingJobsMinimal = getOnDemandMappingJobsMinimal;
42
+ exports.getPendingOnDemandMappingJobs = getPendingOnDemandMappingJobs;
43
+ exports.checkOnDemandMappingJobExists = checkOnDemandMappingJobExists;
44
+ exports.getOrCreateOnDemandMappingJob = getOrCreateOnDemandMappingJob;
45
+ exports.getTargetLinkedInAccountIdForOnDemandJobInOrganization = getTargetLinkedInAccountIdForOnDemandJobInOrganization;
46
+ exports.deleteOnDemandMappingJob = deleteOnDemandMappingJob;
47
+ exports.getRelationshipScoresForOnDemandJob = getRelationshipScoresForOnDemandJob;
48
+ const pg_client_1 = require("../lib/pg-client");
49
+ const db_1 = require("../lib/db");
50
+ const database_service_1 = require("../lib/database-service");
51
+ // =============================================================================
52
+ // CORE OPERATIONS
53
+ // =============================================================================
54
+ /**
55
+ * Create a new on-demand mapping job
56
+ */
57
+ async function createOnDemandMappingJob(params) {
58
+ const { requesterLinkedinAccountId, internalIdentifierAcoa, metadata = {} } = params;
59
+ (0, db_1.debugLogDbOperation)("insert", "monitoring.on_demand_mapping_jobs", { requesterLinkedinAccountId, internalIdentifierAcoa }, undefined, {
60
+ operation: "createOnDemandMappingJob",
61
+ requesterLinkedinAccountId,
62
+ internalIdentifierAcoa,
63
+ });
64
+ try {
65
+ // Verify requester LinkedIn account exists
66
+ const db = await database_service_1.dbService.getDb();
67
+ const requesterSql = `SELECT id FROM linkedin.accounts WHERE id = $1 LIMIT 1`;
68
+ const requesterAccount = await (0, pg_client_1.queryOne)(db, requesterSql, [
69
+ requesterLinkedinAccountId,
70
+ ]);
71
+ if (!requesterAccount) {
72
+ throw new Error(`Requester LinkedIn account with ID ${requesterLinkedinAccountId} not found`);
73
+ }
74
+ // Create the on-demand mapping job
75
+ const insertSql = `
76
+ INSERT INTO monitoring.on_demand_mapping_jobs (
77
+ requester_linkedin_account_id, internal_identifier_acoa, metadata, created_at, updated_at
78
+ )
79
+ VALUES ($1, $2, $3, NOW(), NOW())
80
+ RETURNING id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
81
+ `;
82
+ const onDemandJob = await (0, pg_client_1.queryOne)(db, insertSql, [
83
+ requesterLinkedinAccountId,
84
+ internalIdentifierAcoa,
85
+ JSON.stringify(metadata),
86
+ ]);
87
+ if (!onDemandJob) {
88
+ throw new Error("Failed to create on-demand mapping job");
89
+ }
90
+ return {
91
+ id: onDemandJob.id,
92
+ requesterLinkedinAccountId: onDemandJob.requester_linkedin_account_id,
93
+ internalIdentifierAcoa: onDemandJob.internal_identifier_acoa,
94
+ mappingJobId: onDemandJob.mapping_job_id,
95
+ metadata: onDemandJob.metadata,
96
+ createdAt: onDemandJob.created_at,
97
+ updatedAt: onDemandJob.updated_at,
98
+ };
99
+ }
100
+ catch (error) {
101
+ console.error("Error creating on-demand mapping job:", error);
102
+ throw error;
103
+ }
104
+ }
105
+ /**
106
+ * Get on-demand mapping job by requester and target identifiers
107
+ */
108
+ async function getOnDemandMappingJob(requesterLinkedinAccountId, internalIdentifierAcoa) {
109
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs", { requesterLinkedinAccountId, internalIdentifierAcoa }, undefined, {
110
+ operation: "getOnDemandMappingJob",
111
+ requesterLinkedinAccountId,
112
+ internalIdentifierAcoa,
113
+ });
114
+ try {
115
+ const db = await database_service_1.dbService.getDb();
116
+ const sql = `
117
+ SELECT id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
118
+ FROM monitoring.on_demand_mapping_jobs
119
+ WHERE requester_linkedin_account_id = $1 AND internal_identifier_acoa = $2
120
+ LIMIT 1
121
+ `;
122
+ const result = await (0, pg_client_1.queryOne)(db, sql, [requesterLinkedinAccountId, internalIdentifierAcoa]);
123
+ if (!result)
124
+ return null;
125
+ return {
126
+ id: result.id,
127
+ requesterLinkedinAccountId: result.requester_linkedin_account_id,
128
+ internalIdentifierAcoa: result.internal_identifier_acoa,
129
+ mappingJobId: result.mapping_job_id,
130
+ metadata: result.metadata,
131
+ createdAt: result.created_at,
132
+ updatedAt: result.updated_at,
133
+ };
134
+ }
135
+ catch (error) {
136
+ console.error("Error getting on-demand mapping job:", error);
137
+ throw error;
138
+ }
139
+ }
140
+ /**
141
+ * Get on-demand mapping job by ID
142
+ */
143
+ async function getOnDemandMappingJobById(jobId) {
144
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs", { jobId }, undefined, {
145
+ operation: "getOnDemandMappingJobById",
146
+ jobId,
147
+ });
148
+ try {
149
+ const db = await database_service_1.dbService.getDb();
150
+ const sql = `
151
+ SELECT id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
152
+ FROM monitoring.on_demand_mapping_jobs
153
+ WHERE id = $1
154
+ LIMIT 1
155
+ `;
156
+ const result = await (0, pg_client_1.queryOne)(db, sql, [jobId]);
157
+ if (!result)
158
+ return null;
159
+ return {
160
+ id: result.id,
161
+ requesterLinkedinAccountId: result.requester_linkedin_account_id,
162
+ internalIdentifierAcoa: result.internal_identifier_acoa,
163
+ mappingJobId: result.mapping_job_id,
164
+ metadata: result.metadata,
165
+ createdAt: result.created_at,
166
+ updatedAt: result.updated_at,
167
+ };
168
+ }
169
+ catch (error) {
170
+ console.error("Error getting on-demand mapping job by ID:", error);
171
+ throw error;
172
+ }
173
+ }
174
+ /**
175
+ * Get on-demand mapping job with complete status information
176
+ */
177
+ async function getOnDemandMappingJobWithStatus(requesterLinkedinAccountId, internalIdentifierAcoa) {
178
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs + status", { requesterLinkedinAccountId, internalIdentifierAcoa }, undefined, {
179
+ operation: "getOnDemandMappingJobWithStatus",
180
+ requesterLinkedinAccountId,
181
+ internalIdentifierAcoa,
182
+ });
183
+ try {
184
+ const db = await database_service_1.dbService.getDb();
185
+ // Get the on-demand job with requester details
186
+ const jobSql = `
187
+ SELECT
188
+ odmj.id, odmj.requester_linkedin_account_id, odmj.internal_identifier_acoa,
189
+ odmj.mapping_job_id, odmj.created_at, odmj.updated_at, odmj.metadata,
190
+ la.linkedin_identifier_acoa as requester_linkedin_identifier
191
+ FROM monitoring.on_demand_mapping_jobs odmj
192
+ INNER JOIN linkedin.accounts la ON odmj.requester_linkedin_account_id = la.id
193
+ WHERE odmj.requester_linkedin_account_id = $1 AND odmj.internal_identifier_acoa = $2
194
+ LIMIT 1
195
+ `;
196
+ const job = await (0, pg_client_1.queryOne)(db, jobSql, [requesterLinkedinAccountId, internalIdentifierAcoa]);
197
+ if (!job) {
198
+ return null;
199
+ }
200
+ // Determine status and get mapping job details if available
201
+ let status = "pending";
202
+ let progress = 0;
203
+ let mappingJobDetails;
204
+ let linkedinRelationshipsCount = 0;
205
+ if (job.mapping_job_id) {
206
+ // Get mapping job details
207
+ const mappingJobSql = `
208
+ SELECT created_at, queued_at, started_at, completed_at, metadata
209
+ FROM monitoring.mapping_jobs
210
+ WHERE id = $1
211
+ LIMIT 1
212
+ `;
213
+ const mappingJob = await (0, pg_client_1.queryOne)(db, mappingJobSql, [job.mapping_job_id]);
214
+ if (mappingJob) {
215
+ mappingJobDetails = {
216
+ createdAt: mappingJob.created_at,
217
+ queuedAt: mappingJob.queued_at,
218
+ startedAt: mappingJob.started_at ?? undefined,
219
+ completedAt: mappingJob.completed_at ?? undefined,
220
+ metadata: mappingJob.metadata,
221
+ };
222
+ // Determine status based on mapping job state
223
+ if (mappingJob.completed_at) {
224
+ status = "completed";
225
+ progress = 100;
226
+ }
227
+ else if (mappingJob.started_at) {
228
+ status = "processing";
229
+ progress = 50; // Estimate - could be refined with more detailed progress tracking
230
+ }
231
+ else {
232
+ status = "queued";
233
+ progress = 10;
234
+ }
235
+ // Get relationship scores count for completed jobs
236
+ if (status === "completed") {
237
+ const countSql = `SELECT COUNT(*) as count FROM linkedin.relationships WHERE mapping_job_id = $1`;
238
+ const scoresCount = await (0, pg_client_1.queryOne)(db, countSql, [
239
+ job.mapping_job_id,
240
+ ]);
241
+ linkedinRelationshipsCount = parseInt(scoresCount?.count || "0");
242
+ }
243
+ }
244
+ }
245
+ return {
246
+ id: job.id,
247
+ requesterLinkedinAccountId: job.requester_linkedin_account_id,
248
+ internalIdentifierAcoa: job.internal_identifier_acoa,
249
+ mappingJobId: job.mapping_job_id,
250
+ createdAt: job.created_at,
251
+ updatedAt: job.updated_at,
252
+ metadata: job.metadata,
253
+ status,
254
+ progress,
255
+ requesterLinkedInIdentifier: job.requester_linkedin_identifier || undefined,
256
+ targetLinkedInIdentifier: job.internal_identifier_acoa,
257
+ mappingJobDetails,
258
+ linkedinRelationshipsCount,
259
+ };
260
+ }
261
+ catch (error) {
262
+ console.error("Error getting on-demand mapping job with status:", error);
263
+ throw error;
264
+ }
265
+ }
266
+ /**
267
+ * Update the mapping job ID for an on-demand mapping job
268
+ */
269
+ async function updateOnDemandMappingJobId(requesterLinkedinAccountId, internalIdentifierAcoa, mappingJobId) {
270
+ (0, db_1.debugLogDbOperation)("update", "monitoring.on_demand_mapping_jobs", { requesterLinkedinAccountId, internalIdentifierAcoa, mappingJobId }, undefined, {
271
+ operation: "updateOnDemandMappingJobId",
272
+ requesterLinkedinAccountId,
273
+ internalIdentifierAcoa,
274
+ mappingJobId,
275
+ });
276
+ try {
277
+ const db = await database_service_1.dbService.getDb();
278
+ const sql = `
279
+ UPDATE monitoring.on_demand_mapping_jobs
280
+ SET mapping_job_id = $1, updated_at = NOW()
281
+ WHERE requester_linkedin_account_id = $2 AND internal_identifier_acoa = $3
282
+ RETURNING id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
283
+ `;
284
+ const updatedJob = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId, requesterLinkedinAccountId, internalIdentifierAcoa]);
285
+ if (!updatedJob) {
286
+ throw new Error(`On-demand mapping job for requester ${requesterLinkedinAccountId} and target ${internalIdentifierAcoa} not found`);
287
+ }
288
+ return {
289
+ id: updatedJob.id,
290
+ requesterLinkedinAccountId: updatedJob.requester_linkedin_account_id,
291
+ internalIdentifierAcoa: updatedJob.internal_identifier_acoa,
292
+ mappingJobId: updatedJob.mapping_job_id,
293
+ metadata: updatedJob.metadata,
294
+ createdAt: updatedJob.created_at,
295
+ updatedAt: updatedJob.updated_at,
296
+ };
297
+ }
298
+ catch (error) {
299
+ console.error("Error updating on-demand mapping job ID:", error);
300
+ throw error;
301
+ }
302
+ }
303
+ /**
304
+ * Get minimal on-demand mapping jobs for Chrome extension with pagination
305
+ * Excludes large metadata blocks to reduce response size
306
+ * Includes self-targeting jobs (where requester maps themselves)
307
+ */
308
+ async function getOnDemandMappingJobsMinimal(db, requesterLinkedinAccountId, limit = 50, offset = 0) {
309
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs (minimal with pagination)", { requesterLinkedinAccountId, limit, offset }, undefined, {
310
+ operation: "getOnDemandMappingJobsMinimal",
311
+ requesterLinkedinAccountId,
312
+ });
313
+ try {
314
+ // Get the total count (including self-targeting jobs)
315
+ const countSql = `
316
+ SELECT COUNT(*) as count FROM monitoring.on_demand_mapping_jobs
317
+ WHERE requester_linkedin_account_id = $1
318
+ `;
319
+ const totalCountResult = await (0, pg_client_1.queryOne)(db, countSql, [
320
+ requesterLinkedinAccountId,
321
+ ]);
322
+ const total_items = parseInt(totalCountResult?.count || "0");
323
+ // Get paginated on-demand jobs for the requester with minimal data
324
+ const jobsSql = `
325
+ SELECT id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, created_at, updated_at
326
+ FROM monitoring.on_demand_mapping_jobs
327
+ WHERE requester_linkedin_account_id = $1
328
+ ORDER BY created_at DESC
329
+ LIMIT $2 OFFSET $3
330
+ `;
331
+ const jobs = await (0, pg_client_1.query)(db, jobsSql, [requesterLinkedinAccountId, limit, offset]);
332
+ // Get minimal status for each job
333
+ const jobsWithMinimalStatus = await Promise.all(jobs.map(async (job) => {
334
+ let status = "pending";
335
+ let progress = 0;
336
+ let mappingJobDetails;
337
+ let linkedinRelationshipsCount;
338
+ if (job.mapping_job_id) {
339
+ // Get minimal mapping job details (no large metadata)
340
+ const mappingJobSql = `
341
+ SELECT id, created_at, queued_at, started_at, completed_at, metadata
342
+ FROM monitoring.mapping_jobs
343
+ WHERE id = $1
344
+ LIMIT 1
345
+ `;
346
+ const mappingJob = await (0, pg_client_1.queryOne)(db, mappingJobSql, [job.mapping_job_id]);
347
+ if (mappingJob) {
348
+ // Determine status from mapping job timestamps, not metadata
349
+ // Mapping jobs don't store status in metadata - it's determined by timestamps
350
+ if (mappingJob.completed_at) {
351
+ status = "completed";
352
+ progress = 100;
353
+ }
354
+ else if (mappingJob.started_at) {
355
+ status = "processing";
356
+ progress = 50; // Estimate 50% when started
357
+ }
358
+ else if (mappingJob.queued_at) {
359
+ status = "queued";
360
+ progress = 10; // Estimate 10% when queued
361
+ }
362
+ else {
363
+ status = "pending";
364
+ progress = 0;
365
+ }
366
+ // Only include timing info, no large metadata blocks
367
+ mappingJobDetails = {
368
+ createdAt: mappingJob.created_at,
369
+ queuedAt: mappingJob.queued_at || undefined,
370
+ startedAt: mappingJob.started_at || undefined,
371
+ completedAt: mappingJob.completed_at || undefined,
372
+ };
373
+ // Get relationship scores count if completed
374
+ if (status === "completed") {
375
+ const scores = await getRelationshipScoresForOnDemandJob(job.requester_linkedin_account_id, job.internal_identifier_acoa);
376
+ linkedinRelationshipsCount = scores.length.toString();
377
+ }
378
+ }
379
+ }
380
+ // Get organization assignment job status if mapping job is completed
381
+ let organizationAssignmentStatus = null;
382
+ let organizationAssignmentJobDetails = null;
383
+ let organizations = null;
384
+ if (status === "completed" && job.mapping_job_id) {
385
+ try {
386
+ // Query ALL organization assignment jobs for this mapping job (can be multiple)
387
+ const orgAssignmentSql = `
388
+ SELECT
389
+ oaj.id,
390
+ oaj.created_at,
391
+ oaj.started_at,
392
+ oaj.completed_at,
393
+ oaj.organization_id,
394
+ o.name as organization_name,
395
+ o.workspace_type
396
+ FROM monitoring.organization_assignment_jobs oaj
397
+ INNER JOIN public.organizations o ON oaj.organization_id = o.id
398
+ WHERE oaj.mapping_job_id = $1
399
+ ORDER BY oaj.created_at DESC
400
+ `;
401
+ const orgAssignmentJobs = await (0, pg_client_1.query)(db, orgAssignmentSql, [job.mapping_job_id]);
402
+ if (orgAssignmentJobs && orgAssignmentJobs.length > 0) {
403
+ // Get the most recent organization assignment job for status
404
+ const latestOrgAssignmentJob = orgAssignmentJobs[0];
405
+ // Determine status based on latest job
406
+ if (latestOrgAssignmentJob.completed_at) {
407
+ organizationAssignmentStatus = "completed";
408
+ }
409
+ else if (latestOrgAssignmentJob.started_at) {
410
+ organizationAssignmentStatus = "processing";
411
+ }
412
+ else {
413
+ organizationAssignmentStatus = "queued";
414
+ }
415
+ // Use the latest job for details
416
+ organizationAssignmentJobDetails = {
417
+ id: latestOrgAssignmentJob.id,
418
+ createdAt: latestOrgAssignmentJob.created_at,
419
+ startedAt: latestOrgAssignmentJob.started_at || undefined,
420
+ completedAt: latestOrgAssignmentJob.completed_at || undefined,
421
+ };
422
+ // Collect all unique organizations this job was exported to
423
+ const uniqueOrgs = new Map();
424
+ for (const orgJob of orgAssignmentJobs) {
425
+ if (!uniqueOrgs.has(orgJob.organization_id)) {
426
+ uniqueOrgs.set(orgJob.organization_id, {
427
+ id: orgJob.organization_id,
428
+ name: orgJob.organization_name,
429
+ workspaceType: orgJob.workspace_type,
430
+ });
431
+ }
432
+ }
433
+ organizations = Array.from(uniqueOrgs.values()).map(org => ({
434
+ id: org.id,
435
+ name: org.name,
436
+ workspaceType: org.workspaceType,
437
+ }));
438
+ }
439
+ else {
440
+ // Mapping job completed but no organization assignment job yet
441
+ organizationAssignmentStatus = "pending";
442
+ }
443
+ }
444
+ catch (orgAssignmentError) {
445
+ // If organization assignment job query fails, log but continue
446
+ console.warn("Failed to fetch organization assignment job:", orgAssignmentError);
447
+ // If mapping job is completed but we can't find org assignment job, assume pending
448
+ if (status === "completed") {
449
+ organizationAssignmentStatus = "pending";
450
+ }
451
+ }
452
+ }
453
+ // Fetch profile details for the target LinkedIn identifier
454
+ // internal_identifier_acoa contains the ACoA identifier, we need to get the public identifier
455
+ let targetLinkedInIdentifier = job.internal_identifier_acoa; // Fallback to ACoA if public not found
456
+ let targetProfile = null;
457
+ try {
458
+ const profileSql = `
459
+ SELECT first_name, last_name,
460
+ COALESCE(profile_image_cloudfront_url, profile_picture_url) as profile_picture_url,
461
+ headline,
462
+ public_identifier
463
+ FROM linkedin.accounts
464
+ WHERE linkedin_identifier_acoa = $1
465
+ LIMIT 1
466
+ `;
467
+ const profile = await (0, pg_client_1.queryOne)(db, profileSql, [job.internal_identifier_acoa]);
468
+ // Use public identifier for display if available, otherwise fallback to ACoA
469
+ if (profile?.public_identifier) {
470
+ targetLinkedInIdentifier = profile.public_identifier;
471
+ }
472
+ if (profile) {
473
+ // Get current position from work experience
474
+ let currentPosition = null;
475
+ let currentCompany = null;
476
+ try {
477
+ const workExpSql = `
478
+ SELECT we.position, we.company, we.start_date, we.end_date, we.is_current
479
+ FROM linkedin.work_experience we
480
+ INNER JOIN linkedin.accounts la ON we.linkedin_account_id = la.id
481
+ WHERE la.linkedin_identifier_acoa = $1 AND we.is_current = true
482
+ ORDER BY we.start_date DESC
483
+ LIMIT 1
484
+ `;
485
+ const currentWork = await (0, pg_client_1.queryOne)(db, workExpSql, [job.internal_identifier_acoa]);
486
+ if (currentWork) {
487
+ currentPosition = currentWork.position || null;
488
+ currentCompany = currentWork.company || null;
489
+ }
490
+ }
491
+ catch (workError) {
492
+ // If work experience fetch fails, continue without it
493
+ console.warn("Failed to fetch work experience for profile:", workError);
494
+ }
495
+ targetProfile = {
496
+ name: `${profile.first_name || ""} ${profile.last_name || ""}`.trim() || "Unknown User",
497
+ profileImageUrl: profile.profile_picture_url || null,
498
+ position: currentPosition,
499
+ currentCompany: currentCompany,
500
+ headline: profile.headline || null,
501
+ };
502
+ }
503
+ }
504
+ catch (profileError) {
505
+ // If profile fetch fails, continue without profile details
506
+ console.warn("Failed to fetch profile details:", profileError);
507
+ }
508
+ const minimalJob = {
509
+ id: job.id,
510
+ requesterLinkedinAccountId: job.requester_linkedin_account_id,
511
+ internalIdentifierAcoa: job.internal_identifier_acoa,
512
+ mappingJobId: job.mapping_job_id,
513
+ createdAt: job.created_at,
514
+ updatedAt: job.updated_at,
515
+ status,
516
+ progress,
517
+ targetLinkedInIdentifier,
518
+ mappingJobDetails,
519
+ linkedinRelationshipsCount,
520
+ organizationAssignmentStatus: organizationAssignmentStatus ?? null,
521
+ organizationAssignmentJobDetails: organizationAssignmentJobDetails ?? null,
522
+ organizations: organizations ?? null,
523
+ targetProfile,
524
+ };
525
+ return minimalJob;
526
+ }));
527
+ return {
528
+ jobs: jobsWithMinimalStatus,
529
+ total_items,
530
+ };
531
+ }
532
+ catch (error) {
533
+ console.error("Error getting minimal on-demand mapping jobs:", error);
534
+ throw error;
535
+ }
536
+ }
537
+ /**
538
+ * Get pending on-demand mapping jobs (no mapping job assigned yet)
539
+ */
540
+ async function getPendingOnDemandMappingJobs(options) {
541
+ const { limit = 100 } = options || {};
542
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs", { limit, status: "pending" }, undefined, {
543
+ operation: "getPendingOnDemandMappingJobs",
544
+ });
545
+ try {
546
+ const db = await database_service_1.dbService.getDb();
547
+ const sql = `
548
+ SELECT id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
549
+ FROM monitoring.on_demand_mapping_jobs
550
+ WHERE mapping_job_id IS NULL
551
+ ORDER BY created_at
552
+ LIMIT $1
553
+ `;
554
+ const results = await (0, pg_client_1.query)(db, sql, [limit]);
555
+ return results.map(r => ({
556
+ id: r.id,
557
+ requesterLinkedinAccountId: r.requester_linkedin_account_id,
558
+ internalIdentifierAcoa: r.internal_identifier_acoa,
559
+ mappingJobId: r.mapping_job_id,
560
+ metadata: r.metadata,
561
+ createdAt: r.created_at,
562
+ updatedAt: r.updated_at,
563
+ }));
564
+ }
565
+ catch (error) {
566
+ console.error("Error getting pending on-demand mapping jobs:", error);
567
+ throw error;
568
+ }
569
+ }
570
+ // =============================================================================
571
+ // UTILITY FUNCTIONS
572
+ // =============================================================================
573
+ /**
574
+ * Check if an on-demand mapping job exists for the given parameters
575
+ */
576
+ async function checkOnDemandMappingJobExists(requesterLinkedinAccountId, internalIdentifierAcoa) {
577
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs", { requesterLinkedinAccountId, internalIdentifierAcoa }, undefined, {
578
+ operation: "checkOnDemandMappingJobExists",
579
+ });
580
+ try {
581
+ const db = await database_service_1.dbService.getDb();
582
+ const sql = `
583
+ SELECT id, requester_linkedin_account_id, internal_identifier_acoa, mapping_job_id, metadata, created_at, updated_at
584
+ FROM monitoring.on_demand_mapping_jobs
585
+ WHERE requester_linkedin_account_id = $1 AND internal_identifier_acoa = $2
586
+ LIMIT 1
587
+ `;
588
+ const result = await (0, pg_client_1.queryOne)(db, sql, [requesterLinkedinAccountId, internalIdentifierAcoa]);
589
+ if (!result)
590
+ return null;
591
+ return {
592
+ id: result.id,
593
+ requesterLinkedinAccountId: result.requester_linkedin_account_id,
594
+ internalIdentifierAcoa: result.internal_identifier_acoa,
595
+ mappingJobId: result.mapping_job_id,
596
+ metadata: result.metadata,
597
+ createdAt: result.created_at,
598
+ updatedAt: result.updated_at,
599
+ };
600
+ }
601
+ catch (error) {
602
+ console.error("Error checking on-demand mapping job exists:", error);
603
+ throw error;
604
+ }
605
+ }
606
+ /**
607
+ * Get or create an on-demand mapping job
608
+ */
609
+ async function getOrCreateOnDemandMappingJob(params) {
610
+ try {
611
+ // Check if job already exists
612
+ const existingJob = await checkOnDemandMappingJobExists(params.requesterLinkedinAccountId, params.internalIdentifierAcoa);
613
+ if (existingJob) {
614
+ return { onDemandJob: existingJob, wasCreated: false };
615
+ }
616
+ // Create new job
617
+ const newJob = await createOnDemandMappingJob(params);
618
+ return { onDemandJob: newJob, wasCreated: true };
619
+ }
620
+ catch (error) {
621
+ console.error("Error getting or creating on-demand mapping job:", error);
622
+ throw error;
623
+ }
624
+ }
625
+ /**
626
+ * Get target LinkedIn account ID for on-demand mapping job in an organization
627
+ *
628
+ * For on-demand mapping jobs, relationships are mapped for the TARGET but assigned
629
+ * to the REQUESTER's personal workspace. This function helps identify which account
630
+ * to use when querying relationships (the target's account, not the requester's).
631
+ *
632
+ * @param db - Database instance
633
+ * @param requesterLinkedinAccountId - The requester's LinkedIn account ID
634
+ * @param organizationId - The organization ID (personal workspace)
635
+ * @returns Target LinkedIn account ID if on-demand job exists, null otherwise
636
+ */
637
+ async function getTargetLinkedInAccountIdForOnDemandJobInOrganization(db, requesterLinkedinAccountId, organizationId) {
638
+ (0, db_1.debugLogDbOperation)("select", "monitoring.on_demand_mapping_jobs + organization_assignment_jobs", { requesterLinkedinAccountId, organizationId }, undefined, {
639
+ operation: "getTargetLinkedInAccountIdForOnDemandJobInOrganization",
640
+ requesterLinkedinAccountId,
641
+ organizationId,
642
+ });
643
+ try {
644
+ const sql = `
645
+ SELECT
646
+ la_target.id as target_linkedin_account_id
647
+ FROM monitoring.on_demand_mapping_jobs od
648
+ INNER JOIN monitoring.organization_assignment_jobs oaj
649
+ ON oaj.mapping_job_id = od.mapping_job_id
650
+ INNER JOIN linkedin.accounts la_target
651
+ ON la_target.linkedin_identifier_acoa = od.internal_identifier_acoa
652
+ WHERE
653
+ od.requester_linkedin_account_id = $1
654
+ AND oaj.organization_id = $2
655
+ AND od.mapping_job_id IS NOT NULL
656
+ ORDER BY od.created_at DESC
657
+ LIMIT 1
658
+ `;
659
+ const result = await (0, pg_client_1.queryOne)(db, sql, [requesterLinkedinAccountId, organizationId]);
660
+ return result?.target_linkedin_account_id || null;
661
+ }
662
+ catch (error) {
663
+ console.error("Error getting target LinkedIn account ID for on-demand job:", error);
664
+ throw error;
665
+ }
666
+ }
667
+ async function deleteOnDemandMappingJob(requesterLinkedinAccountId, internalIdentifierAcoa) {
668
+ (0, db_1.debugLogDbOperation)("delete", "monitoring.on_demand_mapping_jobs", { requesterLinkedinAccountId, internalIdentifierAcoa }, undefined, {
669
+ operation: "deleteOnDemandMappingJob",
670
+ requesterLinkedinAccountId,
671
+ internalIdentifierAcoa,
672
+ });
673
+ try {
674
+ const db = await database_service_1.dbService.getDb();
675
+ const sql = `
676
+ DELETE FROM monitoring.on_demand_mapping_jobs
677
+ WHERE requester_linkedin_account_id = $1 AND internal_identifier_acoa = $2
678
+ RETURNING id
679
+ `;
680
+ const result = await (0, pg_client_1.query)(db, sql, [
681
+ requesterLinkedinAccountId,
682
+ internalIdentifierAcoa,
683
+ ]);
684
+ return result.length > 0;
685
+ }
686
+ catch (error) {
687
+ console.error("Error deleting on-demand mapping job:", error);
688
+ throw error;
689
+ }
690
+ }
691
+ /**
692
+ * Get relationship scores for an on-demand mapping job
693
+ */
694
+ async function getRelationshipScoresForOnDemandJob(requesterLinkedinAccountId, internalIdentifierAcoa, options) {
695
+ const { limit = 50, minScore } = options || {};
696
+ (0, db_1.debugLogDbOperation)("select", "linkedin.relationships", { requesterLinkedinAccountId, internalIdentifierAcoa, limit, minScore }, undefined, {
697
+ operation: "getRelationshipScoresForOnDemandJob",
698
+ requesterLinkedinAccountId,
699
+ internalIdentifierAcoa,
700
+ });
701
+ try {
702
+ // Get the on-demand job to find the mapping job ID
703
+ const onDemandJob = await getOnDemandMappingJob(requesterLinkedinAccountId, internalIdentifierAcoa);
704
+ if (!onDemandJob || !onDemandJob.mappingJobId) {
705
+ return [];
706
+ }
707
+ const db = await database_service_1.dbService.getDb();
708
+ let sql = `
709
+ SELECT id, linkedin_account_id_a, linkedin_account_id_b, score, model_version, analysis_type, mapping_job_id, metadata, created_at
710
+ FROM linkedin.relationships
711
+ WHERE mapping_job_id = $1
712
+ `;
713
+ const params = [onDemandJob.mappingJobId];
714
+ if (minScore !== undefined) {
715
+ sql += ` AND score >= $2`;
716
+ params.push(minScore);
717
+ }
718
+ sql += ` ORDER BY score DESC LIMIT $${params.length + 1}`;
719
+ params.push(limit);
720
+ const results = await (0, pg_client_1.query)(db, sql, params);
721
+ return results;
722
+ }
723
+ catch (error) {
724
+ console.error("Error getting relationship scores for on-demand job:", error);
725
+ throw error;
726
+ }
727
+ }
728
+ //# sourceMappingURL=on-demand-mapping-operations.js.map