linkedin-secret-sauce 0.3.29 → 0.5.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.
Files changed (55) hide show
  1. package/dist/cookie-pool.d.ts +1 -1
  2. package/dist/cookie-pool.js +67 -35
  3. package/dist/cosiall-client.d.ts +20 -1
  4. package/dist/cosiall-client.js +48 -25
  5. package/dist/enrichment/index.d.ts +43 -0
  6. package/dist/enrichment/index.js +231 -0
  7. package/dist/enrichment/orchestrator.d.ts +31 -0
  8. package/dist/enrichment/orchestrator.js +218 -0
  9. package/dist/enrichment/providers/apollo.d.ts +11 -0
  10. package/dist/enrichment/providers/apollo.js +136 -0
  11. package/dist/enrichment/providers/construct.d.ts +11 -0
  12. package/dist/enrichment/providers/construct.js +107 -0
  13. package/dist/enrichment/providers/dropcontact.d.ts +16 -0
  14. package/dist/enrichment/providers/dropcontact.js +37 -0
  15. package/dist/enrichment/providers/hunter.d.ts +11 -0
  16. package/dist/enrichment/providers/hunter.js +162 -0
  17. package/dist/enrichment/providers/index.d.ts +9 -0
  18. package/dist/enrichment/providers/index.js +18 -0
  19. package/dist/enrichment/providers/ldd.d.ts +11 -0
  20. package/dist/enrichment/providers/ldd.js +110 -0
  21. package/dist/enrichment/providers/smartprospect.d.ts +11 -0
  22. package/dist/enrichment/providers/smartprospect.js +249 -0
  23. package/dist/enrichment/types.d.ts +329 -0
  24. package/dist/enrichment/types.js +31 -0
  25. package/dist/enrichment/utils/disposable-domains.d.ts +24 -0
  26. package/dist/enrichment/utils/disposable-domains.js +1011 -0
  27. package/dist/enrichment/utils/index.d.ts +6 -0
  28. package/dist/enrichment/utils/index.js +22 -0
  29. package/dist/enrichment/utils/personal-domains.d.ts +31 -0
  30. package/dist/enrichment/utils/personal-domains.js +95 -0
  31. package/dist/enrichment/utils/validation.d.ts +42 -0
  32. package/dist/enrichment/utils/validation.js +130 -0
  33. package/dist/enrichment/verification/index.d.ts +4 -0
  34. package/dist/enrichment/verification/index.js +8 -0
  35. package/dist/enrichment/verification/mx.d.ts +16 -0
  36. package/dist/enrichment/verification/mx.js +168 -0
  37. package/dist/http-client.d.ts +1 -1
  38. package/dist/http-client.js +146 -63
  39. package/dist/index.d.ts +17 -14
  40. package/dist/index.js +20 -1
  41. package/dist/linkedin-api.d.ts +97 -4
  42. package/dist/linkedin-api.js +416 -134
  43. package/dist/parsers/company-parser.d.ts +15 -1
  44. package/dist/parsers/company-parser.js +45 -17
  45. package/dist/parsers/profile-parser.d.ts +19 -1
  46. package/dist/parsers/profile-parser.js +131 -81
  47. package/dist/parsers/search-parser.d.ts +1 -1
  48. package/dist/parsers/search-parser.js +24 -11
  49. package/dist/utils/logger.d.ts +1 -1
  50. package/dist/utils/logger.js +28 -18
  51. package/dist/utils/search-encoder.d.ts +32 -1
  52. package/dist/utils/search-encoder.js +102 -58
  53. package/dist/utils/sentry.d.ts +1 -1
  54. package/dist/utils/sentry.js +56 -8
  55. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import type { LinkedInCookie } from './types';
