@mikkelscheike/email-provider-links 4.0.7 → 4.0.9

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 CHANGED
@@ -51,17 +51,18 @@ npm install @mikkelscheike/email-provider-links
51
51
 
52
52
  ## Requirements
53
53
 
54
- - **Node.js**: `>=18.0.0` (Tested on 18.x, 20.x, 22.x, **24.x**)
54
+ - **Node.js**: `>=18.0.0` (Tested on 18.x, 20.x, 22.x, **24.x**, **25.x**)
55
55
  - **TypeScript**: `>=4.0.0` (optional, but recommended)
56
56
  - **Zero runtime dependencies** - No external packages required
57
57
 
58
- ### Node.js 24 Support ✨
58
+ ### Node.js 24/25 Support ✨
59
59
 
60
- Fully compatible with the latest Node.js 24.x! The library is tested on:
60
+ Fully compatible with the latest Node.js 24.x and 25.x! The library is tested on:
61
61
  - Node.js 18.x (LTS)
62
- - Node.js 20.x (LTS)
63
- - Node.js 22.x (Current)
64
- - **Node.js 24.x (Latest)** - Full support with latest features
62
+ - Node.js 20.x (LTS)
63
+ - Node.js 22.x
64
+ - **Node.js 24.x** - Full support
65
+ - **Node.js 25.x (Latest)** - Full support with latest features
65
66
 
66
67
  ## Supported Providers
67
68
 
