linkedin-secret-sauce 0.12.3 → 0.12.4

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 (154) hide show
  1. package/README.md +6 -49
  2. package/dist/enrichment/index.d.ts +3 -5
  3. package/dist/enrichment/index.js +4 -20
  4. package/dist/enrichment/matching.d.ts +4 -8
  5. package/dist/enrichment/matching.js +6 -5
  6. package/dist/enrichment/orchestrator.d.ts +1 -1
  7. package/dist/enrichment/orchestrator.js +51 -44
  8. package/dist/enrichment/providers/index.d.ts +0 -2
  9. package/dist/enrichment/providers/index.js +1 -8
  10. package/dist/enrichment/providers/snovio.d.ts +4 -4
  11. package/dist/enrichment/providers/snovio.js +14 -14
  12. package/dist/enrichment/types.d.ts +8 -71
  13. package/dist/enrichment/types.js +3 -8
  14. package/dist/enrichment/utils/rate-limiter.js +0 -2
  15. package/dist/index.d.ts +2 -4
  16. package/dist/index.js +2 -2
  17. package/docs/ENRICHMENT.md +3 -45
  18. package/docs/INTEGRATION.md +1 -3
  19. package/docs/PLAYGROUND.md +4 -9
  20. package/docs/api/assets/hierarchy.js +1 -1
  21. package/docs/api/assets/navigation.js +1 -1
  22. package/docs/api/assets/search.js +1 -1
  23. package/docs/api/classes/LinkedInClientError.html +4 -4
  24. package/docs/api/functions/_testGetAccountCookies.html +2 -2
  25. package/docs/api/functions/_testGetAccountEntry.html +2 -2
  26. package/docs/api/functions/_testGetAllAccountIds.html +2 -2
  27. package/docs/api/functions/_testGetPoolState.html +2 -2
  28. package/docs/api/functions/adminResetAccount.html +1 -1
  29. package/docs/api/functions/adminSetCooldown.html +1 -1
  30. package/docs/api/functions/buildCookieHeader.html +1 -1
  31. package/docs/api/functions/clearAllSmartLeadTokens.html +2 -2
  32. package/docs/api/functions/clearRequestHistory.html +1 -1
  33. package/docs/api/functions/clearSessionAccount.html +1 -1
  34. package/docs/api/functions/clearSmartLeadToken.html +2 -2
  35. package/docs/api/functions/createEnrichmentClient.html +3 -3
  36. package/docs/api/functions/extractCsrfToken.html +1 -1
  37. package/docs/api/functions/extractLinkedInHandle.html +2 -2
  38. package/docs/api/functions/fetchCookiesFromCosiall.html +2 -2
  39. package/docs/api/functions/fetchProfileEmailsFromCosiall.html +2 -2
  40. package/docs/api/functions/forceRefreshCookies.html +1 -1
  41. package/docs/api/functions/getAccountForSession.html +1 -1
  42. package/docs/api/functions/getAccountsSummary.html +1 -1
  43. package/docs/api/functions/getCompaniesBatch.html +2 -2
  44. package/docs/api/functions/getCompanyById.html +2 -2
  45. package/docs/api/functions/getCompanyByUrl.html +1 -1
  46. package/docs/api/functions/getConfig.html +1 -1
  47. package/docs/api/functions/getCookiePoolHealth.html +1 -1
  48. package/docs/api/functions/getProfileByUrn.html +2 -2
  49. package/docs/api/functions/getProfileByVanity.html +2 -2
  50. package/docs/api/functions/getProfilesBatch.html +1 -1
  51. package/docs/api/functions/getRequestHistory.html +1 -1
  52. package/docs/api/functions/getSalesNavigatorProfileDetails.html +1 -1
  53. package/docs/api/functions/getSalesNavigatorProfileFull.html +2 -2
  54. package/docs/api/functions/getSmartLeadToken.html +1 -1
  55. package/docs/api/functions/getSmartLeadTokenCacheStats.html +2 -2
  56. package/docs/api/functions/getSmartLeadUser.html +2 -2
  57. package/docs/api/functions/getSnapshot.html +1 -1
  58. package/docs/api/functions/getYearsAtCompanyOptions.html +2 -2
  59. package/docs/api/functions/getYearsInPositionOptions.html +2 -2
  60. package/docs/api/functions/getYearsOfExperienceOptions.html +2 -2
  61. package/docs/api/functions/incrementMetric.html +1 -1
  62. package/docs/api/functions/initializeCookiePool.html +1 -1
  63. package/docs/api/functions/initializeLinkedInClient.html +1 -1
  64. package/docs/api/functions/isBusinessEmail.html +2 -2
  65. package/docs/api/functions/isDisposableDomain.html +2 -2
  66. package/docs/api/functions/isDisposableEmail.html +2 -2
  67. package/docs/api/functions/isPersonalDomain.html +2 -2
  68. package/docs/api/functions/isPersonalEmail.html +2 -2
  69. package/docs/api/functions/isRoleAccount.html +2 -2
  70. package/docs/api/functions/isValidEmailSyntax.html +2 -2
  71. package/docs/api/functions/parseFullProfile.html +2 -2
  72. package/docs/api/functions/parseSalesSearchResults.html +1 -1
  73. package/docs/api/functions/reportAccountFailure.html +1 -1
  74. package/docs/api/functions/reportAccountSuccess.html +1 -1
  75. package/docs/api/functions/resolveCompanyUniversalName.html +1 -1
  76. package/docs/api/functions/searchSalesLeads.html +2 -2
  77. package/docs/api/functions/selectAccountForRequest.html +1 -1
  78. package/docs/api/functions/setAccountForSession.html +1 -1
  79. package/docs/api/functions/typeahead.html +1 -1
  80. package/docs/api/functions/verifyEmailMx.html +1 -1
  81. package/docs/api/hierarchy.html +1 -1
  82. package/docs/api/index.html +3 -3
  83. package/docs/api/interfaces/AccountCookies.html +2 -2
  84. package/docs/api/interfaces/BatchEnrichmentOptions.html +8 -8
  85. package/docs/api/interfaces/CacheAdapter.html +4 -4
  86. package/docs/api/interfaces/CanonicalEmail.html +8 -8
  87. package/docs/api/interfaces/Company.html +2 -2
  88. package/docs/api/interfaces/ConstructConfig.html +5 -5
  89. package/docs/api/interfaces/CosiallProfileEmailsResponse.html +6 -6
  90. package/docs/api/interfaces/EnrichmentCandidate.html +4 -4
  91. package/docs/api/interfaces/EnrichmentClient.html +6 -6
  92. package/docs/api/interfaces/EnrichmentClientConfig.html +7 -7
  93. package/docs/api/interfaces/EnrichmentLogger.html +3 -3
  94. package/docs/api/interfaces/EnrichmentOptions.html +6 -6
  95. package/docs/api/interfaces/HunterConfig.html +3 -3
  96. package/docs/api/interfaces/LddConfig.html +3 -3
  97. package/docs/api/interfaces/LddProfileData.html +2 -2
  98. package/docs/api/interfaces/LinkedInClientConfig.html +2 -2
  99. package/docs/api/interfaces/LinkedInCookie.html +2 -2
  100. package/docs/api/interfaces/LinkedInPosition.html +2 -2
  101. package/docs/api/interfaces/LinkedInProfile.html +2 -2
  102. package/docs/api/interfaces/LinkedInSpotlightBadge.html +2 -2
  103. package/docs/api/interfaces/LinkedInTenure.html +2 -2
  104. package/docs/api/interfaces/Metrics.html +2 -2
  105. package/docs/api/interfaces/MetricsSnapshot.html +2 -2
  106. package/docs/api/interfaces/ProfileEducation.html +2 -2
  107. package/docs/api/interfaces/ProfileEmailsLookupOptions.html +5 -5
  108. package/docs/api/interfaces/ProfilePosition.html +2 -2
  109. package/docs/api/interfaces/ProfileSkill.html +2 -2
  110. package/docs/api/interfaces/ProviderResult.html +6 -6
  111. package/docs/api/interfaces/ProvidersConfig.html +6 -9
  112. package/docs/api/interfaces/RequestHistoryEntry.html +2 -2
  113. package/docs/api/interfaces/SalesLeadSearchResult.html +2 -2
  114. package/docs/api/interfaces/SalesNavigatorContactInfo.html +2 -2
  115. package/docs/api/interfaces/SalesNavigatorPosition.html +2 -2
  116. package/docs/api/interfaces/SalesNavigatorProfile.html +2 -2
  117. package/docs/api/interfaces/SalesNavigatorProfileFull.html +4 -4
  118. package/docs/api/interfaces/SearchSalesResult.html +2 -2
  119. package/docs/api/interfaces/SmartLeadAuthConfig.html +4 -4
  120. package/docs/api/interfaces/SmartLeadCredentials.html +2 -2
  121. package/docs/api/interfaces/SmartLeadLoginResponse.html +2 -2
  122. package/docs/api/interfaces/SmartLeadUser.html +2 -2
  123. package/docs/api/interfaces/SmartProspectConfig.html +8 -8
  124. package/docs/api/interfaces/SmartProspectContact.html +2 -2
  125. package/docs/api/interfaces/SmartProspectSearchFilters.html +21 -21
  126. package/docs/api/interfaces/TypeaheadItem.html +2 -2
  127. package/docs/api/interfaces/TypeaheadResult.html +2 -2
  128. package/docs/api/interfaces/VerificationResult.html +9 -9
  129. package/docs/api/types/CostCallback.html +2 -2
  130. package/docs/api/types/Geo.html +2 -2
  131. package/docs/api/types/LddApiResponse.html +1 -1
  132. package/docs/api/types/ProviderFunc.html +2 -2
  133. package/docs/api/types/ProviderName.html +2 -2
  134. package/docs/api/types/SalesSearchFilters.html +2 -2
  135. package/docs/api/types/TypeaheadType.html +1 -1
  136. package/docs/api/variables/COMPANY_SIZE_OPTIONS.html +1 -1
  137. package/docs/api/variables/DEFAULT_PROVIDER_ORDER.html +3 -4
  138. package/docs/api/variables/DISPOSABLE_DOMAINS.html +2 -2
  139. package/docs/api/variables/FUNCTION_OPTIONS.html +1 -1
  140. package/docs/api/variables/INDUSTRY_OPTIONS.html +1 -1
  141. package/docs/api/variables/LANGUAGE_OPTIONS.html +1 -1
  142. package/docs/api/variables/PERSONAL_DOMAINS.html +2 -2
  143. package/docs/api/variables/PROVIDER_COSTS.html +3 -5
  144. package/docs/api/variables/REGION_OPTIONS.html +1 -1
  145. package/docs/api/variables/SENIORITY_OPTIONS.html +2 -2
  146. package/docs/api/variables/YEARS_OPTIONS.html +1 -1
  147. package/package.json +1 -1
  148. package/dist/enrichment/providers/apollo.d.ts +0 -11
  149. package/dist/enrichment/providers/apollo.js +0 -181
  150. package/dist/enrichment/providers/bouncer.d.ts +0 -67
  151. package/dist/enrichment/providers/bouncer.js +0 -231
  152. package/dist/enrichment/providers/dropcontact.d.ts +0 -22
  153. package/dist/enrichment/providers/dropcontact.js +0 -206
  154. package/docs/api/interfaces/DropcontactConfig.html +0 -3
