eggi-ai-db-schema-2 12.54.2
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.
- package/CHANGELOG.md +750 -0
- package/README.md +655 -0
- package/dist/config/database.d.ts +28 -0
- package/dist/config/database.d.ts.map +1 -0
- package/dist/config/database.js +72 -0
- package/dist/config/database.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/database-service.d.ts +689 -0
- package/dist/lib/database-service.d.ts.map +1 -0
- package/dist/lib/database-service.js +1362 -0
- package/dist/lib/database-service.js.map +1 -0
- package/dist/lib/db-types.d.ts +167 -0
- package/dist/lib/db-types.d.ts.map +1 -0
- package/dist/lib/db-types.js +28 -0
- package/dist/lib/db-types.js.map +1 -0
- package/dist/lib/db.d.ts +58 -0
- package/dist/lib/db.d.ts.map +1 -0
- package/dist/lib/db.js +292 -0
- package/dist/lib/db.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +26 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/pg-client.d.ts +50 -0
- package/dist/lib/pg-client.d.ts.map +1 -0
- package/dist/lib/pg-client.js +106 -0
- package/dist/lib/pg-client.js.map +1 -0
- package/dist/lib/schema.d.ts +298 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +12 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/migration-manager.d.ts +49 -0
- package/dist/migration-manager.d.ts.map +1 -0
- package/dist/migration-manager.js +282 -0
- package/dist/migration-manager.js.map +1 -0
- package/dist/queries/minimal-connections.d.ts +31 -0
- package/dist/queries/minimal-connections.d.ts.map +1 -0
- package/dist/queries/minimal-connections.js +143 -0
- package/dist/queries/minimal-connections.js.map +1 -0
- package/dist/schema.ts +340 -0
- package/dist/seed.d.ts +8 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +40 -0
- package/dist/seed.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/types.d.ts +77 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +3 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/authenticated-user-operations.d.ts +110 -0
- package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
- package/dist/utils/authenticated-user-operations.js +292 -0
- package/dist/utils/authenticated-user-operations.js.map +1 -0
- package/dist/utils/authentication-operations.d.ts +48 -0
- package/dist/utils/authentication-operations.d.ts.map +1 -0
- package/dist/utils/authentication-operations.js +172 -0
- package/dist/utils/authentication-operations.js.map +1 -0
- package/dist/utils/company-mapping-job-operations.d.ts +103 -0
- package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/company-mapping-job-operations.js +413 -0
- package/dist/utils/company-mapping-job-operations.js.map +1 -0
- package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
- package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
- package/dist/utils/company-sheet-upload-operations.js +135 -0
- package/dist/utils/company-sheet-upload-operations.js.map +1 -0
- package/dist/utils/contact-operations.d.ts +70 -0
- package/dist/utils/contact-operations.d.ts.map +1 -0
- package/dist/utils/contact-operations.js +294 -0
- package/dist/utils/contact-operations.js.map +1 -0
- package/dist/utils/forager-linkedin-operations.d.ts +74 -0
- package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/forager-linkedin-operations.js +778 -0
- package/dist/utils/forager-linkedin-operations.js.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
- package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
- package/dist/utils/index.d.ts +29 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +77 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/introduction-request-operations.d.ts +159 -0
- package/dist/utils/introduction-request-operations.d.ts.map +1 -0
- package/dist/utils/introduction-request-operations.js +481 -0
- package/dist/utils/introduction-request-operations.js.map +1 -0
- package/dist/utils/invitation-operations.d.ts +141 -0
- package/dist/utils/invitation-operations.d.ts.map +1 -0
- package/dist/utils/invitation-operations.js +749 -0
- package/dist/utils/invitation-operations.js.map +1 -0
- package/dist/utils/linkedin-account-operations.d.ts +45 -0
- package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-operations.js +279 -0
- package/dist/utils/linkedin-account-operations.js.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.js +274 -0
- package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
- package/dist/utils/linkedin-data-operations.d.ts +102 -0
- package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-data-operations.js +613 -0
- package/dist/utils/linkedin-data-operations.js.map +1 -0
- package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
- package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
- package/dist/utils/linkedin-identifier-utils.js +63 -0
- package/dist/utils/linkedin-identifier-utils.js.map +1 -0
- package/dist/utils/linkedin-profile-cache.d.ts +131 -0
- package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
- package/dist/utils/linkedin-profile-cache.js +418 -0
- package/dist/utils/linkedin-profile-cache.js.map +1 -0
- package/dist/utils/llm-inference-job-operations.d.ts +116 -0
- package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
- package/dist/utils/llm-inference-job-operations.js +266 -0
- package/dist/utils/llm-inference-job-operations.js.map +1 -0
- package/dist/utils/mapping-job-operations.d.ts +272 -0
- package/dist/utils/mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/mapping-job-operations.js +833 -0
- package/dist/utils/mapping-job-operations.js.map +1 -0
- package/dist/utils/mapping-operations.d.ts +80 -0
- package/dist/utils/mapping-operations.d.ts.map +1 -0
- package/dist/utils/mapping-operations.js +318 -0
- package/dist/utils/mapping-operations.js.map +1 -0
- package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
- package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
- package/dist/utils/on-demand-mapping-operations.js +728 -0
- package/dist/utils/on-demand-mapping-operations.js.map +1 -0
- package/dist/utils/onboarding-operations.d.ts +53 -0
- package/dist/utils/onboarding-operations.d.ts.map +1 -0
- package/dist/utils/onboarding-operations.js +223 -0
- package/dist/utils/onboarding-operations.js.map +1 -0
- package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
- package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-job-operations.js +881 -0
- package/dist/utils/organization-assignment-job-operations.js.map +1 -0
- package/dist/utils/organization-assignment-operations.d.ts +59 -0
- package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-operations.js +130 -0
- package/dist/utils/organization-assignment-operations.js.map +1 -0
- package/dist/utils/organization-operations.d.ts +275 -0
- package/dist/utils/organization-operations.d.ts.map +1 -0
- package/dist/utils/organization-operations.js +993 -0
- package/dist/utils/organization-operations.js.map +1 -0
- package/dist/utils/organization-relationship-operations.d.ts +59 -0
- package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
- package/dist/utils/organization-relationship-operations.js +240 -0
- package/dist/utils/organization-relationship-operations.js.map +1 -0
- package/dist/utils/quota-operations.d.ts +107 -0
- package/dist/utils/quota-operations.d.ts.map +1 -0
- package/dist/utils/quota-operations.js +692 -0
- package/dist/utils/quota-operations.js.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.js +169 -0
- package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
- package/dist/utils/relationship-operations.d.ts +130 -0
- package/dist/utils/relationship-operations.d.ts.map +1 -0
- package/dist/utils/relationship-operations.js +329 -0
- package/dist/utils/relationship-operations.js.map +1 -0
- package/dist/utils/sales-pipeline-operations.d.ts +143 -0
- package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
- package/dist/utils/sales-pipeline-operations.js +649 -0
- package/dist/utils/sales-pipeline-operations.js.map +1 -0
- package/dist/utils/skills-operations.d.ts +117 -0
- package/dist/utils/skills-operations.d.ts.map +1 -0
- package/dist/utils/skills-operations.js +487 -0
- package/dist/utils/skills-operations.js.map +1 -0
- package/dist/utils/subscription-operations.d.ts +123 -0
- package/dist/utils/subscription-operations.d.ts.map +1 -0
- package/dist/utils/subscription-operations.js +391 -0
- package/dist/utils/subscription-operations.js.map +1 -0
- package/dist/utils/unipile-account-operations.d.ts +96 -0
- package/dist/utils/unipile-account-operations.d.ts.map +1 -0
- package/dist/utils/unipile-account-operations.js +255 -0
- package/dist/utils/unipile-account-operations.js.map +1 -0
- package/dist/utils/user-industry-operations.d.ts +80 -0
- package/dist/utils/user-industry-operations.d.ts.map +1 -0
- package/dist/utils/user-industry-operations.js +237 -0
- package/dist/utils/user-industry-operations.js.map +1 -0
- package/dist/utils/user-operations.d.ts +87 -0
- package/dist/utils/user-operations.d.ts.map +1 -0
- package/dist/utils/user-operations.js +212 -0
- package/dist/utils/user-operations.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Forager-based LinkedIn Account Operations
|
|
4
|
+
*
|
|
5
|
+
* Migrated to native PostgreSQL queries for better performance and flexibility.
|
|
6
|
+
* All functions maintain the same interface for backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.findLinkedInAccountByForagerId = findLinkedInAccountByForagerId;
|
|
10
|
+
exports.findLinkedInAccountByPublicIdentifier = findLinkedInAccountByPublicIdentifier;
|
|
11
|
+
exports.findLinkedInAccountByAnyIdentifier = findLinkedInAccountByAnyIdentifier;
|
|
12
|
+
exports.findOrCreateLinkedInAccountByForagerId = findOrCreateLinkedInAccountByForagerId;
|
|
13
|
+
exports.findLinkedInAccountWithUserByForagerId = findLinkedInAccountWithUserByForagerId;
|
|
14
|
+
exports.updateLinkedInAccountProfileByForagerId = updateLinkedInAccountProfileByForagerId;
|
|
15
|
+
exports.updateLinkedInAccountAcoaIdentifierByForagerId = updateLinkedInAccountAcoaIdentifierByForagerId;
|
|
16
|
+
exports.updateLinkedInAccountAcoaIdentifierByForagerIdWithChangeDetection = updateLinkedInAccountAcoaIdentifierByForagerIdWithChangeDetection;
|
|
17
|
+
const pg_client_1 = require("../lib/pg-client");
|
|
18
|
+
const db_1 = require("../lib/db");
|
|
19
|
+
/**
|
|
20
|
+
* Maps database row (snake_case) to User interface (camelCase)
|
|
21
|
+
*/
|
|
22
|
+
function mapToUser(row) {
|
|
23
|
+
return {
|
|
24
|
+
id: row.id,
|
|
25
|
+
givenName: row.given_name,
|
|
26
|
+
familyName: row.family_name,
|
|
27
|
+
summary: row.summary,
|
|
28
|
+
embeddingSummary: row.embedding_summary,
|
|
29
|
+
embedding: row.embedding,
|
|
30
|
+
createdAt: row.created_at,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Simple logger for this module
|
|
34
|
+
const logger = {
|
|
35
|
+
info: (message, data) => console.log(`[INFO] ${message}`, data ? JSON.stringify(data, null, 2) : ""),
|
|
36
|
+
error: (message, data) => console.error(`[ERROR] ${message}`, data ? JSON.stringify(data, null, 2) : ""),
|
|
37
|
+
};
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// HELPER FUNCTIONS
|
|
40
|
+
// =============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Convert database row to LinkedInAccountResult with computed profilePictureUrl
|
|
43
|
+
*/
|
|
44
|
+
function mapToLinkedInAccountResult(row) {
|
|
45
|
+
return {
|
|
46
|
+
id: row.id,
|
|
47
|
+
user_id: row.user_id,
|
|
48
|
+
forager_id: row.forager_id,
|
|
49
|
+
public_identifier: row.public_identifier,
|
|
50
|
+
linkedin_identifier_acoa: row.linkedin_identifier_acoa,
|
|
51
|
+
first_name: row.first_name,
|
|
52
|
+
last_name: row.last_name,
|
|
53
|
+
headline: row.headline,
|
|
54
|
+
summary: row.summary,
|
|
55
|
+
location: row.location,
|
|
56
|
+
profile_picture_url: row.profile_picture_url, // Already computed via COALESCE in SQL
|
|
57
|
+
profile_image_cloudfront_url: null, // Always hidden
|
|
58
|
+
profile_image_hash: row.profile_image_hash || null,
|
|
59
|
+
follower_count: row.follower_count,
|
|
60
|
+
connections_count: row.connections_count,
|
|
61
|
+
profiles_updated_at: row.profiles_updated_at,
|
|
62
|
+
created_at: row.created_at,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// FORAGER-BASED LINKEDIN ACCOUNT OPERATIONS
|
|
67
|
+
// =============================================================================
|
|
68
|
+
/**
|
|
69
|
+
* Find LinkedIn account by Forager ID (primary matching method)
|
|
70
|
+
*/
|
|
71
|
+
async function findLinkedInAccountByForagerId(db, foragerId) {
|
|
72
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.accounts", { foragerId }, undefined, {
|
|
73
|
+
operation: "findLinkedInAccountByForagerId",
|
|
74
|
+
foragerId,
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
const sql = `
|
|
78
|
+
SELECT
|
|
79
|
+
id,
|
|
80
|
+
user_id,
|
|
81
|
+
forager_id,
|
|
82
|
+
public_identifier,
|
|
83
|
+
linkedin_identifier_acoa,
|
|
84
|
+
first_name,
|
|
85
|
+
last_name,
|
|
86
|
+
headline,
|
|
87
|
+
summary,
|
|
88
|
+
location,
|
|
89
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) AS profile_picture_url,
|
|
90
|
+
follower_count,
|
|
91
|
+
connections_count,
|
|
92
|
+
profiles_updated_at,
|
|
93
|
+
created_at
|
|
94
|
+
FROM linkedin.accounts
|
|
95
|
+
WHERE forager_id = $1
|
|
96
|
+
LIMIT 1
|
|
97
|
+
`;
|
|
98
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [foragerId]);
|
|
99
|
+
return result ? mapToLinkedInAccountResult(result) : null;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
console.error("Error finding LinkedIn account by Forager ID:", error);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Find LinkedIn account by public identifier (fallback method)
|
|
108
|
+
*/
|
|
109
|
+
async function findLinkedInAccountByPublicIdentifier(db, publicIdentifier) {
|
|
110
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.accounts", { publicIdentifier }, undefined, {
|
|
111
|
+
operation: "findLinkedInAccountByPublicIdentifier",
|
|
112
|
+
publicIdentifier,
|
|
113
|
+
});
|
|
114
|
+
try {
|
|
115
|
+
const sql = `
|
|
116
|
+
SELECT
|
|
117
|
+
id,
|
|
118
|
+
user_id,
|
|
119
|
+
forager_id,
|
|
120
|
+
public_identifier,
|
|
121
|
+
linkedin_identifier_acoa,
|
|
122
|
+
first_name,
|
|
123
|
+
last_name,
|
|
124
|
+
headline,
|
|
125
|
+
summary,
|
|
126
|
+
location,
|
|
127
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) AS profile_picture_url,
|
|
128
|
+
follower_count,
|
|
129
|
+
connections_count,
|
|
130
|
+
profiles_updated_at,
|
|
131
|
+
created_at
|
|
132
|
+
FROM linkedin.accounts
|
|
133
|
+
WHERE public_identifier = $1
|
|
134
|
+
LIMIT 1
|
|
135
|
+
`;
|
|
136
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [publicIdentifier]);
|
|
137
|
+
return result ? mapToLinkedInAccountResult(result) : null;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error("Error finding LinkedIn account by public identifier:", error);
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Find LinkedIn account by any identifier (Forager ID, public identifier, or ACoA)
|
|
146
|
+
* Priority: forager_id > public_identifier > linkedin_identifier_acoa
|
|
147
|
+
*/
|
|
148
|
+
async function findLinkedInAccountByAnyIdentifier(db, identifier) {
|
|
149
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.accounts", { identifier }, undefined, {
|
|
150
|
+
operation: "findLinkedInAccountByAnyIdentifier",
|
|
151
|
+
identifier,
|
|
152
|
+
});
|
|
153
|
+
try {
|
|
154
|
+
// Try Forager ID first if it's a number
|
|
155
|
+
if (typeof identifier === "number") {
|
|
156
|
+
const foragerResult = await findLinkedInAccountByForagerId(db, identifier);
|
|
157
|
+
if (foragerResult)
|
|
158
|
+
return foragerResult;
|
|
159
|
+
}
|
|
160
|
+
// Try public identifier
|
|
161
|
+
if (typeof identifier === "string") {
|
|
162
|
+
const publicResult = await findLinkedInAccountByPublicIdentifier(db, identifier);
|
|
163
|
+
if (publicResult)
|
|
164
|
+
return publicResult;
|
|
165
|
+
}
|
|
166
|
+
// Try ACoA identifier as last resort
|
|
167
|
+
if (typeof identifier === "string" && identifier.startsWith("ACoA")) {
|
|
168
|
+
const sql = `
|
|
169
|
+
SELECT
|
|
170
|
+
id,
|
|
171
|
+
user_id,
|
|
172
|
+
forager_id,
|
|
173
|
+
public_identifier,
|
|
174
|
+
linkedin_identifier_acoa,
|
|
175
|
+
first_name,
|
|
176
|
+
last_name,
|
|
177
|
+
headline,
|
|
178
|
+
summary,
|
|
179
|
+
location,
|
|
180
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) AS profile_picture_url,
|
|
181
|
+
follower_count,
|
|
182
|
+
connections_count,
|
|
183
|
+
profiles_updated_at,
|
|
184
|
+
created_at
|
|
185
|
+
FROM linkedin.accounts
|
|
186
|
+
WHERE linkedin_identifier_acoa = $1
|
|
187
|
+
LIMIT 1
|
|
188
|
+
`;
|
|
189
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [identifier]);
|
|
190
|
+
return result ? mapToLinkedInAccountResult(result) : null;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
console.error("Error finding LinkedIn account by any identifier:", error);
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Find or create LinkedIn account by Forager ID
|
|
201
|
+
*/
|
|
202
|
+
async function findOrCreateLinkedInAccountByForagerId(db, foragerId, publicIdentifier, linkedinIdentifierAcoa, userId) {
|
|
203
|
+
(0, db_1.debugLogDbOperation)("upsert", "linkedin.accounts", {
|
|
204
|
+
foragerId,
|
|
205
|
+
publicIdentifier,
|
|
206
|
+
linkedinIdentifierAcoa,
|
|
207
|
+
userId,
|
|
208
|
+
}, undefined, {
|
|
209
|
+
operation: "findOrCreateLinkedInAccountByForagerId",
|
|
210
|
+
foragerId,
|
|
211
|
+
});
|
|
212
|
+
try {
|
|
213
|
+
// First, check if a record already exists with the same foragerId
|
|
214
|
+
const existingByForagerIdSql = `
|
|
215
|
+
SELECT id, forager_id
|
|
216
|
+
FROM linkedin.accounts
|
|
217
|
+
WHERE forager_id = $1
|
|
218
|
+
LIMIT 1
|
|
219
|
+
`;
|
|
220
|
+
const existingByForagerId = await (0, pg_client_1.queryOne)(db, existingByForagerIdSql, [foragerId]);
|
|
221
|
+
if (existingByForagerId) {
|
|
222
|
+
// Record already exists - update it
|
|
223
|
+
// First, check current values to determine if update will change data
|
|
224
|
+
const currentValuesSql = `
|
|
225
|
+
SELECT
|
|
226
|
+
public_identifier,
|
|
227
|
+
linkedin_identifier_acoa,
|
|
228
|
+
user_id
|
|
229
|
+
FROM linkedin.accounts
|
|
230
|
+
WHERE id = $1
|
|
231
|
+
`;
|
|
232
|
+
const currentValues = await (0, pg_client_1.queryOne)(db, currentValuesSql, [existingByForagerId.id]);
|
|
233
|
+
if (!currentValues) {
|
|
234
|
+
throw new Error(`LinkedIn account not found for id: ${existingByForagerId.id}`);
|
|
235
|
+
}
|
|
236
|
+
// Determine if update will actually change data
|
|
237
|
+
const willUpdatePublicIdentifier = publicIdentifier !== null &&
|
|
238
|
+
publicIdentifier !== undefined &&
|
|
239
|
+
currentValues.public_identifier !== publicIdentifier;
|
|
240
|
+
const willUpdateAcoa = linkedinIdentifierAcoa !== null &&
|
|
241
|
+
linkedinIdentifierAcoa !== undefined &&
|
|
242
|
+
currentValues.linkedin_identifier_acoa !== linkedinIdentifierAcoa;
|
|
243
|
+
const willUpdateUserId = userId !== undefined && userId !== null && currentValues.user_id !== userId;
|
|
244
|
+
const willUpdate = willUpdatePublicIdentifier || willUpdateAcoa || willUpdateUserId;
|
|
245
|
+
// Log the decision-making process for tracking
|
|
246
|
+
logger.info("LinkedIn account update decision", {
|
|
247
|
+
foragerId,
|
|
248
|
+
accountId: existingByForagerId.id,
|
|
249
|
+
willUpdate,
|
|
250
|
+
willUpdatePublicIdentifier,
|
|
251
|
+
willUpdateAcoa,
|
|
252
|
+
willUpdateUserId,
|
|
253
|
+
currentPublicIdentifier: currentValues.public_identifier,
|
|
254
|
+
newPublicIdentifier: publicIdentifier,
|
|
255
|
+
currentAcoa: currentValues.linkedin_identifier_acoa,
|
|
256
|
+
newAcoa: linkedinIdentifierAcoa,
|
|
257
|
+
currentUserId: currentValues.user_id,
|
|
258
|
+
newUserId: userId,
|
|
259
|
+
});
|
|
260
|
+
// Perform update if there are changes
|
|
261
|
+
if (willUpdate) {
|
|
262
|
+
const updateSql = `
|
|
263
|
+
UPDATE linkedin.accounts
|
|
264
|
+
SET
|
|
265
|
+
public_identifier = COALESCE($2, public_identifier),
|
|
266
|
+
linkedin_identifier_acoa = COALESCE($3, linkedin_identifier_acoa)
|
|
267
|
+
${userId !== undefined ? ", user_id = $4" : ""}
|
|
268
|
+
WHERE id = $1
|
|
269
|
+
RETURNING id
|
|
270
|
+
`;
|
|
271
|
+
const updateParams = userId !== undefined
|
|
272
|
+
? [existingByForagerId.id, publicIdentifier, linkedinIdentifierAcoa, userId]
|
|
273
|
+
: [existingByForagerId.id, publicIdentifier, linkedinIdentifierAcoa];
|
|
274
|
+
await (0, pg_client_1.queryOne)(db, updateSql, updateParams);
|
|
275
|
+
logger.info("LinkedIn account updated successfully", {
|
|
276
|
+
foragerId,
|
|
277
|
+
accountId: existingByForagerId.id,
|
|
278
|
+
wasUpdated: true,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
logger.info("LinkedIn account exists but no changes needed", {
|
|
283
|
+
foragerId,
|
|
284
|
+
accountId: existingByForagerId.id,
|
|
285
|
+
wasUpdated: false,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
id: existingByForagerId.id,
|
|
290
|
+
wasNewlyCreated: false,
|
|
291
|
+
wasUpdated: willUpdate,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
// Check if a record exists with the same ACoA identifier (different foragerId)
|
|
295
|
+
if (linkedinIdentifierAcoa) {
|
|
296
|
+
const existingByAcoaSql = `
|
|
297
|
+
SELECT id, forager_id
|
|
298
|
+
FROM linkedin.accounts
|
|
299
|
+
WHERE linkedin_identifier_acoa = $1
|
|
300
|
+
LIMIT 1
|
|
301
|
+
`;
|
|
302
|
+
const existingByAcoa = await (0, pg_client_1.queryOne)(db, existingByAcoaSql, [linkedinIdentifierAcoa]);
|
|
303
|
+
if (existingByAcoa) {
|
|
304
|
+
// Update existing record with new foragerId
|
|
305
|
+
// First, check current values to determine if update will change data
|
|
306
|
+
const currentValuesSql = `
|
|
307
|
+
SELECT
|
|
308
|
+
forager_id,
|
|
309
|
+
public_identifier,
|
|
310
|
+
user_id
|
|
311
|
+
FROM linkedin.accounts
|
|
312
|
+
WHERE id = $1
|
|
313
|
+
`;
|
|
314
|
+
const currentValues = await (0, pg_client_1.queryOne)(db, currentValuesSql, [existingByAcoa.id]);
|
|
315
|
+
if (!currentValues) {
|
|
316
|
+
throw new Error(`LinkedIn account not found for id: ${existingByAcoa.id}`);
|
|
317
|
+
}
|
|
318
|
+
// Determine if update will actually change data
|
|
319
|
+
const willUpdateForagerId = currentValues.forager_id !== foragerId;
|
|
320
|
+
const willUpdatePublicIdentifier = publicIdentifier !== null &&
|
|
321
|
+
publicIdentifier !== undefined &&
|
|
322
|
+
currentValues.public_identifier !== publicIdentifier;
|
|
323
|
+
const willUpdateUserId = userId !== undefined && userId !== null && currentValues.user_id !== userId;
|
|
324
|
+
const willUpdate = willUpdateForagerId || willUpdatePublicIdentifier || willUpdateUserId;
|
|
325
|
+
// Log the decision-making process for tracking (ACoA match)
|
|
326
|
+
logger.info("LinkedIn account update decision (ACoA match)", {
|
|
327
|
+
foragerId,
|
|
328
|
+
accountId: existingByAcoa.id,
|
|
329
|
+
willUpdate,
|
|
330
|
+
willUpdateForagerId,
|
|
331
|
+
willUpdatePublicIdentifier,
|
|
332
|
+
willUpdateUserId,
|
|
333
|
+
currentForagerId: currentValues.forager_id,
|
|
334
|
+
newForagerId: foragerId,
|
|
335
|
+
currentPublicIdentifier: currentValues.public_identifier,
|
|
336
|
+
newPublicIdentifier: publicIdentifier,
|
|
337
|
+
currentUserId: currentValues.user_id,
|
|
338
|
+
newUserId: userId,
|
|
339
|
+
});
|
|
340
|
+
// Perform update if there are changes
|
|
341
|
+
if (willUpdate) {
|
|
342
|
+
const updateSql = `
|
|
343
|
+
UPDATE linkedin.accounts
|
|
344
|
+
SET
|
|
345
|
+
forager_id = $2,
|
|
346
|
+
public_identifier = COALESCE($3, public_identifier)
|
|
347
|
+
${userId !== undefined ? ", user_id = $4" : ""}
|
|
348
|
+
WHERE id = $1
|
|
349
|
+
RETURNING id
|
|
350
|
+
`;
|
|
351
|
+
const updateParams = userId !== undefined
|
|
352
|
+
? [existingByAcoa.id, foragerId, publicIdentifier, userId]
|
|
353
|
+
: [existingByAcoa.id, foragerId, publicIdentifier];
|
|
354
|
+
await (0, pg_client_1.queryOne)(db, updateSql, updateParams);
|
|
355
|
+
logger.info("LinkedIn account updated successfully (ACoA match)", {
|
|
356
|
+
foragerId,
|
|
357
|
+
accountId: existingByAcoa.id,
|
|
358
|
+
wasUpdated: true,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
logger.info("LinkedIn account exists but no changes needed (ACoA match)", {
|
|
363
|
+
foragerId,
|
|
364
|
+
accountId: existingByAcoa.id,
|
|
365
|
+
wasUpdated: false,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
id: existingByAcoa.id,
|
|
370
|
+
wasNewlyCreated: false,
|
|
371
|
+
wasUpdated: willUpdate,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// No existing record found - create new one
|
|
376
|
+
const insertSql = `
|
|
377
|
+
INSERT INTO linkedin.accounts (
|
|
378
|
+
forager_id,
|
|
379
|
+
public_identifier,
|
|
380
|
+
linkedin_identifier_acoa,
|
|
381
|
+
user_id,
|
|
382
|
+
created_at
|
|
383
|
+
) VALUES ($1, $2, $3, $4, NOW())
|
|
384
|
+
RETURNING id
|
|
385
|
+
`;
|
|
386
|
+
const result = await (0, pg_client_1.queryOne)(db, insertSql, [
|
|
387
|
+
foragerId,
|
|
388
|
+
publicIdentifier || null,
|
|
389
|
+
linkedinIdentifierAcoa || null,
|
|
390
|
+
userId || null,
|
|
391
|
+
]);
|
|
392
|
+
if (!result) {
|
|
393
|
+
throw new Error("Failed to create LinkedIn account");
|
|
394
|
+
}
|
|
395
|
+
logger.info("LinkedIn account created successfully", {
|
|
396
|
+
foragerId,
|
|
397
|
+
accountId: result.id,
|
|
398
|
+
publicIdentifier,
|
|
399
|
+
linkedinIdentifierAcoa,
|
|
400
|
+
userId,
|
|
401
|
+
wasNewlyCreated: true,
|
|
402
|
+
wasUpdated: false,
|
|
403
|
+
});
|
|
404
|
+
return {
|
|
405
|
+
id: result.id,
|
|
406
|
+
wasNewlyCreated: true,
|
|
407
|
+
wasUpdated: false, // New record, not an update
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
// If it's a duplicate key constraint violation on linkedin_identifier_acoa,
|
|
412
|
+
// try to find the existing record instead of failing
|
|
413
|
+
if (error instanceof Error &&
|
|
414
|
+
error.message.includes('duplicate key value violates unique constraint "accounts_linkedin_identifier_acoa_unique"')) {
|
|
415
|
+
logger.info("Found existing LinkedIn account with same ACoA identifier, updating it", {
|
|
416
|
+
foragerId,
|
|
417
|
+
linkedinIdentifierAcoa,
|
|
418
|
+
publicIdentifier,
|
|
419
|
+
userId,
|
|
420
|
+
});
|
|
421
|
+
// Find the existing record by ACoA identifier
|
|
422
|
+
const existingByAcoaSql = `
|
|
423
|
+
SELECT id, forager_id
|
|
424
|
+
FROM linkedin.accounts
|
|
425
|
+
WHERE linkedin_identifier_acoa = $1
|
|
426
|
+
LIMIT 1
|
|
427
|
+
`;
|
|
428
|
+
const existingByAcoa = await (0, pg_client_1.queryOne)(db, existingByAcoaSql, [linkedinIdentifierAcoa]);
|
|
429
|
+
if (existingByAcoa) {
|
|
430
|
+
// Update the existing record with new foragerId and userId if provided
|
|
431
|
+
// First, check current values to determine if update will change data
|
|
432
|
+
const currentValuesSql = `
|
|
433
|
+
SELECT
|
|
434
|
+
forager_id,
|
|
435
|
+
public_identifier,
|
|
436
|
+
user_id
|
|
437
|
+
FROM linkedin.accounts
|
|
438
|
+
WHERE id = $1
|
|
439
|
+
`;
|
|
440
|
+
const currentValues = await (0, pg_client_1.queryOne)(db, currentValuesSql, [existingByAcoa.id]);
|
|
441
|
+
if (!currentValues) {
|
|
442
|
+
throw new Error(`LinkedIn account not found for id: ${existingByAcoa.id}`);
|
|
443
|
+
}
|
|
444
|
+
// Determine if update will actually change data
|
|
445
|
+
const willUpdateForagerId = currentValues.forager_id !== foragerId;
|
|
446
|
+
const willUpdatePublicIdentifier = publicIdentifier !== null &&
|
|
447
|
+
publicIdentifier !== undefined &&
|
|
448
|
+
currentValues.public_identifier !== publicIdentifier;
|
|
449
|
+
const willUpdateUserId = userId !== undefined && userId !== null && currentValues.user_id !== userId;
|
|
450
|
+
const willUpdate = willUpdateForagerId || willUpdatePublicIdentifier || willUpdateUserId;
|
|
451
|
+
// Log the decision-making process for tracking (duplicate key recovery)
|
|
452
|
+
logger.info("LinkedIn account update decision (duplicate key recovery)", {
|
|
453
|
+
foragerId,
|
|
454
|
+
accountId: existingByAcoa.id,
|
|
455
|
+
willUpdate,
|
|
456
|
+
willUpdateForagerId,
|
|
457
|
+
willUpdatePublicIdentifier,
|
|
458
|
+
willUpdateUserId,
|
|
459
|
+
currentForagerId: currentValues.forager_id,
|
|
460
|
+
newForagerId: foragerId,
|
|
461
|
+
currentPublicIdentifier: currentValues.public_identifier,
|
|
462
|
+
newPublicIdentifier: publicIdentifier,
|
|
463
|
+
currentUserId: currentValues.user_id,
|
|
464
|
+
newUserId: userId,
|
|
465
|
+
});
|
|
466
|
+
// Perform update if there are changes
|
|
467
|
+
if (willUpdate) {
|
|
468
|
+
const updateSql = `
|
|
469
|
+
UPDATE linkedin.accounts
|
|
470
|
+
SET
|
|
471
|
+
forager_id = $2,
|
|
472
|
+
public_identifier = COALESCE($3, public_identifier)
|
|
473
|
+
${userId !== undefined ? ", user_id = $4" : ""}
|
|
474
|
+
WHERE id = $1
|
|
475
|
+
RETURNING id
|
|
476
|
+
`;
|
|
477
|
+
const updateParams = userId !== undefined
|
|
478
|
+
? [existingByAcoa.id, foragerId, publicIdentifier, userId]
|
|
479
|
+
: [existingByAcoa.id, foragerId, publicIdentifier];
|
|
480
|
+
await (0, pg_client_1.queryOne)(db, updateSql, updateParams);
|
|
481
|
+
logger.info("LinkedIn account updated successfully (duplicate key recovery)", {
|
|
482
|
+
foragerId,
|
|
483
|
+
accountId: existingByAcoa.id,
|
|
484
|
+
wasUpdated: true,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
logger.info("LinkedIn account exists but no changes needed (duplicate key recovery)", {
|
|
489
|
+
foragerId,
|
|
490
|
+
accountId: existingByAcoa.id,
|
|
491
|
+
wasUpdated: false,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
id: existingByAcoa.id,
|
|
496
|
+
wasNewlyCreated: false,
|
|
497
|
+
wasUpdated: willUpdate,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
// If existingByAcoa is null, fall through to error handling
|
|
501
|
+
}
|
|
502
|
+
console.error("Error in findOrCreateLinkedInAccountByForagerId:", error);
|
|
503
|
+
throw error;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Find LinkedIn account with associated user by Forager ID
|
|
508
|
+
*/
|
|
509
|
+
async function findLinkedInAccountWithUserByForagerId(db, foragerId) {
|
|
510
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.accounts + users", { foragerId }, undefined, {
|
|
511
|
+
operation: "findLinkedInAccountWithUserByForagerId",
|
|
512
|
+
foragerId,
|
|
513
|
+
});
|
|
514
|
+
try {
|
|
515
|
+
const sql = `
|
|
516
|
+
SELECT
|
|
517
|
+
la.id,
|
|
518
|
+
la.user_id,
|
|
519
|
+
la.forager_id,
|
|
520
|
+
la.public_identifier,
|
|
521
|
+
la.linkedin_identifier_acoa,
|
|
522
|
+
la.first_name,
|
|
523
|
+
la.last_name,
|
|
524
|
+
la.headline,
|
|
525
|
+
la.summary,
|
|
526
|
+
la.location,
|
|
527
|
+
COALESCE(la.profile_image_cloudfront_url, la.profile_picture_url) AS profile_picture_url,
|
|
528
|
+
la.follower_count,
|
|
529
|
+
la.connections_count,
|
|
530
|
+
la.profiles_updated_at,
|
|
531
|
+
la.created_at,
|
|
532
|
+
u.id AS user_id_joined,
|
|
533
|
+
u.given_name AS user_given_name,
|
|
534
|
+
u.family_name AS user_family_name,
|
|
535
|
+
u.created_at AS user_created_at
|
|
536
|
+
FROM linkedin.accounts la
|
|
537
|
+
LEFT JOIN public.users u ON la.user_id = u.id
|
|
538
|
+
WHERE la.forager_id = $1
|
|
539
|
+
LIMIT 1
|
|
540
|
+
`;
|
|
541
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [foragerId]);
|
|
542
|
+
if (!result) {
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
account: mapToLinkedInAccountResult(result),
|
|
547
|
+
user: result.user_id_joined
|
|
548
|
+
? mapToUser({
|
|
549
|
+
id: result.user_id_joined,
|
|
550
|
+
given_name: result.user_given_name,
|
|
551
|
+
family_name: result.user_family_name,
|
|
552
|
+
summary: null,
|
|
553
|
+
embedding_summary: null,
|
|
554
|
+
embedding: null,
|
|
555
|
+
created_at: result.user_created_at,
|
|
556
|
+
})
|
|
557
|
+
: null,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
console.error("Error finding LinkedIn account with user by Forager ID:", error);
|
|
562
|
+
throw error;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Update LinkedIn account profile data by Forager ID
|
|
567
|
+
*/
|
|
568
|
+
async function updateLinkedInAccountProfileByForagerId(db, foragerId, profileData) {
|
|
569
|
+
(0, db_1.debugLogDbOperation)("update", "linkedin.accounts", { foragerId, ...profileData }, undefined, {
|
|
570
|
+
operation: "updateLinkedInAccountProfileByForagerId",
|
|
571
|
+
foragerId,
|
|
572
|
+
});
|
|
573
|
+
try {
|
|
574
|
+
// Build dynamic SET clause
|
|
575
|
+
const updates = [];
|
|
576
|
+
const params = [foragerId];
|
|
577
|
+
let paramIndex = 2;
|
|
578
|
+
if (profileData.firstName !== undefined) {
|
|
579
|
+
updates.push(`first_name = $${paramIndex++}`);
|
|
580
|
+
params.push(profileData.firstName);
|
|
581
|
+
}
|
|
582
|
+
if (profileData.lastName !== undefined) {
|
|
583
|
+
updates.push(`last_name = $${paramIndex++}`);
|
|
584
|
+
params.push(profileData.lastName);
|
|
585
|
+
}
|
|
586
|
+
if (profileData.headline !== undefined) {
|
|
587
|
+
updates.push(`headline = $${paramIndex++}`);
|
|
588
|
+
params.push(profileData.headline);
|
|
589
|
+
}
|
|
590
|
+
if (profileData.summary !== undefined) {
|
|
591
|
+
updates.push(`summary = $${paramIndex++}`);
|
|
592
|
+
params.push(profileData.summary);
|
|
593
|
+
}
|
|
594
|
+
if (profileData.location !== undefined) {
|
|
595
|
+
updates.push(`location = $${paramIndex++}`);
|
|
596
|
+
params.push(profileData.location);
|
|
597
|
+
}
|
|
598
|
+
if (profileData.profilePictureUrl !== undefined) {
|
|
599
|
+
updates.push(`profile_picture_url = $${paramIndex++}`);
|
|
600
|
+
params.push(profileData.profilePictureUrl);
|
|
601
|
+
}
|
|
602
|
+
if (profileData.followerCount !== undefined) {
|
|
603
|
+
updates.push(`follower_count = $${paramIndex++}`);
|
|
604
|
+
params.push(profileData.followerCount);
|
|
605
|
+
}
|
|
606
|
+
if (profileData.connectionsCount !== undefined) {
|
|
607
|
+
updates.push(`connections_count = $${paramIndex++}`);
|
|
608
|
+
params.push(profileData.connectionsCount);
|
|
609
|
+
}
|
|
610
|
+
// Always update profiles_updated_at
|
|
611
|
+
updates.push(`profiles_updated_at = NOW()`);
|
|
612
|
+
const sql = `
|
|
613
|
+
UPDATE linkedin.accounts
|
|
614
|
+
SET ${updates.join(", ")}
|
|
615
|
+
WHERE forager_id = $1
|
|
616
|
+
RETURNING
|
|
617
|
+
id,
|
|
618
|
+
user_id,
|
|
619
|
+
forager_id,
|
|
620
|
+
public_identifier,
|
|
621
|
+
linkedin_identifier_acoa,
|
|
622
|
+
first_name,
|
|
623
|
+
last_name,
|
|
624
|
+
headline,
|
|
625
|
+
summary,
|
|
626
|
+
location,
|
|
627
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) AS profile_picture_url,
|
|
628
|
+
follower_count,
|
|
629
|
+
connections_count,
|
|
630
|
+
profiles_updated_at,
|
|
631
|
+
created_at
|
|
632
|
+
`;
|
|
633
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, params);
|
|
634
|
+
if (!result) {
|
|
635
|
+
throw new Error(`LinkedIn account with Forager ID ${foragerId} not found`);
|
|
636
|
+
}
|
|
637
|
+
return mapToLinkedInAccountResult(result);
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
console.error("Error updating LinkedIn account profile by Forager ID:", error);
|
|
641
|
+
throw error;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Update LinkedIn account ACoA identifier by Forager ID
|
|
646
|
+
*/
|
|
647
|
+
async function updateLinkedInAccountAcoaIdentifierByForagerId(db, foragerId, linkedinIdentifierAcoa) {
|
|
648
|
+
(0, db_1.debugLogDbOperation)("update", "linkedin.accounts", { foragerId, linkedinIdentifierAcoa }, undefined, {
|
|
649
|
+
operation: "updateLinkedInAccountAcoaIdentifierByForagerId",
|
|
650
|
+
foragerId,
|
|
651
|
+
});
|
|
652
|
+
try {
|
|
653
|
+
const sql = `
|
|
654
|
+
UPDATE linkedin.accounts
|
|
655
|
+
SET
|
|
656
|
+
linkedin_identifier_acoa = $2,
|
|
657
|
+
profiles_updated_at = NOW()
|
|
658
|
+
WHERE forager_id = $1
|
|
659
|
+
RETURNING
|
|
660
|
+
id,
|
|
661
|
+
user_id,
|
|
662
|
+
forager_id,
|
|
663
|
+
public_identifier,
|
|
664
|
+
linkedin_identifier_acoa,
|
|
665
|
+
first_name,
|
|
666
|
+
last_name,
|
|
667
|
+
headline,
|
|
668
|
+
summary,
|
|
669
|
+
location,
|
|
670
|
+
profile_picture_url,
|
|
671
|
+
profile_image_cloudfront_url,
|
|
672
|
+
follower_count,
|
|
673
|
+
connections_count,
|
|
674
|
+
profiles_updated_at,
|
|
675
|
+
created_at
|
|
676
|
+
`;
|
|
677
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [foragerId, linkedinIdentifierAcoa]);
|
|
678
|
+
if (!result) {
|
|
679
|
+
throw new Error(`LinkedIn account with Forager ID ${foragerId} not found`);
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
...mapToLinkedInAccountResult(result),
|
|
683
|
+
profile_image_cloudfront_url: null,
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
catch (error) {
|
|
687
|
+
console.error("Error updating LinkedIn account ACoA identifier by Forager ID:", error);
|
|
688
|
+
throw error;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Update LinkedIn account ACoA identifier by Forager ID with change detection
|
|
693
|
+
* Returns whether the value actually changed
|
|
694
|
+
*/
|
|
695
|
+
async function updateLinkedInAccountAcoaIdentifierByForagerIdWithChangeDetection(db, foragerId, linkedinIdentifierAcoa) {
|
|
696
|
+
(0, db_1.debugLogDbOperation)("update", "linkedin.accounts", { foragerId, linkedinIdentifierAcoa }, undefined, {
|
|
697
|
+
operation: "updateLinkedInAccountAcoaIdentifierByForagerIdWithChangeDetection",
|
|
698
|
+
foragerId,
|
|
699
|
+
});
|
|
700
|
+
try {
|
|
701
|
+
// Use a single query with RETURNING to get both old and new values
|
|
702
|
+
const sql = `
|
|
703
|
+
UPDATE linkedin.accounts
|
|
704
|
+
SET
|
|
705
|
+
linkedin_identifier_acoa = $2,
|
|
706
|
+
profiles_updated_at = NOW()
|
|
707
|
+
WHERE forager_id = $1
|
|
708
|
+
RETURNING
|
|
709
|
+
id,
|
|
710
|
+
user_id,
|
|
711
|
+
forager_id,
|
|
712
|
+
public_identifier,
|
|
713
|
+
linkedin_identifier_acoa AS new_acoa,
|
|
714
|
+
(SELECT linkedin_identifier_acoa FROM linkedin.accounts WHERE forager_id = $1 FOR UPDATE) AS old_acoa,
|
|
715
|
+
first_name,
|
|
716
|
+
last_name,
|
|
717
|
+
headline,
|
|
718
|
+
summary,
|
|
719
|
+
location,
|
|
720
|
+
profile_picture_url,
|
|
721
|
+
profile_image_cloudfront_url,
|
|
722
|
+
follower_count,
|
|
723
|
+
connections_count,
|
|
724
|
+
profiles_updated_at,
|
|
725
|
+
created_at
|
|
726
|
+
`;
|
|
727
|
+
// Better approach: two queries in transaction for clarity
|
|
728
|
+
const currentSql = `SELECT linkedin_identifier_acoa FROM linkedin.accounts WHERE forager_id = $1`;
|
|
729
|
+
const currentResult = await (0, pg_client_1.queryOne)(db, currentSql, [foragerId]);
|
|
730
|
+
if (!currentResult) {
|
|
731
|
+
throw new Error(`LinkedIn account with Forager ID ${foragerId} not found`);
|
|
732
|
+
}
|
|
733
|
+
const oldValue = currentResult.linkedin_identifier_acoa;
|
|
734
|
+
const wasChanged = oldValue !== linkedinIdentifierAcoa;
|
|
735
|
+
// Update the account
|
|
736
|
+
const updateSql = `
|
|
737
|
+
UPDATE linkedin.accounts
|
|
738
|
+
SET
|
|
739
|
+
linkedin_identifier_acoa = $2,
|
|
740
|
+
profiles_updated_at = NOW()
|
|
741
|
+
WHERE forager_id = $1
|
|
742
|
+
RETURNING
|
|
743
|
+
id,
|
|
744
|
+
user_id,
|
|
745
|
+
forager_id,
|
|
746
|
+
public_identifier,
|
|
747
|
+
linkedin_identifier_acoa,
|
|
748
|
+
first_name,
|
|
749
|
+
last_name,
|
|
750
|
+
headline,
|
|
751
|
+
summary,
|
|
752
|
+
location,
|
|
753
|
+
profile_picture_url,
|
|
754
|
+
profile_image_cloudfront_url,
|
|
755
|
+
follower_count,
|
|
756
|
+
connections_count,
|
|
757
|
+
profiles_updated_at,
|
|
758
|
+
created_at
|
|
759
|
+
`;
|
|
760
|
+
const updatedAccount = await (0, pg_client_1.queryOne)(db, updateSql, [foragerId, linkedinIdentifierAcoa]);
|
|
761
|
+
if (!updatedAccount) {
|
|
762
|
+
throw new Error(`Failed to update LinkedIn account with Forager ID ${foragerId}`);
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
account: {
|
|
766
|
+
...mapToLinkedInAccountResult(updatedAccount),
|
|
767
|
+
profile_image_cloudfront_url: null,
|
|
768
|
+
},
|
|
769
|
+
wasChanged,
|
|
770
|
+
oldValue,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
catch (error) {
|
|
774
|
+
console.error("Error updating LinkedIn account ACoA identifier by Forager ID with change detection:", error);
|
|
775
|
+
throw error;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
//# sourceMappingURL=forager-linkedin-operations.js.map
|