linkedin-secret-sauce 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/enrichment/auth/index.d.ts +4 -0
- package/dist/enrichment/auth/index.js +12 -0
- package/dist/enrichment/auth/smartlead-auth.d.ts +50 -0
- package/dist/enrichment/auth/smartlead-auth.js +156 -0
- package/dist/enrichment/index.d.ts +44 -0
- package/dist/enrichment/index.js +244 -0
- package/dist/enrichment/orchestrator.d.ts +31 -0
- package/dist/enrichment/orchestrator.js +218 -0
- package/dist/enrichment/providers/apollo.d.ts +11 -0
- package/dist/enrichment/providers/apollo.js +136 -0
- package/dist/enrichment/providers/construct.d.ts +11 -0
- package/dist/enrichment/providers/construct.js +107 -0
- package/dist/enrichment/providers/dropcontact.d.ts +16 -0
- package/dist/enrichment/providers/dropcontact.js +37 -0
- package/dist/enrichment/providers/hunter.d.ts +11 -0
- package/dist/enrichment/providers/hunter.js +162 -0
- package/dist/enrichment/providers/index.d.ts +9 -0
- package/dist/enrichment/providers/index.js +18 -0
- package/dist/enrichment/providers/ldd.d.ts +11 -0
- package/dist/enrichment/providers/ldd.js +110 -0
- package/dist/enrichment/providers/smartprospect.d.ts +19 -0
- package/dist/enrichment/providers/smartprospect.js +333 -0
- package/dist/enrichment/types.d.ts +343 -0
- package/dist/enrichment/types.js +31 -0
- package/dist/enrichment/utils/disposable-domains.d.ts +24 -0
- package/dist/enrichment/utils/disposable-domains.js +1011 -0
- package/dist/enrichment/utils/index.d.ts +6 -0
- package/dist/enrichment/utils/index.js +22 -0
- package/dist/enrichment/utils/personal-domains.d.ts +31 -0
- package/dist/enrichment/utils/personal-domains.js +95 -0
- package/dist/enrichment/utils/validation.d.ts +42 -0
- package/dist/enrichment/utils/validation.js +130 -0
- package/dist/enrichment/verification/index.d.ts +4 -0
- package/dist/enrichment/verification/index.js +8 -0
- package/dist/enrichment/verification/mx.d.ts +16 -0
- package/dist/enrichment/verification/mx.js +168 -0
- package/dist/index.d.ts +18 -14
- package/dist/index.js +26 -1
- package/package.json +15 -16
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication modules for enrichment providers
|
|
3
|
+
*/
|
|
4
|
+
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from './smartlead-auth';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authentication modules for enrichment providers
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
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; } });
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
export interface SmartLeadCredentials {
|
|
8
|
+
email: string;
|
|
9
|
+
password: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SmartLeadAuthConfig {
|
|
12
|
+
credentials: SmartLeadCredentials;
|
|
13
|
+
/** Login API URL (default: https://server.smartlead.ai/api/auth/login) */
|
|
14
|
+
loginUrl?: string;
|
|
15
|
+
/** Token refresh buffer in ms - refresh this much before expiry (default: 5 min) */
|
|
16
|
+
refreshBufferMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SmartLeadUser {
|
|
19
|
+
id: number;
|
|
20
|
+
uuid: string;
|
|
21
|
+
email: string;
|
|
22
|
+
name: string;
|
|
23
|
+
role: string;
|
|
24
|
+
api_key: string;
|
|
25
|
+
region: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SmartLeadLoginResponse {
|
|
28
|
+
user: SmartLeadUser;
|
|
29
|
+
token: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function getSmartLeadToken(config: SmartLeadAuthConfig): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Get SmartLead user info (from cached login)
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSmartLeadUser(config: SmartLeadAuthConfig): Promise<SmartLeadUser>;
|
|
36
|
+
/**
|
|
37
|
+
* Force clear cached token (e.g., on 401 error)
|
|
38
|
+
*/
|
|
39
|
+
export declare function clearSmartLeadToken(email: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Clear all cached tokens
|
|
42
|
+
*/
|
|
43
|
+
export declare function clearAllSmartLeadTokens(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get token cache stats (for debugging)
|
|
46
|
+
*/
|
|
47
|
+
export declare function getSmartLeadTokenCacheStats(): {
|
|
48
|
+
cachedEmails: string[];
|
|
49
|
+
totalCached: number;
|
|
50
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getSmartLeadToken = getSmartLeadToken;
|
|
10
|
+
exports.getSmartLeadUser = getSmartLeadUser;
|
|
11
|
+
exports.clearSmartLeadToken = clearSmartLeadToken;
|
|
12
|
+
exports.clearAllSmartLeadTokens = clearAllSmartLeadTokens;
|
|
13
|
+
exports.getSmartLeadTokenCacheStats = getSmartLeadTokenCacheStats;
|
|
14
|
+
const DEFAULT_LOGIN_URL = 'https://server.smartlead.ai/api/auth/login';
|
|
15
|
+
const DEFAULT_REFRESH_BUFFER_MS = 5 * 60 * 1000; // 5 minutes
|
|
16
|
+
const TOKEN_LIFETIME_MS = 24 * 60 * 60 * 1000; // Assume 24h JWT lifetime (conservative)
|
|
17
|
+
// In-memory token cache keyed by email
|
|
18
|
+
const tokenCache = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Parse JWT to extract expiration time
|
|
21
|
+
*/
|
|
22
|
+
function parseJwtExpiry(token) {
|
|
23
|
+
try {
|
|
24
|
+
const parts = token.split('.');
|
|
25
|
+
if (parts.length !== 3)
|
|
26
|
+
return null;
|
|
27
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf8'));
|
|
28
|
+
if (payload.exp) {
|
|
29
|
+
return payload.exp * 1000; // Convert to ms
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Login to SmartLead and obtain JWT token
|
|
39
|
+
*/
|
|
40
|
+
async function login(config) {
|
|
41
|
+
const { credentials, loginUrl = DEFAULT_LOGIN_URL } = config;
|
|
42
|
+
const response = await fetch(loginUrl, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
Accept: 'application/json, text/plain, */*',
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
Origin: 'https://app.smartlead.ai',
|
|
48
|
+
Referer: 'https://app.smartlead.ai/',
|
|
49
|
+
'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',
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify({
|
|
52
|
+
email: credentials.email,
|
|
53
|
+
password: credentials.password,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const errorText = await response.text().catch(() => '');
|
|
58
|
+
throw new Error(`SmartLead login failed: ${response.status} - ${errorText}`);
|
|
59
|
+
}
|
|
60
|
+
const data = (await response.json());
|
|
61
|
+
if (!data.token || !data.user) {
|
|
62
|
+
throw new Error('SmartLead login response missing token or user');
|
|
63
|
+
}
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
// Try to parse expiry from JWT, fallback to assumed lifetime
|
|
66
|
+
let expiresAt = parseJwtExpiry(data.token);
|
|
67
|
+
if (!expiresAt) {
|
|
68
|
+
expiresAt = now + TOKEN_LIFETIME_MS;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
token: data.token,
|
|
72
|
+
user: data.user,
|
|
73
|
+
expiresAt,
|
|
74
|
+
obtainedAt: now,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if cached token is still valid (with buffer for refresh)
|
|
79
|
+
*/
|
|
80
|
+
function isTokenValid(cached, refreshBufferMs) {
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
return cached.expiresAt - refreshBufferMs > now;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get a valid SmartLead JWT token
|
|
86
|
+
*
|
|
87
|
+
* Returns cached token if still valid, otherwise performs fresh login.
|
|
88
|
+
* Thread-safe via promise deduplication.
|
|
89
|
+
*/
|
|
90
|
+
const pendingLogins = new Map();
|
|
91
|
+
async function getSmartLeadToken(config) {
|
|
92
|
+
const { credentials, refreshBufferMs = DEFAULT_REFRESH_BUFFER_MS } = config;
|
|
93
|
+
const cacheKey = credentials.email.toLowerCase();
|
|
94
|
+
// Check cache first
|
|
95
|
+
const cached = tokenCache.get(cacheKey);
|
|
96
|
+
if (cached && isTokenValid(cached, refreshBufferMs)) {
|
|
97
|
+
return cached.token;
|
|
98
|
+
}
|
|
99
|
+
// Check if login already in progress (dedup concurrent requests)
|
|
100
|
+
const pending = pendingLogins.get(cacheKey);
|
|
101
|
+
if (pending) {
|
|
102
|
+
const result = await pending;
|
|
103
|
+
return result.token;
|
|
104
|
+
}
|
|
105
|
+
// Perform login
|
|
106
|
+
const loginPromise = login(config);
|
|
107
|
+
pendingLogins.set(cacheKey, loginPromise);
|
|
108
|
+
try {
|
|
109
|
+
const result = await loginPromise;
|
|
110
|
+
tokenCache.set(cacheKey, result);
|
|
111
|
+
return result.token;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
pendingLogins.delete(cacheKey);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get SmartLead user info (from cached login)
|
|
119
|
+
*/
|
|
120
|
+
async function getSmartLeadUser(config) {
|
|
121
|
+
const { credentials, refreshBufferMs = DEFAULT_REFRESH_BUFFER_MS } = config;
|
|
122
|
+
const cacheKey = credentials.email.toLowerCase();
|
|
123
|
+
// Check cache first
|
|
124
|
+
const cached = tokenCache.get(cacheKey);
|
|
125
|
+
if (cached && isTokenValid(cached, refreshBufferMs)) {
|
|
126
|
+
return cached.user;
|
|
127
|
+
}
|
|
128
|
+
// Perform login to get fresh user info
|
|
129
|
+
await getSmartLeadToken(config);
|
|
130
|
+
const freshCached = tokenCache.get(cacheKey);
|
|
131
|
+
if (!freshCached) {
|
|
132
|
+
throw new Error('SmartLead auth: failed to obtain user info');
|
|
133
|
+
}
|
|
134
|
+
return freshCached.user;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Force clear cached token (e.g., on 401 error)
|
|
138
|
+
*/
|
|
139
|
+
function clearSmartLeadToken(email) {
|
|
140
|
+
tokenCache.delete(email.toLowerCase());
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Clear all cached tokens
|
|
144
|
+
*/
|
|
145
|
+
function clearAllSmartLeadTokens() {
|
|
146
|
+
tokenCache.clear();
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get token cache stats (for debugging)
|
|
150
|
+
*/
|
|
151
|
+
function getSmartLeadTokenCacheStats() {
|
|
152
|
+
return {
|
|
153
|
+
cachedEmails: Array.from(tokenCache.keys()),
|
|
154
|
+
totalCached: tokenCache.size,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Enrichment Module
|
|
3
|
+
*
|
|
4
|
+
* Provides email enrichment capabilities with multiple provider support,
|
|
5
|
+
* waterfall orchestration, and configurable options.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { createEnrichmentClient } from 'linkedin-secret-sauce';
|
|
10
|
+
*
|
|
11
|
+
* const enricher = createEnrichmentClient({
|
|
12
|
+
* providers: {
|
|
13
|
+
* hunter: { apiKey: process.env.HUNTER_API_KEY },
|
|
14
|
+
* apollo: { apiKey: process.env.APOLLO_API_KEY },
|
|
15
|
+
* },
|
|
16
|
+
* options: {
|
|
17
|
+
* maxCostPerEmail: 0.05,
|
|
18
|
+
* confidenceThreshold: 50,
|
|
19
|
+
* },
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* const result = await enricher.enrich({
|
|
23
|
+
* firstName: 'John',
|
|
24
|
+
* lastName: 'Doe',
|
|
25
|
+
* company: 'Acme Corp',
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import type { EnrichmentClientConfig, EnrichmentClient } from "./types";
|
|
30
|
+
/**
|
|
31
|
+
* Create an enrichment client with the given configuration
|
|
32
|
+
*
|
|
33
|
+
* @param config - Configuration for the enrichment client
|
|
34
|
+
* @returns An enrichment client with enrich and enrichBatch methods
|
|
35
|
+
*/
|
|
36
|
+
export declare function createEnrichmentClient(config: EnrichmentClientConfig): EnrichmentClient;
|
|
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 { enrichBusinessEmail, enrichBatch } from "./orchestrator";
|
|
44
|
+
export { getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, type SmartLeadCredentials, type SmartLeadAuthConfig, type SmartLeadUser, type SmartLeadLoginResponse, } from "./auth";
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Email Enrichment Module
|
|
4
|
+
*
|
|
5
|
+
* Provides email enrichment capabilities with multiple provider support,
|
|
6
|
+
* waterfall orchestration, and configurable options.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { createEnrichmentClient } from 'linkedin-secret-sauce';
|
|
11
|
+
*
|
|
12
|
+
* const enricher = createEnrichmentClient({
|
|
13
|
+
* providers: {
|
|
14
|
+
* hunter: { apiKey: process.env.HUNTER_API_KEY },
|
|
15
|
+
* apollo: { apiKey: process.env.APOLLO_API_KEY },
|
|
16
|
+
* },
|
|
17
|
+
* options: {
|
|
18
|
+
* maxCostPerEmail: 0.05,
|
|
19
|
+
* confidenceThreshold: 50,
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* const result = await enricher.enrich({
|
|
24
|
+
* firstName: 'John',
|
|
25
|
+
* lastName: 'Doe',
|
|
26
|
+
* company: 'Acme Corp',
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
33
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
34
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperty(o, k2, desc);
|
|
37
|
+
}) : (function(o, m, k, k2) {
|
|
38
|
+
if (k2 === undefined) k2 = k;
|
|
39
|
+
o[k2] = m[k];
|
|
40
|
+
}));
|
|
41
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
42
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
43
|
+
};
|
|
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;
|
|
46
|
+
exports.createEnrichmentClient = createEnrichmentClient;
|
|
47
|
+
const orchestrator_1 = require("./orchestrator");
|
|
48
|
+
const construct_1 = require("./providers/construct");
|
|
49
|
+
const ldd_1 = require("./providers/ldd");
|
|
50
|
+
const smartprospect_1 = require("./providers/smartprospect");
|
|
51
|
+
const hunter_1 = require("./providers/hunter");
|
|
52
|
+
const apollo_1 = require("./providers/apollo");
|
|
53
|
+
const dropcontact_1 = require("./providers/dropcontact");
|
|
54
|
+
/**
|
|
55
|
+
* Default provider order
|
|
56
|
+
*/
|
|
57
|
+
const DEFAULT_ORDER = [
|
|
58
|
+
"construct",
|
|
59
|
+
"ldd",
|
|
60
|
+
"smartprospect",
|
|
61
|
+
"hunter",
|
|
62
|
+
"apollo",
|
|
63
|
+
"dropcontact",
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* Create an enrichment client with the given configuration
|
|
67
|
+
*
|
|
68
|
+
* @param config - Configuration for the enrichment client
|
|
69
|
+
* @returns An enrichment client with enrich and enrichBatch methods
|
|
70
|
+
*/
|
|
71
|
+
function createEnrichmentClient(config) {
|
|
72
|
+
const { providers: providerConfigs, options = {}, cache, onCost, logger, } = config;
|
|
73
|
+
// Build provider functions based on configuration
|
|
74
|
+
const providerFuncs = new Map();
|
|
75
|
+
// Always create construct provider (free, no API key needed)
|
|
76
|
+
providerFuncs.set("construct", (0, construct_1.createConstructProvider)(providerConfigs.construct));
|
|
77
|
+
// Create other providers if configured
|
|
78
|
+
if (providerConfigs.ldd) {
|
|
79
|
+
providerFuncs.set("ldd", (0, ldd_1.createLddProvider)(providerConfigs.ldd));
|
|
80
|
+
}
|
|
81
|
+
if (providerConfigs.smartprospect) {
|
|
82
|
+
providerFuncs.set("smartprospect", (0, smartprospect_1.createSmartProspectProvider)(providerConfigs.smartprospect));
|
|
83
|
+
}
|
|
84
|
+
if (providerConfigs.hunter) {
|
|
85
|
+
providerFuncs.set("hunter", (0, hunter_1.createHunterProvider)(providerConfigs.hunter));
|
|
86
|
+
}
|
|
87
|
+
if (providerConfigs.apollo) {
|
|
88
|
+
providerFuncs.set("apollo", (0, apollo_1.createApolloProvider)(providerConfigs.apollo));
|
|
89
|
+
}
|
|
90
|
+
if (providerConfigs.dropcontact) {
|
|
91
|
+
providerFuncs.set("dropcontact", (0, dropcontact_1.createDropcontactProvider)(providerConfigs.dropcontact));
|
|
92
|
+
}
|
|
93
|
+
// Build ordered provider list
|
|
94
|
+
const providerOrder = options.providerOrder ?? DEFAULT_ORDER;
|
|
95
|
+
const orderedProviders = [];
|
|
96
|
+
for (const name of providerOrder) {
|
|
97
|
+
const provider = providerFuncs.get(name);
|
|
98
|
+
if (provider) {
|
|
99
|
+
orderedProviders.push(provider);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Orchestrator options
|
|
103
|
+
const orchestratorOptions = {
|
|
104
|
+
providers: orderedProviders,
|
|
105
|
+
maxCostPerEmail: options.maxCostPerEmail,
|
|
106
|
+
confidenceThreshold: options.confidenceThreshold,
|
|
107
|
+
retryMs: options.retryMs,
|
|
108
|
+
onCost,
|
|
109
|
+
logger,
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
/**
|
|
113
|
+
* Enrich a single candidate with business email
|
|
114
|
+
*/
|
|
115
|
+
async enrich(candidate) {
|
|
116
|
+
// Check cache first
|
|
117
|
+
if (cache) {
|
|
118
|
+
const cacheKey = buildCacheKey(candidate);
|
|
119
|
+
if (cacheKey) {
|
|
120
|
+
try {
|
|
121
|
+
const cached = await cache.get(cacheKey);
|
|
122
|
+
if (cached) {
|
|
123
|
+
logger?.debug?.("enrichment.cache.hit", { cacheKey });
|
|
124
|
+
return cached;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Ignore cache errors
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Run enrichment
|
|
133
|
+
const result = await (0, orchestrator_1.enrichBusinessEmail)(candidate, orchestratorOptions);
|
|
134
|
+
// Store in cache
|
|
135
|
+
if (cache && result.business_email) {
|
|
136
|
+
const cacheKey = buildCacheKey(candidate);
|
|
137
|
+
if (cacheKey) {
|
|
138
|
+
try {
|
|
139
|
+
await cache.set(cacheKey, result, 30 * 24 * 60 * 60 * 1000); // 30 days TTL
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Ignore cache errors
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Enrich multiple candidates in batches
|
|
150
|
+
*/
|
|
151
|
+
async enrichBatch(candidates, batchOptions) {
|
|
152
|
+
return (0, orchestrator_1.enrichBatch)(candidates, {
|
|
153
|
+
...orchestratorOptions,
|
|
154
|
+
...batchOptions,
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build a cache key from candidate data
|
|
161
|
+
*/
|
|
162
|
+
function buildCacheKey(candidate) {
|
|
163
|
+
const parts = [];
|
|
164
|
+
// Use LinkedIn URL/username as primary key if available
|
|
165
|
+
const linkedinUrl = candidate.linkedinUrl || candidate.linkedin_url;
|
|
166
|
+
const linkedinUsername = candidate.linkedinUsername || candidate.linkedin_username;
|
|
167
|
+
const linkedinId = candidate.linkedinId || candidate.linkedin_id;
|
|
168
|
+
if (linkedinUrl) {
|
|
169
|
+
parts.push(`li:${linkedinUrl}`);
|
|
170
|
+
}
|
|
171
|
+
else if (linkedinUsername) {
|
|
172
|
+
parts.push(`li:${linkedinUsername}`);
|
|
173
|
+
}
|
|
174
|
+
else if (linkedinId) {
|
|
175
|
+
parts.push(`li:${linkedinId}`);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// 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
|
+
candidate.companyDomain ||
|
|
183
|
+
candidate.company_domain ||
|
|
184
|
+
"";
|
|
185
|
+
const company = candidate.company ||
|
|
186
|
+
candidate.currentCompany ||
|
|
187
|
+
candidate.organization ||
|
|
188
|
+
"";
|
|
189
|
+
if (firstName && (domain || company)) {
|
|
190
|
+
parts.push(`name:${firstName.toLowerCase()}`);
|
|
191
|
+
if (lastName)
|
|
192
|
+
parts.push(lastName.toLowerCase());
|
|
193
|
+
if (domain)
|
|
194
|
+
parts.push(`dom:${domain.toLowerCase()}`);
|
|
195
|
+
else if (company)
|
|
196
|
+
parts.push(`co:${company.toLowerCase()}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (parts.length === 0) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return parts.join("|");
|
|
203
|
+
}
|
|
204
|
+
// Re-export types
|
|
205
|
+
__exportStar(require("./types"), exports);
|
|
206
|
+
// Re-export utilities
|
|
207
|
+
var personal_domains_1 = require("./utils/personal-domains");
|
|
208
|
+
Object.defineProperty(exports, "isPersonalEmail", { enumerable: true, get: function () { return personal_domains_1.isPersonalEmail; } });
|
|
209
|
+
Object.defineProperty(exports, "isBusinessEmail", { enumerable: true, get: function () { return personal_domains_1.isBusinessEmail; } });
|
|
210
|
+
Object.defineProperty(exports, "isPersonalDomain", { enumerable: true, get: function () { return personal_domains_1.isPersonalDomain; } });
|
|
211
|
+
Object.defineProperty(exports, "PERSONAL_DOMAINS", { enumerable: true, get: function () { return personal_domains_1.PERSONAL_DOMAINS; } });
|
|
212
|
+
var disposable_domains_1 = require("./utils/disposable-domains");
|
|
213
|
+
Object.defineProperty(exports, "isDisposableEmail", { enumerable: true, get: function () { return disposable_domains_1.isDisposableEmail; } });
|
|
214
|
+
Object.defineProperty(exports, "isDisposableDomain", { enumerable: true, get: function () { return disposable_domains_1.isDisposableDomain; } });
|
|
215
|
+
Object.defineProperty(exports, "DISPOSABLE_DOMAINS", { enumerable: true, get: function () { return disposable_domains_1.DISPOSABLE_DOMAINS; } });
|
|
216
|
+
var validation_1 = require("./utils/validation");
|
|
217
|
+
Object.defineProperty(exports, "isValidEmailSyntax", { enumerable: true, get: function () { return validation_1.isValidEmailSyntax; } });
|
|
218
|
+
Object.defineProperty(exports, "isRoleAccount", { enumerable: true, get: function () { return validation_1.isRoleAccount; } });
|
|
219
|
+
Object.defineProperty(exports, "asciiFold", { enumerable: true, get: function () { return validation_1.asciiFold; } });
|
|
220
|
+
Object.defineProperty(exports, "cleanNamePart", { enumerable: true, get: function () { return validation_1.cleanNamePart; } });
|
|
221
|
+
Object.defineProperty(exports, "hostnameFromUrl", { enumerable: true, get: function () { return validation_1.hostnameFromUrl; } });
|
|
222
|
+
Object.defineProperty(exports, "extractLinkedInUsername", { enumerable: true, get: function () { return validation_1.extractLinkedInUsername; } });
|
|
223
|
+
// Re-export verification
|
|
224
|
+
var mx_1 = require("./verification/mx");
|
|
225
|
+
Object.defineProperty(exports, "verifyEmailMx", { enumerable: true, get: function () { return mx_1.verifyEmailMx; } });
|
|
226
|
+
// Re-export providers (for advanced usage)
|
|
227
|
+
var providers_1 = require("./providers");
|
|
228
|
+
Object.defineProperty(exports, "createConstructProvider", { enumerable: true, get: function () { return providers_1.createConstructProvider; } });
|
|
229
|
+
Object.defineProperty(exports, "createLddProvider", { enumerable: true, get: function () { return providers_1.createLddProvider; } });
|
|
230
|
+
Object.defineProperty(exports, "createSmartProspectProvider", { enumerable: true, get: function () { return providers_1.createSmartProspectProvider; } });
|
|
231
|
+
Object.defineProperty(exports, "createHunterProvider", { enumerable: true, get: function () { return providers_1.createHunterProvider; } });
|
|
232
|
+
Object.defineProperty(exports, "createApolloProvider", { enumerable: true, get: function () { return providers_1.createApolloProvider; } });
|
|
233
|
+
Object.defineProperty(exports, "createDropcontactProvider", { enumerable: true, get: function () { return providers_1.createDropcontactProvider; } });
|
|
234
|
+
// Re-export orchestrator (for advanced usage)
|
|
235
|
+
var orchestrator_2 = require("./orchestrator");
|
|
236
|
+
Object.defineProperty(exports, "enrichBusinessEmail", { enumerable: true, get: function () { return orchestrator_2.enrichBusinessEmail; } });
|
|
237
|
+
Object.defineProperty(exports, "enrichBatch", { enumerable: true, get: function () { return orchestrator_2.enrichBatch; } });
|
|
238
|
+
// Re-export auth utilities (for advanced usage)
|
|
239
|
+
var auth_1 = require("./auth");
|
|
240
|
+
Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return auth_1.getSmartLeadToken; } });
|
|
241
|
+
Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return auth_1.getSmartLeadUser; } });
|
|
242
|
+
Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return auth_1.clearSmartLeadToken; } });
|
|
243
|
+
Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return auth_1.clearAllSmartLeadTokens; } });
|
|
244
|
+
Object.defineProperty(exports, "getSmartLeadTokenCacheStats", { enumerable: true, get: function () { return auth_1.getSmartLeadTokenCacheStats; } });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Enrichment Waterfall Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Runs providers in sequence until a verified email is found that meets
|
|
5
|
+
* the confidence threshold. Supports budget tracking and cost callbacks.
|
|
6
|
+
*/
|
|
7
|
+
import type { CanonicalEmail, EnrichmentCandidate, ProviderFunc, BatchEnrichmentOptions, CostCallback, EnrichmentLogger } from './types';
|
|
8
|
+
export interface OrchestratorOptions {
|
|
9
|
+
/** Provider functions in order */
|
|
10
|
+
providers: ProviderFunc[];
|
|
11
|
+
/** Maximum cost per email in USD */
|
|
12
|
+
maxCostPerEmail?: number;
|
|
13
|
+
/** Minimum confidence threshold (0-100) */
|
|
14
|
+
confidenceThreshold?: number;
|
|
15
|
+
/** Retry delay in ms */
|
|
16
|
+
retryMs?: number;
|
|
17
|
+
/** Cost callback */
|
|
18
|
+
onCost?: CostCallback;
|
|
19
|
+
/** Logger */
|
|
20
|
+
logger?: EnrichmentLogger;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Enrich a single candidate with business email
|
|
24
|
+
*/
|
|
25
|
+
export declare function enrichBusinessEmail(candidate: EnrichmentCandidate, options: OrchestratorOptions): Promise<CanonicalEmail>;
|
|
26
|
+
/**
|
|
27
|
+
* Enrich multiple candidates in batches
|
|
28
|
+
*/
|
|
29
|
+
export declare function enrichBatch(candidates: EnrichmentCandidate[], options: OrchestratorOptions & BatchEnrichmentOptions): Promise<Array<{
|
|
30
|
+
candidate: EnrichmentCandidate;
|
|
31
|
+
} & CanonicalEmail>>;
|