linkedin-secret-sauce 0.5.0 → 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 +4 -0
- package/dist/enrichment/auth/index.js +17 -0
- package/dist/enrichment/auth/smartlead-auth.d.ts +82 -0
- package/dist/enrichment/auth/smartlead-auth.js +321 -0
- package/dist/enrichment/index.d.ts +11 -8
- package/dist/enrichment/index.js +75 -20
- 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 +72 -2
- package/dist/enrichment/providers/smartprospect.js +512 -72
- package/dist/enrichment/types.d.ts +156 -14
- package/dist/enrichment/types.js +56 -7
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication modules for enrichment providers
|
|
3
|
+
*/
|
|
4
|
+
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, enableFileCache, disableFileCache, isFileCacheEnabled, clearFileCache, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from './smartlead-auth';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authentication modules for enrichment providers
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = void 0;
|
|
7
|
+
var smartlead_auth_1 = require("./smartlead-auth");
|
|
8
|
+
Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return smartlead_auth_1.getSmartLeadToken; } });
|
|
9
|
+
Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return smartlead_auth_1.getSmartLeadUser; } });
|
|
10
|
+
Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return smartlead_auth_1.clearSmartLeadToken; } });
|
|
11
|
+
Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return smartlead_auth_1.clearAllSmartLeadTokens; } });
|
|
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; } });
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SmartLead Authentication Client
|
|
3
|
+
*
|
|
4
|
+
* Handles JWT token acquisition via email/password login.
|
|
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()`.
|
|
9
|
+
*/
|
|
10
|
+
export interface SmartLeadCredentials {
|
|
11
|
+
email: string;
|
|
12
|
+
password: string;
|
|
13
|
+
}
|
|
14
|
+
export interface SmartLeadAuthConfig {
|
|
15
|
+
credentials: SmartLeadCredentials;
|
|
16
|
+
/** Login API URL (default: https://server.smartlead.ai/api/auth/login) */
|
|
17
|
+
loginUrl?: string;
|
|
18
|
+
/** Token refresh buffer in ms - refresh this much before expiry (default: 5 min) */
|
|
19
|
+
refreshBufferMs?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface SmartLeadUser {
|
|
22
|
+
id: number;
|
|
23
|
+
uuid: string;
|
|
24
|
+
email: string;
|
|
25
|
+
name: string;
|
|
26
|
+
role: string;
|
|
27
|
+
api_key: string;
|
|
28
|
+
region: string;
|
|
29
|
+
}
|
|
30
|
+
export interface SmartLeadLoginResponse {
|
|
31
|
+
user: SmartLeadUser;
|
|
32
|
+
token: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function getSmartLeadToken(config: SmartLeadAuthConfig): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Get SmartLead user info (from cached login)
|
|
37
|
+
*/
|
|
38
|
+
export declare function getSmartLeadUser(config: SmartLeadAuthConfig): Promise<SmartLeadUser>;
|
|
39
|
+
/**
|
|
40
|
+
* Force clear cached token (e.g., on 401 error)
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearSmartLeadToken(email: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Clear all cached tokens
|
|
45
|
+
*/
|
|
46
|
+
export declare function clearAllSmartLeadTokens(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get token cache stats (for debugging)
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSmartLeadTokenCacheStats(): {
|
|
51
|
+
cachedEmails: string[];
|
|
52
|
+
totalCached: number;
|
|
53
|
+
fileCacheEnabled: boolean;
|
|
54
|
+
fileCachePath: string | null;
|
|
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;
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SmartLead Authentication Client
|
|
4
|
+
*
|
|
5
|
+
* Handles JWT token acquisition via email/password login.
|
|
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()`.
|
|
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
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.getSmartLeadToken = getSmartLeadToken;
|
|
46
|
+
exports.getSmartLeadUser = getSmartLeadUser;
|
|
47
|
+
exports.clearSmartLeadToken = clearSmartLeadToken;
|
|
48
|
+
exports.clearAllSmartLeadTokens = clearAllSmartLeadTokens;
|
|
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"));
|
|
57
|
+
const DEFAULT_LOGIN_URL = 'https://server.smartlead.ai/api/auth/login';
|
|
58
|
+
const DEFAULT_REFRESH_BUFFER_MS = 5 * 60 * 1000; // 5 minutes
|
|
59
|
+
const TOKEN_LIFETIME_MS = 24 * 60 * 60 * 1000; // Assume 24h JWT lifetime (conservative)
|
|
60
|
+
// In-memory token cache keyed by email
|
|
61
|
+
const tokenCache = new Map();
|
|
62
|
+
/**
|
|
63
|
+
* Parse JWT to extract expiration time
|
|
64
|
+
*/
|
|
65
|
+
function parseJwtExpiry(token) {
|
|
66
|
+
try {
|
|
67
|
+
const parts = token.split('.');
|
|
68
|
+
if (parts.length !== 3)
|
|
69
|
+
return null;
|
|
70
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf8'));
|
|
71
|
+
if (payload.exp) {
|
|
72
|
+
return payload.exp * 1000; // Convert to ms
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Login to SmartLead and obtain JWT token
|
|
82
|
+
*/
|
|
83
|
+
async function login(config) {
|
|
84
|
+
const { credentials, loginUrl = DEFAULT_LOGIN_URL } = config;
|
|
85
|
+
const response = await fetch(loginUrl, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: {
|
|
88
|
+
Accept: 'application/json, text/plain, */*',
|
|
89
|
+
'Content-Type': 'application/json',
|
|
90
|
+
Origin: 'https://app.smartlead.ai',
|
|
91
|
+
Referer: 'https://app.smartlead.ai/',
|
|
92
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36',
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify({
|
|
95
|
+
email: credentials.email,
|
|
96
|
+
password: credentials.password,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const errorText = await response.text().catch(() => '');
|
|
101
|
+
throw new Error(`SmartLead login failed: ${response.status} - ${errorText}`);
|
|
102
|
+
}
|
|
103
|
+
const data = (await response.json());
|
|
104
|
+
if (!data.token || !data.user) {
|
|
105
|
+
throw new Error('SmartLead login response missing token or user');
|
|
106
|
+
}
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
// Try to parse expiry from JWT, fallback to assumed lifetime
|
|
109
|
+
let expiresAt = parseJwtExpiry(data.token);
|
|
110
|
+
if (!expiresAt) {
|
|
111
|
+
expiresAt = now + TOKEN_LIFETIME_MS;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
token: data.token,
|
|
115
|
+
user: data.user,
|
|
116
|
+
expiresAt,
|
|
117
|
+
obtainedAt: now,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Check if cached token is still valid (with buffer for refresh)
|
|
122
|
+
*/
|
|
123
|
+
function isTokenValid(cached, refreshBufferMs) {
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
return cached.expiresAt - refreshBufferMs > now;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get a valid SmartLead JWT token
|
|
129
|
+
*
|
|
130
|
+
* Returns cached token if still valid, otherwise performs fresh login.
|
|
131
|
+
* Thread-safe via promise deduplication.
|
|
132
|
+
*/
|
|
133
|
+
const pendingLogins = new Map();
|
|
134
|
+
async function getSmartLeadToken(config) {
|
|
135
|
+
const { credentials, refreshBufferMs = DEFAULT_REFRESH_BUFFER_MS } = config;
|
|
136
|
+
const cacheKey = credentials.email.toLowerCase();
|
|
137
|
+
// Check cache first
|
|
138
|
+
const cached = tokenCache.get(cacheKey);
|
|
139
|
+
if (cached && isTokenValid(cached, refreshBufferMs)) {
|
|
140
|
+
return cached.token;
|
|
141
|
+
}
|
|
142
|
+
// Check if login already in progress (dedup concurrent requests)
|
|
143
|
+
const pending = pendingLogins.get(cacheKey);
|
|
144
|
+
if (pending) {
|
|
145
|
+
const result = await pending;
|
|
146
|
+
return result.token;
|
|
147
|
+
}
|
|
148
|
+
// Perform login
|
|
149
|
+
const loginPromise = login(config);
|
|
150
|
+
pendingLogins.set(cacheKey, loginPromise);
|
|
151
|
+
try {
|
|
152
|
+
const result = await loginPromise;
|
|
153
|
+
tokenCache.set(cacheKey, result);
|
|
154
|
+
return result.token;
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
pendingLogins.delete(cacheKey);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get SmartLead user info (from cached login)
|
|
162
|
+
*/
|
|
163
|
+
async function getSmartLeadUser(config) {
|
|
164
|
+
const { credentials, refreshBufferMs = DEFAULT_REFRESH_BUFFER_MS } = config;
|
|
165
|
+
const cacheKey = credentials.email.toLowerCase();
|
|
166
|
+
// Check cache first
|
|
167
|
+
const cached = tokenCache.get(cacheKey);
|
|
168
|
+
if (cached && isTokenValid(cached, refreshBufferMs)) {
|
|
169
|
+
return cached.user;
|
|
170
|
+
}
|
|
171
|
+
// Perform login to get fresh user info
|
|
172
|
+
await getSmartLeadToken(config);
|
|
173
|
+
const freshCached = tokenCache.get(cacheKey);
|
|
174
|
+
if (!freshCached) {
|
|
175
|
+
throw new Error('SmartLead auth: failed to obtain user info');
|
|
176
|
+
}
|
|
177
|
+
return freshCached.user;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Force clear cached token (e.g., on 401 error)
|
|
181
|
+
*/
|
|
182
|
+
function clearSmartLeadToken(email) {
|
|
183
|
+
tokenCache.delete(email.toLowerCase());
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Clear all cached tokens
|
|
187
|
+
*/
|
|
188
|
+
function clearAllSmartLeadTokens() {
|
|
189
|
+
tokenCache.clear();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get token cache stats (for debugging)
|
|
193
|
+
*/
|
|
194
|
+
function getSmartLeadTokenCacheStats() {
|
|
195
|
+
return {
|
|
196
|
+
cachedEmails: Array.from(tokenCache.keys()),
|
|
197
|
+
totalCached: tokenCache.size,
|
|
198
|
+
fileCacheEnabled,
|
|
199
|
+
fileCachePath: fileCacheEnabled ? getFileCachePath() : null,
|
|
200
|
+
};
|
|
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
|
+
};
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* });
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
import type { EnrichmentClientConfig, EnrichmentClient } from
|
|
29
|
+
import type { EnrichmentClientConfig, EnrichmentClient } from "./types";
|
|
30
30
|
/**
|
|
31
31
|
* Create an enrichment client with the given configuration
|
|
32
32
|
*
|
|
@@ -34,10 +34,13 @@ import type { EnrichmentClientConfig, EnrichmentClient } from './types';
|
|
|
34
34
|
* @returns An enrichment client with enrich and enrichBatch methods
|
|
35
35
|
*/
|
|
36
36
|
export declare function createEnrichmentClient(config: EnrichmentClientConfig): EnrichmentClient;
|
|
37
|
-
export * from
|
|
38
|
-
export { isPersonalEmail, isBusinessEmail, isPersonalDomain, PERSONAL_DOMAINS, } from
|
|
39
|
-
export { isDisposableEmail, isDisposableDomain, DISPOSABLE_DOMAINS, } from
|
|
40
|
-
export { isValidEmailSyntax, isRoleAccount, asciiFold, cleanNamePart, hostnameFromUrl, extractLinkedInUsername, } from
|
|
41
|
-
export { verifyEmailMx } from
|
|
42
|
-
export { createConstructProvider, createLddProvider, createSmartProspectProvider, createHunterProvider, createApolloProvider, createDropcontactProvider, } from
|
|
43
|
-
export {
|
|
37
|
+
export * from "./types";
|
|
38
|
+
export { isPersonalEmail, isBusinessEmail, isPersonalDomain, PERSONAL_DOMAINS, } from "./utils/personal-domains";
|
|
39
|
+
export { isDisposableEmail, isDisposableDomain, DISPOSABLE_DOMAINS, } from "./utils/disposable-domains";
|
|
40
|
+
export { isValidEmailSyntax, isRoleAccount, asciiFold, cleanNamePart, hostnameFromUrl, extractLinkedInUsername, } from "./utils/validation";
|
|
41
|
+
export { verifyEmailMx } from "./verification/mx";
|
|
42
|
+
export { createConstructProvider, createLddProvider, createSmartProspectProvider, createHunterProvider, createApolloProvider, createDropcontactProvider, } from "./providers";
|
|
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.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");
|
|
@@ -55,12 +55,12 @@ const dropcontact_1 = require("./providers/dropcontact");
|
|
|
55
55
|
* Default provider order
|
|
56
56
|
*/
|
|
57
57
|
const DEFAULT_ORDER = [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
"construct",
|
|
59
|
+
"ldd",
|
|
60
|
+
"smartprospect",
|
|
61
|
+
"hunter",
|
|
62
|
+
"apollo",
|
|
63
|
+
"dropcontact",
|
|
64
64
|
];
|
|
65
65
|
/**
|
|
66
66
|
* Create an enrichment client with the given configuration
|
|
@@ -69,26 +69,26 @@ const DEFAULT_ORDER = [
|
|
|
69
69
|
* @returns An enrichment client with enrich and enrichBatch methods
|
|
70
70
|
*/
|
|
71
71
|
function createEnrichmentClient(config) {
|
|
72
|
-
const { providers: providerConfigs, options = {}, cache, onCost, logger } = config;
|
|
72
|
+
const { providers: providerConfigs, options = {}, cache, onCost, logger, } = config;
|
|
73
73
|
// Build provider functions based on configuration
|
|
74
74
|
const providerFuncs = new Map();
|
|
75
75
|
// Always create construct provider (free, no API key needed)
|
|
76
|
-
providerFuncs.set(
|
|
76
|
+
providerFuncs.set("construct", (0, construct_1.createConstructProvider)(providerConfigs.construct));
|
|
77
77
|
// Create other providers if configured
|
|
78
78
|
if (providerConfigs.ldd) {
|
|
79
|
-
providerFuncs.set(
|
|
79
|
+
providerFuncs.set("ldd", (0, ldd_1.createLddProvider)(providerConfigs.ldd));
|
|
80
80
|
}
|
|
81
81
|
if (providerConfigs.smartprospect) {
|
|
82
|
-
providerFuncs.set(
|
|
82
|
+
providerFuncs.set("smartprospect", (0, smartprospect_1.createSmartProspectProvider)(providerConfigs.smartprospect));
|
|
83
83
|
}
|
|
84
84
|
if (providerConfigs.hunter) {
|
|
85
|
-
providerFuncs.set(
|
|
85
|
+
providerFuncs.set("hunter", (0, hunter_1.createHunterProvider)(providerConfigs.hunter));
|
|
86
86
|
}
|
|
87
87
|
if (providerConfigs.apollo) {
|
|
88
|
-
providerFuncs.set(
|
|
88
|
+
providerFuncs.set("apollo", (0, apollo_1.createApolloProvider)(providerConfigs.apollo));
|
|
89
89
|
}
|
|
90
90
|
if (providerConfigs.dropcontact) {
|
|
91
|
-
providerFuncs.set(
|
|
91
|
+
providerFuncs.set("dropcontact", (0, dropcontact_1.createDropcontactProvider)(providerConfigs.dropcontact));
|
|
92
92
|
}
|
|
93
93
|
// Build ordered provider list
|
|
94
94
|
const providerOrder = options.providerOrder ?? DEFAULT_ORDER;
|
|
@@ -120,7 +120,7 @@ function createEnrichmentClient(config) {
|
|
|
120
120
|
try {
|
|
121
121
|
const cached = await cache.get(cacheKey);
|
|
122
122
|
if (cached) {
|
|
123
|
-
logger?.debug?.(
|
|
123
|
+
logger?.debug?.("enrichment.cache.hit", { cacheKey });
|
|
124
124
|
return cached;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
@@ -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
|
/**
|
|
@@ -176,10 +195,16 @@ function buildCacheKey(candidate) {
|
|
|
176
195
|
}
|
|
177
196
|
else {
|
|
178
197
|
// Fall back to name + domain/company
|
|
179
|
-
const firstName = candidate.firstName || candidate.first_name || candidate.first ||
|
|
180
|
-
const lastName = candidate.lastName || candidate.last_name || candidate.last ||
|
|
181
|
-
const domain = candidate.domain ||
|
|
182
|
-
|
|
198
|
+
const firstName = candidate.firstName || candidate.first_name || candidate.first || "";
|
|
199
|
+
const lastName = candidate.lastName || candidate.last_name || candidate.last || "";
|
|
200
|
+
const domain = candidate.domain ||
|
|
201
|
+
candidate.companyDomain ||
|
|
202
|
+
candidate.company_domain ||
|
|
203
|
+
"";
|
|
204
|
+
const company = candidate.company ||
|
|
205
|
+
candidate.currentCompany ||
|
|
206
|
+
candidate.organization ||
|
|
207
|
+
"";
|
|
183
208
|
if (firstName && (domain || company)) {
|
|
184
209
|
parts.push(`name:${firstName.toLowerCase()}`);
|
|
185
210
|
if (lastName)
|
|
@@ -193,7 +218,7 @@ function buildCacheKey(candidate) {
|
|
|
193
218
|
if (parts.length === 0) {
|
|
194
219
|
return null;
|
|
195
220
|
}
|
|
196
|
-
return parts.join(
|
|
221
|
+
return parts.join("|");
|
|
197
222
|
}
|
|
198
223
|
// Re-export types
|
|
199
224
|
__exportStar(require("./types"), exports);
|
|
@@ -225,7 +250,37 @@ Object.defineProperty(exports, "createSmartProspectProvider", { enumerable: true
|
|
|
225
250
|
Object.defineProperty(exports, "createHunterProvider", { enumerable: true, get: function () { return providers_1.createHunterProvider; } });
|
|
226
251
|
Object.defineProperty(exports, "createApolloProvider", { enumerable: true, get: function () { return providers_1.createApolloProvider; } });
|
|
227
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; } });
|
|
228
256
|
// Re-export orchestrator (for advanced usage)
|
|
229
257
|
var orchestrator_2 = require("./orchestrator");
|
|
230
258
|
Object.defineProperty(exports, "enrichBusinessEmail", { enumerable: true, get: function () { return orchestrator_2.enrichBusinessEmail; } });
|
|
231
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; } });
|
|
262
|
+
// Re-export auth utilities (for advanced usage)
|
|
263
|
+
var auth_1 = require("./auth");
|
|
264
|
+
Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return auth_1.getSmartLeadToken; } });
|
|
265
|
+
Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return auth_1.getSmartLeadUser; } });
|
|
266
|
+
Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return auth_1.clearSmartLeadToken; } });
|
|
267
|
+
Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return auth_1.clearAllSmartLeadTokens; } });
|
|
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; } });
|