linkedin-secret-sauce 0.10.1 → 0.11.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.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Snov.io Email Finder Provider
3
+ *
4
+ * Provides email finding with 98% delivery rate and built-in verification.
5
+ * Best for finding emails when pattern guessing fails or on catch-all domains.
6
+ *
7
+ * Features:
8
+ * - Email finding by name + domain
9
+ * - Built-in email verification
10
+ * - Database of 70M+ contacts
11
+ * - LinkedIn profile support
12
+ *
13
+ * @see https://snov.io/api
14
+ */
15
+ import type { EnrichmentCandidate, ProviderResult, ProviderMultiResult, SnovioConfig, SnovioGetEmailsResponse, SnovioVerificationStatus } from '../types';
16
+ /**
17
+ * Create the Snov.io email finder provider
18
+ *
19
+ * This provider uses Snov.io's database to find verified emails
20
+ * when pattern guessing fails or for catch-all domains.
21
+ */
22
+ export declare function createSnovioProvider(config: SnovioConfig): (candidate: EnrichmentCandidate) => Promise<ProviderResult | ProviderMultiResult | null>;
23
+ /**
24
+ * Standalone function to find emails via Snov.io
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const result = await findEmailsWithSnovio(
29
+ * 'John',
30
+ * 'Doe',
31
+ * 'example.com',
32
+ * {
33
+ * userId: process.env.SNOVIO_USER_ID,
34
+ * apiSecret: process.env.SNOVIO_API_SECRET,
35
+ * }
36
+ * );
37
+ * ```
38
+ */
39
+ export declare function findEmailsWithSnovio(firstName: string, lastName: string, domain: string, config: SnovioConfig): Promise<SnovioGetEmailsResponse | null>;
40
+ /**
41
+ * Verify a single email via Snov.io
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const result = await verifyEmailWithSnovio('test@example.com', {
46
+ * userId: process.env.SNOVIO_USER_ID,
47
+ * apiSecret: process.env.SNOVIO_API_SECRET,
48
+ * });
49
+ * ```
50
+ */
51
+ export declare function verifyEmailWithSnovio(email: string, config: SnovioConfig): Promise<{
52
+ email: string;
53
+ status: SnovioVerificationStatus;
54
+ } | null>;
55
+ /**
56
+ * Clear the cached access token (useful for testing)
57
+ */
58
+ export declare function clearSnovioTokenCache(): void;
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /**
3
+ * Snov.io Email Finder Provider
4
+ *
5
+ * Provides email finding with 98% delivery rate and built-in verification.
6
+ * Best for finding emails when pattern guessing fails or on catch-all domains.
7
+ *
8
+ * Features:
9
+ * - Email finding by name + domain
10
+ * - Built-in email verification
11
+ * - Database of 70M+ contacts
12
+ * - LinkedIn profile support
13
+ *
14
+ * @see https://snov.io/api
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.createSnovioProvider = createSnovioProvider;
18
+ exports.findEmailsWithSnovio = findEmailsWithSnovio;
19
+ exports.verifyEmailWithSnovio = verifyEmailWithSnovio;
20
+ exports.clearSnovioTokenCache = clearSnovioTokenCache;
21
+ const DEFAULT_API_URL = 'https://api.snov.io';
22
+ const DEFAULT_TIMEOUT_MS = 30000;
23
+ // Token cache
24
+ let cachedAccessToken = null;
25
+ let tokenExpiresAt = 0;
26
+ /**
27
+ * Map Snov.io verification status to confidence score
28
+ */
29
+ function statusToConfidence(status) {
30
+ switch (status) {
31
+ case 'valid':
32
+ return 95; // High confidence - verified email
33
+ case 'catch_all':
34
+ return 60; // Medium confidence - catch-all domain
35
+ case 'unverifiable':
36
+ return 40; // Low confidence - could not verify
37
+ case 'not_valid':
38
+ return 0; // Invalid email
39
+ case 'unknown':
40
+ default:
41
+ return 30;
42
+ }
43
+ }
44
+ /**
45
+ * Extract name and domain from candidate
46
+ */
47
+ function extractNameAndDomain(candidate) {
48
+ const firstName = candidate.firstName ||
49
+ candidate.first_name ||
50
+ candidate.first ||
51
+ candidate.name?.split(' ')?.[0] ||
52
+ '';
53
+ const lastName = candidate.lastName ||
54
+ candidate.last_name ||
55
+ candidate.last ||
56
+ candidate.name?.split(' ')?.slice(1).join(' ') ||
57
+ '';
58
+ const domain = candidate.domain ||
59
+ candidate.companyDomain ||
60
+ candidate.company_domain ||
61
+ '';
62
+ if (!firstName || !domain) {
63
+ return null;
64
+ }
65
+ return { firstName, lastName, domain };
66
+ }
67
+ /**
68
+ * Get OAuth access token from Snov.io
69
+ */
70
+ async function getAccessToken(userId, apiSecret, apiUrl, timeoutMs) {
71
+ // Return cached token if valid
72
+ if (cachedAccessToken && Date.now() < tokenExpiresAt) {
73
+ return cachedAccessToken;
74
+ }
75
+ const controller = new AbortController();
76
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
77
+ try {
78
+ const response = await fetch(`${apiUrl}/v1/oauth/access_token`, {
79
+ method: 'POST',
80
+ headers: {
81
+ 'Content-Type': 'application/json',
82
+ },
83
+ body: JSON.stringify({
84
+ grant_type: 'client_credentials',
85
+ client_id: userId,
86
+ client_secret: apiSecret,
87
+ }),
88
+ signal: controller.signal,
89
+ });
90
+ if (!response.ok) {
91
+ return null;
92
+ }
93
+ const data = await response.json();
94
+ // Cache token with 5 minute buffer
95
+ cachedAccessToken = data.access_token;
96
+ tokenExpiresAt = Date.now() + (data.expires_in - 300) * 1000;
97
+ return data.access_token;
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ finally {
103
+ clearTimeout(timeoutId);
104
+ }
105
+ }
106
+ /**
107
+ * Find emails using Snov.io's get-emails-from-name API
108
+ */
109
+ async function findEmailsByName(firstName, lastName, domain, accessToken, apiUrl, timeoutMs) {
110
+ const controller = new AbortController();
111
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
112
+ try {
113
+ const params = new URLSearchParams({
114
+ access_token: accessToken,
115
+ firstName,
116
+ lastName,
117
+ domain,
118
+ });
119
+ const response = await fetch(`${apiUrl}/v1/get-emails-from-names?${params}`, {
120
+ method: 'GET',
121
+ headers: {
122
+ 'Accept': 'application/json',
123
+ },
124
+ signal: controller.signal,
125
+ });
126
+ if (!response.ok) {
127
+ // Handle rate limiting
128
+ if (response.status === 429) {
129
+ throw new Error('Rate limited by Snov.io API');
130
+ }
131
+ return null;
132
+ }
133
+ const data = await response.json();
134
+ return data;
135
+ }
136
+ catch (error) {
137
+ if (error instanceof Error && error.name === 'AbortError') {
138
+ return null; // Timeout
139
+ }
140
+ throw error;
141
+ }
142
+ finally {
143
+ clearTimeout(timeoutId);
144
+ }
145
+ }
146
+ /**
147
+ * Create the Snov.io email finder provider
148
+ *
149
+ * This provider uses Snov.io's database to find verified emails
150
+ * when pattern guessing fails or for catch-all domains.
151
+ */
152
+ function createSnovioProvider(config) {
153
+ const { userId, apiSecret, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
154
+ if (!userId || !apiSecret) {
155
+ // Return no-op provider if not configured
156
+ const noop = async () => null;
157
+ noop.__name = 'snovio';
158
+ return noop;
159
+ }
160
+ async function findEmails(candidate) {
161
+ const nameAndDomain = extractNameAndDomain(candidate);
162
+ if (!nameAndDomain) {
163
+ return null;
164
+ }
165
+ const { firstName, lastName, domain } = nameAndDomain;
166
+ // Get access token
167
+ const accessToken = await getAccessToken(userId, apiSecret, apiUrl, timeoutMs);
168
+ if (!accessToken) {
169
+ return null;
170
+ }
171
+ // Find emails
172
+ const result = await findEmailsByName(firstName, lastName, domain, accessToken, apiUrl, timeoutMs);
173
+ if (!result || !result.success || !result.data?.emails?.length) {
174
+ return null;
175
+ }
176
+ // Convert to provider multi-result format
177
+ const emails = result.data.emails
178
+ .filter((e) => e.email && e.emailStatus !== 'not_valid')
179
+ .map((e) => ({
180
+ email: e.email,
181
+ verified: e.emailStatus === 'valid',
182
+ confidence: statusToConfidence(e.emailStatus),
183
+ isCatchAll: e.emailStatus === 'catch_all',
184
+ metadata: {
185
+ snovioStatus: e.emailStatus,
186
+ firstName: e.firstName,
187
+ lastName: e.lastName,
188
+ position: e.position,
189
+ companyName: e.companyName,
190
+ sourcePage: e.sourcePage,
191
+ type: e.type,
192
+ },
193
+ }));
194
+ if (emails.length === 0) {
195
+ return null;
196
+ }
197
+ // Sort by confidence
198
+ emails.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0));
199
+ return { emails };
200
+ }
201
+ // Mark provider name for orchestrator
202
+ findEmails.__name = 'snovio';
203
+ return findEmails;
204
+ }
205
+ /**
206
+ * Standalone function to find emails via Snov.io
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const result = await findEmailsWithSnovio(
211
+ * 'John',
212
+ * 'Doe',
213
+ * 'example.com',
214
+ * {
215
+ * userId: process.env.SNOVIO_USER_ID,
216
+ * apiSecret: process.env.SNOVIO_API_SECRET,
217
+ * }
218
+ * );
219
+ * ```
220
+ */
221
+ async function findEmailsWithSnovio(firstName, lastName, domain, config) {
222
+ const { userId, apiSecret, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
223
+ const accessToken = await getAccessToken(userId, apiSecret, apiUrl, timeoutMs);
224
+ if (!accessToken) {
225
+ return null;
226
+ }
227
+ return findEmailsByName(firstName, lastName, domain, accessToken, apiUrl, timeoutMs);
228
+ }
229
+ /**
230
+ * Verify a single email via Snov.io
231
+ *
232
+ * @example
233
+ * ```typescript
234
+ * const result = await verifyEmailWithSnovio('test@example.com', {
235
+ * userId: process.env.SNOVIO_USER_ID,
236
+ * apiSecret: process.env.SNOVIO_API_SECRET,
237
+ * });
238
+ * ```
239
+ */
240
+ async function verifyEmailWithSnovio(email, config) {
241
+ const { userId, apiSecret, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
242
+ const accessToken = await getAccessToken(userId, apiSecret, apiUrl, timeoutMs);
243
+ if (!accessToken) {
244
+ return null;
245
+ }
246
+ const controller = new AbortController();
247
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
248
+ try {
249
+ const params = new URLSearchParams({
250
+ access_token: accessToken,
251
+ email,
252
+ });
253
+ const response = await fetch(`${apiUrl}/v1/email-verifier?${params}`, {
254
+ method: 'GET',
255
+ headers: {
256
+ 'Accept': 'application/json',
257
+ },
258
+ signal: controller.signal,
259
+ });
260
+ if (!response.ok) {
261
+ return null;
262
+ }
263
+ const data = await response.json();
264
+ if (!data.success || !data.data?.emails?.length) {
265
+ return null;
266
+ }
267
+ const result = data.data.emails[0];
268
+ return {
269
+ email: result.email,
270
+ status: result.result,
271
+ };
272
+ }
273
+ catch {
274
+ return null;
275
+ }
276
+ finally {
277
+ clearTimeout(timeoutId);
278
+ }
279
+ }
280
+ /**
281
+ * Clear the cached access token (useful for testing)
282
+ */
283
+ function clearSnovioTokenCache() {
284
+ cachedAccessToken = null;
285
+ tokenExpiresAt = 0;
286
+ }
@@ -126,12 +126,6 @@ export interface EnrichmentCandidate {
126
126
  export interface HunterConfig {
127
127
  apiKey: string;
128
128
  }
129
- /**
130
- * Apollo.io provider configuration
131
- */
132
- export interface ApolloConfig {
133
- apiKey: string;
134
- }
135
129
  /**
136
130
  * SmartProspect/Smartlead provider configuration
137
131
  *
@@ -166,6 +160,109 @@ export interface LddConfig {
166
160
  export interface DropcontactConfig {
167
161
  apiKey: string;
168
162
  }
163
+ /**
164
+ * Bouncer.io provider configuration
165
+ *
166
+ * Bouncer provides SMTP email verification with 99%+ accuracy.
167
+ * Best for verifying pattern-guessed emails on non-catch-all domains.
168
+ *
169
+ * @see https://docs.usebouncer.com
170
+ */
171
+ export interface BouncerConfig {
172
+ /** Bouncer API key */
173
+ apiKey: string;
174
+ /** API URL override (default: https://api.usebouncer.com/v1.1) */
175
+ apiUrl?: string;
176
+ /** Timeout in ms (default: 30000) */
177
+ timeoutMs?: number;
178
+ }
179
+ /**
180
+ * Bouncer verification result status
181
+ */
182
+ export type BouncerStatus = 'deliverable' | 'undeliverable' | 'risky' | 'unknown';
183
+ /**
184
+ * Bouncer verification result reason
185
+ */
186
+ export type BouncerReason = 'accepted_email' | 'rejected_email' | 'invalid_domain' | 'invalid_email' | 'unavailable_smtp' | 'dns_error' | 'low_deliverability' | 'low_quality' | 'catch_all' | 'full_mailbox' | 'role_account' | 'disposable' | 'timeout' | 'unknown';
187
+ /**
188
+ * Bouncer API response for single email verification
189
+ */
190
+ export interface BouncerVerifyResponse {
191
+ status: BouncerStatus;
192
+ reason: BouncerReason;
193
+ email: string;
194
+ domain: string;
195
+ account: string;
196
+ /** Whether this is a free email provider (Gmail, Yahoo, etc.) */
197
+ free: boolean;
198
+ /** Whether this is a disposable email */
199
+ disposable: boolean;
200
+ /** Whether this is a role-based email */
201
+ role: boolean;
202
+ /** Whether domain is catch-all (accepts all emails) */
203
+ acceptAll: boolean;
204
+ /** Did you mean suggestion for typos */
205
+ didYouMean?: string;
206
+ /** DNS information */
207
+ dns?: {
208
+ type: string;
209
+ record: string;
210
+ };
211
+ /** Toxicity score (0-5, higher = more risky) */
212
+ toxicity?: number;
213
+ }
214
+ /**
215
+ * Snov.io provider configuration
216
+ *
217
+ * Snov.io provides email finding with 98% delivery rate and built-in verification.
218
+ * Best for finding emails when pattern guessing fails or on catch-all domains.
219
+ *
220
+ * @see https://snov.io/api
221
+ */
222
+ export interface SnovioConfig {
223
+ /** Snov.io API user ID */
224
+ userId: string;
225
+ /** Snov.io API secret */
226
+ apiSecret: string;
227
+ /** API URL override (default: https://api.snov.io) */
228
+ apiUrl?: string;
229
+ /** Timeout in ms (default: 30000) */
230
+ timeoutMs?: number;
231
+ }
232
+ /**
233
+ * Snov.io email verification status
234
+ */
235
+ export type SnovioVerificationStatus = 'valid' | 'not_valid' | 'catch_all' | 'unverifiable' | 'unknown';
236
+ /**
237
+ * Snov.io email result
238
+ */
239
+ export interface SnovioEmailResult {
240
+ email: string;
241
+ emailStatus: SnovioVerificationStatus;
242
+ firstName?: string;
243
+ lastName?: string;
244
+ position?: string;
245
+ sourcePage?: string;
246
+ companyName?: string;
247
+ type?: 'prospect' | 'personal';
248
+ status?: string;
249
+ }
250
+ /**
251
+ * Snov.io get-emails-from-name API response
252
+ */
253
+ export interface SnovioGetEmailsResponse {
254
+ success: boolean;
255
+ data: {
256
+ firstName: string;
257
+ lastName: string;
258
+ emails: SnovioEmailResult[];
259
+ };
260
+ params?: {
261
+ firstName: string;
262
+ lastName: string;
263
+ domain: string;
264
+ };
265
+ }
169
266
  /**
170
267
  * Email construction provider configuration (no API key needed)
171
268
  */
@@ -174,6 +271,8 @@ export interface ConstructConfig {
174
271
  maxAttempts?: number;
175
272
  /** Timeout for MX verification in ms (default: 5000) */
176
273
  timeoutMs?: number;
274
+ /** Delay between SMTP verification checks in ms (default: 2000) */
275
+ smtpVerifyDelayMs?: number;
177
276
  }
178
277
  /**
179
278
  * All provider configurations
@@ -183,8 +282,11 @@ export interface ProvidersConfig {
183
282
  ldd?: LddConfig;
184
283
  smartprospect?: SmartProspectConfig;
185
284
  hunter?: HunterConfig;
186
- apollo?: ApolloConfig;
187
285
  dropcontact?: DropcontactConfig;
286
+ /** Bouncer.io for SMTP email verification (99%+ accuracy) */
287
+ bouncer?: BouncerConfig;
288
+ /** Snov.io for email finding (98% delivery rate) */
289
+ snovio?: SnovioConfig;
188
290
  }
189
291
  /**
190
292
  * Options for enrichment operations
@@ -194,7 +296,7 @@ export interface EnrichmentOptions {
194
296
  maxCostPerEmail?: number;
195
297
  /** Minimum confidence threshold 0-100 (default: 0) */
196
298
  confidenceThreshold?: number;
197
- /** Provider order (default: ['construct', 'ldd', 'smartprospect', 'hunter', 'apollo', 'dropcontact']) */
299
+ /** Provider order (default: ['ldd', 'smartprospect', 'construct', 'bouncer', 'snovio', 'hunter']) */
198
300
  providerOrder?: ProviderName[];
199
301
  /** Retry delay in ms on transient errors (default: 200) */
200
302
  retryMs?: number;
@@ -263,13 +365,34 @@ export interface EnrichmentClient {
263
365
  /**
264
366
  * Available provider names
265
367
  */
266
- export type ProviderName = "construct" | "ldd" | "smartprospect" | "hunter" | "apollo" | "dropcontact";
368
+ export type ProviderName = "construct" | "ldd" | "smartprospect" | "hunter" | "dropcontact" | "bouncer" | "snovio";
267
369
  /**
268
- * Default provider order
370
+ * Default provider order - 2-Phase Strategy
371
+ *
372
+ * PHASE 1 - Free lookups (run in parallel):
373
+ * - ldd: LinkedIn Data Dump - real verified emails (FREE with subscription)
374
+ * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
375
+ * - construct: Pattern guessing + MX check (FREE)
376
+ *
377
+ * PHASE 2 - Paid verification/finding (only if Phase 1 inconclusive):
378
+ * - bouncer: SMTP verify constructed emails ($0.006/email)
379
+ * - snovio: Email finder for catch-all domains ($0.02/email)
380
+ * - hunter: Hunter.io fallback ($0.005/email)
381
+ *
382
+ * Note: dropcontact available but not in default order (expensive at $0.01)
269
383
  */
270
384
  export declare const DEFAULT_PROVIDER_ORDER: ProviderName[];
271
385
  /**
272
386
  * Provider costs in USD per lookup
387
+ *
388
+ * Costs based on 2025 pricing:
389
+ * - ldd: FREE (subscription-based)
390
+ * - smartprospect: FREE (included in SmartLead subscription)
391
+ * - construct: FREE (pattern guessing + MX check)
392
+ * - bouncer: $0.006/email (SMTP verification, 99%+ accuracy)
393
+ * - snovio: $0.02/email (email finding + verification)
394
+ * - hunter: $0.005/email
395
+ * - dropcontact: $0.01/email (not in default order)
273
396
  */
274
397
  export declare const PROVIDER_COSTS: Record<ProviderName, number>;
275
398
  /**
@@ -8,26 +8,48 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.SMARTPROSPECT_SUB_INDUSTRIES = exports.PROVIDER_COSTS = exports.DEFAULT_PROVIDER_ORDER = void 0;
10
10
  /**
11
- * Default provider order
11
+ * Default provider order - 2-Phase Strategy
12
+ *
13
+ * PHASE 1 - Free lookups (run in parallel):
14
+ * - ldd: LinkedIn Data Dump - real verified emails (FREE with subscription)
15
+ * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
16
+ * - construct: Pattern guessing + MX check (FREE)
17
+ *
18
+ * PHASE 2 - Paid verification/finding (only if Phase 1 inconclusive):
19
+ * - bouncer: SMTP verify constructed emails ($0.006/email)
20
+ * - snovio: Email finder for catch-all domains ($0.02/email)
21
+ * - hunter: Hunter.io fallback ($0.005/email)
22
+ *
23
+ * Note: dropcontact available but not in default order (expensive at $0.01)
12
24
  */
13
25
  exports.DEFAULT_PROVIDER_ORDER = [
14
- "construct",
15
26
  "ldd",
16
27
  "smartprospect",
28
+ "construct",
29
+ "bouncer",
30
+ "snovio",
17
31
  "hunter",
18
- "apollo",
19
- "dropcontact",
20
32
  ];
21
33
  /**
22
34
  * Provider costs in USD per lookup
35
+ *
36
+ * Costs based on 2025 pricing:
37
+ * - ldd: FREE (subscription-based)
38
+ * - smartprospect: FREE (included in SmartLead subscription)
39
+ * - construct: FREE (pattern guessing + MX check)
40
+ * - bouncer: $0.006/email (SMTP verification, 99%+ accuracy)
41
+ * - snovio: $0.02/email (email finding + verification)
42
+ * - hunter: $0.005/email
43
+ * - dropcontact: $0.01/email (not in default order)
23
44
  */
24
45
  exports.PROVIDER_COSTS = {
25
46
  construct: 0,
26
47
  ldd: 0,
27
- smartprospect: 0.01,
48
+ smartprospect: 0,
28
49
  hunter: 0.005,
29
- apollo: 0,
30
50
  dropcontact: 0.01,
51
+ bouncer: 0.006,
52
+ snovio: 0.02,
31
53
  };
32
54
  /**
33
55
  * SmartProspect Sub-Industry values (exact API values - partial list)
@@ -0,0 +1,96 @@
1
+ /**
2
+ * HTTP Retry Utilities
3
+ *
4
+ * Shared utilities for HTTP requests with retry logic, rate limit handling,
5
+ * and exponential backoff. Used across all enrichment providers.
6
+ */
7
+ /**
8
+ * Delay execution for specified milliseconds
9
+ */
10
+ export declare function delay(ms: number): Promise<void>;
11
+ /**
12
+ * Check if a value is truthy (not null, undefined, or empty string)
13
+ */
14
+ export declare function truthy(v: unknown): boolean;
15
+ /**
16
+ * Map common verification status strings to boolean
17
+ */
18
+ export declare function mapVerifiedStatus(status: string | undefined | null): boolean | undefined;
19
+ /**
20
+ * Options for fetch with retry
21
+ */
22
+ export interface FetchWithRetryOptions {
23
+ /** Number of retries (default: 1) */
24
+ retries?: number;
25
+ /** Initial backoff in ms (default: 200) */
26
+ backoffMs?: number;
27
+ /** Timeout in ms (default: 30000) */
28
+ timeoutMs?: number;
29
+ /** HTTP status codes that should trigger retry (default: [429, 502, 503, 504]) */
30
+ retryOnStatus?: number[];
31
+ }
32
+ /**
33
+ * Generic API response type
34
+ */
35
+ export interface ApiResponse {
36
+ data?: unknown;
37
+ result?: unknown;
38
+ people?: unknown[];
39
+ matches?: unknown[];
40
+ emails?: unknown[];
41
+ success?: boolean;
42
+ message?: string;
43
+ [key: string]: unknown;
44
+ }
45
+ /**
46
+ * HTTP request with retry on rate limit and transient errors
47
+ *
48
+ * Features:
49
+ * - Exponential backoff on rate limit (429)
50
+ * - Retry on server errors (502, 503, 504)
51
+ * - Configurable timeout
52
+ * - Returns typed response
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const response = await fetchWithRetry<MyApiResponse>(
57
+ * 'https://api.example.com/data',
58
+ * {
59
+ * method: 'POST',
60
+ * headers: { 'Content-Type': 'application/json' },
61
+ * body: JSON.stringify({ query: 'test' }),
62
+ * },
63
+ * { retries: 2, backoffMs: 300 }
64
+ * );
65
+ * ```
66
+ */
67
+ export declare function fetchWithRetry<T = ApiResponse>(url: string, init?: RequestInit, options?: FetchWithRetryOptions): Promise<T>;
68
+ /**
69
+ * Simpler GET request with retry (no request body)
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const data = await getWithRetry<UserData>(
74
+ * `https://api.example.com/users/${id}`,
75
+ * { 'Authorization': `Bearer ${token}` }
76
+ * );
77
+ * ```
78
+ */
79
+ export declare function getWithRetry<T = ApiResponse>(url: string, headers?: Record<string, string>, options?: FetchWithRetryOptions): Promise<T>;
80
+ /**
81
+ * POST request with JSON body and retry
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const result = await postWithRetry<SearchResult>(
86
+ * 'https://api.example.com/search',
87
+ * { query: 'test', limit: 10 },
88
+ * { 'X-Api-Key': apiKey }
89
+ * );
90
+ * ```
91
+ */
92
+ export declare function postWithRetry<T = ApiResponse>(url: string, body: Record<string, unknown>, headers?: Record<string, string>, options?: FetchWithRetryOptions): Promise<T>;
93
+ /**
94
+ * Safe JSON parse with fallback
95
+ */
96
+ export declare function safeJsonParse<T>(str: string, fallback: T): T;