@mikkelscheike/email-provider-links 2.6.1 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -126
- package/dist/alias-detection.d.ts +1 -0
- package/dist/alias-detection.js +74 -13
- package/dist/api.d.ts +6 -5
- package/dist/api.js +18 -13
- package/dist/concurrent-dns.d.ts +2 -1
- package/dist/concurrent-dns.js +20 -9
- package/dist/hash-verifier.d.ts +1 -0
- package/dist/hash-verifier.js +2 -1
- package/dist/idn.d.ts +1 -0
- package/dist/idn.js +1 -0
- package/dist/index.d.ts +158 -10
- package/dist/index.js +300 -22
- package/dist/loader.d.ts +1 -0
- package/dist/loader.js +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +1 -0
- package/dist/secure-loader.d.ts +1 -0
- package/dist/secure-loader.js +1 -0
- package/dist/url-validator.d.ts +1 -0
- package/dist/url-validator.js +1 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -2,24 +2,30 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Email Provider Links
|
|
4
4
|
*
|
|
5
|
-
* A
|
|
5
|
+
* A modern, robust email provider detection library with:
|
|
6
6
|
* - 93+ verified email providers covering 180+ domains
|
|
7
7
|
* - Concurrent DNS detection for business domains
|
|
8
8
|
* - Zero runtime dependencies
|
|
9
|
-
* - Comprehensive error handling
|
|
10
|
-
* -
|
|
9
|
+
* - Comprehensive error handling with detailed context
|
|
10
|
+
* - International email validation (IDN support)
|
|
11
|
+
* - Email alias normalization and deduplication
|
|
12
|
+
* - Enterprise-grade security features
|
|
11
13
|
*
|
|
12
14
|
* @author Email Provider Links Team
|
|
13
15
|
* @license MIT
|
|
16
|
+
* @version 2.7.0
|
|
14
17
|
*/
|
|
15
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.DOMAIN_COUNT = exports.PROVIDER_COUNT = exports.detectProviderConcurrent = exports.loadProviders = exports.Config = exports.emailsMatch = exports.normalizeEmail = exports.getEmailProviderFast = exports.getEmailProviderSync = exports.getEmailProvider = void 0;
|
|
19
|
+
exports.VERSION = exports.DOMAIN_COUNT = exports.PROVIDER_COUNT = exports.isValidEmailAddress = exports.domainToPunycode = exports.emailToPunycode = exports.validateInternationalEmail = exports.detectProviderConcurrent = exports.loadProviders = exports.Config = exports.emailsMatch = exports.normalizeEmail = exports.getEmailProviderFast = exports.getEmailProviderSync = exports.getEmailProvider = void 0;
|
|
20
|
+
exports.validateEmailAddress = validateEmailAddress;
|
|
17
21
|
exports.getSupportedProviders = getSupportedProviders;
|
|
18
22
|
exports.isEmailProviderSupported = isEmailProviderSupported;
|
|
19
23
|
exports.extractDomain = extractDomain;
|
|
20
24
|
exports.isValidEmail = isValidEmail;
|
|
25
|
+
exports.getLibraryStats = getLibraryStats;
|
|
26
|
+
exports.batchProcessEmails = batchProcessEmails;
|
|
21
27
|
// ===== PRIMARY API =====
|
|
22
|
-
//
|
|
28
|
+
// Core functions that 95% of users need
|
|
23
29
|
var api_1 = require("./api");
|
|
24
30
|
Object.defineProperty(exports, "getEmailProvider", { enumerable: true, get: function () { return api_1.getEmailProvider; } });
|
|
25
31
|
Object.defineProperty(exports, "getEmailProviderSync", { enumerable: true, get: function () { return api_1.getEmailProviderSync; } });
|
|
@@ -28,68 +34,340 @@ Object.defineProperty(exports, "normalizeEmail", { enumerable: true, get: functi
|
|
|
28
34
|
Object.defineProperty(exports, "emailsMatch", { enumerable: true, get: function () { return api_1.emailsMatch; } });
|
|
29
35
|
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return api_1.Config; } });
|
|
30
36
|
// ===== ADVANCED FEATURES =====
|
|
31
|
-
//
|
|
37
|
+
// For power users and custom implementations
|
|
32
38
|
var loader_1 = require("./loader");
|
|
33
39
|
Object.defineProperty(exports, "loadProviders", { enumerable: true, get: function () { return loader_1.loadProviders; } });
|
|
34
40
|
var concurrent_dns_1 = require("./concurrent-dns");
|
|
35
41
|
Object.defineProperty(exports, "detectProviderConcurrent", { enumerable: true, get: function () { return concurrent_dns_1.detectProviderConcurrent; } });
|
|
42
|
+
var idn_1 = require("./idn");
|
|
43
|
+
Object.defineProperty(exports, "validateInternationalEmail", { enumerable: true, get: function () { return idn_1.validateInternationalEmail; } });
|
|
44
|
+
Object.defineProperty(exports, "emailToPunycode", { enumerable: true, get: function () { return idn_1.emailToPunycode; } });
|
|
45
|
+
Object.defineProperty(exports, "domainToPunycode", { enumerable: true, get: function () { return idn_1.domainToPunycode; } });
|
|
46
|
+
// ===== EMAIL VALIDATION =====
|
|
47
|
+
// Enhanced validation with international support
|
|
48
|
+
/**
|
|
49
|
+
* Enhanced email validation with comprehensive error reporting
|
|
50
|
+
*
|
|
51
|
+
* @param email - Email address to validate
|
|
52
|
+
* @returns Validation result with detailed error information
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const result = validateEmailAddress('user@example.com');
|
|
57
|
+
* if (result.isValid) {
|
|
58
|
+
* console.log('Email is valid');
|
|
59
|
+
* } else {
|
|
60
|
+
* console.log('Error:', result.error.message);
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
function validateEmailAddress(email) {
|
|
65
|
+
// Input validation
|
|
66
|
+
if (!email || typeof email !== 'string') {
|
|
67
|
+
return {
|
|
68
|
+
isValid: false,
|
|
69
|
+
error: {
|
|
70
|
+
type: 'INVALID_INPUT',
|
|
71
|
+
code: 'MISSING_EMAIL',
|
|
72
|
+
message: 'Email address is required and must be a string'
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Trim whitespace
|
|
77
|
+
const trimmedEmail = email.trim();
|
|
78
|
+
if (trimmedEmail.length === 0) {
|
|
79
|
+
return {
|
|
80
|
+
isValid: false,
|
|
81
|
+
error: {
|
|
82
|
+
type: 'INVALID_INPUT',
|
|
83
|
+
code: 'EMPTY_EMAIL',
|
|
84
|
+
message: 'Email address cannot be empty'
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Use international validation
|
|
89
|
+
const idnError = (0, idn_2.validateInternationalEmail)(trimmedEmail);
|
|
90
|
+
if (idnError) {
|
|
91
|
+
return {
|
|
92
|
+
isValid: false,
|
|
93
|
+
error: {
|
|
94
|
+
type: idnError.type,
|
|
95
|
+
code: idnError.code,
|
|
96
|
+
message: idnError.message
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
isValid: true,
|
|
102
|
+
normalizedEmail: trimmedEmail.toLowerCase()
|
|
103
|
+
};
|
|
104
|
+
}
|
|
36
105
|
// ===== UTILITY FUNCTIONS =====
|
|
37
106
|
// Helper functions for common tasks
|
|
38
107
|
const loader_2 = require("./loader");
|
|
39
108
|
const api_2 = require("./api");
|
|
109
|
+
const concurrent_dns_2 = require("./concurrent-dns");
|
|
110
|
+
const idn_2 = require("./idn");
|
|
40
111
|
/**
|
|
41
|
-
* Get list of all supported email providers
|
|
42
|
-
*
|
|
112
|
+
* Get comprehensive list of all supported email providers
|
|
113
|
+
*
|
|
114
|
+
* @returns Array of all email providers with metadata
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const providers = getSupportedProviders();
|
|
119
|
+
* console.log(`Supports ${providers.length} providers`);
|
|
120
|
+
*
|
|
121
|
+
* const gmailProvider = providers.find(p => p.domains.includes('gmail.com'));
|
|
122
|
+
* console.log(gmailProvider?.companyProvider); // "Gmail"
|
|
123
|
+
* ```
|
|
43
124
|
*/
|
|
44
125
|
function getSupportedProviders() {
|
|
45
|
-
|
|
46
|
-
|
|
126
|
+
try {
|
|
127
|
+
const { providers } = (0, loader_2.loadProviders)();
|
|
128
|
+
return [...providers]; // Return defensive copy to prevent external mutations
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.warn('Failed to load providers:', error);
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
47
134
|
}
|
|
48
135
|
/**
|
|
49
|
-
* Check if an email provider is supported
|
|
136
|
+
* Check if an email provider is supported (synchronous)
|
|
137
|
+
*
|
|
50
138
|
* @param email - Email address to check
|
|
51
139
|
* @returns true if the provider is supported
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* if (isEmailProviderSupported('user@gmail.com')) {
|
|
144
|
+
* console.log('Gmail is supported');
|
|
145
|
+
* }
|
|
146
|
+
* ```
|
|
52
147
|
*/
|
|
53
148
|
function isEmailProviderSupported(email) {
|
|
54
|
-
|
|
55
|
-
|
|
149
|
+
try {
|
|
150
|
+
if (!email || typeof email !== 'string') {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const result = (0, api_2.getEmailProviderSync)(email);
|
|
154
|
+
return result.provider !== null;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
56
159
|
}
|
|
57
160
|
/**
|
|
58
|
-
* Extract domain from email address
|
|
161
|
+
* Extract and normalize domain from email address
|
|
162
|
+
*
|
|
59
163
|
* @param email - Email address
|
|
60
|
-
* @returns
|
|
164
|
+
* @returns Normalized domain portion or null if invalid
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* const domain = extractDomain('USER@GMAIL.COM');
|
|
169
|
+
* console.log(domain); // "gmail.com"
|
|
170
|
+
*
|
|
171
|
+
* const invalid = extractDomain('invalid-email');
|
|
172
|
+
* console.log(invalid); // null
|
|
173
|
+
* ```
|
|
61
174
|
*/
|
|
62
175
|
function extractDomain(email) {
|
|
63
|
-
|
|
64
|
-
|
|
176
|
+
try {
|
|
177
|
+
if (!email || typeof email !== 'string') {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
const validation = validateEmailAddress(email);
|
|
181
|
+
if (!validation.isValid || !validation.normalizedEmail) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const parts = validation.normalizedEmail.split('@');
|
|
185
|
+
return parts[1] || null;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
65
188
|
return null;
|
|
66
189
|
}
|
|
67
|
-
return email.split('@')[1]?.toLowerCase() || null;
|
|
68
190
|
}
|
|
69
191
|
/**
|
|
70
|
-
* Validate email format
|
|
192
|
+
* Validate email format using enhanced rules
|
|
193
|
+
*
|
|
71
194
|
* @param email - Email address to validate
|
|
72
195
|
* @returns true if valid format
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* if (isValidEmail('user@example.com')) {
|
|
200
|
+
* console.log('Email format is valid');
|
|
201
|
+
* }
|
|
202
|
+
*
|
|
203
|
+
* if (isValidEmail('user@münchen.de')) {
|
|
204
|
+
* console.log('International domain is valid');
|
|
205
|
+
* }
|
|
206
|
+
* ```
|
|
73
207
|
*/
|
|
74
208
|
function isValidEmail(email) {
|
|
75
|
-
const
|
|
76
|
-
return
|
|
209
|
+
const validation = validateEmailAddress(email);
|
|
210
|
+
return validation.isValid;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get library metadata and statistics
|
|
214
|
+
*
|
|
215
|
+
* @returns Object with current library statistics
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* const stats = getLibraryStats();
|
|
220
|
+
* console.log(`Supports ${stats.providerCount} providers across ${stats.domainCount} domains`);
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
function getLibraryStats() {
|
|
224
|
+
try {
|
|
225
|
+
const providers = getSupportedProviders();
|
|
226
|
+
const domainCount = providers.reduce((total, provider) => total + (provider.domains?.length || 0), 0);
|
|
227
|
+
return {
|
|
228
|
+
providerCount: providers.length,
|
|
229
|
+
domainCount,
|
|
230
|
+
version: '2.7.0',
|
|
231
|
+
supportsAsync: true,
|
|
232
|
+
supportsIDN: true,
|
|
233
|
+
supportsAliasDetection: true,
|
|
234
|
+
supportsConcurrentDNS: true
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return {
|
|
239
|
+
providerCount: 0,
|
|
240
|
+
domainCount: 0,
|
|
241
|
+
version: '2.7.0',
|
|
242
|
+
supportsAsync: true,
|
|
243
|
+
supportsIDN: true,
|
|
244
|
+
supportsAliasDetection: true,
|
|
245
|
+
supportsConcurrentDNS: true
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Batch process multiple email addresses efficiently
|
|
251
|
+
*
|
|
252
|
+
* @param emails - Array of email addresses to process
|
|
253
|
+
* @param options - Processing options
|
|
254
|
+
* @returns Array of results in the same order as input
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* const emails = ['user@gmail.com', 'test@yahoo.com', 'invalid-email'];
|
|
259
|
+
* const results = batchProcessEmails(emails);
|
|
260
|
+
*
|
|
261
|
+
* results.forEach((result, index) => {
|
|
262
|
+
* console.log(`${emails[index]}: ${result.isValid ? 'Valid' : 'Invalid'}`);
|
|
263
|
+
* });
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
function batchProcessEmails(emails, options = {}) {
|
|
267
|
+
const { includeProviderInfo = false, normalizeEmails = false, deduplicateAliases = false } = options;
|
|
268
|
+
const results = [];
|
|
269
|
+
const seenNormalized = new Set();
|
|
270
|
+
for (const email of emails) {
|
|
271
|
+
try {
|
|
272
|
+
const validation = validateEmailAddress(email);
|
|
273
|
+
const result = {
|
|
274
|
+
email,
|
|
275
|
+
isValid: validation.isValid
|
|
276
|
+
};
|
|
277
|
+
if (!validation.isValid) {
|
|
278
|
+
result.error = validation.error?.message;
|
|
279
|
+
results.push(result);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
// Add normalized email if requested
|
|
283
|
+
if (normalizeEmails && validation.normalizedEmail) {
|
|
284
|
+
try {
|
|
285
|
+
result.normalized = (0, api_2.normalizeEmail)(validation.normalizedEmail);
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
result.normalized = validation.normalizedEmail;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Check for duplicates if requested
|
|
292
|
+
if (deduplicateAliases && result.normalized) {
|
|
293
|
+
if (seenNormalized.has(result.normalized)) {
|
|
294
|
+
result.isDuplicate = true;
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
seenNormalized.add(result.normalized);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Add provider info if requested
|
|
301
|
+
if (includeProviderInfo && validation.normalizedEmail) {
|
|
302
|
+
try {
|
|
303
|
+
const providerResult = (0, api_2.getEmailProviderSync)(validation.normalizedEmail);
|
|
304
|
+
result.provider = providerResult.provider?.companyProvider || null;
|
|
305
|
+
result.loginUrl = providerResult.loginUrl;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
result.provider = null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
results.push(result);
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
results.push({
|
|
315
|
+
email,
|
|
316
|
+
isValid: false,
|
|
317
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return results;
|
|
77
322
|
}
|
|
323
|
+
// ===== LEGACY COMPATIBILITY =====
|
|
324
|
+
// Maintain backward compatibility
|
|
78
325
|
/**
|
|
79
|
-
*
|
|
326
|
+
* @deprecated Use validateEmailAddress instead for better error handling
|
|
327
|
+
*/
|
|
328
|
+
exports.isValidEmailAddress = isValidEmail;
|
|
329
|
+
/**
|
|
330
|
+
* Library metadata (legacy constants)
|
|
80
331
|
*/
|
|
81
332
|
exports.PROVIDER_COUNT = 93;
|
|
82
333
|
exports.DOMAIN_COUNT = 178;
|
|
83
334
|
/**
|
|
84
335
|
* Default export for convenience
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* import EmailProviderLinks from '@mikkelscheike/email-provider-links';
|
|
340
|
+
*
|
|
341
|
+
* const result = await EmailProviderLinks.getEmailProvider('user@gmail.com');
|
|
342
|
+
* ```
|
|
85
343
|
*/
|
|
86
344
|
exports.default = {
|
|
345
|
+
// Core functions
|
|
87
346
|
getEmailProvider: api_2.getEmailProvider,
|
|
88
347
|
getEmailProviderSync: api_2.getEmailProviderSync,
|
|
89
348
|
getEmailProviderFast: api_2.getEmailProviderFast,
|
|
349
|
+
// Validation
|
|
350
|
+
validateEmailAddress,
|
|
351
|
+
isValidEmail,
|
|
90
352
|
normalizeEmail: api_2.normalizeEmail,
|
|
91
353
|
emailsMatch: api_2.emailsMatch,
|
|
354
|
+
// Utilities
|
|
355
|
+
getSupportedProviders,
|
|
356
|
+
isEmailProviderSupported,
|
|
357
|
+
extractDomain,
|
|
358
|
+
getLibraryStats,
|
|
359
|
+
batchProcessEmails,
|
|
360
|
+
// Advanced
|
|
361
|
+
loadProviders: loader_2.loadProviders,
|
|
362
|
+
detectProviderConcurrent: concurrent_dns_2.detectProviderConcurrent,
|
|
363
|
+
validateInternationalEmail: idn_2.validateInternationalEmail,
|
|
364
|
+
// Constants
|
|
92
365
|
Config: api_2.Config,
|
|
93
366
|
PROVIDER_COUNT: exports.PROVIDER_COUNT,
|
|
94
367
|
DOMAIN_COUNT: exports.DOMAIN_COUNT
|
|
95
368
|
};
|
|
369
|
+
/**
|
|
370
|
+
* Version information
|
|
371
|
+
*/
|
|
372
|
+
exports.VERSION = '2.7.0';
|
|
373
|
+
//# sourceMappingURL=index.js.map
|
package/dist/loader.d.ts
CHANGED
package/dist/loader.js
CHANGED
package/dist/schema.d.ts
CHANGED
package/dist/schema.js
CHANGED
package/dist/secure-loader.d.ts
CHANGED
package/dist/secure-loader.js
CHANGED
package/dist/url-validator.d.ts
CHANGED
package/dist/url-validator.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikkelscheike/email-provider-links",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "TypeScript library for email provider detection with 93 providers (178 domains), concurrent DNS resolution, optimized performance, 91.75% test coverage, and enterprise security for login and password reset flows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
"!dist/**/*.map"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"
|
|
14
|
+
"verify-hashes": "tsx scripts/verify-hashes.ts",
|
|
15
|
+
"build": "tsx scripts/verify-hashes.ts && tsc",
|
|
15
16
|
"test": "jest --silent",
|
|
16
17
|
"test:watch": "jest --watch",
|
|
17
18
|
"test:coverage": "jest --coverage",
|
|
18
|
-
"prepublishOnly": "npm run build",
|
|
19
|
+
"prepublishOnly": "npm run verify-hashes && npm run build",
|
|
19
20
|
"dev": "tsx src/index.ts",
|
|
20
21
|
"sync-versions": "node scripts/sync-versions.js",
|
|
21
22
|
"pretest": "node scripts/sync-versions.js",
|