@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 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
@@ -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 };
@@ -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
+ }