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.
@@ -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 { enrichBusinessEmail, enrichBatch } from "./orchestrator";
44
- export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from "./auth";
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";
@@ -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;