@@ -224,7 +224,7 @@ class ConcurrentDNSDetector {
224
224
  async queryMX(domain) {
225
225
  const startTime = Date.now();
226
226
  try {
227
- const records = await this.withTimeout(resolveMxAsync(domain), this.config.timeout);
227
+ const records = await this.withTimeout(() => resolveMxAsync(domain), this.config.timeout);
228
228
  return {
229
229
  type: 'mx',
230
230
  success: true,
@@ -248,7 +248,7 @@ class ConcurrentDNSDetector {
248
248
  async queryTXT(domain) {
249
249
  const startTime = Date.now();
250
250
  try {
251
- const records = await this.withTimeout(resolveTxtAsync(domain), this.config.timeout);
251
+ const records = await this.withTimeout(() => resolveTxtAsync(domain), this.config.timeout);
252
252
  const flatRecords = records.flat();
253
253
  return {
254
254
  type: 'txt',
@@ -396,29 +396,34 @@ class ConcurrentDNSDetector {
396
396
  /**
397
397
  * Wrap a promise with a timeout
398
398
  */
399
- withTimeout(promise, ms) {
399
+ withTimeout(fn, ms) {
400
+ // For extremely small timeouts, avoid starting the underlying DNS query at all
401
+ if (ms <= 1) {
402
+ return Promise.reject(new Error(`DNS query timeout after ${ms}ms`));
403
+ }
400
404
  let rejectFn;
401
- const timeoutPromise = new Promise((resolve, reject) => {
405
+ const wrappedPromise = new Promise((resolve, reject) => {
402
406
  rejectFn = reject;
403
407
  const timeout = setTimeout(() => reject(new Error(`DNS query timeout after ${ms}ms`)), ms).unref();
404
- promise
408
+ // Start the underlying operation only after setting up the timeout
409
+ fn()
405
410
  .then(resolve)
406
411
  .catch(reject)
407
412
  .finally(() => {
408
413
  clearTimeout(timeout);
409
414
  // Clean up active query
410
- const queryEntry = Array.from(this.activeQueries).find(entry => entry.promise === timeoutPromise);
415
+ const queryEntry = Array.from(this.activeQueries).find(entry => entry.promise === wrappedPromise);
411
416
  if (queryEntry) {
412
417
  this.activeQueries.delete(queryEntry);
413
418
  }
414
419
  });
415
420
  });
416
- // Only add to active queries if we have a reject function
421
+ // Track active query for potential cleanup in tests
417
422
  if (rejectFn) {
418
- const queryEntry = { promise: timeoutPromise, reject: rejectFn };
423
+ const queryEntry = { promise: wrappedPromise, reject: rejectFn };
419
424
  this.activeQueries.add(queryEntry);
420
425
  }
421
- return timeoutPromise;
426
+ return wrappedPromise;
422
427
  }
423
428
  }
424
429
  exports.ConcurrentDNSDetector = ConcurrentDNSDetector;
@@ -29,7 +29,7 @@ const KNOWN_GOOD_HASHES = {
29
29
  // SHA-256 hash of the legitimate emailproviders.json
30
30
  'emailproviders.json': 'c74455b537534268c28b7312664c676cb0f511e6674367da603a15c5fe30e16f',
31
31
  // You can add hashes for other critical files
32
- 'package.json': '53897d42221839ee7fa6509523d58ccc01daf2b66a0dbbc731aa2b2aa4216771',
32
+ 'package.json': 'a607656e9301d446d24e9251f2f192f482989bfc0360b37f212dd2e86dfafaa7',
33
33
  };
34
34
  /**
35
35
  * Calculates SHA-256 hash of a file or string content
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikkelscheike/email-provider-links",
3
- "version": "4.0.7",
3
+ "version": "4.0.9",
4
4
  "description": "TypeScript library for email provider detection with 93 providers (207 domains), concurrent DNS resolution, optimized performance, 94.65% 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,7 +11,7 @@
11
11
  "!dist/**/*.map"
12
12
  ],
13
13
  "scripts": {
14
- "clean": "rm -rf dist",
14
+ "clean": "node -e \"try{require('fs').rmSync('dist',{recursive:true,force:true});}catch(e){}\"",
15
15
  "verify-hashes": "tsx scripts/verify-hashes.ts",
16
16
  "build": "npm run clean && tsx scripts/verify-hashes.ts && tsc",
17
17
  "test": "jest",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "engines": {
57
57
  "node": ">=18.0.0",
58
- "comment": "Supports Node.js 18.x, 20.x, 22.x, and 24.x"
58
+ "comment": "Supports Node.js 18.x, 20.x, 22.x, 24.x, and 25.x"
59
59
  },
60
60
  "publishConfig": {
61
61
  "access": "public",
@@ -66,20 +66,20 @@
66
66
  "test-exclude": "^7.0.1"
67
67
  },
68
68
  "devDependencies": {
69
- "@jest/globals": "^30.0.3",
69
+ "@jest/globals": "^30.2.0",
70
70
  "@semantic-release/commit-analyzer": "^13.0.1",
71
71
  "@semantic-release/exec": "^7.1.0",
72
72
  "@semantic-release/git": "^10.0.1",
73
- "@semantic-release/github": "^11.0.3",
74
- "@semantic-release/npm": "^12.0.2",
75
- "@semantic-release/release-notes-generator": "^14.0.3",
73
+ "@semantic-release/github": "^12.0.2",
74
+ "@semantic-release/npm": "^13.1.2",
75
+ "@semantic-release/release-notes-generator": "^14.1.0",
76
76
  "@types/jest": "^30.0.0",
77
- "@types/node": "^24.0.4",
78
- "conventional-changelog-conventionalcommits": "^9.0.0",
79
- "jest": "^30.0.3",
80
- "semantic-release": "^24.2.5",
81
- "ts-jest": "^29.4.0",
82
- "tsx": "^4.20.3",
83
- "typescript": "^5.8.3"
77
+ "@types/node": "^24.10.1",
78
+ "conventional-changelog-conventionalcommits": "^9.1.0",
79
+ "jest": "^30.2.0",
80
+ "semantic-release": "^25.0.2",
81
+ "ts-jest": "^29.4.6",
82
+ "tsx": "^4.21.0",
83
+ "typescript": "^5.9.3"
84
84
  }
85
85
  }