@@ -1,231 +0,0 @@
1
- "use strict";
2
- /**
3
- * Bouncer.io Email Verification Provider
4
- *
5
- * Provides SMTP-level email verification with 99%+ accuracy.
6
- * Best for verifying pattern-guessed emails on non-catch-all domains.
7
- *
8
- * Features:
9
- * - SMTP verification (checks if mailbox exists)
10
- * - Catch-all domain detection
11
- * - Disposable email detection
12
- * - Role account detection
13
- * - Toxicity scoring (0-5)
14
- *
15
- * @see https://docs.usebouncer.com
16
- */
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.createBouncerProvider = createBouncerProvider;
19
- exports.verifyEmailWithBouncer = verifyEmailWithBouncer;
20
- exports.checkCatchAllDomain = checkCatchAllDomain;
21
- exports.verifyEmailsBatch = verifyEmailsBatch;
22
- const noop_provider_1 = require("../utils/noop-provider");
23
- const DEFAULT_API_URL = "https://api.usebouncer.com/v1.1";
24
- const DEFAULT_TIMEOUT_MS = 30000;
25
- /**
26
- * Map Bouncer status to confidence score
27
- */
28
- function statusToConfidence(status, response) {
29
- switch (status) {
30
- case "deliverable":
31
- // High confidence - email verified as deliverable
32
- // Reduce slightly if catch-all or high toxicity
33
- let score = 95;
34
- if (response.acceptAll)
35
- score -= 20; // Catch-all reduces confidence
36
- if (response.toxicity && response.toxicity >= 3)
37
- score -= 10;
38
- if (response.role)
39
- score -= 5; // Role accounts slightly lower
40
- return Math.max(50, score);
41
- case "risky":
42
- // Medium confidence - risky but might work
43
- return response.acceptAll ? 40 : 50;
44
- case "undeliverable":
45
- // Email does not exist
46
- return 0;
47
- case "unknown":
48
- // Could not verify
49
- return 30;
50
- default:
51
- return 0;
52
- }
53
- }
54
- /**
55
- * Extract email candidates from the enrichment candidate
56
- * Bouncer is a VERIFICATION provider, so it needs emails to verify
57
- */
58
- function extractEmailsToVerify(candidate) {
59
- const emails = [];
60
- // Check if candidate has pre-generated email patterns in metadata
61
- const metadata = candidate._emailCandidates;
62
- if (Array.isArray(metadata)) {
63
- emails.push(...metadata.filter((e) => typeof e === "string"));
64
- }
65
- return emails;
66
- }
67
- /**
68
- * Verify a single email via Bouncer API
69
- */
70
- async function verifyEmail(email, apiKey, apiUrl, timeoutMs) {
71
- const controller = new AbortController();
72
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
73
- try {
74
- const url = `${apiUrl}/email/verify?email=${encodeURIComponent(email)}`;
75
- const response = await fetch(url, {
76
- method: "GET",
77
- headers: {
78
- "x-api-key": apiKey,
79
- Accept: "application/json",
80
- },
81
- signal: controller.signal,
82
- });
83
- if (!response.ok) {
84
- // All HTTP errors return null - let caller decide how to handle
85
- return null;
86
- }
87
- const data = (await response.json());
88
- return data;
89
- }
90
- catch {
91
- // All errors (network, timeout, etc.) return null
92
- return null;
93
- }
94
- finally {
95
- clearTimeout(timeoutId);
96
- }
97
- }
98
- /**
99
- * Create the Bouncer verification provider
100
- *
101
- * NOTE: This provider is a VERIFIER, not a FINDER. It verifies emails
102
- * that were generated by the construct provider or passed in the candidate.
103
- *
104
- * Usage in the enrichment flow:
105
- * 1. construct provider generates email patterns
106
- * 2. bouncer provider verifies which patterns are deliverable
107
- * 3. Only verified emails are returned
108
- */
109
- function createBouncerProvider(config) {
110
- const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
111
- if (!apiKey) {
112
- return (0, noop_provider_1.createNoOpProvider)("bouncer");
113
- }
114
- async function verifyEmails(candidate) {
115
- const emailsToVerify = extractEmailsToVerify(candidate);
116
- // If no emails to verify, return null
117
- // The orchestrator will need to pass emails from construct
118
- if (emailsToVerify.length === 0) {
119
- return null;
120
- }
121
- const verifiedEmails = [];
122
- // Verify each email candidate
123
- for (const email of emailsToVerify) {
124
- try {
125
- const result = await verifyEmail(email, apiKey, apiUrl, timeoutMs);
126
- if (result) {
127
- const confidence = statusToConfidence(result.status, result);
128
- // Only include emails that are potentially deliverable
129
- if (result.status === "deliverable" || result.status === "risky") {
130
- verifiedEmails.push({
131
- email: result.email,
132
- verified: result.status === "deliverable",
133
- confidence,
134
- isCatchAll: result.acceptAll,
135
- metadata: {
136
- bouncerStatus: result.status,
137
- bouncerReason: result.reason,
138
- toxicity: result.toxicity,
139
- isDisposable: result.disposable,
140
- isRole: result.role,
141
- isFreeProvider: result.free,
142
- },
143
- });
144
- }
145
- }
146
- }
147
- catch {
148
- // Continue with other emails on error
149
- continue;
150
- }
151
- }
152
- if (verifiedEmails.length === 0) {
153
- return null;
154
- }
155
- // Sort by confidence
156
- verifiedEmails.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0));
157
- return { emails: verifiedEmails };
158
- }
159
- // Mark provider name for orchestrator
160
- verifyEmails.__name = "bouncer";
161
- return verifyEmails;
162
- }
163
- /**
164
- * Standalone function to verify a single email via Bouncer
165
- *
166
- * Useful for ad-hoc verification outside the enrichment flow.
167
- *
168
- * @example
169
- * ```typescript
170
- * const result = await verifyEmailWithBouncer('test@example.com', {
171
- * apiKey: process.env.BOUNCER_API_KEY,
172
- * });
173
- * console.log(result.status); // 'deliverable' | 'undeliverable' | 'risky' | 'unknown'
174
- * ```
175
- */
176
- async function verifyEmailWithBouncer(email, config) {
177
- const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
178
- return verifyEmail(email, apiKey, apiUrl, timeoutMs);
179
- }
180
- /**
181
- * Check if a domain is catch-all via Bouncer
182
- *
183
- * Sends a verification request for a random email and checks acceptAll flag.
184
- *
185
- * @example
186
- * ```typescript
187
- * const isCatchAll = await checkCatchAllDomain('example.com', {
188
- * apiKey: process.env.BOUNCER_API_KEY,
189
- * });
190
- * ```
191
- */
192
- async function checkCatchAllDomain(domain, config) {
193
- const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
194
- // Generate a random email that almost certainly doesn't exist
195
- const randomLocal = `bounce-test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
196
- const testEmail = `${randomLocal}@${domain}`;
197
- const result = await verifyEmail(testEmail, apiKey, apiUrl, timeoutMs);
198
- if (!result) {
199
- return null; // Could not determine
200
- }
201
- // If acceptAll is true, the domain accepts all emails (catch-all)
202
- return result.acceptAll;
203
- }
204
- /**
205
- * Verify multiple emails in batch via Bouncer
206
- *
207
- * @example
208
- * ```typescript
209
- * const results = await verifyEmailsBatch(
210
- * ['john@example.com', 'jane@example.com'],
211
- * { apiKey: process.env.BOUNCER_API_KEY }
212
- * );
213
- * ```
214
- */
215
- async function verifyEmailsBatch(emails, config) {
216
- const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
217
- const results = new Map();
218
- // Verify in parallel with concurrency limit
219
- const CONCURRENCY = 5;
220
- for (let i = 0; i < emails.length; i += CONCURRENCY) {
221
- const batch = emails.slice(i, i + CONCURRENCY);
222
- const batchResults = await Promise.all(batch.map(async (email) => {
223
- const result = await verifyEmail(email, apiKey, apiUrl, timeoutMs);
224
- return { email, result };
225
- }));
226
- for (const { email, result } of batchResults) {
227
- results.set(email, result);
228
- }
229
- }
230
- return results;
231
- }
@@ -1,22 +0,0 @@
1
- /**
2
- * Dropcontact Provider
3
- *
4
- * Dropcontact API for email finding and enrichment.
5
- * Uses the batch enrichment API with polling for results.
6
- *
7
- * API Flow:
8
- * 1. POST /batch to submit contacts for enrichment
9
- * 2. GET /batch/{request_id} to poll for results
10
- *
11
- * Features:
12
- * - Email finding from name + company/website
13
- * - Email verification (deliverable/undeliverable)
14
- * - GDPR compliant (EU-based)
15
- *
16
- * @see https://developer.dropcontact.com/
17
- */
18
- import type { EnrichmentCandidate, ProviderResult, DropcontactConfig } from "../types";
19
- /**
20
- * Create the Dropcontact provider function
21
- */
22
- export declare function createDropcontactProvider(config: DropcontactConfig): (candidate: EnrichmentCandidate) => Promise<ProviderResult | null>;
@@ -1,206 +0,0 @@
1
- "use strict";
2
- /**
3
- * Dropcontact Provider
4
- *
5
- * Dropcontact API for email finding and enrichment.
6
- * Uses the batch enrichment API with polling for results.
7
- *
8
- * API Flow:
9
- * 1. POST /batch to submit contacts for enrichment
10
- * 2. GET /batch/{request_id} to poll for results
11
- *
12
- * Features:
13
- * - Email finding from name + company/website
14
- * - Email verification (deliverable/undeliverable)
15
- * - GDPR compliant (EU-based)
16
- *
17
- * @see https://developer.dropcontact.com/
18
- */
19
- Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.createDropcontactProvider = createDropcontactProvider;
21
- const http_retry_1 = require("../utils/http-retry");
22
- const noop_provider_1 = require("../utils/noop-provider");
23
- const API_BASE = "https://api.dropcontact.io";
24
- /**
25
- * Extract inputs from candidate for Dropcontact API
26
- */
27
- function extractInputs(candidate) {
28
- const name = candidate.name || candidate.fullName || candidate.full_name;
29
- const first = candidate.first ||
30
- candidate.first_name ||
31
- candidate.firstName ||
32
- name?.split?.(" ")?.[0];
33
- const last = candidate.last ||
34
- candidate.last_name ||
35
- candidate.lastName ||
36
- name?.split?.(" ")?.slice(1).join(" ") ||
37
- undefined;
38
- const domain = candidate.domain ||
39
- candidate.companyDomain ||
40
- candidate.company_domain ||
41
- undefined;
42
- const company = candidate.company ||
43
- candidate.currentCompany ||
44
- candidate.organization ||
45
- candidate.org ||
46
- undefined;
47
- const linkedin = candidate.linkedinUrl ||
48
- candidate.linkedin_url ||
49
- (candidate.linkedinHandle
50
- ? `https://www.linkedin.com/in/${candidate.linkedinHandle}`
51
- : undefined) ||
52
- (candidate.linkedin_handle
53
- ? `https://www.linkedin.com/in/${candidate.linkedin_handle}`
54
- : undefined) ||
55
- undefined;
56
- return {
57
- first_name: first,
58
- last_name: last,
59
- full_name: name,
60
- company: company,
61
- website: domain,
62
- linkedin: linkedin,
63
- };
64
- }
65
- /**
66
- * Create the Dropcontact provider function
67
- */
68
- function createDropcontactProvider(config) {
69
- const { apiKey } = config;
70
- if (!apiKey) {
71
- return (0, noop_provider_1.createNoOpProvider)("dropcontact");
72
- }
73
- /**
74
- * Submit a batch request to Dropcontact
75
- */
76
- async function submitBatch(contacts) {
77
- const body = {
78
- data: contacts,
79
- siren: false, // We don't need French company registration numbers
80
- language: "en",
81
- };
82
- try {
83
- const response = await (0, http_retry_1.postWithRetry)(`${API_BASE}/batch`, body, { "X-Access-Token": apiKey }, { retries: 2, backoffMs: 500, timeoutMs: 30000 });
84
- if (response.error) {
85
- return null;
86
- }
87
- return response.request_id || null;
88
- }
89
- catch {
90
- return null;
91
- }
92
- }
93
- /**
94
- * Poll for batch results with exponential backoff
95
- */
96
- async function pollResults(requestId, maxAttempts = 10, initialDelayMs = 2000) {
97
- let delayMs = initialDelayMs;
98
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
99
- await (0, http_retry_1.delay)(delayMs);
100
- try {
101
- const response = await (0, http_retry_1.getWithRetry)(`${API_BASE}/batch/${requestId}`, { "X-Access-Token": apiKey }, { retries: 1, backoffMs: 500, timeoutMs: 30000 });
102
- // Check if processing is complete
103
- if (response.error) {
104
- return null;
105
- }
106
- // If we have data and status is finished (or we got data back), return it
107
- if (response.data && response.data.length > 0) {
108
- // Check if still processing
109
- if (response.status === "pending") {
110
- // Increase delay for next poll (max 10 seconds)
111
- delayMs = Math.min(delayMs * 1.5, 10000);
112
- continue;
113
- }
114
- return response.data;
115
- }
116
- // If explicitly finished but no data
117
- if (response.status === "finished") {
118
- return response.data || null;
119
- }
120
- // Still processing, increase delay
121
- delayMs = Math.min(delayMs * 1.5, 10000);
122
- }
123
- catch {
124
- // Network error, retry with backoff
125
- delayMs = Math.min(delayMs * 2, 10000);
126
- }
127
- }
128
- return null; // Timeout after max attempts
129
- }
130
- /**
131
- * Fetch email for a candidate
132
- */
133
- async function fetchEmail(candidate) {
134
- const contact = extractInputs(candidate);
135
- // Need at least a name and company/website to search
136
- const hasName = (0, http_retry_1.truthy)(contact.first_name) || (0, http_retry_1.truthy)(contact.full_name);
137
- const hasCompanyInfo = (0, http_retry_1.truthy)(contact.company) || (0, http_retry_1.truthy)(contact.website);
138
- const hasLinkedIn = (0, http_retry_1.truthy)(contact.linkedin);
139
- if (!hasName && !hasLinkedIn) {
140
- return null; // Need at least name or LinkedIn URL
141
- }
142
- if (!hasCompanyInfo && !hasLinkedIn) {
143
- return null; // Need company info or LinkedIn URL
144
- }
145
- // Submit single contact as batch
146
- const requestId = await submitBatch([contact]);
147
- if (!requestId) {
148
- return null;
149
- }
150
- // Poll for results
151
- const results = await pollResults(requestId);
152
- if (!results || results.length === 0) {
153
- return null;
154
- }
155
- // Extract email from first result
156
- const enriched = results[0];
157
- if (!enriched.email || enriched.email.length === 0) {
158
- return null;
159
- }
160
- // Find the best email (prefer valid ones)
161
- let bestEmail = null;
162
- for (const emailObj of enriched.email) {
163
- if (!emailObj.email)
164
- continue;
165
- // Prefer valid emails
166
- if (emailObj.qualification === "valid") {
167
- bestEmail = emailObj;
168
- break;
169
- }
170
- // Take catch-all if no valid found yet
171
- if (!bestEmail ||
172
- (bestEmail.qualification !== "valid" &&
173
- emailObj.qualification === "catch_all")) {
174
- bestEmail = emailObj;
175
- }
176
- // Take any email if nothing else
177
- if (!bestEmail) {
178
- bestEmail = emailObj;
179
- }
180
- }
181
- if (!bestEmail || !bestEmail.email) {
182
- return null;
183
- }
184
- // Map qualification to verified status
185
- const verified = (0, http_retry_1.mapVerifiedStatus)(bestEmail.qualification);
186
- // Confidence based on qualification
187
- let score = 50;
188
- if (bestEmail.qualification === "valid") {
189
- score = 95;
190
- }
191
- else if (bestEmail.qualification === "catch_all") {
192
- score = 60;
193
- }
194
- else if (bestEmail.qualification === "invalid") {
195
- score = 10;
196
- }
197
- return {
198
- email: bestEmail.email,
199
- verified,
200
- score,
201
- };
202
- }
203
- // Mark provider name for orchestrator
204
- fetchEmail.__name = "dropcontact";
205
- return fetchEmail;
206
- }
@@ -1,3 +0,0 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>DropcontactConfig | LinkedIn Secret Sauce - v0.12.3</title><meta name="description" content="Documentation for LinkedIn Secret Sauce"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">LinkedIn Secret Sauce - v0.12.3</a><div id="tsd-toolbar-links"><a href="https://github.com/enerage/LinkedInSecretSauce">GitHub</a><a href="https://www.npmjs.com/package/linkedin-secret-sauce">npm</a></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">DropcontactConfig</a></li></ul><h1>Interface DropcontactConfig</h1></div><section class="tsd-panel tsd-comment"><div class="tsd-comment tsd-typography"><p>Dropcontact provider configuration</p>
2
- </div></section><div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">DropcontactConfig</span> <span class="tsd-signature-symbol">{</span><br/>    <a class="tsd-kind-property" href="#apikey">apiKey</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br/><span class="tsd-signature-symbol">}</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/enerage/LinkedInSecretSauce/blob/142a9d0b85e83a724e9d23b89f1efc205b5a6dbd/src/enrichment/types.ts#L216">src/enrichment/types.ts:216</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h5 class="tsd-index-heading uppercase">Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="#apikey" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>api<wbr/>Key</span></a>
3
- </div></section></div></details></section></section><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h2>Properties</h2></summary><section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="apikey"><span>api<wbr/>Key</span><a href="#apikey" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">apiKey</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/enerage/LinkedInSecretSauce/blob/142a9d0b85e83a724e9d23b89f1efc205b5a6dbd/src/enrichment/types.ts#L217">src/enrichment/types.ts:217</a></li></ul></aside></section></section></details></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#apikey"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>api<wbr/>Key</span></a></div></details></div></details></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://github.com/enerage/LinkedInSecretSauce" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/linkedin-secret-sauce" class="tsd-nav-link">npm</a></nav><nav class="tsd-navigation"><a href="../index.html">LinkedIn Secret Sauce - v0.12.3</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>