1
+ import type { LinkedInCookie } from "./types";
2
2
  interface AccountEntry {
3
3
  accountId: string;
4
4
  cookies: LinkedInCookie[];
@@ -74,7 +74,7 @@ function nowSec() {
74
74
  return Math.floor(Date.now() / 1000);
75
75
  }
76
76
  function toEpochSeconds(v) {
77
- if (typeof v !== 'number')
77
+ if (typeof v !== "number")
78
78
  return undefined;
79
79
  if (!Number.isFinite(v) || v <= 0)
80
80
  return undefined;
@@ -82,7 +82,7 @@ function toEpochSeconds(v) {
82
82
  return v > 1e10 ? Math.floor(v / 1000) : Math.floor(v);
83
83
  }
84
84
  function isExpired(entry) {
85
- const jsession = entry.cookies.find(c => String(c.name).toUpperCase() === 'JSESSIONID');
85
+ const jsession = entry.cookies.find((c) => String(c.name).toUpperCase() === "JSESSIONID");
86
86
  const jsExp = toEpochSeconds(jsession?.expires);
87
87
  if (jsExp && jsExp < nowSec())
88
88
  return true;
@@ -110,10 +110,10 @@ async function ensureInitialized() {
110
110
  }
111
111
  poolState.rrIndex = 0;
112
112
  poolState.initialized = true;
113
- (0, logger_1.log)('info', 'cookiePool.initialized', { count: accounts.length });
113
+ (0, logger_1.log)("info", "cookiePool.initialized", { count: accounts.length });
114
114
  // Start lightweight periodic refresh (guard against duplicate timers)
115
- if (!poolState.refreshTimer && process.env.NODE_ENV !== 'test') {
116
- const interval = Math.max(60_000, ((0, config_1.getConfig)().cookieRefreshInterval ?? 15 * 60 * 1000));
115
+ if (!poolState.refreshTimer && process.env.NODE_ENV !== "test") {
116
+ const interval = Math.max(60_000, (0, config_1.getConfig)().cookieRefreshInterval ?? 15 * 60 * 1000);
117
117
  poolState.refreshTimer = setInterval(async () => {
118
118
  try {
119
119
  const refreshed = await (0, cosiall_client_1.fetchCookiesFromCosiall)();
@@ -133,21 +133,36 @@ async function ensureInitialized() {
133
133
  }
134
134
  poolState.accounts = newMap;
135
135
  poolState.order = newOrder;
136
- (0, logger_1.log)('info', 'cookiePool.refreshed', { count: refreshed.length });
136
+ (0, logger_1.log)("info", "cookiePool.refreshed", { count: refreshed.length });
137
137
  }
138
138
  catch (e) {
139
139
  const err = e;
140
- (0, logger_1.log)('warn', 'cookiePool.refreshFailed', { error: err?.message });
140
+ (0, logger_1.log)("warn", "cookiePool.refreshFailed", { error: err?.message });
141
141
  // Report to Sentry if configured
142
142
  try {
143
- const { reportWarningToSentry } = await Promise.resolve().then(() => __importStar(require('./utils/sentry')));
144
- reportWarningToSentry('Cookie refresh failed', {
143
+ const { reportWarningToSentry } = await Promise.resolve().then(() => __importStar(require("./utils/sentry")));
144
+ reportWarningToSentry("Cookie refresh failed", {
145
145
  error: err?.message,
146
- tags: { component: 'cookie-pool', severity: 'medium' },
146
+ tags: { component: "cookie-pool", severity: "medium" },
147
147
  });
148
148
  }
149
149
  catch { }
150
150
  }
151
+ // Cleanup expired sessions to prevent memory leaks in long-running processes
152
+ const now = Date.now();
153
+ let expiredCount = 0;
154
+ for (const [sessionId, session] of sessionAccountMap.entries()) {
155
+ if (now > session.expiresAt) {
156
+ sessionAccountMap.delete(sessionId);
157
+ expiredCount++;
158
+ }
159
+ }
160
+ if (expiredCount > 0) {
161
+ (0, logger_1.log)("debug", "cookiePool.sessionCleanup", {
162
+ expiredSessions: expiredCount,
163
+ remainingSessions: sessionAccountMap.size,
164
+ });
165
+ }
151
166
  }, interval);
152
167
  }
153
168
  }
@@ -171,15 +186,15 @@ function getCookiePoolHealth() {
171
186
  return {
172
187
  initialized: true,
173
188
  totalAccounts: accounts.length,
174
- healthyAccounts: accounts.filter(a => !isExpired(a) && a.failures === 0 && a.cooldownUntil <= now).length,
175
- expiredAccounts: accounts.filter(a => isExpired(a)).length,
176
- coolingDownAccounts: accounts.filter(a => a.cooldownUntil > now).length,
189
+ healthyAccounts: accounts.filter((a) => !isExpired(a) && a.failures === 0 && a.cooldownUntil <= now).length,
190
+ expiredAccounts: accounts.filter((a) => isExpired(a)).length,
191
+ coolingDownAccounts: accounts.filter((a) => a.cooldownUntil > now).length,
177
192
  };
178
193
  }
179
194
  // Force refresh cookies (for mass failures)
180
195
  async function forceRefreshCookies() {
181
196
  try {
182
- (0, logger_1.log)('info', 'cookiePool.forceRefresh', {});
197
+ (0, logger_1.log)("info", "cookiePool.forceRefresh", {});
183
198
  const refreshed = await (0, cosiall_client_1.fetchCookiesFromCosiall)();
184
199
  // Rebuild state (same logic as periodic refresh)
185
200
  const newMap = new Map();
@@ -198,11 +213,11 @@ async function forceRefreshCookies() {
198
213
  poolState.accounts = newMap;
199
214
  poolState.order = newOrder;
200
215
  poolState.consecutiveMassFailures = 0; // Reset counter
201
- (0, logger_1.log)('info', 'cookiePool.forceRefreshed', { count: refreshed.length });
216
+ (0, logger_1.log)("info", "cookiePool.forceRefreshed", { count: refreshed.length });
202
217
  }
203
218
  catch (e) {
204
219
  const err = e;
205
- (0, logger_1.log)('error', 'cookiePool.forceRefreshFailed', { error: err?.message });
220
+ (0, logger_1.log)("error", "cookiePool.forceRefreshFailed", { error: err?.message });
206
221
  throw e;
207
222
  }
208
223
  }
@@ -218,7 +233,9 @@ function getAccountForSession(sessionId) {
218
233
  }
219
234
  // Check if account is still healthy
220
235
  const entry = poolState.accounts.get(session.accountId);
221
- if (!entry || isExpired(entry) || entry.failures >= getSettings().maxFailures) {
236
+ if (!entry ||
237
+ isExpired(entry) ||
238
+ entry.failures >= getSettings().maxFailures) {
222
239
  sessionAccountMap.delete(sessionId);
223
240
  return undefined;
224
241
  }
@@ -228,13 +245,13 @@ function setAccountForSession(sessionId, accountId) {
228
245
  sessionAccountMap.set(sessionId, {
229
246
  accountId,
230
247
  lastUsedAt: Date.now(),
231
- expiresAt: Date.now() + (30 * 60 * 1000), // 30 minutes
248
+ expiresAt: Date.now() + 30 * 60 * 1000, // 30 minutes
232
249
  });
233
- (0, logger_1.log)('debug', 'cookiePool.sessionSticky', { sessionId, accountId });
250
+ (0, logger_1.log)("debug", "cookiePool.sessionSticky", { sessionId, accountId });
234
251
  }
235
252
  function clearSessionAccount(sessionId) {
236
253
  sessionAccountMap.delete(sessionId);
237
- (0, logger_1.log)('debug', 'cookiePool.sessionCleared', { sessionId });
254
+ (0, logger_1.log)("debug", "cookiePool.sessionCleared", { sessionId });
238
255
  }
239
256
  // Modified selectAccountForRequest to support sessions (Phase 2.1)
240
257
  async function selectAccountForRequest(sessionId) {
@@ -245,8 +262,14 @@ async function selectAccountForRequest(sessionId) {
245
262
  const stickyAccountId = getAccountForSession(sessionId);
246
263
  if (stickyAccountId) {
247
264
  const entry = poolState.accounts.get(stickyAccountId);
248
- if (entry && !isExpired(entry) && entry.failures < settings.maxFailures && entry.cooldownUntil <= nowMs()) {
249
- (0, logger_1.log)('debug', 'cookiePool.sessionReuse', { sessionId, accountId: stickyAccountId });
265
+ if (entry &&
266
+ !isExpired(entry) &&
267
+ entry.failures < settings.maxFailures &&
268
+ entry.cooldownUntil <= nowMs()) {
269
+ (0, logger_1.log)("debug", "cookiePool.sessionReuse", {
270
+ sessionId,
271
+ accountId: stickyAccountId,
272
+ });
250
273
  entry.lastUsedAt = nowMs();
251
274
  return { accountId: stickyAccountId, cookies: entry.cookies };
252
275
  }
@@ -272,8 +295,12 @@ async function selectAccountForRequest(sessionId) {
272
295
  continue;
273
296
  // Select this account
274
297
  poolState.rrIndex = (idx + 1) % n;
275
- (0, logger_1.log)('debug', 'cookiePool.select', { accountId: entry.accountId, rrIndex: poolState.rrIndex, sessionId: sessionId || 'none' });
276
- (0, metrics_1.incrementMetric)('accountSelections');
298
+ (0, logger_1.log)("debug", "cookiePool.select", {
299
+ accountId: entry.accountId,
300
+ rrIndex: poolState.rrIndex,
301
+ sessionId: sessionId || "none",
302
+ });
303
+ (0, metrics_1.incrementMetric)("accountSelections");
277
304
  entry.lastUsedAt = nowMs();
278
305
  // Set sticky session if sessionId provided
279
306
  if (sessionId) {
@@ -281,7 +308,7 @@ async function selectAccountForRequest(sessionId) {
281
308
  }
282
309
  return { accountId: entry.accountId, cookies: entry.cookies };
283
310
  }
284
- throw new errors_1.LinkedInClientError('No valid LinkedIn accounts', 'NO_VALID_ACCOUNTS', 503);
311
+ throw new errors_1.LinkedInClientError("No valid LinkedIn accounts", "NO_VALID_ACCOUNTS", 503);
285
312
  }
286
313
  function getAccountsSummary() {
287
314
  const now = nowMs();
@@ -314,9 +341,14 @@ function reportAccountFailure(accountId, isAuthError) {
314
341
  if (isAuthError || entry.failures >= settings.maxFailures) {
315
342
  entry.cooldownUntil = nowMs() + settings.cooldownMs;
316
343
  }
317
- (0, logger_1.log)('warn', 'cookiePool.failure', { accountId, failures: entry.failures, isAuthError, cooldownUntil: entry.cooldownUntil });
344
+ (0, logger_1.log)("warn", "cookiePool.failure", {
345
+ accountId,
346
+ failures: entry.failures,
347
+ isAuthError,
348
+ cooldownUntil: entry.cooldownUntil,
349
+ });
318
350
  if (isAuthError)
319
- (0, metrics_1.incrementMetric)('authErrors');
351
+ (0, metrics_1.incrementMetric)("authErrors");
320
352
  }
321
353
  function reportAccountSuccess(accountId) {
322
354
  const entry = poolState.accounts.get(accountId);
@@ -324,16 +356,16 @@ function reportAccountSuccess(accountId) {
324
356
  return;
325
357
  entry.failures = 0;
326
358
  entry.cooldownUntil = 0;
327
- (0, logger_1.log)('debug', 'cookiePool.success', { accountId });
359
+ (0, logger_1.log)("debug", "cookiePool.success", { accountId });
328
360
  }
329
361
  function buildCookieHeader(cookies) {
330
- return cookies.map(c => `${c.name}=${c.value}`).join('; ');
362
+ return cookies.map((c) => `${c.name}=${c.value}`).join("; ");
331
363
  }
332
364
  function extractCsrfToken(cookies) {
333
- const jsession = cookies.find(c => c.name.toUpperCase() === 'JSESSIONID');
365
+ const jsession = cookies.find((c) => c.name.toUpperCase() === "JSESSIONID");
334
366
  if (!jsession || !jsession.value)
335
- throw new Error('Missing CSRF token');
336
- return jsession.value.replace(/^\"|\"$/g, '');
367
+ throw new Error("Missing CSRF token");
368
+ return jsession.value.replace(/^\"|\"$/g, "");
337
369
  }
338
370
  function getSettings() {
339
371
  try {
@@ -372,7 +404,7 @@ function adminResetAccount(accountId) {
372
404
  */
373
405
  function _testGetAllAccountIds() {
374
406
  if (!poolState.initialized) {
375
- throw new Error('TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.');
407
+ throw new Error("TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.");
376
408
  }
377
409
  return Array.from(poolState.accounts.keys());
378
410
  }
@@ -383,7 +415,7 @@ function _testGetAllAccountIds() {
383
415
  */
384
416
  function _testGetAccountCookies(accountId) {
385
417
  if (!poolState.initialized) {
386
- throw new Error('TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.');
418
+ throw new Error("TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.");
387
419
  }
388
420
  return poolState.accounts.get(accountId)?.cookies;
389
421
  }
@@ -394,7 +426,7 @@ function _testGetAccountCookies(accountId) {
394
426
  */
395
427
  function _testGetAccountEntry(accountId) {
396
428
  if (!poolState.initialized) {
397
- throw new Error('TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.');
429
+ throw new Error("TEST: Cookie pool not initialized. Call initializeLinkedInClient() first.");
398
430
  }
399
431
  return poolState.accounts.get(accountId);
400
432
  }
@@ -1,2 +1,21 @@
1
- import type { AccountCookies } from './types';
1
+ import type { AccountCookies } from "./types";
2
+ /**
3
+ * Fetches LinkedIn cookies for all available accounts from the Cosiall API.
4
+ * These cookies are used for authenticating requests to LinkedIn's API.
5
+ *
6
+ * @returns Array of AccountCookies, each containing accountId, cookies array, and optional expiresAt
7
+ * @throws LinkedInClientError with code REQUEST_FAILED if Cosiall API returns non-OK status
8
+ * @throws LinkedInClientError with code REQUEST_FAILED if response format is invalid
9
+ *
10
+ * @remarks
11
+ * - Reports failures to Sentry if configured
12
+ * - Validates each account has required cookie structure
13
+ * - Filters out malformed account entries
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const accounts = await fetchCookiesFromCosiall();
18
+ * console.log(`Loaded ${accounts.length} LinkedIn accounts`);
19
+ * ```
20
+ */
2
21
  export declare function fetchCookiesFromCosiall(): Promise<AccountCookies[]>;
@@ -38,69 +38,92 @@ const config_1 = require("./config");
38
38
  const errors_1 = require("./utils/errors");
39
39
  const logger_1 = require("./utils/logger");
40
40
  const metrics_1 = require("./utils/metrics");
41
+ /**
42
+ * Fetches LinkedIn cookies for all available accounts from the Cosiall API.
43
+ * These cookies are used for authenticating requests to LinkedIn's API.
44
+ *
45
+ * @returns Array of AccountCookies, each containing accountId, cookies array, and optional expiresAt
46
+ * @throws LinkedInClientError with code REQUEST_FAILED if Cosiall API returns non-OK status
47
+ * @throws LinkedInClientError with code REQUEST_FAILED if response format is invalid
48
+ *
49
+ * @remarks
50
+ * - Reports failures to Sentry if configured
51
+ * - Validates each account has required cookie structure
52
+ * - Filters out malformed account entries
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const accounts = await fetchCookiesFromCosiall();
57
+ * console.log(`Loaded ${accounts.length} LinkedIn accounts`);
58
+ * ```
59
+ */
41
60
  async function fetchCookiesFromCosiall() {
42
61
  const { cosiallApiUrl, cosiallApiKey } = (0, config_1.getConfig)();
43
- const base = cosiallApiUrl.replace(/\/+$/, '');
62
+ const base = cosiallApiUrl.replace(/\/+$/, "");
44
63
  const url = `${base}/api/flexiq/linkedin-cookies/all`;
45
- (0, logger_1.log)('info', 'cosiall.fetch.start', { url });
46
- (0, metrics_1.incrementMetric)('cosiallFetches');
64
+ (0, logger_1.log)("info", "cosiall.fetch.start", { url });
65
+ (0, metrics_1.incrementMetric)("cosiallFetches");
47
66
  const response = await fetch(url, {
48
- method: 'GET',
67
+ method: "GET",
49
68
  headers: {
50
- 'X-API-Key': cosiallApiKey,
51
- 'Accept': 'application/json',
69
+ "X-API-Key": cosiallApiKey,
70
+ Accept: "application/json",
52
71
  },
53
72
  });
54
73
  if (!response.ok) {
55
- (0, logger_1.log)('warn', 'cosiall.fetch.error', { status: response.status });
56
- (0, metrics_1.incrementMetric)('cosiallFailures');
74
+ (0, logger_1.log)("warn", "cosiall.fetch.error", { status: response.status });
75
+ (0, metrics_1.incrementMetric)("cosiallFailures");
57
76
  // Report Cosiall downtime to Sentry (critical for operations)
58
77
  try {
59
- const { reportCriticalError } = await Promise.resolve().then(() => __importStar(require('./utils/sentry')));
60
- reportCriticalError('Cosiall API failure - cookie service unavailable', {
78
+ const { reportCriticalError } = await Promise.resolve().then(() => __importStar(require("./utils/sentry")));
79
+ reportCriticalError("Cosiall API failure - cookie service unavailable", {
61
80
  status: response.status,
62
81
  url,
63
- tags: { component: 'cosiall-client', severity: 'critical' },
82
+ tags: { component: "cosiall-client", severity: "critical" },
64
83
  });
65
84
  }
66
85
  catch { }
67
- throw new errors_1.LinkedInClientError('Cosiall fetch failed', 'REQUEST_FAILED', response.status);
86
+ throw new errors_1.LinkedInClientError("Cosiall fetch failed", "REQUEST_FAILED", response.status);
68
87
  }
69
88
  const data = await response.json();
70
89
  if (!Array.isArray(data)) {
71
- (0, logger_1.log)('error', 'cosiall.fetch.invalidFormat', { dataType: typeof data });
90
+ (0, logger_1.log)("error", "cosiall.fetch.invalidFormat", { dataType: typeof data });
72
91
  // Report data format issues to Sentry
73
92
  try {
74
- const { reportCriticalError } = await Promise.resolve().then(() => __importStar(require('./utils/sentry')));
75
- reportCriticalError('Cosiall API returned invalid format', {
76
- expectedType: 'array',
93
+ const { reportCriticalError } = await Promise.resolve().then(() => __importStar(require("./utils/sentry")));
94
+ reportCriticalError("Cosiall API returned invalid format", {
95
+ expectedType: "array",
77
96
  actualType: typeof data,
78
- tags: { component: 'cosiall-client', severity: 'critical' },
97
+ tags: { component: "cosiall-client", severity: "critical" },
79
98
  });
80
99
  }
81
100
  catch { }
82
- throw new errors_1.LinkedInClientError('Invalid Cosiall response format', 'REQUEST_FAILED', 500);
101
+ throw new errors_1.LinkedInClientError("Invalid Cosiall response format", "REQUEST_FAILED", 500);
83
102
  }
84
- (0, logger_1.log)('info', 'cosiall.fetch.success', { count: data.length });
85
- (0, metrics_1.incrementMetric)('cosiallSuccess');
103
+ (0, logger_1.log)("info", "cosiall.fetch.success", { count: data.length });
104
+ (0, metrics_1.incrementMetric)("cosiallSuccess");
86
105
  function isCookie(obj) {
87
- return !!obj && typeof obj === 'object' && 'name' in obj && 'value' in obj;
106
+ return !!obj && typeof obj === "object" && "name" in obj && "value" in obj;
88
107
  }
89
108
  function isItem(obj) {
90
- if (!obj || typeof obj !== 'object')
109
+ if (!obj || typeof obj !== "object")
91
110
  return false;
92
111
  const rec = obj;
93
- if (typeof rec.accountId !== 'string')
112
+ if (typeof rec.accountId !== "string")
94
113
  return false;
95
114
  if (!Array.isArray(rec.cookies))
96
115
  return false;
97
116
  if (!rec.cookies.every(isCookie))
98
117
  return false;
99
- if (rec.expiresAt !== undefined && typeof rec.expiresAt !== 'number')
118
+ if (rec.expiresAt !== undefined && typeof rec.expiresAt !== "number")
100
119
  return false;
101
120
  return true;
102
121
  }
103
122
  return data
104
123
  .filter(isItem)
105
- .map((item) => ({ accountId: item.accountId, cookies: item.cookies, expiresAt: item.expiresAt }));
124
+ .map((item) => ({
125
+ accountId: item.accountId,
126
+ cookies: item.cookies,
127
+ expiresAt: item.expiresAt,
128
+ }));
106
129
  }
@@ -0,0 +1,43 @@
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';