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.
- package/CHANGELOG.md +750 -0
- package/README.md +660 -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 +714 -0
- package/dist/lib/database-service.d.ts.map +1 -0
- package/dist/lib/database-service.js +1394 -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 +160 -0
- package/dist/utils/introduction-request-operations.d.ts.map +1 -0
- package/dist/utils/introduction-request-operations.js +492 -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 +267 -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 +284 -0
- package/dist/utils/organization-operations.d.ts.map +1 -0
- package/dist/utils/organization-operations.js +1030 -0
- package/dist/utils/organization-operations.js.map +1 -0
- package/dist/utils/organization-relationship-operations.d.ts +79 -0
- package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
- package/dist/utils/organization-relationship-operations.js +294 -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 +163 -0
- package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
- package/dist/utils/sales-pipeline-operations.js +725 -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,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LinkedIn Identifier Utilities for RDS Schema Package
|
|
4
|
+
*
|
|
5
|
+
* Utilities for validating and working with LinkedIn identifiers
|
|
6
|
+
* Now uses consolidated linkedin.accounts table for centralized identifier management
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.InvalidAcoIdentifierError = void 0;
|
|
10
|
+
exports.validateAcoIdentifier = validateAcoIdentifier;
|
|
11
|
+
exports.extractLinkedInIdentifiers = extractLinkedInIdentifiers;
|
|
12
|
+
/**
|
|
13
|
+
* Validation error for invalid ACoA identifiers
|
|
14
|
+
*/
|
|
15
|
+
class InvalidAcoIdentifierError extends Error {
|
|
16
|
+
constructor(identifier, reason) {
|
|
17
|
+
super(`Invalid ACoA identifier "${identifier}": ${reason}`);
|
|
18
|
+
this.name = "InvalidAcoIdentifierError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.InvalidAcoIdentifierError = InvalidAcoIdentifierError;
|
|
22
|
+
/**
|
|
23
|
+
* Validates that an ACoA identifier meets all requirements:
|
|
24
|
+
* - Starts with "ACoA"
|
|
25
|
+
* - Is exactly 39 characters long
|
|
26
|
+
* - Contains only valid characters (alphanumeric + underscores, hyphens)
|
|
27
|
+
*/
|
|
28
|
+
function validateAcoIdentifier(identifier) {
|
|
29
|
+
if (!identifier) {
|
|
30
|
+
throw new InvalidAcoIdentifierError(identifier, "identifier cannot be empty or null");
|
|
31
|
+
}
|
|
32
|
+
const trimmed = identifier.trim();
|
|
33
|
+
if (!trimmed.startsWith("ACoA")) {
|
|
34
|
+
throw new InvalidAcoIdentifierError(identifier, "must start with 'ACoA'");
|
|
35
|
+
}
|
|
36
|
+
if (trimmed.length !== 39) {
|
|
37
|
+
throw new InvalidAcoIdentifierError(identifier, `must be exactly 39 characters long, got ${trimmed.length} characters`);
|
|
38
|
+
}
|
|
39
|
+
// Optional: Validate character set (LinkedIn identifiers typically use alphanumeric + some special chars)
|
|
40
|
+
const validPattern = /^ACoA[A-Za-z0-9_-]+$/;
|
|
41
|
+
if (!validPattern.test(trimmed)) {
|
|
42
|
+
throw new InvalidAcoIdentifierError(identifier, "contains invalid characters (only alphanumeric, underscore, and hyphen allowed after 'ACoA')");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extract LinkedIn identifiers from profile data for linkedin.accounts table
|
|
47
|
+
* This is the consolidated approach that replaces the old identifier mapping logic
|
|
48
|
+
*/
|
|
49
|
+
function extractLinkedInIdentifiers(requestIdentifier, profileData) {
|
|
50
|
+
// Extract ACoA identifier (prioritize provider_id from Ghost Genius)
|
|
51
|
+
const acoaIdentifier = profileData.provider_id || requestIdentifier;
|
|
52
|
+
// Extract public identifier
|
|
53
|
+
const publicIdentifier = profileData.public_identifier || "unknown";
|
|
54
|
+
// Validate ACoA identifier if it looks like one
|
|
55
|
+
if (acoaIdentifier.startsWith("ACoA")) {
|
|
56
|
+
validateAcoIdentifier(acoaIdentifier);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
linkedinIdentifierAcoa: acoaIdentifier,
|
|
60
|
+
publicIdentifier,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=linkedin-identifier-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin-identifier-utils.js","sourceRoot":"","sources":["../../src/utils/linkedin-identifier-utils.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAkBH,sDA0BC;AAMD,gEAsBC;AAtED;;GAEG;AACH,MAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAY,UAAkB,EAAE,MAAc;QAC5C,KAAK,CAAC,4BAA4B,UAAU,MAAM,MAAM,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AALD,8DAKC;AAED;;;;;GAKG;AACH,SAAgB,qBAAqB,CAAC,UAAkB;IACtD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,yBAAyB,CAAC,UAAU,EAAE,oCAAoC,CAAC,CAAC;IACxF,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAElC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,yBAAyB,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,yBAAyB,CACjC,UAAU,EACV,2CAA2C,OAAO,CAAC,MAAM,aAAa,CACvE,CAAC;IACJ,CAAC;IAED,0GAA0G;IAC1G,MAAM,YAAY,GAAG,sBAAsB,CAAC;IAC5C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,yBAAyB,CACjC,UAAU,EACV,8FAA8F,CAC/F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,0BAA0B,CACxC,iBAAyB,EACzB,WAAyF;IAKzF,qEAAqE;IACrE,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,IAAI,iBAAiB,CAAC;IAEpE,4BAA4B;IAC5B,MAAM,gBAAgB,GAAG,WAAW,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAEpE,gDAAgD;IAChD,IAAI,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,qBAAqB,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IAED,OAAO;QACL,sBAAsB,EAAE,cAAc;QACtC,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LinkedIn Profile Caching Utilities - Consolidated Schema
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to check for existing LinkedIn profiles and retrieve cached data
|
|
5
|
+
* to avoid unnecessary API calls when profile data is already available.
|
|
6
|
+
* Updated to work with the new consolidated linkedin.accounts schema.
|
|
7
|
+
*/
|
|
8
|
+
import { Pool, PoolClient } from 'pg';
|
|
9
|
+
import type { Database } from "../lib/db";
|
|
10
|
+
/**
|
|
11
|
+
* Result of checking if a LinkedIn profile exists in cache
|
|
12
|
+
*/
|
|
13
|
+
export interface ProfileCacheCheckResult {
|
|
14
|
+
exists: boolean;
|
|
15
|
+
linkedinAccountId?: number;
|
|
16
|
+
firstName?: string | undefined;
|
|
17
|
+
lastName?: string | undefined;
|
|
18
|
+
headline?: string | undefined;
|
|
19
|
+
location?: string | undefined;
|
|
20
|
+
profilePictureUrl?: string | undefined;
|
|
21
|
+
followerCount?: number | undefined;
|
|
22
|
+
connectionsCount?: number | undefined;
|
|
23
|
+
linkedinIdentifierAcoa?: string | undefined;
|
|
24
|
+
publicIdentifier?: string | undefined;
|
|
25
|
+
createdAt?: Date | undefined;
|
|
26
|
+
updatedAt?: Date | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Complete cached profile data in Ghost Genius format
|
|
30
|
+
*/
|
|
31
|
+
export interface CachedLinkedInProfile {
|
|
32
|
+
provider_id: string;
|
|
33
|
+
public_identifier?: string | undefined;
|
|
34
|
+
first_name?: string | undefined;
|
|
35
|
+
last_name?: string | undefined;
|
|
36
|
+
headline?: string | undefined;
|
|
37
|
+
summary?: string | undefined;
|
|
38
|
+
location?: string | undefined;
|
|
39
|
+
profile_picture_url?: string | undefined;
|
|
40
|
+
follower_count?: number | undefined;
|
|
41
|
+
connections_count?: number | undefined;
|
|
42
|
+
skills?: Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
}>;
|
|
45
|
+
work_experience?: Array<{
|
|
46
|
+
position?: string | undefined;
|
|
47
|
+
company?: string | undefined;
|
|
48
|
+
company_id?: string | undefined;
|
|
49
|
+
company_linkedin_url?: string | undefined;
|
|
50
|
+
location?: string | undefined;
|
|
51
|
+
employment_type?: string | undefined;
|
|
52
|
+
description?: string | undefined;
|
|
53
|
+
is_current?: boolean | undefined;
|
|
54
|
+
start_date?: string | undefined;
|
|
55
|
+
end_date?: string | undefined;
|
|
56
|
+
skills?: Array<{
|
|
57
|
+
name: string;
|
|
58
|
+
}>;
|
|
59
|
+
}>;
|
|
60
|
+
education?: Array<{
|
|
61
|
+
degree?: string | undefined;
|
|
62
|
+
school?: string | undefined;
|
|
63
|
+
school_id?: string | undefined;
|
|
64
|
+
field_of_study?: string | undefined;
|
|
65
|
+
grade?: string | undefined;
|
|
66
|
+
description?: string | undefined;
|
|
67
|
+
activities_and_societies?: string | undefined;
|
|
68
|
+
school_linkedin_url?: string | undefined;
|
|
69
|
+
start_date?: string | undefined;
|
|
70
|
+
end_date?: string | undefined;
|
|
71
|
+
skills?: Array<{
|
|
72
|
+
name: string;
|
|
73
|
+
}>;
|
|
74
|
+
}>;
|
|
75
|
+
certifications?: Array<{
|
|
76
|
+
name?: string | undefined;
|
|
77
|
+
authority?: string | undefined;
|
|
78
|
+
license_number?: string | undefined;
|
|
79
|
+
url?: string | undefined;
|
|
80
|
+
start_date?: string | undefined;
|
|
81
|
+
end_date?: string | undefined;
|
|
82
|
+
}>;
|
|
83
|
+
projects?: Array<{
|
|
84
|
+
title?: string | undefined;
|
|
85
|
+
description?: string | undefined;
|
|
86
|
+
url?: string | undefined;
|
|
87
|
+
start_date?: string | undefined;
|
|
88
|
+
end_date?: string | undefined;
|
|
89
|
+
}>;
|
|
90
|
+
contact_info?: Array<{
|
|
91
|
+
type: "EMAIL" | "PHONE_NUMBER" | "URL";
|
|
92
|
+
value: string;
|
|
93
|
+
source?: string;
|
|
94
|
+
}>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if LinkedIn profiles exist in cache for multiple ACoA identifiers
|
|
98
|
+
* Returns basic profile information for cache hit determination
|
|
99
|
+
*/
|
|
100
|
+
export declare function checkLinkedInProfilesExistInCache(db: Database | Pool | PoolClient, acoIdentifiers: string[]): Promise<ProfileCacheCheckResult[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Check if a single LinkedIn profile exists in cache
|
|
103
|
+
*/
|
|
104
|
+
export declare function checkLinkedInProfileExistsInCache(db: Database | Pool | PoolClient, identifier: string): Promise<ProfileCacheCheckResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Get complete cached LinkedIn profile data in Ghost Genius format
|
|
107
|
+
* Supports both ACoA identifiers and public identifiers
|
|
108
|
+
*/
|
|
109
|
+
export declare function getCachedLinkedInProfile(db: Database | Pool | PoolClient, identifier: string): Promise<CachedLinkedInProfile | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Get complete cached LinkedIn profile data by LinkedIn account ID
|
|
112
|
+
* More efficient when you already have the account ID (avoids identifier lookup)
|
|
113
|
+
*/
|
|
114
|
+
export declare function getCachedLinkedInProfileById(db: Database | Pool | PoolClient, linkedinAccountId: number): Promise<CachedLinkedInProfile | null>;
|
|
115
|
+
/**
|
|
116
|
+
* Get multiple cached LinkedIn profiles by ACoA identifiers
|
|
117
|
+
*/
|
|
118
|
+
export declare function getCachedLinkedInProfiles(db: Database | Pool | PoolClient, identifiers: string[]): Promise<(CachedLinkedInProfile | null)[]>;
|
|
119
|
+
/**
|
|
120
|
+
* Check if a LinkedIn profile has complete data (useful for cache validation)
|
|
121
|
+
*/
|
|
122
|
+
export declare function isProfileDataComplete(profile: CachedLinkedInProfile): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Get the age of cached profile data in hours
|
|
125
|
+
*/
|
|
126
|
+
export declare function getCachedProfileAge(cacheCheckResult: ProfileCacheCheckResult): number | null;
|
|
127
|
+
/**
|
|
128
|
+
* Determine if cached profile data should be refreshed based on age
|
|
129
|
+
*/
|
|
130
|
+
export declare function shouldRefreshCachedProfile(cacheCheckResult: ProfileCacheCheckResult, maxAgeHours?: number): boolean;
|
|
131
|
+
//# sourceMappingURL=linkedin-profile-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin-profile-cache.d.ts","sourceRoot":"","sources":["../../src/utils/linkedin-profile-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LinkedIn Profile Caching Utilities - Consolidated Schema
|
|
4
|
+
*
|
|
5
|
+
* Provides functions to check for existing LinkedIn profiles and retrieve cached data
|
|
6
|
+
* to avoid unnecessary API calls when profile data is already available.
|
|
7
|
+
* Updated to work with the new consolidated linkedin.accounts schema.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.checkLinkedInProfilesExistInCache = checkLinkedInProfilesExistInCache;
|
|
11
|
+
exports.checkLinkedInProfileExistsInCache = checkLinkedInProfileExistsInCache;
|
|
12
|
+
exports.getCachedLinkedInProfile = getCachedLinkedInProfile;
|
|
13
|
+
exports.getCachedLinkedInProfileById = getCachedLinkedInProfileById;
|
|
14
|
+
exports.getCachedLinkedInProfiles = getCachedLinkedInProfiles;
|
|
15
|
+
exports.isProfileDataComplete = isProfileDataComplete;
|
|
16
|
+
exports.getCachedProfileAge = getCachedProfileAge;
|
|
17
|
+
exports.shouldRefreshCachedProfile = shouldRefreshCachedProfile;
|
|
18
|
+
const pg_client_1 = require("../lib/pg-client");
|
|
19
|
+
/**
|
|
20
|
+
* Helper function to handle optional string fields
|
|
21
|
+
* Returns undefined if value is null, undefined, or empty string
|
|
22
|
+
* This ensures optional fields are omitted from JSON response when not present
|
|
23
|
+
*/
|
|
24
|
+
function optionalString(value) {
|
|
25
|
+
if (value === null || value === undefined || value.trim() === "") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Helper function for required string fields
|
|
32
|
+
* Returns empty string if value is null/undefined (required fields must be present)
|
|
33
|
+
*/
|
|
34
|
+
function requiredString(value) {
|
|
35
|
+
return value || "";
|
|
36
|
+
}
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// CACHE CHECK FUNCTIONS
|
|
39
|
+
// =============================================================================
|
|
40
|
+
/**
|
|
41
|
+
* Check if LinkedIn profiles exist in cache for multiple ACoA identifiers
|
|
42
|
+
* Returns basic profile information for cache hit determination
|
|
43
|
+
*/
|
|
44
|
+
async function checkLinkedInProfilesExistInCache(db, acoIdentifiers) {
|
|
45
|
+
if (acoIdentifiers.length === 0) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const placeholders = acoIdentifiers.map((_, i) => `$${i + 1}`).join(', ');
|
|
50
|
+
const sql = `
|
|
51
|
+
SELECT
|
|
52
|
+
id as linkedin_account_id,
|
|
53
|
+
first_name,
|
|
54
|
+
last_name,
|
|
55
|
+
headline,
|
|
56
|
+
location,
|
|
57
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) as profile_picture_url,
|
|
58
|
+
follower_count,
|
|
59
|
+
connections_count,
|
|
60
|
+
linkedin_identifier_acoa,
|
|
61
|
+
public_identifier,
|
|
62
|
+
created_at,
|
|
63
|
+
profiles_updated_at
|
|
64
|
+
FROM linkedin.accounts
|
|
65
|
+
WHERE linkedin_identifier_acoa IN (${placeholders})
|
|
66
|
+
`;
|
|
67
|
+
const results = await (0, pg_client_1.query)(db, sql, acoIdentifiers);
|
|
68
|
+
// Create a map of found profiles
|
|
69
|
+
const foundProfiles = new Map();
|
|
70
|
+
results.forEach(result => {
|
|
71
|
+
if (result.linkedin_identifier_acoa) {
|
|
72
|
+
foundProfiles.set(result.linkedin_identifier_acoa, {
|
|
73
|
+
exists: true,
|
|
74
|
+
linkedinAccountId: result.linkedin_account_id,
|
|
75
|
+
firstName: result.first_name || undefined,
|
|
76
|
+
lastName: result.last_name || undefined,
|
|
77
|
+
headline: result.headline || undefined,
|
|
78
|
+
location: result.location || undefined,
|
|
79
|
+
profilePictureUrl: result.profile_picture_url || undefined,
|
|
80
|
+
followerCount: result.follower_count || undefined,
|
|
81
|
+
connectionsCount: result.connections_count || undefined,
|
|
82
|
+
linkedinIdentifierAcoa: result.linkedin_identifier_acoa,
|
|
83
|
+
publicIdentifier: result.public_identifier || undefined,
|
|
84
|
+
createdAt: result.created_at,
|
|
85
|
+
updatedAt: result.profiles_updated_at || undefined,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Return results in the same order as input, with exists: false for missing profiles
|
|
90
|
+
return acoIdentifiers.map(identifier => {
|
|
91
|
+
return foundProfiles.get(identifier) || { exists: false };
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error("Error checking LinkedIn profiles in cache:", error);
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if a single LinkedIn profile exists in cache
|
|
101
|
+
*/
|
|
102
|
+
async function checkLinkedInProfileExistsInCache(db, identifier) {
|
|
103
|
+
const results = await checkLinkedInProfilesExistInCache(db, [identifier]);
|
|
104
|
+
return results[0] || { exists: false };
|
|
105
|
+
}
|
|
106
|
+
// =============================================================================
|
|
107
|
+
// COMPLETE PROFILE RETRIEVAL
|
|
108
|
+
// =============================================================================
|
|
109
|
+
/**
|
|
110
|
+
* Get complete cached LinkedIn profile data in Ghost Genius format
|
|
111
|
+
* Supports both ACoA identifiers and public identifiers
|
|
112
|
+
*/
|
|
113
|
+
async function getCachedLinkedInProfile(db, identifier) {
|
|
114
|
+
try {
|
|
115
|
+
// Find the LinkedIn account by identifier (ACoA or public)
|
|
116
|
+
const accountSql = `
|
|
117
|
+
SELECT
|
|
118
|
+
id as linkedin_account_id,
|
|
119
|
+
first_name,
|
|
120
|
+
last_name,
|
|
121
|
+
headline,
|
|
122
|
+
summary,
|
|
123
|
+
location,
|
|
124
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) as profile_picture_url,
|
|
125
|
+
follower_count,
|
|
126
|
+
connections_count,
|
|
127
|
+
linkedin_identifier_acoa,
|
|
128
|
+
public_identifier
|
|
129
|
+
FROM linkedin.accounts
|
|
130
|
+
WHERE linkedin_identifier_acoa = $1 OR public_identifier = $1
|
|
131
|
+
LIMIT 1
|
|
132
|
+
`;
|
|
133
|
+
const account = await (0, pg_client_1.queryOne)(db, accountSql, [identifier]);
|
|
134
|
+
if (!account) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const linkedinAccountId = account.linkedin_account_id;
|
|
138
|
+
// Get all related data in parallel
|
|
139
|
+
const [workExperience, education, certifications, projects, profileSkills] = await Promise.all([
|
|
140
|
+
// Work experience
|
|
141
|
+
(0, pg_client_1.query)(db, `SELECT id, position, company, company_id, company_linkedin_url, location, employment_type, description, is_current, start_date, end_date
|
|
142
|
+
FROM linkedin.work_experience
|
|
143
|
+
WHERE linkedin_account_id = $1`, [linkedinAccountId]),
|
|
144
|
+
// Education
|
|
145
|
+
(0, pg_client_1.query)(db, `SELECT id, degree, school, school_id, field_of_study, grade, description, activities_and_societies, school_linkedin_url, start_date, end_date
|
|
146
|
+
FROM linkedin.education
|
|
147
|
+
WHERE linkedin_account_id = $1`, [linkedinAccountId]),
|
|
148
|
+
// Certifications
|
|
149
|
+
(0, pg_client_1.query)(db, `SELECT name, organization, url
|
|
150
|
+
FROM linkedin.certifications
|
|
151
|
+
WHERE linkedin_account_id = $1`, [linkedinAccountId]),
|
|
152
|
+
// Projects
|
|
153
|
+
(0, pg_client_1.query)(db, `SELECT name, description, start_date, end_date
|
|
154
|
+
FROM linkedin.projects
|
|
155
|
+
WHERE linkedin_account_id = $1`, [linkedinAccountId]),
|
|
156
|
+
// Profile skills
|
|
157
|
+
(0, pg_client_1.query)(db, `SELECT s.name as skill_name
|
|
158
|
+
FROM linkedin.profile_skills ps
|
|
159
|
+
INNER JOIN linkedin.skills s ON ps.skill_id = s.id
|
|
160
|
+
WHERE ps.linkedin_account_id = $1`, [linkedinAccountId]),
|
|
161
|
+
]);
|
|
162
|
+
// Get work experience skills
|
|
163
|
+
const workExpSkills = await Promise.all(workExperience.map(async (exp) => {
|
|
164
|
+
const expSkills = await (0, pg_client_1.query)(db, `SELECT s.name as skill_name
|
|
165
|
+
FROM linkedin.work_experience_skills wes
|
|
166
|
+
INNER JOIN linkedin.skills s ON wes.skill_id = s.id
|
|
167
|
+
WHERE wes.work_experience_id = $1`, [exp.id]);
|
|
168
|
+
return {
|
|
169
|
+
workExperienceId: exp.id,
|
|
170
|
+
skills: expSkills.map(s => ({ name: s.skill_name })),
|
|
171
|
+
};
|
|
172
|
+
}));
|
|
173
|
+
// Get education skills
|
|
174
|
+
const eduSkills = await Promise.all(education.map(async (edu) => {
|
|
175
|
+
const eduSkillsData = await (0, pg_client_1.query)(db, `SELECT s.name as skill_name
|
|
176
|
+
FROM linkedin.education_skills es
|
|
177
|
+
INNER JOIN linkedin.skills s ON es.skill_id = s.id
|
|
178
|
+
WHERE es.education_id = $1`, [edu.id]);
|
|
179
|
+
return {
|
|
180
|
+
educationId: edu.id,
|
|
181
|
+
skills: eduSkillsData.map(s => ({ name: s.skill_name })),
|
|
182
|
+
};
|
|
183
|
+
}));
|
|
184
|
+
// Create skills maps for easy lookup
|
|
185
|
+
const workExpSkillsMap = new Map(workExpSkills.map(item => [item.workExperienceId, item.skills]));
|
|
186
|
+
const eduSkillsMap = new Map(eduSkills.map(item => [item.educationId, item.skills]));
|
|
187
|
+
// Build the complete profile in Ghost Genius format
|
|
188
|
+
const cachedProfile = {
|
|
189
|
+
provider_id: account.linkedin_identifier_acoa || "",
|
|
190
|
+
public_identifier: optionalString(account.public_identifier),
|
|
191
|
+
first_name: optionalString(account.first_name),
|
|
192
|
+
last_name: optionalString(account.last_name),
|
|
193
|
+
headline: optionalString(account.headline),
|
|
194
|
+
summary: optionalString(account.summary),
|
|
195
|
+
location: optionalString(account.location),
|
|
196
|
+
profile_picture_url: optionalString(account.profile_picture_url),
|
|
197
|
+
follower_count: account.follower_count || undefined,
|
|
198
|
+
connections_count: account.connections_count || undefined,
|
|
199
|
+
skills: profileSkills.map(skill => ({ name: skill.skill_name })),
|
|
200
|
+
work_experience: workExperience.map(exp => ({
|
|
201
|
+
position: optionalString(exp.position),
|
|
202
|
+
company: optionalString(exp.company),
|
|
203
|
+
company_id: optionalString(exp.company_id),
|
|
204
|
+
company_linkedin_url: optionalString(exp.company_linkedin_url),
|
|
205
|
+
location: optionalString(exp.location),
|
|
206
|
+
employment_type: optionalString(exp.employment_type),
|
|
207
|
+
description: optionalString(exp.description),
|
|
208
|
+
is_current: exp.is_current || false,
|
|
209
|
+
start_date: optionalString(exp.start_date),
|
|
210
|
+
end_date: optionalString(exp.end_date),
|
|
211
|
+
skills: workExpSkillsMap.get(exp.id) || [],
|
|
212
|
+
})),
|
|
213
|
+
education: education.map(edu => ({
|
|
214
|
+
degree: optionalString(edu.degree),
|
|
215
|
+
school: optionalString(edu.school),
|
|
216
|
+
school_id: optionalString(edu.school_id),
|
|
217
|
+
field_of_study: optionalString(edu.field_of_study),
|
|
218
|
+
grade: optionalString(edu.grade),
|
|
219
|
+
description: optionalString(edu.description),
|
|
220
|
+
activities_and_societies: optionalString(edu.activities_and_societies),
|
|
221
|
+
school_linkedin_url: optionalString(edu.school_linkedin_url),
|
|
222
|
+
start_date: optionalString(edu.start_date),
|
|
223
|
+
end_date: optionalString(edu.end_date),
|
|
224
|
+
skills: eduSkillsMap.get(edu.id) || [],
|
|
225
|
+
})),
|
|
226
|
+
certifications: certifications.map(cert => ({
|
|
227
|
+
name: optionalString(cert.name),
|
|
228
|
+
authority: optionalString(cert.organization),
|
|
229
|
+
license_number: undefined,
|
|
230
|
+
url: optionalString(cert.url),
|
|
231
|
+
start_date: undefined,
|
|
232
|
+
end_date: undefined,
|
|
233
|
+
})),
|
|
234
|
+
projects: projects.map(project => ({
|
|
235
|
+
title: optionalString(project.name),
|
|
236
|
+
description: optionalString(project.description),
|
|
237
|
+
url: undefined,
|
|
238
|
+
start_date: optionalString(project.start_date),
|
|
239
|
+
end_date: optionalString(project.end_date),
|
|
240
|
+
})),
|
|
241
|
+
contact_info: [],
|
|
242
|
+
};
|
|
243
|
+
return cachedProfile;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
console.error("Error getting cached LinkedIn profile:", error);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get complete cached LinkedIn profile data by LinkedIn account ID
|
|
252
|
+
* More efficient when you already have the account ID (avoids identifier lookup)
|
|
253
|
+
*/
|
|
254
|
+
async function getCachedLinkedInProfileById(db, linkedinAccountId) {
|
|
255
|
+
try {
|
|
256
|
+
// Direct query by account ID - no need to lookup by identifier
|
|
257
|
+
const accountSql = `
|
|
258
|
+
SELECT
|
|
259
|
+
id as linkedin_account_id,
|
|
260
|
+
first_name,
|
|
261
|
+
last_name,
|
|
262
|
+
headline,
|
|
263
|
+
summary,
|
|
264
|
+
location,
|
|
265
|
+
COALESCE(profile_image_cloudfront_url, profile_picture_url) as profile_picture_url,
|
|
266
|
+
follower_count,
|
|
267
|
+
connections_count,
|
|
268
|
+
linkedin_identifier_acoa,
|
|
269
|
+
public_identifier
|
|
270
|
+
FROM linkedin.accounts
|
|
271
|
+
WHERE id = $1
|
|
272
|
+
LIMIT 1
|
|
273
|
+
`;
|
|
274
|
+
const account = await (0, pg_client_1.queryOne)(db, accountSql, [linkedinAccountId]);
|
|
275
|
+
if (!account) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
const accountId = account.linkedin_account_id;
|
|
279
|
+
// Get all related data in parallel
|
|
280
|
+
const [workExperience, education, certifications, projects, profileSkills] = await Promise.all([
|
|
281
|
+
// Work experience
|
|
282
|
+
(0, pg_client_1.query)(db, `SELECT id, position, company, company_id, company_linkedin_url, location, employment_type, description, is_current, start_date, end_date
|
|
283
|
+
FROM linkedin.work_experience
|
|
284
|
+
WHERE linkedin_account_id = $1
|
|
285
|
+
ORDER BY start_date DESC`, [accountId]),
|
|
286
|
+
// Education
|
|
287
|
+
(0, pg_client_1.query)(db, `SELECT id, school, school_id, school_linkedin_url, degree, field_of_study, grade, description, activities_and_societies, start_date, end_date
|
|
288
|
+
FROM linkedin.education
|
|
289
|
+
WHERE linkedin_account_id = $1
|
|
290
|
+
ORDER BY start_date DESC`, [accountId]),
|
|
291
|
+
// Certifications
|
|
292
|
+
(0, pg_client_1.query)(db, `SELECT id, name, organization, url
|
|
293
|
+
FROM linkedin.certifications
|
|
294
|
+
WHERE linkedin_account_id = $1`, [accountId]),
|
|
295
|
+
// Projects
|
|
296
|
+
(0, pg_client_1.query)(db, `SELECT id, name, description, start_date, end_date
|
|
297
|
+
FROM linkedin.projects
|
|
298
|
+
WHERE linkedin_account_id = $1
|
|
299
|
+
ORDER BY start_date DESC`, [accountId]),
|
|
300
|
+
// Profile skills
|
|
301
|
+
(0, pg_client_1.query)(db, `SELECT s.name as skill_name
|
|
302
|
+
FROM linkedin.profile_skills ps
|
|
303
|
+
INNER JOIN linkedin.skills s ON ps.skill_id = s.id
|
|
304
|
+
WHERE ps.linkedin_account_id = $1`, [accountId]),
|
|
305
|
+
]);
|
|
306
|
+
// Build the complete profile in Ghost Genius format
|
|
307
|
+
const cachedProfile = {
|
|
308
|
+
provider_id: account.linkedin_identifier_acoa || "",
|
|
309
|
+
public_identifier: optionalString(account.public_identifier),
|
|
310
|
+
first_name: optionalString(account.first_name),
|
|
311
|
+
last_name: optionalString(account.last_name),
|
|
312
|
+
headline: optionalString(account.headline),
|
|
313
|
+
summary: optionalString(account.summary),
|
|
314
|
+
location: optionalString(account.location),
|
|
315
|
+
profile_picture_url: optionalString(account.profile_picture_url),
|
|
316
|
+
follower_count: account.follower_count || undefined,
|
|
317
|
+
connections_count: account.connections_count || undefined,
|
|
318
|
+
skills: profileSkills.map(skill => ({ name: skill.skill_name })),
|
|
319
|
+
work_experience: workExperience.map(exp => ({
|
|
320
|
+
position: optionalString(exp.position),
|
|
321
|
+
company: optionalString(exp.company),
|
|
322
|
+
company_id: optionalString(exp.company_id),
|
|
323
|
+
company_linkedin_url: optionalString(exp.company_linkedin_url),
|
|
324
|
+
location: optionalString(exp.location),
|
|
325
|
+
employment_type: optionalString(exp.employment_type),
|
|
326
|
+
description: optionalString(exp.description),
|
|
327
|
+
is_current: exp.is_current || false,
|
|
328
|
+
start_date: exp.start_date || undefined,
|
|
329
|
+
end_date: exp.end_date || undefined,
|
|
330
|
+
})),
|
|
331
|
+
education: education.map(edu => ({
|
|
332
|
+
school: optionalString(edu.school),
|
|
333
|
+
school_id: optionalString(edu.school_id),
|
|
334
|
+
school_linkedin_url: optionalString(edu.school_linkedin_url),
|
|
335
|
+
degree: optionalString(edu.degree),
|
|
336
|
+
field_of_study: optionalString(edu.field_of_study),
|
|
337
|
+
grade: optionalString(edu.grade),
|
|
338
|
+
description: optionalString(edu.description),
|
|
339
|
+
activities_and_societies: optionalString(edu.activities_and_societies),
|
|
340
|
+
start_date: edu.start_date || undefined,
|
|
341
|
+
end_date: edu.end_date || undefined,
|
|
342
|
+
})),
|
|
343
|
+
certifications: certifications.map(cert => ({
|
|
344
|
+
name: optionalString(cert.name),
|
|
345
|
+
authority: optionalString(cert.organization),
|
|
346
|
+
url: optionalString(cert.url),
|
|
347
|
+
})),
|
|
348
|
+
projects: projects.map(proj => ({
|
|
349
|
+
title: optionalString(proj.name),
|
|
350
|
+
description: optionalString(proj.description),
|
|
351
|
+
start_date: proj.start_date || undefined,
|
|
352
|
+
end_date: proj.end_date || undefined,
|
|
353
|
+
})),
|
|
354
|
+
contact_info: [],
|
|
355
|
+
};
|
|
356
|
+
return cachedProfile;
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
console.error("Error getting cached LinkedIn profile by ID:", error);
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Get multiple cached LinkedIn profiles by ACoA identifiers
|
|
365
|
+
*/
|
|
366
|
+
async function getCachedLinkedInProfiles(db, identifiers) {
|
|
367
|
+
if (identifiers.length === 0) {
|
|
368
|
+
return [];
|
|
369
|
+
}
|
|
370
|
+
try {
|
|
371
|
+
// Get all profiles in parallel
|
|
372
|
+
const profiles = await Promise.all(identifiers.map(identifier => getCachedLinkedInProfile(db, identifier)));
|
|
373
|
+
return profiles;
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
console.error("Error getting cached LinkedIn profiles:", error);
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// =============================================================================
|
|
381
|
+
// UTILITY FUNCTIONS
|
|
382
|
+
// =============================================================================
|
|
383
|
+
/**
|
|
384
|
+
* Check if a LinkedIn profile has complete data (useful for cache validation)
|
|
385
|
+
*/
|
|
386
|
+
function isProfileDataComplete(profile) {
|
|
387
|
+
return !!(profile.first_name &&
|
|
388
|
+
profile.last_name &&
|
|
389
|
+
profile.headline &&
|
|
390
|
+
(profile.work_experience?.length || 0) > 0);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get the age of cached profile data in hours
|
|
394
|
+
*/
|
|
395
|
+
function getCachedProfileAge(cacheCheckResult) {
|
|
396
|
+
if (!cacheCheckResult.exists || !cacheCheckResult.updatedAt) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
const now = new Date();
|
|
400
|
+
const updatedAt = new Date(cacheCheckResult.updatedAt);
|
|
401
|
+
const diffMs = now.getTime() - updatedAt.getTime();
|
|
402
|
+
const diffHours = diffMs / (1000 * 60 * 60);
|
|
403
|
+
return diffHours;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Determine if cached profile data should be refreshed based on age
|
|
407
|
+
*/
|
|
408
|
+
function shouldRefreshCachedProfile(cacheCheckResult, maxAgeHours = 24) {
|
|
409
|
+
if (!cacheCheckResult.exists) {
|
|
410
|
+
return true; // No cache, needs refresh
|
|
411
|
+
}
|
|
412
|
+
const age = getCachedProfileAge(cacheCheckResult);
|
|
413
|
+
if (age === null) {
|
|
414
|
+
return true; // No update timestamp, needs refresh
|
|
415
|
+
}
|
|
416
|
+
return age > maxAgeHours;
|
|
417
|
+
}
|
|
418
|
+
//# sourceMappingURL=linkedin-profile-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkedin-profile-cache.js","sourceRoot":"","sources":["../../src/utils/linkedin-profile-cache.ts"],"names":[],"mappings":"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"}
|