@rocketverifier/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -0
- package/dist/index.d.mts +256 -0
- package/dist/index.d.ts +256 -0
- package/dist/index.js +313 -0
- package/dist/index.mjs +283 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# @rocketverifier/sdk
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for [RocketVerifier](https://rocketverifier.com) - Professional Email Verification API.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Full TypeScript Support** - Complete type definitions included
|
|
8
|
+
- ⚡ **Lightweight** - Zero dependencies
|
|
9
|
+
- 🔄 **Auto Retry** - Built-in retry logic with exponential backoff
|
|
10
|
+
- 📦 **ESM & CommonJS** - Works with any module system
|
|
11
|
+
- 🛡️ **Error Handling** - Typed error classes for easy handling
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @rocketverifier/sdk
|
|
17
|
+
# or
|
|
18
|
+
yarn add @rocketverifier/sdk
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @rocketverifier/sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import RocketVerifier from '@rocketverifier/sdk';
|
|
27
|
+
|
|
28
|
+
const rv = new RocketVerifier('rv_live_your_api_key');
|
|
29
|
+
|
|
30
|
+
// Verify a single email
|
|
31
|
+
const result = await rv.verify('user@example.com');
|
|
32
|
+
|
|
33
|
+
console.log(result.status); // 'deliverable'
|
|
34
|
+
console.log(result.score); // 95
|
|
35
|
+
console.log(result.provider); // 'google.com'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Single Email Verification
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const result = await rv.verify('user@example.com');
|
|
42
|
+
|
|
43
|
+
// Result object
|
|
44
|
+
{
|
|
45
|
+
email: 'user@example.com',
|
|
46
|
+
status: 'deliverable', // 'deliverable' | 'undeliverable' | 'risky' | 'unknown'
|
|
47
|
+
reason: 'accepted_email',
|
|
48
|
+
score: 95, // 0-100 confidence score
|
|
49
|
+
domain: {
|
|
50
|
+
name: 'example.com',
|
|
51
|
+
acceptAll: false, // Catch-all domain
|
|
52
|
+
disposable: false, // Disposable email provider
|
|
53
|
+
free: false // Free email provider
|
|
54
|
+
},
|
|
55
|
+
provider: 'google.com' // Email service provider
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Batch Verification
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// Create a batch job
|
|
63
|
+
const job = await rv.batch.create({
|
|
64
|
+
name: 'My Email List',
|
|
65
|
+
emails: ['user1@example.com', 'user2@example.com', /* ... */],
|
|
66
|
+
webhookUrl: 'https://yoursite.com/webhook' // Optional
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
console.log(job.id); // 'job_abc123'
|
|
70
|
+
|
|
71
|
+
// Check job status
|
|
72
|
+
const status = await rv.batch.get(job.id);
|
|
73
|
+
console.log(status.processedEmails); // 150
|
|
74
|
+
|
|
75
|
+
// Wait for completion with progress updates
|
|
76
|
+
const completed = await rv.batch.wait(job.id, {
|
|
77
|
+
pollInterval: 5000,
|
|
78
|
+
onProgress: (job) => {
|
|
79
|
+
console.log(`Progress: ${job.processedEmails}/${job.totalEmails}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Download results
|
|
84
|
+
const results = await rv.batch.download(job.id);
|
|
85
|
+
console.log(results.length); // 1000
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Domain Check
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
const domain = await rv.domain.check('example.com');
|
|
92
|
+
|
|
93
|
+
console.log(domain.provider); // 'google.com'
|
|
94
|
+
console.log(domain.acceptAll); // false
|
|
95
|
+
console.log(domain.disposable); // false
|
|
96
|
+
console.log(domain.hasValidMx); // true
|
|
97
|
+
console.log(domain.mxRecords); // [{ priority: 10, host: 'aspmx.l.google.com' }]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Check Credits
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
const credits = await rv.getCredits();
|
|
104
|
+
|
|
105
|
+
console.log(credits.credits); // 10000
|
|
106
|
+
console.log(credits.usedToday); // 150
|
|
107
|
+
console.log(credits.usedThisMonth); // 2500
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Error Handling
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import RocketVerifier, {
|
|
114
|
+
AuthenticationError,
|
|
115
|
+
InsufficientCreditsError,
|
|
116
|
+
RateLimitError,
|
|
117
|
+
ValidationError
|
|
118
|
+
} from '@rocketverifier/sdk';
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const result = await rv.verify('user@example.com');
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof AuthenticationError) {
|
|
124
|
+
console.log('Invalid API key');
|
|
125
|
+
} else if (error instanceof InsufficientCreditsError) {
|
|
126
|
+
console.log('Need more credits:', error.creditsRequired);
|
|
127
|
+
} else if (error instanceof RateLimitError) {
|
|
128
|
+
console.log('Rate limited. Retry after:', error.retryAfter, 'seconds');
|
|
129
|
+
} else if (error instanceof ValidationError) {
|
|
130
|
+
console.log('Invalid input:', error.message);
|
|
131
|
+
} else {
|
|
132
|
+
console.log('Unknown error:', error.message);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Configuration
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
const rv = new RocketVerifier('rv_live_xxx', {
|
|
141
|
+
// Custom API URL (for testing)
|
|
142
|
+
baseUrl: 'https://api.rocketverifier.com',
|
|
143
|
+
|
|
144
|
+
// Request timeout in ms (default: 30000)
|
|
145
|
+
timeout: 60000,
|
|
146
|
+
|
|
147
|
+
// Max retry attempts (default: 3)
|
|
148
|
+
maxRetries: 5,
|
|
149
|
+
|
|
150
|
+
// Custom headers
|
|
151
|
+
headers: {
|
|
152
|
+
'X-Custom-Header': 'value'
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## TypeScript
|
|
158
|
+
|
|
159
|
+
All types are exported for TypeScript users:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import RocketVerifier, {
|
|
163
|
+
VerificationResult,
|
|
164
|
+
BatchJob,
|
|
165
|
+
DomainCheckResult,
|
|
166
|
+
CreditBalance,
|
|
167
|
+
RocketVerifierConfig
|
|
168
|
+
} from '@rocketverifier/sdk';
|
|
169
|
+
|
|
170
|
+
// Fully typed responses
|
|
171
|
+
const result: VerificationResult = await rv.verify('user@example.com');
|
|
172
|
+
|
|
173
|
+
// Type-safe status checks
|
|
174
|
+
if (result.status === 'deliverable') {
|
|
175
|
+
console.log('Email is valid!');
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Requirements
|
|
180
|
+
|
|
181
|
+
- Node.js 16.0.0 or higher
|
|
182
|
+
|
|
183
|
+
## Links
|
|
184
|
+
|
|
185
|
+
- [Documentation](https://docs.rocketverifier.com/sdks/nodejs)
|
|
186
|
+
- [API Reference](https://docs.rocketverifier.com/api)
|
|
187
|
+
- [GitHub](https://github.com/rocketverifier/sdk-node)
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RocketVerifier Node.js SDK
|
|
3
|
+
* Professional Email Verification
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import RocketVerifier from '@rocketverifier/sdk';
|
|
8
|
+
*
|
|
9
|
+
* const rv = new RocketVerifier('rv_live_xxx');
|
|
10
|
+
* const result = await rv.verify('user@example.com');
|
|
11
|
+
* console.log(result.status); // 'deliverable'
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
interface ApiErrorPayload {
|
|
15
|
+
error?: {
|
|
16
|
+
message?: string;
|
|
17
|
+
code?: string;
|
|
18
|
+
details?: Record<string, unknown> & {
|
|
19
|
+
creditsRequired?: number;
|
|
20
|
+
creditsAvailable?: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
jobs?: Array<Record<string, unknown>>;
|
|
24
|
+
}
|
|
25
|
+
interface RocketVerifierConfig {
|
|
26
|
+
/** API key for authentication */
|
|
27
|
+
apiKey: string;
|
|
28
|
+
/** Base URL for API (default: https://api.rocketverifier.com) */
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
31
|
+
timeout?: number;
|
|
32
|
+
/** Maximum retry attempts (default: 3) */
|
|
33
|
+
maxRetries?: number;
|
|
34
|
+
/** Custom headers to include in requests */
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
interface DomainInfo {
|
|
38
|
+
/** Domain name */
|
|
39
|
+
name: string;
|
|
40
|
+
/** Whether domain accepts all emails (catch-all) */
|
|
41
|
+
acceptAll: boolean;
|
|
42
|
+
/** Whether domain is disposable */
|
|
43
|
+
disposable: boolean;
|
|
44
|
+
/** Whether domain is a free email provider */
|
|
45
|
+
free: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface AccountInfo {
|
|
48
|
+
/** Whether email is role-based (admin@, info@, etc.) */
|
|
49
|
+
role: boolean;
|
|
50
|
+
/** Whether account is disabled */
|
|
51
|
+
disabled: boolean;
|
|
52
|
+
/** Whether mailbox is full */
|
|
53
|
+
fullMailbox: boolean | null;
|
|
54
|
+
}
|
|
55
|
+
interface DNSInfo {
|
|
56
|
+
/** DNS record type (usually "MX") */
|
|
57
|
+
type: string;
|
|
58
|
+
/** Primary MX record */
|
|
59
|
+
record: string;
|
|
60
|
+
}
|
|
61
|
+
interface VerificationResult {
|
|
62
|
+
/** The verified email address */
|
|
63
|
+
email: string;
|
|
64
|
+
/** Verification status: deliverable, undeliverable, risky, unknown */
|
|
65
|
+
status: 'deliverable' | 'undeliverable' | 'risky' | 'unknown';
|
|
66
|
+
/** Detailed reason for the status */
|
|
67
|
+
reason: string;
|
|
68
|
+
/** Domain information */
|
|
69
|
+
domain: DomainInfo;
|
|
70
|
+
/** Account information */
|
|
71
|
+
account?: AccountInfo;
|
|
72
|
+
/** DNS/MX information */
|
|
73
|
+
dns?: DNSInfo;
|
|
74
|
+
/** Email service provider (e.g., google.com) */
|
|
75
|
+
provider: string | null;
|
|
76
|
+
/** Confidence score (0-100) */
|
|
77
|
+
score: number;
|
|
78
|
+
}
|
|
79
|
+
interface BatchJob {
|
|
80
|
+
/** Unique job ID */
|
|
81
|
+
id: string;
|
|
82
|
+
/** Job name */
|
|
83
|
+
name: string | null;
|
|
84
|
+
/** Job status */
|
|
85
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
86
|
+
/** Total emails in job */
|
|
87
|
+
totalEmails: number;
|
|
88
|
+
/** Emails processed so far */
|
|
89
|
+
processedEmails: number;
|
|
90
|
+
/** Count of valid emails */
|
|
91
|
+
validCount: number;
|
|
92
|
+
/** Count of invalid emails */
|
|
93
|
+
invalidCount: number;
|
|
94
|
+
/** Count of risky emails */
|
|
95
|
+
riskyCount: number;
|
|
96
|
+
/** Count of unknown emails */
|
|
97
|
+
unknownCount: number;
|
|
98
|
+
/** Download URL (available when completed) */
|
|
99
|
+
downloadUrl?: string;
|
|
100
|
+
/** Job creation timestamp */
|
|
101
|
+
createdAt: string;
|
|
102
|
+
/** Job completion timestamp */
|
|
103
|
+
completedAt?: string;
|
|
104
|
+
/** Estimated completion time */
|
|
105
|
+
estimatedCompletion?: string;
|
|
106
|
+
}
|
|
107
|
+
interface BatchCreateOptions {
|
|
108
|
+
/** Job name (optional) */
|
|
109
|
+
name?: string;
|
|
110
|
+
/** List of emails to verify */
|
|
111
|
+
emails: string[];
|
|
112
|
+
/** Webhook URL for completion notification */
|
|
113
|
+
webhookUrl?: string;
|
|
114
|
+
/** Custom data to include in webhook */
|
|
115
|
+
callbackData?: Record<string, any>;
|
|
116
|
+
}
|
|
117
|
+
interface BatchWaitOptions {
|
|
118
|
+
/** Polling interval in milliseconds (default: 5000) */
|
|
119
|
+
pollInterval?: number;
|
|
120
|
+
/** Maximum wait time in milliseconds (default: 300000) */
|
|
121
|
+
timeout?: number;
|
|
122
|
+
/** Callback for progress updates */
|
|
123
|
+
onProgress?: (job: BatchJob) => void;
|
|
124
|
+
}
|
|
125
|
+
interface DomainCheckResult {
|
|
126
|
+
/** Domain name */
|
|
127
|
+
domain: string;
|
|
128
|
+
/** MX records */
|
|
129
|
+
mxRecords: Array<{
|
|
130
|
+
priority: number;
|
|
131
|
+
host: string;
|
|
132
|
+
}>;
|
|
133
|
+
/** Email service provider */
|
|
134
|
+
provider: string | null;
|
|
135
|
+
/** Whether domain accepts all emails */
|
|
136
|
+
acceptAll: boolean;
|
|
137
|
+
/** Whether domain is disposable */
|
|
138
|
+
disposable: boolean;
|
|
139
|
+
/** Whether domain has valid MX records */
|
|
140
|
+
hasValidMx: boolean;
|
|
141
|
+
}
|
|
142
|
+
interface CreditBalance {
|
|
143
|
+
/** Available credits */
|
|
144
|
+
credits: number;
|
|
145
|
+
/** Credits used today */
|
|
146
|
+
usedToday?: number;
|
|
147
|
+
/** Credits used this month */
|
|
148
|
+
usedThisMonth?: number;
|
|
149
|
+
}
|
|
150
|
+
declare class RocketVerifierError extends Error {
|
|
151
|
+
code: string;
|
|
152
|
+
statusCode?: number | undefined;
|
|
153
|
+
details?: any | undefined;
|
|
154
|
+
constructor(message: string, code: string, statusCode?: number | undefined, details?: any | undefined);
|
|
155
|
+
}
|
|
156
|
+
declare class AuthenticationError extends RocketVerifierError {
|
|
157
|
+
constructor(message?: string);
|
|
158
|
+
}
|
|
159
|
+
declare class InsufficientCreditsError extends RocketVerifierError {
|
|
160
|
+
creditsRequired?: number | undefined;
|
|
161
|
+
creditsAvailable?: number | undefined;
|
|
162
|
+
constructor(message?: string, creditsRequired?: number | undefined, creditsAvailable?: number | undefined);
|
|
163
|
+
}
|
|
164
|
+
declare class RateLimitError extends RocketVerifierError {
|
|
165
|
+
retryAfter?: number | undefined;
|
|
166
|
+
constructor(message?: string, retryAfter?: number | undefined);
|
|
167
|
+
}
|
|
168
|
+
declare class ValidationError extends RocketVerifierError {
|
|
169
|
+
constructor(message: string, details?: any);
|
|
170
|
+
}
|
|
171
|
+
declare class RocketVerifier {
|
|
172
|
+
private apiKey;
|
|
173
|
+
private baseUrl;
|
|
174
|
+
private timeout;
|
|
175
|
+
private maxRetries;
|
|
176
|
+
private headers;
|
|
177
|
+
/**
|
|
178
|
+
* Create a new RocketVerifier client
|
|
179
|
+
* @param apiKey - Your RocketVerifier API key
|
|
180
|
+
* @param config - Optional configuration
|
|
181
|
+
*/
|
|
182
|
+
constructor(apiKey: string, config?: Partial<Omit<RocketVerifierConfig, 'apiKey'>>);
|
|
183
|
+
/**
|
|
184
|
+
* Make an authenticated API request
|
|
185
|
+
*/
|
|
186
|
+
private request;
|
|
187
|
+
private sleep;
|
|
188
|
+
/**
|
|
189
|
+
* Verify a single email address
|
|
190
|
+
* @param email - Email address to verify
|
|
191
|
+
* @returns Verification result
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const result = await rv.verify('user@example.com');
|
|
195
|
+
* if (result.status === 'deliverable') {
|
|
196
|
+
* console.log('Email is valid!');
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
verify(email: string): Promise<VerificationResult>;
|
|
201
|
+
/**
|
|
202
|
+
* Batch verification methods
|
|
203
|
+
*/
|
|
204
|
+
batch: {
|
|
205
|
+
/**
|
|
206
|
+
* Create a new batch verification job
|
|
207
|
+
* @param options - Batch job options
|
|
208
|
+
* @returns Created job
|
|
209
|
+
*/
|
|
210
|
+
create: (options: BatchCreateOptions) => Promise<BatchJob>;
|
|
211
|
+
/**
|
|
212
|
+
* Get the status of a batch job
|
|
213
|
+
* @param jobId - Job ID
|
|
214
|
+
* @returns Job status
|
|
215
|
+
*/
|
|
216
|
+
get: (jobId: string) => Promise<BatchJob>;
|
|
217
|
+
/**
|
|
218
|
+
* Wait for a batch job to complete
|
|
219
|
+
* @param jobId - Job ID
|
|
220
|
+
* @param options - Wait options
|
|
221
|
+
* @returns Completed job
|
|
222
|
+
*/
|
|
223
|
+
wait: (jobId: string, options?: BatchWaitOptions) => Promise<BatchJob>;
|
|
224
|
+
/**
|
|
225
|
+
* Download results for a completed batch job
|
|
226
|
+
* @param jobId - Job ID
|
|
227
|
+
* @returns Array of verification results
|
|
228
|
+
*/
|
|
229
|
+
download: (jobId: string) => Promise<VerificationResult[]>;
|
|
230
|
+
/**
|
|
231
|
+
* List all batch jobs
|
|
232
|
+
* @param limit - Maximum jobs to return
|
|
233
|
+
* @param offset - Offset for pagination
|
|
234
|
+
* @returns List of jobs
|
|
235
|
+
*/
|
|
236
|
+
list: (limit?: number, page?: number) => Promise<BatchJob[]>;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Domain check methods
|
|
240
|
+
*/
|
|
241
|
+
domain: {
|
|
242
|
+
/**
|
|
243
|
+
* Check a domain's email configuration
|
|
244
|
+
* @param domain - Domain to check
|
|
245
|
+
* @returns Domain information
|
|
246
|
+
*/
|
|
247
|
+
check: (domain: string) => Promise<DomainCheckResult>;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Get your credit balance
|
|
251
|
+
* @returns Credit balance information
|
|
252
|
+
*/
|
|
253
|
+
getCredits(): Promise<CreditBalance>;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export { type AccountInfo, type ApiErrorPayload, AuthenticationError, type BatchCreateOptions, type BatchJob, type BatchWaitOptions, type CreditBalance, type DNSInfo, type DomainCheckResult, type DomainInfo, InsufficientCreditsError, RateLimitError, RocketVerifier, type RocketVerifierConfig, RocketVerifierError, ValidationError, type VerificationResult, RocketVerifier as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RocketVerifier Node.js SDK
|
|
3
|
+
* Professional Email Verification
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import RocketVerifier from '@rocketverifier/sdk';
|
|
8
|
+
*
|
|
9
|
+
* const rv = new RocketVerifier('rv_live_xxx');
|
|
10
|
+
* const result = await rv.verify('user@example.com');
|
|
11
|
+
* console.log(result.status); // 'deliverable'
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
interface ApiErrorPayload {
|
|
15
|
+
error?: {
|
|
16
|
+
message?: string;
|
|
17
|
+
code?: string;
|
|
18
|
+
details?: Record<string, unknown> & {
|
|
19
|
+
creditsRequired?: number;
|
|
20
|
+
creditsAvailable?: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
jobs?: Array<Record<string, unknown>>;
|
|
24
|
+
}
|
|
25
|
+
interface RocketVerifierConfig {
|
|
26
|
+
/** API key for authentication */
|
|
27
|
+
apiKey: string;
|
|
28
|
+
/** Base URL for API (default: https://api.rocketverifier.com) */
|
|
29
|
+
baseUrl?: string;
|
|
30
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
31
|
+
timeout?: number;
|
|
32
|
+
/** Maximum retry attempts (default: 3) */
|
|
33
|
+
maxRetries?: number;
|
|
34
|
+
/** Custom headers to include in requests */
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
interface DomainInfo {
|
|
38
|
+
/** Domain name */
|
|
39
|
+
name: string;
|
|
40
|
+
/** Whether domain accepts all emails (catch-all) */
|
|
41
|
+
acceptAll: boolean;
|
|
42
|
+
/** Whether domain is disposable */
|
|
43
|
+
disposable: boolean;
|
|
44
|
+
/** Whether domain is a free email provider */
|
|
45
|
+
free: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface AccountInfo {
|
|
48
|
+
/** Whether email is role-based (admin@, info@, etc.) */
|
|
49
|
+
role: boolean;
|
|
50
|
+
/** Whether account is disabled */
|
|
51
|
+
disabled: boolean;
|
|
52
|
+
/** Whether mailbox is full */
|
|
53
|
+
fullMailbox: boolean | null;
|
|
54
|
+
}
|
|
55
|
+
interface DNSInfo {
|
|
56
|
+
/** DNS record type (usually "MX") */
|
|
57
|
+
type: string;
|
|
58
|
+
/** Primary MX record */
|
|
59
|
+
record: string;
|
|
60
|
+
}
|
|
61
|
+
interface VerificationResult {
|
|
62
|
+
/** The verified email address */
|
|
63
|
+
email: string;
|
|
64
|
+
/** Verification status: deliverable, undeliverable, risky, unknown */
|
|
65
|
+
status: 'deliverable' | 'undeliverable' | 'risky' | 'unknown';
|
|
66
|
+
/** Detailed reason for the status */
|
|
67
|
+
reason: string;
|
|
68
|
+
/** Domain information */
|
|
69
|
+
domain: DomainInfo;
|
|
70
|
+
/** Account information */
|
|
71
|
+
account?: AccountInfo;
|
|
72
|
+
/** DNS/MX information */
|
|
73
|
+
dns?: DNSInfo;
|
|
74
|
+
/** Email service provider (e.g., google.com) */
|
|
75
|
+
provider: string | null;
|
|
76
|
+
/** Confidence score (0-100) */
|
|
77
|
+
score: number;
|
|
78
|
+
}
|
|
79
|
+
interface BatchJob {
|
|
80
|
+
/** Unique job ID */
|
|
81
|
+
id: string;
|
|
82
|
+
/** Job name */
|
|
83
|
+
name: string | null;
|
|
84
|
+
/** Job status */
|
|
85
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
86
|
+
/** Total emails in job */
|
|
87
|
+
totalEmails: number;
|
|
88
|
+
/** Emails processed so far */
|
|
89
|
+
processedEmails: number;
|
|
90
|
+
/** Count of valid emails */
|
|
91
|
+
validCount: number;
|
|
92
|
+
/** Count of invalid emails */
|
|
93
|
+
invalidCount: number;
|
|
94
|
+
/** Count of risky emails */
|
|
95
|
+
riskyCount: number;
|
|
96
|
+
/** Count of unknown emails */
|
|
97
|
+
unknownCount: number;
|
|
98
|
+
/** Download URL (available when completed) */
|
|
99
|
+
downloadUrl?: string;
|
|
100
|
+
/** Job creation timestamp */
|
|
101
|
+
createdAt: string;
|
|
102
|
+
/** Job completion timestamp */
|
|
103
|
+
completedAt?: string;
|
|
104
|
+
/** Estimated completion time */
|
|
105
|
+
estimatedCompletion?: string;
|
|
106
|
+
}
|
|
107
|
+
interface BatchCreateOptions {
|
|
108
|
+
/** Job name (optional) */
|
|
109
|
+
name?: string;
|
|
110
|
+
/** List of emails to verify */
|
|
111
|
+
emails: string[];
|
|
112
|
+
/** Webhook URL for completion notification */
|
|
113
|
+
webhookUrl?: string;
|
|
114
|
+
/** Custom data to include in webhook */
|
|
115
|
+
callbackData?: Record<string, any>;
|
|
116
|
+
}
|
|
117
|
+
interface BatchWaitOptions {
|
|
118
|
+
/** Polling interval in milliseconds (default: 5000) */
|
|
119
|
+
pollInterval?: number;
|
|
120
|
+
/** Maximum wait time in milliseconds (default: 300000) */
|
|
121
|
+
timeout?: number;
|
|
122
|
+
/** Callback for progress updates */
|
|
123
|
+
onProgress?: (job: BatchJob) => void;
|
|
124
|
+
}
|
|
125
|
+
interface DomainCheckResult {
|
|
126
|
+
/** Domain name */
|
|
127
|
+
domain: string;
|
|
128
|
+
/** MX records */
|
|
129
|
+
mxRecords: Array<{
|
|
130
|
+
priority: number;
|
|
131
|
+
host: string;
|
|
132
|
+
}>;
|
|
133
|
+
/** Email service provider */
|
|
134
|
+
provider: string | null;
|
|
135
|
+
/** Whether domain accepts all emails */
|
|
136
|
+
acceptAll: boolean;
|
|
137
|
+
/** Whether domain is disposable */
|
|
138
|
+
disposable: boolean;
|
|
139
|
+
/** Whether domain has valid MX records */
|
|
140
|
+
hasValidMx: boolean;
|
|
141
|
+
}
|
|
142
|
+
interface CreditBalance {
|
|
143
|
+
/** Available credits */
|
|
144
|
+
credits: number;
|
|
145
|
+
/** Credits used today */
|
|
146
|
+
usedToday?: number;
|
|
147
|
+
/** Credits used this month */
|
|
148
|
+
usedThisMonth?: number;
|
|
149
|
+
}
|
|
150
|
+
declare class RocketVerifierError extends Error {
|
|
151
|
+
code: string;
|
|
152
|
+
statusCode?: number | undefined;
|
|
153
|
+
details?: any | undefined;
|
|
154
|
+
constructor(message: string, code: string, statusCode?: number | undefined, details?: any | undefined);
|
|
155
|
+
}
|
|
156
|
+
declare class AuthenticationError extends RocketVerifierError {
|
|
157
|
+
constructor(message?: string);
|
|
158
|
+
}
|
|
159
|
+
declare class InsufficientCreditsError extends RocketVerifierError {
|
|
160
|
+
creditsRequired?: number | undefined;
|
|
161
|
+
creditsAvailable?: number | undefined;
|
|
162
|
+
constructor(message?: string, creditsRequired?: number | undefined, creditsAvailable?: number | undefined);
|
|
163
|
+
}
|
|
164
|
+
declare class RateLimitError extends RocketVerifierError {
|
|
165
|
+
retryAfter?: number | undefined;
|
|
166
|
+
constructor(message?: string, retryAfter?: number | undefined);
|
|
167
|
+
}
|
|
168
|
+
declare class ValidationError extends RocketVerifierError {
|
|
169
|
+
constructor(message: string, details?: any);
|
|
170
|
+
}
|
|
171
|
+
declare class RocketVerifier {
|
|
172
|
+
private apiKey;
|
|
173
|
+
private baseUrl;
|
|
174
|
+
private timeout;
|
|
175
|
+
private maxRetries;
|
|
176
|
+
private headers;
|
|
177
|
+
/**
|
|
178
|
+
* Create a new RocketVerifier client
|
|
179
|
+
* @param apiKey - Your RocketVerifier API key
|
|
180
|
+
* @param config - Optional configuration
|
|
181
|
+
*/
|
|
182
|
+
constructor(apiKey: string, config?: Partial<Omit<RocketVerifierConfig, 'apiKey'>>);
|
|
183
|
+
/**
|
|
184
|
+
* Make an authenticated API request
|
|
185
|
+
*/
|
|
186
|
+
private request;
|
|
187
|
+
private sleep;
|
|
188
|
+
/**
|
|
189
|
+
* Verify a single email address
|
|
190
|
+
* @param email - Email address to verify
|
|
191
|
+
* @returns Verification result
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const result = await rv.verify('user@example.com');
|
|
195
|
+
* if (result.status === 'deliverable') {
|
|
196
|
+
* console.log('Email is valid!');
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
verify(email: string): Promise<VerificationResult>;
|
|
201
|
+
/**
|
|
202
|
+
* Batch verification methods
|
|
203
|
+
*/
|
|
204
|
+
batch: {
|
|
205
|
+
/**
|
|
206
|
+
* Create a new batch verification job
|
|
207
|
+
* @param options - Batch job options
|
|
208
|
+
* @returns Created job
|
|
209
|
+
*/
|
|
210
|
+
create: (options: BatchCreateOptions) => Promise<BatchJob>;
|
|
211
|
+
/**
|
|
212
|
+
* Get the status of a batch job
|
|
213
|
+
* @param jobId - Job ID
|
|
214
|
+
* @returns Job status
|
|
215
|
+
*/
|
|
216
|
+
get: (jobId: string) => Promise<BatchJob>;
|
|
217
|
+
/**
|
|
218
|
+
* Wait for a batch job to complete
|
|
219
|
+
* @param jobId - Job ID
|
|
220
|
+
* @param options - Wait options
|
|
221
|
+
* @returns Completed job
|
|
222
|
+
*/
|
|
223
|
+
wait: (jobId: string, options?: BatchWaitOptions) => Promise<BatchJob>;
|
|
224
|
+
/**
|
|
225
|
+
* Download results for a completed batch job
|
|
226
|
+
* @param jobId - Job ID
|
|
227
|
+
* @returns Array of verification results
|
|
228
|
+
*/
|
|
229
|
+
download: (jobId: string) => Promise<VerificationResult[]>;
|
|
230
|
+
/**
|
|
231
|
+
* List all batch jobs
|
|
232
|
+
* @param limit - Maximum jobs to return
|
|
233
|
+
* @param offset - Offset for pagination
|
|
234
|
+
* @returns List of jobs
|
|
235
|
+
*/
|
|
236
|
+
list: (limit?: number, page?: number) => Promise<BatchJob[]>;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Domain check methods
|
|
240
|
+
*/
|
|
241
|
+
domain: {
|
|
242
|
+
/**
|
|
243
|
+
* Check a domain's email configuration
|
|
244
|
+
* @param domain - Domain to check
|
|
245
|
+
* @returns Domain information
|
|
246
|
+
*/
|
|
247
|
+
check: (domain: string) => Promise<DomainCheckResult>;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Get your credit balance
|
|
251
|
+
* @returns Credit balance information
|
|
252
|
+
*/
|
|
253
|
+
getCredits(): Promise<CreditBalance>;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export { type AccountInfo, type ApiErrorPayload, AuthenticationError, type BatchCreateOptions, type BatchJob, type BatchWaitOptions, type CreditBalance, type DNSInfo, type DomainCheckResult, type DomainInfo, InsufficientCreditsError, RateLimitError, RocketVerifier, type RocketVerifierConfig, RocketVerifierError, ValidationError, type VerificationResult, RocketVerifier as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AuthenticationError: () => AuthenticationError,
|
|
24
|
+
InsufficientCreditsError: () => InsufficientCreditsError,
|
|
25
|
+
RateLimitError: () => RateLimitError,
|
|
26
|
+
RocketVerifier: () => RocketVerifier,
|
|
27
|
+
RocketVerifierError: () => RocketVerifierError,
|
|
28
|
+
ValidationError: () => ValidationError,
|
|
29
|
+
default: () => index_default
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
var RocketVerifierError = class extends Error {
|
|
33
|
+
constructor(message, code, statusCode, details) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.code = code;
|
|
36
|
+
this.statusCode = statusCode;
|
|
37
|
+
this.details = details;
|
|
38
|
+
this.name = "RocketVerifierError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var AuthenticationError = class extends RocketVerifierError {
|
|
42
|
+
constructor(message = "Invalid API key") {
|
|
43
|
+
super(message, "unauthorized", 401);
|
|
44
|
+
this.name = "AuthenticationError";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var InsufficientCreditsError = class extends RocketVerifierError {
|
|
48
|
+
constructor(message = "Insufficient credits", creditsRequired, creditsAvailable) {
|
|
49
|
+
super(message, "insufficient_credits", 402, { creditsRequired, creditsAvailable });
|
|
50
|
+
this.creditsRequired = creditsRequired;
|
|
51
|
+
this.creditsAvailable = creditsAvailable;
|
|
52
|
+
this.name = "InsufficientCreditsError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var RateLimitError = class extends RocketVerifierError {
|
|
56
|
+
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
57
|
+
super(message, "rate_limit_exceeded", 429, { retryAfter });
|
|
58
|
+
this.retryAfter = retryAfter;
|
|
59
|
+
this.name = "RateLimitError";
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var ValidationError = class extends RocketVerifierError {
|
|
63
|
+
constructor(message, details) {
|
|
64
|
+
super(message, "validation_error", 400, details);
|
|
65
|
+
this.name = "ValidationError";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var RocketVerifier = class {
|
|
69
|
+
/**
|
|
70
|
+
* Create a new RocketVerifier client
|
|
71
|
+
* @param apiKey - Your RocketVerifier API key
|
|
72
|
+
* @param config - Optional configuration
|
|
73
|
+
*/
|
|
74
|
+
constructor(apiKey, config) {
|
|
75
|
+
// =========================================================================
|
|
76
|
+
// Batch Verification
|
|
77
|
+
// =========================================================================
|
|
78
|
+
/**
|
|
79
|
+
* Batch verification methods
|
|
80
|
+
*/
|
|
81
|
+
this.batch = {
|
|
82
|
+
/**
|
|
83
|
+
* Create a new batch verification job
|
|
84
|
+
* @param options - Batch job options
|
|
85
|
+
* @returns Created job
|
|
86
|
+
*/
|
|
87
|
+
create: async (options) => {
|
|
88
|
+
if (!options.emails || options.emails.length === 0) {
|
|
89
|
+
throw new ValidationError("At least one email is required");
|
|
90
|
+
}
|
|
91
|
+
return this.request("POST", "/v1/verify/bulk", {
|
|
92
|
+
emails: options.emails,
|
|
93
|
+
name: options.name
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
/**
|
|
97
|
+
* Get the status of a batch job
|
|
98
|
+
* @param jobId - Job ID
|
|
99
|
+
* @returns Job status
|
|
100
|
+
*/
|
|
101
|
+
get: async (jobId) => {
|
|
102
|
+
const job = await this.request("GET", `/v1/jobs/${jobId}`);
|
|
103
|
+
return {
|
|
104
|
+
id: job.id,
|
|
105
|
+
name: job.name,
|
|
106
|
+
status: job.status,
|
|
107
|
+
totalEmails: job.total_emails ?? job.totalEmails,
|
|
108
|
+
processedEmails: job.processed_emails ?? job.processedEmails,
|
|
109
|
+
validCount: job.valid_count ?? job.validCount ?? 0,
|
|
110
|
+
invalidCount: job.invalid_count ?? job.invalidCount ?? 0,
|
|
111
|
+
riskyCount: job.risky_count ?? job.riskyCount ?? 0,
|
|
112
|
+
unknownCount: job.unknown_count ?? job.unknownCount ?? 0,
|
|
113
|
+
downloadUrl: job.download_url ?? job.downloadUrl,
|
|
114
|
+
createdAt: job.created_at ?? job.createdAt,
|
|
115
|
+
completedAt: job.completed_at ?? job.completedAt
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Wait for a batch job to complete
|
|
120
|
+
* @param jobId - Job ID
|
|
121
|
+
* @param options - Wait options
|
|
122
|
+
* @returns Completed job
|
|
123
|
+
*/
|
|
124
|
+
wait: async (jobId, options) => {
|
|
125
|
+
const pollInterval = options?.pollInterval || 5e3;
|
|
126
|
+
const timeout = options?.timeout || 3e5;
|
|
127
|
+
const startTime = Date.now();
|
|
128
|
+
while (true) {
|
|
129
|
+
const job = await this.batch.get(jobId);
|
|
130
|
+
if (options?.onProgress) {
|
|
131
|
+
options.onProgress(job);
|
|
132
|
+
}
|
|
133
|
+
if (job.status === "completed" || job.status === "failed") {
|
|
134
|
+
return job;
|
|
135
|
+
}
|
|
136
|
+
if (Date.now() - startTime > timeout) {
|
|
137
|
+
throw new RocketVerifierError("Timeout waiting for job", "timeout", 408);
|
|
138
|
+
}
|
|
139
|
+
await this.sleep(pollInterval);
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
/**
|
|
143
|
+
* Download results for a completed batch job
|
|
144
|
+
* @param jobId - Job ID
|
|
145
|
+
* @returns Array of verification results
|
|
146
|
+
*/
|
|
147
|
+
download: async (jobId) => {
|
|
148
|
+
return this.request("GET", `/v1/jobs/${jobId}/download`);
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* List all batch jobs
|
|
152
|
+
* @param limit - Maximum jobs to return
|
|
153
|
+
* @param offset - Offset for pagination
|
|
154
|
+
* @returns List of jobs
|
|
155
|
+
*/
|
|
156
|
+
list: async (limit = 10, page = 1) => {
|
|
157
|
+
const data = await this.request("GET", `/v1/jobs?limit=${limit}&page=${page}`);
|
|
158
|
+
return (data.jobs || []).map((job) => ({
|
|
159
|
+
id: job.id,
|
|
160
|
+
name: job.name,
|
|
161
|
+
status: job.status,
|
|
162
|
+
totalEmails: job.total_emails ?? job.totalEmails,
|
|
163
|
+
processedEmails: job.processed_emails ?? job.processedEmails,
|
|
164
|
+
validCount: job.valid_count ?? job.validCount ?? 0,
|
|
165
|
+
invalidCount: job.invalid_count ?? job.invalidCount ?? 0,
|
|
166
|
+
riskyCount: job.risky_count ?? job.riskyCount ?? 0,
|
|
167
|
+
unknownCount: job.unknown_count ?? job.unknownCount ?? 0,
|
|
168
|
+
downloadUrl: job.download_url ?? job.downloadUrl,
|
|
169
|
+
createdAt: job.created_at ?? job.createdAt,
|
|
170
|
+
completedAt: job.completed_at ?? job.completedAt
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
// =========================================================================
|
|
175
|
+
// Domain Check
|
|
176
|
+
// =========================================================================
|
|
177
|
+
/**
|
|
178
|
+
* Domain check methods
|
|
179
|
+
*/
|
|
180
|
+
this.domain = {
|
|
181
|
+
/**
|
|
182
|
+
* Check a domain's email configuration
|
|
183
|
+
* @param domain - Domain to check
|
|
184
|
+
* @returns Domain information
|
|
185
|
+
*/
|
|
186
|
+
check: async (domain) => {
|
|
187
|
+
if (!domain) {
|
|
188
|
+
throw new ValidationError("Domain is required");
|
|
189
|
+
}
|
|
190
|
+
return this.request("POST", "/v1/domain/check", { domain });
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
if (!apiKey) {
|
|
194
|
+
throw new AuthenticationError("API key is required");
|
|
195
|
+
}
|
|
196
|
+
this.apiKey = apiKey;
|
|
197
|
+
this.baseUrl = config?.baseUrl || "https://api.rocketverifier.com";
|
|
198
|
+
this.timeout = config?.timeout || 3e4;
|
|
199
|
+
this.maxRetries = config?.maxRetries || 3;
|
|
200
|
+
this.headers = config?.headers || {};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Make an authenticated API request
|
|
204
|
+
*/
|
|
205
|
+
async request(method, path, body, retries = 0) {
|
|
206
|
+
const url = `${this.baseUrl}${path}`;
|
|
207
|
+
const controller = new AbortController();
|
|
208
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
209
|
+
try {
|
|
210
|
+
const response = await fetch(url, {
|
|
211
|
+
method,
|
|
212
|
+
headers: {
|
|
213
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
214
|
+
"Content-Type": "application/json",
|
|
215
|
+
"User-Agent": "@rocketverifier/sdk/1.0.0",
|
|
216
|
+
...this.headers
|
|
217
|
+
},
|
|
218
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
219
|
+
signal: controller.signal
|
|
220
|
+
});
|
|
221
|
+
clearTimeout(timeoutId);
|
|
222
|
+
const data = await response.json().catch(() => ({}));
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
const error = data.error || {};
|
|
225
|
+
const message = error.message || `HTTP ${response.status}`;
|
|
226
|
+
const code = error.code || "unknown_error";
|
|
227
|
+
switch (response.status) {
|
|
228
|
+
case 401:
|
|
229
|
+
throw new AuthenticationError(message);
|
|
230
|
+
case 402:
|
|
231
|
+
throw new InsufficientCreditsError(
|
|
232
|
+
message,
|
|
233
|
+
error.details?.creditsRequired,
|
|
234
|
+
error.details?.creditsAvailable
|
|
235
|
+
);
|
|
236
|
+
case 429:
|
|
237
|
+
const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
|
|
238
|
+
if (retries < this.maxRetries) {
|
|
239
|
+
await this.sleep(retryAfter * 1e3);
|
|
240
|
+
return this.request(method, path, body, retries + 1);
|
|
241
|
+
}
|
|
242
|
+
throw new RateLimitError(message, retryAfter);
|
|
243
|
+
case 400:
|
|
244
|
+
throw new ValidationError(message, error.details);
|
|
245
|
+
default:
|
|
246
|
+
throw new RocketVerifierError(message, code, response.status, error.details);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return data;
|
|
250
|
+
} catch (error) {
|
|
251
|
+
clearTimeout(timeoutId);
|
|
252
|
+
if (error instanceof RocketVerifierError) {
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
if (error.name === "AbortError") {
|
|
256
|
+
throw new RocketVerifierError("Request timeout", "timeout", 408);
|
|
257
|
+
}
|
|
258
|
+
if (retries < this.maxRetries) {
|
|
259
|
+
await this.sleep(1e3 * (retries + 1));
|
|
260
|
+
return this.request(method, path, body, retries + 1);
|
|
261
|
+
}
|
|
262
|
+
throw new RocketVerifierError(
|
|
263
|
+
error.message || "Network error",
|
|
264
|
+
"network_error",
|
|
265
|
+
0
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
sleep(ms) {
|
|
270
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
271
|
+
}
|
|
272
|
+
// =========================================================================
|
|
273
|
+
// Single Verification
|
|
274
|
+
// =========================================================================
|
|
275
|
+
/**
|
|
276
|
+
* Verify a single email address
|
|
277
|
+
* @param email - Email address to verify
|
|
278
|
+
* @returns Verification result
|
|
279
|
+
* @example
|
|
280
|
+
* ```typescript
|
|
281
|
+
* const result = await rv.verify('user@example.com');
|
|
282
|
+
* if (result.status === 'deliverable') {
|
|
283
|
+
* console.log('Email is valid!');
|
|
284
|
+
* }
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
async verify(email) {
|
|
288
|
+
if (!email || !email.includes("@")) {
|
|
289
|
+
throw new ValidationError("Invalid email format");
|
|
290
|
+
}
|
|
291
|
+
return this.request("POST", "/v1/verify", { email });
|
|
292
|
+
}
|
|
293
|
+
// =========================================================================
|
|
294
|
+
// Credits
|
|
295
|
+
// =========================================================================
|
|
296
|
+
/**
|
|
297
|
+
* Get your credit balance
|
|
298
|
+
* @returns Credit balance information
|
|
299
|
+
*/
|
|
300
|
+
async getCredits() {
|
|
301
|
+
return this.request("GET", "/v1/credits");
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
var index_default = RocketVerifier;
|
|
305
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
306
|
+
0 && (module.exports = {
|
|
307
|
+
AuthenticationError,
|
|
308
|
+
InsufficientCreditsError,
|
|
309
|
+
RateLimitError,
|
|
310
|
+
RocketVerifier,
|
|
311
|
+
RocketVerifierError,
|
|
312
|
+
ValidationError
|
|
313
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var RocketVerifierError = class extends Error {
|
|
3
|
+
constructor(message, code, statusCode, details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.statusCode = statusCode;
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "RocketVerifierError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var AuthenticationError = class extends RocketVerifierError {
|
|
12
|
+
constructor(message = "Invalid API key") {
|
|
13
|
+
super(message, "unauthorized", 401);
|
|
14
|
+
this.name = "AuthenticationError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var InsufficientCreditsError = class extends RocketVerifierError {
|
|
18
|
+
constructor(message = "Insufficient credits", creditsRequired, creditsAvailable) {
|
|
19
|
+
super(message, "insufficient_credits", 402, { creditsRequired, creditsAvailable });
|
|
20
|
+
this.creditsRequired = creditsRequired;
|
|
21
|
+
this.creditsAvailable = creditsAvailable;
|
|
22
|
+
this.name = "InsufficientCreditsError";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var RateLimitError = class extends RocketVerifierError {
|
|
26
|
+
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
27
|
+
super(message, "rate_limit_exceeded", 429, { retryAfter });
|
|
28
|
+
this.retryAfter = retryAfter;
|
|
29
|
+
this.name = "RateLimitError";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var ValidationError = class extends RocketVerifierError {
|
|
33
|
+
constructor(message, details) {
|
|
34
|
+
super(message, "validation_error", 400, details);
|
|
35
|
+
this.name = "ValidationError";
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var RocketVerifier = class {
|
|
39
|
+
/**
|
|
40
|
+
* Create a new RocketVerifier client
|
|
41
|
+
* @param apiKey - Your RocketVerifier API key
|
|
42
|
+
* @param config - Optional configuration
|
|
43
|
+
*/
|
|
44
|
+
constructor(apiKey, config) {
|
|
45
|
+
// =========================================================================
|
|
46
|
+
// Batch Verification
|
|
47
|
+
// =========================================================================
|
|
48
|
+
/**
|
|
49
|
+
* Batch verification methods
|
|
50
|
+
*/
|
|
51
|
+
this.batch = {
|
|
52
|
+
/**
|
|
53
|
+
* Create a new batch verification job
|
|
54
|
+
* @param options - Batch job options
|
|
55
|
+
* @returns Created job
|
|
56
|
+
*/
|
|
57
|
+
create: async (options) => {
|
|
58
|
+
if (!options.emails || options.emails.length === 0) {
|
|
59
|
+
throw new ValidationError("At least one email is required");
|
|
60
|
+
}
|
|
61
|
+
return this.request("POST", "/v1/verify/bulk", {
|
|
62
|
+
emails: options.emails,
|
|
63
|
+
name: options.name
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Get the status of a batch job
|
|
68
|
+
* @param jobId - Job ID
|
|
69
|
+
* @returns Job status
|
|
70
|
+
*/
|
|
71
|
+
get: async (jobId) => {
|
|
72
|
+
const job = await this.request("GET", `/v1/jobs/${jobId}`);
|
|
73
|
+
return {
|
|
74
|
+
id: job.id,
|
|
75
|
+
name: job.name,
|
|
76
|
+
status: job.status,
|
|
77
|
+
totalEmails: job.total_emails ?? job.totalEmails,
|
|
78
|
+
processedEmails: job.processed_emails ?? job.processedEmails,
|
|
79
|
+
validCount: job.valid_count ?? job.validCount ?? 0,
|
|
80
|
+
invalidCount: job.invalid_count ?? job.invalidCount ?? 0,
|
|
81
|
+
riskyCount: job.risky_count ?? job.riskyCount ?? 0,
|
|
82
|
+
unknownCount: job.unknown_count ?? job.unknownCount ?? 0,
|
|
83
|
+
downloadUrl: job.download_url ?? job.downloadUrl,
|
|
84
|
+
createdAt: job.created_at ?? job.createdAt,
|
|
85
|
+
completedAt: job.completed_at ?? job.completedAt
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* Wait for a batch job to complete
|
|
90
|
+
* @param jobId - Job ID
|
|
91
|
+
* @param options - Wait options
|
|
92
|
+
* @returns Completed job
|
|
93
|
+
*/
|
|
94
|
+
wait: async (jobId, options) => {
|
|
95
|
+
const pollInterval = options?.pollInterval || 5e3;
|
|
96
|
+
const timeout = options?.timeout || 3e5;
|
|
97
|
+
const startTime = Date.now();
|
|
98
|
+
while (true) {
|
|
99
|
+
const job = await this.batch.get(jobId);
|
|
100
|
+
if (options?.onProgress) {
|
|
101
|
+
options.onProgress(job);
|
|
102
|
+
}
|
|
103
|
+
if (job.status === "completed" || job.status === "failed") {
|
|
104
|
+
return job;
|
|
105
|
+
}
|
|
106
|
+
if (Date.now() - startTime > timeout) {
|
|
107
|
+
throw new RocketVerifierError("Timeout waiting for job", "timeout", 408);
|
|
108
|
+
}
|
|
109
|
+
await this.sleep(pollInterval);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* Download results for a completed batch job
|
|
114
|
+
* @param jobId - Job ID
|
|
115
|
+
* @returns Array of verification results
|
|
116
|
+
*/
|
|
117
|
+
download: async (jobId) => {
|
|
118
|
+
return this.request("GET", `/v1/jobs/${jobId}/download`);
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* List all batch jobs
|
|
122
|
+
* @param limit - Maximum jobs to return
|
|
123
|
+
* @param offset - Offset for pagination
|
|
124
|
+
* @returns List of jobs
|
|
125
|
+
*/
|
|
126
|
+
list: async (limit = 10, page = 1) => {
|
|
127
|
+
const data = await this.request("GET", `/v1/jobs?limit=${limit}&page=${page}`);
|
|
128
|
+
return (data.jobs || []).map((job) => ({
|
|
129
|
+
id: job.id,
|
|
130
|
+
name: job.name,
|
|
131
|
+
status: job.status,
|
|
132
|
+
totalEmails: job.total_emails ?? job.totalEmails,
|
|
133
|
+
processedEmails: job.processed_emails ?? job.processedEmails,
|
|
134
|
+
validCount: job.valid_count ?? job.validCount ?? 0,
|
|
135
|
+
invalidCount: job.invalid_count ?? job.invalidCount ?? 0,
|
|
136
|
+
riskyCount: job.risky_count ?? job.riskyCount ?? 0,
|
|
137
|
+
unknownCount: job.unknown_count ?? job.unknownCount ?? 0,
|
|
138
|
+
downloadUrl: job.download_url ?? job.downloadUrl,
|
|
139
|
+
createdAt: job.created_at ?? job.createdAt,
|
|
140
|
+
completedAt: job.completed_at ?? job.completedAt
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
// =========================================================================
|
|
145
|
+
// Domain Check
|
|
146
|
+
// =========================================================================
|
|
147
|
+
/**
|
|
148
|
+
* Domain check methods
|
|
149
|
+
*/
|
|
150
|
+
this.domain = {
|
|
151
|
+
/**
|
|
152
|
+
* Check a domain's email configuration
|
|
153
|
+
* @param domain - Domain to check
|
|
154
|
+
* @returns Domain information
|
|
155
|
+
*/
|
|
156
|
+
check: async (domain) => {
|
|
157
|
+
if (!domain) {
|
|
158
|
+
throw new ValidationError("Domain is required");
|
|
159
|
+
}
|
|
160
|
+
return this.request("POST", "/v1/domain/check", { domain });
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
if (!apiKey) {
|
|
164
|
+
throw new AuthenticationError("API key is required");
|
|
165
|
+
}
|
|
166
|
+
this.apiKey = apiKey;
|
|
167
|
+
this.baseUrl = config?.baseUrl || "https://api.rocketverifier.com";
|
|
168
|
+
this.timeout = config?.timeout || 3e4;
|
|
169
|
+
this.maxRetries = config?.maxRetries || 3;
|
|
170
|
+
this.headers = config?.headers || {};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Make an authenticated API request
|
|
174
|
+
*/
|
|
175
|
+
async request(method, path, body, retries = 0) {
|
|
176
|
+
const url = `${this.baseUrl}${path}`;
|
|
177
|
+
const controller = new AbortController();
|
|
178
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
179
|
+
try {
|
|
180
|
+
const response = await fetch(url, {
|
|
181
|
+
method,
|
|
182
|
+
headers: {
|
|
183
|
+
"Authorization": `Bearer ${this.apiKey}`,
|
|
184
|
+
"Content-Type": "application/json",
|
|
185
|
+
"User-Agent": "@rocketverifier/sdk/1.0.0",
|
|
186
|
+
...this.headers
|
|
187
|
+
},
|
|
188
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
189
|
+
signal: controller.signal
|
|
190
|
+
});
|
|
191
|
+
clearTimeout(timeoutId);
|
|
192
|
+
const data = await response.json().catch(() => ({}));
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
const error = data.error || {};
|
|
195
|
+
const message = error.message || `HTTP ${response.status}`;
|
|
196
|
+
const code = error.code || "unknown_error";
|
|
197
|
+
switch (response.status) {
|
|
198
|
+
case 401:
|
|
199
|
+
throw new AuthenticationError(message);
|
|
200
|
+
case 402:
|
|
201
|
+
throw new InsufficientCreditsError(
|
|
202
|
+
message,
|
|
203
|
+
error.details?.creditsRequired,
|
|
204
|
+
error.details?.creditsAvailable
|
|
205
|
+
);
|
|
206
|
+
case 429:
|
|
207
|
+
const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
|
|
208
|
+
if (retries < this.maxRetries) {
|
|
209
|
+
await this.sleep(retryAfter * 1e3);
|
|
210
|
+
return this.request(method, path, body, retries + 1);
|
|
211
|
+
}
|
|
212
|
+
throw new RateLimitError(message, retryAfter);
|
|
213
|
+
case 400:
|
|
214
|
+
throw new ValidationError(message, error.details);
|
|
215
|
+
default:
|
|
216
|
+
throw new RocketVerifierError(message, code, response.status, error.details);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return data;
|
|
220
|
+
} catch (error) {
|
|
221
|
+
clearTimeout(timeoutId);
|
|
222
|
+
if (error instanceof RocketVerifierError) {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
if (error.name === "AbortError") {
|
|
226
|
+
throw new RocketVerifierError("Request timeout", "timeout", 408);
|
|
227
|
+
}
|
|
228
|
+
if (retries < this.maxRetries) {
|
|
229
|
+
await this.sleep(1e3 * (retries + 1));
|
|
230
|
+
return this.request(method, path, body, retries + 1);
|
|
231
|
+
}
|
|
232
|
+
throw new RocketVerifierError(
|
|
233
|
+
error.message || "Network error",
|
|
234
|
+
"network_error",
|
|
235
|
+
0
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
sleep(ms) {
|
|
240
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
241
|
+
}
|
|
242
|
+
// =========================================================================
|
|
243
|
+
// Single Verification
|
|
244
|
+
// =========================================================================
|
|
245
|
+
/**
|
|
246
|
+
* Verify a single email address
|
|
247
|
+
* @param email - Email address to verify
|
|
248
|
+
* @returns Verification result
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const result = await rv.verify('user@example.com');
|
|
252
|
+
* if (result.status === 'deliverable') {
|
|
253
|
+
* console.log('Email is valid!');
|
|
254
|
+
* }
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
async verify(email) {
|
|
258
|
+
if (!email || !email.includes("@")) {
|
|
259
|
+
throw new ValidationError("Invalid email format");
|
|
260
|
+
}
|
|
261
|
+
return this.request("POST", "/v1/verify", { email });
|
|
262
|
+
}
|
|
263
|
+
// =========================================================================
|
|
264
|
+
// Credits
|
|
265
|
+
// =========================================================================
|
|
266
|
+
/**
|
|
267
|
+
* Get your credit balance
|
|
268
|
+
* @returns Credit balance information
|
|
269
|
+
*/
|
|
270
|
+
async getCredits() {
|
|
271
|
+
return this.request("GET", "/v1/credits");
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
var index_default = RocketVerifier;
|
|
275
|
+
export {
|
|
276
|
+
AuthenticationError,
|
|
277
|
+
InsufficientCreditsError,
|
|
278
|
+
RateLimitError,
|
|
279
|
+
RocketVerifier,
|
|
280
|
+
RocketVerifierError,
|
|
281
|
+
ValidationError,
|
|
282
|
+
index_default as default
|
|
283
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rocketverifier/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official RocketVerifier Node.js SDK - Professional Email Verification",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
20
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
21
|
+
"test": "vitest",
|
|
22
|
+
"lint": "eslint src/",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"email",
|
|
27
|
+
"verification",
|
|
28
|
+
"validation",
|
|
29
|
+
"email-verification",
|
|
30
|
+
"email-validation",
|
|
31
|
+
"rocketverifier",
|
|
32
|
+
"smtp",
|
|
33
|
+
"mx",
|
|
34
|
+
"deliverability"
|
|
35
|
+
],
|
|
36
|
+
"author": "RocketVerifier",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/rocketverifier/sdk-node.git"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://docs.rocketverifier.com/sdks/nodejs",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/rocketverifier/sdk-node/issues"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=16.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^20.0.0",
|
|
51
|
+
"tsup": "^8.0.0",
|
|
52
|
+
"typescript": "^5.0.0",
|
|
53
|
+
"vitest": "^1.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|