linkedin-secret-sauce 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/enrichment/auth/index.d.ts +1 -1
- package/dist/enrichment/auth/index.js +6 -1
- package/dist/enrichment/auth/smartlead-auth.d.ts +32 -0
- package/dist/enrichment/auth/smartlead-auth.js +165 -0
- package/dist/enrichment/index.d.ts +4 -2
- package/dist/enrichment/index.js +43 -1
- package/dist/enrichment/matching.d.ts +239 -0
- package/dist/enrichment/matching.js +619 -0
- package/dist/enrichment/orchestrator.d.ts +13 -1
- package/dist/enrichment/orchestrator.js +220 -3
- package/dist/enrichment/providers/apollo.d.ts +2 -2
- package/dist/enrichment/providers/apollo.js +59 -14
- package/dist/enrichment/providers/construct.d.ts +2 -2
- package/dist/enrichment/providers/construct.js +16 -4
- package/dist/enrichment/providers/hunter.d.ts +2 -2
- package/dist/enrichment/providers/hunter.js +48 -22
- package/dist/enrichment/providers/ldd.d.ts +2 -2
- package/dist/enrichment/providers/ldd.js +16 -8
- package/dist/enrichment/providers/smartprospect.d.ts +64 -2
- package/dist/enrichment/providers/smartprospect.js +391 -35
- package/dist/enrichment/types.d.ts +139 -11
- package/dist/enrichment/types.js +50 -1
- package/package.json +16 -15
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Authentication modules for enrichment providers
|
|
3
3
|
*/
|
|
4
|
-
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from './smartlead-auth';
|
|
4
|
+
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, enableFileCache, disableFileCache, isFileCacheEnabled, clearFileCache, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from './smartlead-auth';
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
* Authentication modules for enrichment providers
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = void 0;
|
|
6
|
+
exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = void 0;
|
|
7
7
|
var smartlead_auth_1 = require("./smartlead-auth");
|
|
8
8
|
Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return smartlead_auth_1.getSmartLeadToken; } });
|
|
9
9
|
Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return smartlead_auth_1.getSmartLeadUser; } });
|
|
10
10
|
Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return smartlead_auth_1.clearSmartLeadToken; } });
|
|
11
11
|
Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return smartlead_auth_1.clearAllSmartLeadTokens; } });
|
|
12
12
|
Object.defineProperty(exports, "getSmartLeadTokenCacheStats", { enumerable: true, get: function () { return smartlead_auth_1.getSmartLeadTokenCacheStats; } });
|
|
13
|
+
// File cache utilities for development/testing
|
|
14
|
+
Object.defineProperty(exports, "enableFileCache", { enumerable: true, get: function () { return smartlead_auth_1.enableFileCache; } });
|
|
15
|
+
Object.defineProperty(exports, "disableFileCache", { enumerable: true, get: function () { return smartlead_auth_1.disableFileCache; } });
|
|
16
|
+
Object.defineProperty(exports, "isFileCacheEnabled", { enumerable: true, get: function () { return smartlead_auth_1.isFileCacheEnabled; } });
|
|
17
|
+
Object.defineProperty(exports, "clearFileCache", { enumerable: true, get: function () { return smartlead_auth_1.clearFileCache; } });
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handles JWT token acquisition via email/password login.
|
|
5
5
|
* Tokens are cached in-memory with automatic refresh before expiry.
|
|
6
|
+
*
|
|
7
|
+
* For development/testing, file-based caching is supported to avoid
|
|
8
|
+
* repeated logins during test runs. Enable via `enableFileCache()`.
|
|
6
9
|
*/
|
|
7
10
|
export interface SmartLeadCredentials {
|
|
8
11
|
email: string;
|
|
@@ -47,4 +50,33 @@ export declare function clearAllSmartLeadTokens(): void;
|
|
|
47
50
|
export declare function getSmartLeadTokenCacheStats(): {
|
|
48
51
|
cachedEmails: string[];
|
|
49
52
|
totalCached: number;
|
|
53
|
+
fileCacheEnabled: boolean;
|
|
54
|
+
fileCachePath: string | null;
|
|
50
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Enable file-based token caching for development/testing
|
|
58
|
+
*
|
|
59
|
+
* When enabled, tokens are persisted to ~/.smartlead-tokens.json
|
|
60
|
+
* This avoids repeated logins during test development.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* // In your test setup
|
|
65
|
+
* import { enableFileCache } from 'linkedin-secret-sauce/enrichment';
|
|
66
|
+
*
|
|
67
|
+
* enableFileCache(); // Now tokens persist between test runs
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function enableFileCache(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Disable file-based token caching
|
|
73
|
+
*/
|
|
74
|
+
export declare function disableFileCache(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Check if file cache is enabled
|
|
77
|
+
*/
|
|
78
|
+
export declare function isFileCacheEnabled(): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Clear the file cache
|
|
81
|
+
*/
|
|
82
|
+
export declare function clearFileCache(): void;
|
|
@@ -4,13 +4,56 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Handles JWT token acquisition via email/password login.
|
|
6
6
|
* Tokens are cached in-memory with automatic refresh before expiry.
|
|
7
|
+
*
|
|
8
|
+
* For development/testing, file-based caching is supported to avoid
|
|
9
|
+
* repeated logins during test runs. Enable via `enableFileCache()`.
|
|
7
10
|
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
8
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
45
|
exports.getSmartLeadToken = getSmartLeadToken;
|
|
10
46
|
exports.getSmartLeadUser = getSmartLeadUser;
|
|
11
47
|
exports.clearSmartLeadToken = clearSmartLeadToken;
|
|
12
48
|
exports.clearAllSmartLeadTokens = clearAllSmartLeadTokens;
|
|
13
49
|
exports.getSmartLeadTokenCacheStats = getSmartLeadTokenCacheStats;
|
|
50
|
+
exports.enableFileCache = enableFileCache;
|
|
51
|
+
exports.disableFileCache = disableFileCache;
|
|
52
|
+
exports.isFileCacheEnabled = isFileCacheEnabled;
|
|
53
|
+
exports.clearFileCache = clearFileCache;
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
const os = __importStar(require("os"));
|
|
14
57
|
const DEFAULT_LOGIN_URL = 'https://server.smartlead.ai/api/auth/login';
|
|
15
58
|
const DEFAULT_REFRESH_BUFFER_MS = 5 * 60 * 1000; // 5 minutes
|
|
16
59
|
const TOKEN_LIFETIME_MS = 24 * 60 * 60 * 1000; // Assume 24h JWT lifetime (conservative)
|
|
@@ -152,5 +195,127 @@ function getSmartLeadTokenCacheStats() {
|
|
|
152
195
|
return {
|
|
153
196
|
cachedEmails: Array.from(tokenCache.keys()),
|
|
154
197
|
totalCached: tokenCache.size,
|
|
198
|
+
fileCacheEnabled,
|
|
199
|
+
fileCachePath: fileCacheEnabled ? getFileCachePath() : null,
|
|
155
200
|
};
|
|
156
201
|
}
|
|
202
|
+
// =============================================================================
|
|
203
|
+
// File-based Token Cache (for development/testing)
|
|
204
|
+
// =============================================================================
|
|
205
|
+
let fileCacheEnabled = false;
|
|
206
|
+
const FILE_CACHE_NAME = '.smartlead-tokens.json';
|
|
207
|
+
/**
|
|
208
|
+
* Get the file cache path
|
|
209
|
+
*/
|
|
210
|
+
function getFileCachePath() {
|
|
211
|
+
// Store in user's home directory or temp
|
|
212
|
+
const homeDir = os.homedir();
|
|
213
|
+
return path.join(homeDir, FILE_CACHE_NAME);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Load tokens from file cache
|
|
217
|
+
*/
|
|
218
|
+
function loadFileCache() {
|
|
219
|
+
const cache = new Map();
|
|
220
|
+
if (!fileCacheEnabled)
|
|
221
|
+
return cache;
|
|
222
|
+
try {
|
|
223
|
+
const filePath = getFileCachePath();
|
|
224
|
+
if (fs.existsSync(filePath)) {
|
|
225
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
226
|
+
const data = JSON.parse(content);
|
|
227
|
+
for (const [key, value] of Object.entries(data)) {
|
|
228
|
+
// Validate structure
|
|
229
|
+
if (value && value.token && value.expiresAt && value.obtainedAt) {
|
|
230
|
+
cache.set(key, value);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Ignore file read errors
|
|
237
|
+
}
|
|
238
|
+
return cache;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Save tokens to file cache
|
|
242
|
+
*/
|
|
243
|
+
function saveFileCache() {
|
|
244
|
+
if (!fileCacheEnabled)
|
|
245
|
+
return;
|
|
246
|
+
try {
|
|
247
|
+
const filePath = getFileCachePath();
|
|
248
|
+
const data = {};
|
|
249
|
+
for (const [key, value] of tokenCache.entries()) {
|
|
250
|
+
data[key] = value;
|
|
251
|
+
}
|
|
252
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Ignore file write errors
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Enable file-based token caching for development/testing
|
|
260
|
+
*
|
|
261
|
+
* When enabled, tokens are persisted to ~/.smartlead-tokens.json
|
|
262
|
+
* This avoids repeated logins during test development.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```ts
|
|
266
|
+
* // In your test setup
|
|
267
|
+
* import { enableFileCache } from 'linkedin-secret-sauce/enrichment';
|
|
268
|
+
*
|
|
269
|
+
* enableFileCache(); // Now tokens persist between test runs
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
function enableFileCache() {
|
|
273
|
+
fileCacheEnabled = true;
|
|
274
|
+
// Load existing tokens from file into memory cache
|
|
275
|
+
const fileTokens = loadFileCache();
|
|
276
|
+
for (const [key, value] of fileTokens.entries()) {
|
|
277
|
+
// Only load if not already in memory and still valid
|
|
278
|
+
if (!tokenCache.has(key) && isTokenValid(value, DEFAULT_REFRESH_BUFFER_MS)) {
|
|
279
|
+
tokenCache.set(key, value);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Disable file-based token caching
|
|
285
|
+
*/
|
|
286
|
+
function disableFileCache() {
|
|
287
|
+
fileCacheEnabled = false;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Check if file cache is enabled
|
|
291
|
+
*/
|
|
292
|
+
function isFileCacheEnabled() {
|
|
293
|
+
return fileCacheEnabled;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Clear the file cache
|
|
297
|
+
*/
|
|
298
|
+
function clearFileCache() {
|
|
299
|
+
try {
|
|
300
|
+
const filePath = getFileCachePath();
|
|
301
|
+
if (fs.existsSync(filePath)) {
|
|
302
|
+
fs.unlinkSync(filePath);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
// Ignore errors
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Patch the existing getSmartLeadToken to save to file cache after login
|
|
310
|
+
const originalGetSmartLeadToken = getSmartLeadToken;
|
|
311
|
+
// We need to modify the token caching behavior to persist to file
|
|
312
|
+
// This is done by wrapping the cache set operation
|
|
313
|
+
// Override tokenCache.set to also persist to file
|
|
314
|
+
const originalSet = tokenCache.set.bind(tokenCache);
|
|
315
|
+
tokenCache.set = function (key, value) {
|
|
316
|
+
const result = originalSet(key, value);
|
|
317
|
+
if (fileCacheEnabled) {
|
|
318
|
+
saveFileCache();
|
|
319
|
+
}
|
|
320
|
+
return result;
|
|
321
|
+
};
|
|
@@ -40,5 +40,7 @@ export { isDisposableEmail, isDisposableDomain, DISPOSABLE_DOMAINS, } from "./ut
|
|
|
40
40
|
export { isValidEmailSyntax, isRoleAccount, asciiFold, cleanNamePart, hostnameFromUrl, extractLinkedInUsername, } from "./utils/validation";
|
|
41
41
|
export { verifyEmailMx } from "./verification/mx";
|
|
42
42
|
export { createConstructProvider, createLddProvider, createSmartProspectProvider, createHunterProvider, createApolloProvider, createDropcontactProvider, } from "./providers";
|
|
43
|
-
export {
|
|
44
|
-
export {
|
|
43
|
+
export { createSmartProspectClient, type SmartProspectClient, type SmartProspectLocationOptions, } from "./providers/smartprospect";
|
|
44
|
+
export { enrichBusinessEmail, enrichBatch, enrichAllEmails, enrichAllBatch } from "./orchestrator";
|
|
45
|
+
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, enableFileCache, disableFileCache, isFileCacheEnabled, clearFileCache, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from "./auth";
|
|
46
|
+
export { calculateMatchConfidence, classifyMatchQuality, findBestMatch, matchContacts, buildSmartProspectFiltersFromLinkedIn, parseLinkedInSearchResponse, enrichLinkedInContact, enrichLinkedInContactsBatch, createLinkedInEnricher, type LinkedInContact, type MatchResult, type MatchOptions, type LinkedInEnrichmentResult, type LinkedInEnrichmentOptions, } from "./matching";
|
package/dist/enrichment/index.js
CHANGED
|
@@ -42,7 +42,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
42
42
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.enrichBatch = exports.enrichBusinessEmail = exports.createDropcontactProvider = exports.createApolloProvider = exports.createHunterProvider = exports.createSmartProspectProvider = exports.createLddProvider = exports.createConstructProvider = exports.verifyEmailMx = exports.extractLinkedInUsername = exports.hostnameFromUrl = exports.cleanNamePart = exports.asciiFold = exports.isRoleAccount = exports.isValidEmailSyntax = exports.DISPOSABLE_DOMAINS = exports.isDisposableDomain = exports.isDisposableEmail = exports.PERSONAL_DOMAINS = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = void 0;
|
|
45
|
+
exports.createLinkedInEnricher = exports.enrichLinkedInContactsBatch = exports.enrichLinkedInContact = exports.parseLinkedInSearchResponse = exports.buildSmartProspectFiltersFromLinkedIn = exports.matchContacts = exports.findBestMatch = exports.classifyMatchQuality = exports.calculateMatchConfidence = exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.enrichAllBatch = exports.enrichAllEmails = exports.enrichBatch = exports.enrichBusinessEmail = exports.createSmartProspectClient = exports.createDropcontactProvider = exports.createApolloProvider = exports.createHunterProvider = exports.createSmartProspectProvider = exports.createLddProvider = exports.createConstructProvider = exports.verifyEmailMx = exports.extractLinkedInUsername = exports.hostnameFromUrl = exports.cleanNamePart = exports.asciiFold = exports.isRoleAccount = exports.isValidEmailSyntax = exports.DISPOSABLE_DOMAINS = exports.isDisposableDomain = exports.isDisposableEmail = exports.PERSONAL_DOMAINS = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = void 0;
|
|
46
46
|
exports.createEnrichmentClient = createEnrichmentClient;
|
|
47
47
|
const orchestrator_1 = require("./orchestrator");
|
|
48
48
|
const construct_1 = require("./providers/construct");
|
|
@@ -154,6 +154,25 @@ function createEnrichmentClient(config) {
|
|
|
154
154
|
...batchOptions,
|
|
155
155
|
});
|
|
156
156
|
},
|
|
157
|
+
/**
|
|
158
|
+
* Enrich a single candidate and return ALL found emails from ALL providers
|
|
159
|
+
*
|
|
160
|
+
* Unlike `enrich()` which returns the first valid business email,
|
|
161
|
+
* this method queries all providers and returns every email found,
|
|
162
|
+
* including personal emails, with type classifications and scores.
|
|
163
|
+
*/
|
|
164
|
+
async enrichAll(candidate) {
|
|
165
|
+
return (0, orchestrator_1.enrichAllEmails)(candidate, orchestratorOptions);
|
|
166
|
+
},
|
|
167
|
+
/**
|
|
168
|
+
* Enrich multiple candidates and return ALL found emails for each
|
|
169
|
+
*/
|
|
170
|
+
async enrichAllBatch(candidates, batchOptions) {
|
|
171
|
+
return (0, orchestrator_1.enrichAllBatch)(candidates, {
|
|
172
|
+
...orchestratorOptions,
|
|
173
|
+
...batchOptions,
|
|
174
|
+
});
|
|
175
|
+
},
|
|
157
176
|
};
|
|
158
177
|
}
|
|
159
178
|
/**
|
|
@@ -231,10 +250,15 @@ Object.defineProperty(exports, "createSmartProspectProvider", { enumerable: true
|
|
|
231
250
|
Object.defineProperty(exports, "createHunterProvider", { enumerable: true, get: function () { return providers_1.createHunterProvider; } });
|
|
232
251
|
Object.defineProperty(exports, "createApolloProvider", { enumerable: true, get: function () { return providers_1.createApolloProvider; } });
|
|
233
252
|
Object.defineProperty(exports, "createDropcontactProvider", { enumerable: true, get: function () { return providers_1.createDropcontactProvider; } });
|
|
253
|
+
// Re-export SmartProspect client for direct API access
|
|
254
|
+
var smartprospect_2 = require("./providers/smartprospect");
|
|
255
|
+
Object.defineProperty(exports, "createSmartProspectClient", { enumerable: true, get: function () { return smartprospect_2.createSmartProspectClient; } });
|
|
234
256
|
// Re-export orchestrator (for advanced usage)
|
|
235
257
|
var orchestrator_2 = require("./orchestrator");
|
|
236
258
|
Object.defineProperty(exports, "enrichBusinessEmail", { enumerable: true, get: function () { return orchestrator_2.enrichBusinessEmail; } });
|
|
237
259
|
Object.defineProperty(exports, "enrichBatch", { enumerable: true, get: function () { return orchestrator_2.enrichBatch; } });
|
|
260
|
+
Object.defineProperty(exports, "enrichAllEmails", { enumerable: true, get: function () { return orchestrator_2.enrichAllEmails; } });
|
|
261
|
+
Object.defineProperty(exports, "enrichAllBatch", { enumerable: true, get: function () { return orchestrator_2.enrichAllBatch; } });
|
|
238
262
|
// Re-export auth utilities (for advanced usage)
|
|
239
263
|
var auth_1 = require("./auth");
|
|
240
264
|
Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return auth_1.getSmartLeadToken; } });
|
|
@@ -242,3 +266,21 @@ Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: func
|
|
|
242
266
|
Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return auth_1.clearSmartLeadToken; } });
|
|
243
267
|
Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return auth_1.clearAllSmartLeadTokens; } });
|
|
244
268
|
Object.defineProperty(exports, "getSmartLeadTokenCacheStats", { enumerable: true, get: function () { return auth_1.getSmartLeadTokenCacheStats; } });
|
|
269
|
+
// File cache utilities for development/testing
|
|
270
|
+
Object.defineProperty(exports, "enableFileCache", { enumerable: true, get: function () { return auth_1.enableFileCache; } });
|
|
271
|
+
Object.defineProperty(exports, "disableFileCache", { enumerable: true, get: function () { return auth_1.disableFileCache; } });
|
|
272
|
+
Object.defineProperty(exports, "isFileCacheEnabled", { enumerable: true, get: function () { return auth_1.isFileCacheEnabled; } });
|
|
273
|
+
Object.defineProperty(exports, "clearFileCache", { enumerable: true, get: function () { return auth_1.clearFileCache; } });
|
|
274
|
+
// Re-export matching utilities (LinkedIn <-> SmartProspect)
|
|
275
|
+
var matching_1 = require("./matching");
|
|
276
|
+
// Low-level matching functions
|
|
277
|
+
Object.defineProperty(exports, "calculateMatchConfidence", { enumerable: true, get: function () { return matching_1.calculateMatchConfidence; } });
|
|
278
|
+
Object.defineProperty(exports, "classifyMatchQuality", { enumerable: true, get: function () { return matching_1.classifyMatchQuality; } });
|
|
279
|
+
Object.defineProperty(exports, "findBestMatch", { enumerable: true, get: function () { return matching_1.findBestMatch; } });
|
|
280
|
+
Object.defineProperty(exports, "matchContacts", { enumerable: true, get: function () { return matching_1.matchContacts; } });
|
|
281
|
+
Object.defineProperty(exports, "buildSmartProspectFiltersFromLinkedIn", { enumerable: true, get: function () { return matching_1.buildSmartProspectFiltersFromLinkedIn; } });
|
|
282
|
+
Object.defineProperty(exports, "parseLinkedInSearchResponse", { enumerable: true, get: function () { return matching_1.parseLinkedInSearchResponse; } });
|
|
283
|
+
// High-level enrichment functions
|
|
284
|
+
Object.defineProperty(exports, "enrichLinkedInContact", { enumerable: true, get: function () { return matching_1.enrichLinkedInContact; } });
|
|
285
|
+
Object.defineProperty(exports, "enrichLinkedInContactsBatch", { enumerable: true, get: function () { return matching_1.enrichLinkedInContactsBatch; } });
|
|
286
|
+
Object.defineProperty(exports, "createLinkedInEnricher", { enumerable: true, get: function () { return matching_1.createLinkedInEnricher; } });
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact Matching Utilities
|
|
3
|
+
*
|
|
4
|
+
* Matches contacts between LinkedIn Sales Navigator and SmartProspect
|
|
5
|
+
* to find the same person across both platforms.
|
|
6
|
+
*/
|
|
7
|
+
import type { SmartProspectContact, SmartProspectConfig, SmartProspectFetchResponse } from './types';
|
|
8
|
+
import { type SmartProspectClient } from './providers/smartprospect';
|
|
9
|
+
/**
|
|
10
|
+
* LinkedIn Sales Navigator contact (simplified from API response)
|
|
11
|
+
*/
|
|
12
|
+
export interface LinkedInContact {
|
|
13
|
+
/** LinkedIn member URN (e.g., "urn:li:member:1044675597") */
|
|
14
|
+
objectUrn?: string;
|
|
15
|
+
/** Sales Nav entity URN */
|
|
16
|
+
entityUrn?: string;
|
|
17
|
+
firstName: string;
|
|
18
|
+
lastName: string;
|
|
19
|
+
fullName?: string;
|
|
20
|
+
/** Geographic region (e.g., "Sofia, Sofia City, Bulgaria") */
|
|
21
|
+
geoRegion?: string;
|
|
22
|
+
/** Current positions array */
|
|
23
|
+
currentPositions?: Array<{
|
|
24
|
+
companyName?: string;
|
|
25
|
+
title?: string;
|
|
26
|
+
companyUrn?: string;
|
|
27
|
+
companyUrnResolutionResult?: {
|
|
28
|
+
name?: string;
|
|
29
|
+
website?: string;
|
|
30
|
+
industry?: string;
|
|
31
|
+
location?: string;
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
34
|
+
/** Profile picture */
|
|
35
|
+
profilePictureDisplayImage?: {
|
|
36
|
+
rootUrl?: string;
|
|
37
|
+
artifacts?: Array<{
|
|
38
|
+
fileIdentifyingUrlPathSegment?: string;
|
|
39
|
+
}>;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Match result with confidence score
|
|
44
|
+
*/
|
|
45
|
+
export interface MatchResult {
|
|
46
|
+
/** The matched SmartProspect contact */
|
|
47
|
+
smartProspectContact: SmartProspectContact;
|
|
48
|
+
/** The LinkedIn contact that was matched */
|
|
49
|
+
linkedInContact: LinkedInContact;
|
|
50
|
+
/** Match confidence score (0-100) */
|
|
51
|
+
confidence: number;
|
|
52
|
+
/** Which fields matched */
|
|
53
|
+
matchedFields: string[];
|
|
54
|
+
/** Match quality classification */
|
|
55
|
+
quality: 'exact' | 'high' | 'medium' | 'low' | 'none';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Options for matching
|
|
59
|
+
*/
|
|
60
|
+
export interface MatchOptions {
|
|
61
|
+
/** Minimum confidence threshold (default: 50) */
|
|
62
|
+
minConfidence?: number;
|
|
63
|
+
/** Whether to use fuzzy matching for names (default: true) */
|
|
64
|
+
fuzzyNames?: boolean;
|
|
65
|
+
/** Whether to use fuzzy matching for company names (default: true) */
|
|
66
|
+
fuzzyCompany?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Calculate match confidence between a LinkedIn contact and SmartProspect contact
|
|
70
|
+
*/
|
|
71
|
+
export declare function calculateMatchConfidence(linkedin: LinkedInContact, smartprospect: SmartProspectContact, options?: MatchOptions): {
|
|
72
|
+
confidence: number;
|
|
73
|
+
matchedFields: string[];
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Classify match quality based on confidence and matched fields
|
|
77
|
+
*/
|
|
78
|
+
export declare function classifyMatchQuality(confidence: number, matchedFields: string[]): 'exact' | 'high' | 'medium' | 'low' | 'none';
|
|
79
|
+
/**
|
|
80
|
+
* Find the best matching SmartProspect contact for a LinkedIn contact
|
|
81
|
+
*/
|
|
82
|
+
export declare function findBestMatch(linkedInContact: LinkedInContact, smartProspectContacts: SmartProspectContact[], options?: MatchOptions): MatchResult | null;
|
|
83
|
+
/**
|
|
84
|
+
* Match multiple LinkedIn contacts to SmartProspect contacts
|
|
85
|
+
*/
|
|
86
|
+
export declare function matchContacts(linkedInContacts: LinkedInContact[], smartProspectContacts: SmartProspectContact[], options?: MatchOptions): MatchResult[];
|
|
87
|
+
/**
|
|
88
|
+
* Build SmartProspect search filters from a LinkedIn contact
|
|
89
|
+
* This helps you search SmartProspect for a specific LinkedIn contact
|
|
90
|
+
*/
|
|
91
|
+
export declare function buildSmartProspectFiltersFromLinkedIn(linkedInContact: LinkedInContact): {
|
|
92
|
+
firstName: string[];
|
|
93
|
+
lastName: string[];
|
|
94
|
+
companyName?: string[];
|
|
95
|
+
title?: string[];
|
|
96
|
+
country?: string[];
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Parse LinkedIn Sales Navigator API response elements into LinkedInContact array
|
|
100
|
+
*/
|
|
101
|
+
export declare function parseLinkedInSearchResponse(elements: Array<Record<string, unknown>>): LinkedInContact[];
|
|
102
|
+
/**
|
|
103
|
+
* Result of enriching a LinkedIn contact via SmartProspect
|
|
104
|
+
*/
|
|
105
|
+
export interface LinkedInEnrichmentResult {
|
|
106
|
+
/** Whether enrichment was successful */
|
|
107
|
+
success: boolean;
|
|
108
|
+
/** The original LinkedIn contact */
|
|
109
|
+
linkedInContact: LinkedInContact;
|
|
110
|
+
/** The matched SmartProspect contact (if found) */
|
|
111
|
+
matchedContact: SmartProspectContact | null;
|
|
112
|
+
/** Match confidence score (0-100) */
|
|
113
|
+
matchConfidence: number;
|
|
114
|
+
/** Match quality classification */
|
|
115
|
+
matchQuality: 'exact' | 'high' | 'medium' | 'low' | 'none';
|
|
116
|
+
/** Which fields matched */
|
|
117
|
+
matchedFields: string[];
|
|
118
|
+
/** Enriched email (if fetched) */
|
|
119
|
+
email: string | null;
|
|
120
|
+
/** Email deliverability score (0-1) */
|
|
121
|
+
emailDeliverability: number;
|
|
122
|
+
/** Email verification status */
|
|
123
|
+
verificationStatus: string | null;
|
|
124
|
+
/** All candidate contacts found in SmartProspect */
|
|
125
|
+
allCandidates: SmartProspectContact[];
|
|
126
|
+
/** Total candidates found in search */
|
|
127
|
+
totalCandidatesFound: number;
|
|
128
|
+
/** Error message if failed */
|
|
129
|
+
error?: string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Options for LinkedIn contact enrichment
|
|
133
|
+
*/
|
|
134
|
+
export interface LinkedInEnrichmentOptions {
|
|
135
|
+
/** Minimum match confidence to consider (default: 60) */
|
|
136
|
+
minConfidence?: number;
|
|
137
|
+
/** Whether to auto-fetch email if good match found (default: true) - COSTS CREDITS */
|
|
138
|
+
autoFetch?: boolean;
|
|
139
|
+
/** Whether to use fuzzy name matching (default: true) */
|
|
140
|
+
fuzzyNames?: boolean;
|
|
141
|
+
/** Whether to use fuzzy company matching (default: true) */
|
|
142
|
+
fuzzyCompany?: boolean;
|
|
143
|
+
/** Search limit - how many candidates to retrieve (default: 25) */
|
|
144
|
+
searchLimit?: number;
|
|
145
|
+
/** Whether to include company name in search (default: true) */
|
|
146
|
+
includeCompany?: boolean;
|
|
147
|
+
/** Whether to include location in search (default: false) */
|
|
148
|
+
includeLocation?: boolean;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Enrich a LinkedIn Sales Navigator contact using SmartProspect
|
|
152
|
+
*
|
|
153
|
+
* This is the main function consumers should use. It:
|
|
154
|
+
* 1. Takes a LinkedIn contact from Sales Navigator search results
|
|
155
|
+
* 2. Searches SmartProspect for matching candidates
|
|
156
|
+
* 3. Uses intelligent matching to find the exact same person
|
|
157
|
+
* 4. Optionally fetches their verified email (costs credits)
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* import { enrichLinkedInContact } from 'linkedin-secret-sauce';
|
|
162
|
+
*
|
|
163
|
+
* // From your LinkedIn Sales Nav search result
|
|
164
|
+
* const linkedInContact = {
|
|
165
|
+
* firstName: 'Valentin',
|
|
166
|
+
* lastName: 'Rangelov',
|
|
167
|
+
* geoRegion: 'Sofia, Sofia City, Bulgaria',
|
|
168
|
+
* currentPositions: [{
|
|
169
|
+
* companyName: 'Recruitica',
|
|
170
|
+
* title: 'Chief Technology Officer'
|
|
171
|
+
* }]
|
|
172
|
+
* };
|
|
173
|
+
*
|
|
174
|
+
* const result = await enrichLinkedInContact(linkedInContact, {
|
|
175
|
+
* email: process.env.SMARTLEAD_EMAIL,
|
|
176
|
+
* password: process.env.SMARTLEAD_PASSWORD
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* if (result.success && result.email) {
|
|
180
|
+
* console.log(`Found email: ${result.email}`);
|
|
181
|
+
* console.log(`Match confidence: ${result.matchConfidence}%`);
|
|
182
|
+
* console.log(`Deliverability: ${result.emailDeliverability * 100}%`);
|
|
183
|
+
* }
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
export declare function enrichLinkedInContact(linkedInContact: LinkedInContact, smartProspectConfig: SmartProspectConfig, options?: LinkedInEnrichmentOptions): Promise<LinkedInEnrichmentResult>;
|
|
187
|
+
/**
|
|
188
|
+
* Enrich multiple LinkedIn contacts in batch
|
|
189
|
+
*
|
|
190
|
+
* Processes contacts sequentially to avoid rate limits.
|
|
191
|
+
* For parallel processing, use Promise.all with rate limiting.
|
|
192
|
+
*/
|
|
193
|
+
export declare function enrichLinkedInContactsBatch(linkedInContacts: LinkedInContact[], smartProspectConfig: SmartProspectConfig, options?: LinkedInEnrichmentOptions & {
|
|
194
|
+
/** Delay between requests in ms (default: 200) */
|
|
195
|
+
delayMs?: number;
|
|
196
|
+
/** Callback for progress updates */
|
|
197
|
+
onProgress?: (completed: number, total: number, result: LinkedInEnrichmentResult) => void;
|
|
198
|
+
}): Promise<LinkedInEnrichmentResult[]>;
|
|
199
|
+
/**
|
|
200
|
+
* Create a reusable enricher function with pre-configured SmartProspect client
|
|
201
|
+
*
|
|
202
|
+
* More efficient for multiple enrichments as it reuses the same client/token.
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ```ts
|
|
206
|
+
* const enricher = createLinkedInEnricher({
|
|
207
|
+
* email: process.env.SMARTLEAD_EMAIL,
|
|
208
|
+
* password: process.env.SMARTLEAD_PASSWORD
|
|
209
|
+
* });
|
|
210
|
+
*
|
|
211
|
+
* // Now use for multiple contacts
|
|
212
|
+
* const result1 = await enricher.enrich(contact1);
|
|
213
|
+
* const result2 = await enricher.enrich(contact2);
|
|
214
|
+
*
|
|
215
|
+
* // Or batch
|
|
216
|
+
* const results = await enricher.enrichBatch([contact1, contact2, contact3]);
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
export declare function createLinkedInEnricher(smartProspectConfig: SmartProspectConfig, defaultOptions?: LinkedInEnrichmentOptions): {
|
|
220
|
+
/** The underlying SmartProspect client */
|
|
221
|
+
client: SmartProspectClient;
|
|
222
|
+
/** Enrich a single LinkedIn contact */
|
|
223
|
+
enrich: (contact: LinkedInContact, options?: LinkedInEnrichmentOptions) => Promise<LinkedInEnrichmentResult>;
|
|
224
|
+
/** Enrich multiple LinkedIn contacts */
|
|
225
|
+
enrichBatch: (contacts: LinkedInContact[], options?: LinkedInEnrichmentOptions & {
|
|
226
|
+
delayMs?: number;
|
|
227
|
+
onProgress?: (completed: number, total: number, result: LinkedInEnrichmentResult) => void;
|
|
228
|
+
}) => Promise<LinkedInEnrichmentResult[]>;
|
|
229
|
+
/** Search SmartProspect for a LinkedIn contact without fetching (FREE) */
|
|
230
|
+
searchOnly: (contact: LinkedInContact, options?: {
|
|
231
|
+
searchLimit?: number;
|
|
232
|
+
includeCompany?: boolean;
|
|
233
|
+
}) => Promise<{
|
|
234
|
+
candidates: SmartProspectContact[];
|
|
235
|
+
bestMatch: MatchResult | null;
|
|
236
|
+
}>;
|
|
237
|
+
/** Fetch email for a specific SmartProspect contact ID (COSTS CREDITS) */
|
|
238
|
+
fetchEmail: (contactId: string) => Promise<SmartProspectFetchResponse>;
|
|
239
|
+
} | null;
|