zynor 0.0.82 → 0.0.89
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/dist/index.cjs +3 -3
- package/dist/index.d.ts +224 -27
- package/dist/index.js +3 -3
- package/dist/native.cjs +71567 -0
- package/dist/native.d.ts +3780 -0
- package/dist/native.js +71567 -0
- package/package.json +18 -2
- package/rust/zynor-native.darwin-arm64.node +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -673,6 +673,87 @@ export interface IResolver {
|
|
|
673
673
|
reverse(ip: string, options: AbortOptions): Promise<string[]>;
|
|
674
674
|
reverse(ip: string, options: AbortOptions, provider: ProviderName): Promise<string[]>;
|
|
675
675
|
}
|
|
676
|
+
declare class NativeProvider {
|
|
677
|
+
private queue;
|
|
678
|
+
private config;
|
|
679
|
+
/** Injected hickory binding, or null for the libuv path. Provided by the
|
|
680
|
+
* `'zynor/native'` entry; never loaded here. */
|
|
681
|
+
private rustBinding;
|
|
682
|
+
/**
|
|
683
|
+
* Creates a new native DNS provider instance.
|
|
684
|
+
*
|
|
685
|
+
* @param config - Provider config (concurrency, rate limiting, enabled).
|
|
686
|
+
* @param runtime - Internal: `rust` is the hickory binding injected by the
|
|
687
|
+
* `'zynor/native'` entry. When present, MX/A/AAAA/etc. route through it;
|
|
688
|
+
* when absent, everything uses libuv. Not part of the public surface.
|
|
689
|
+
*/
|
|
690
|
+
constructor(config?: ProviderConfig);
|
|
691
|
+
/**
|
|
692
|
+
* Updates the provider configuration.
|
|
693
|
+
*/
|
|
694
|
+
updateConfig(config: ProviderConfig): void;
|
|
695
|
+
get enabled(): boolean;
|
|
696
|
+
get queueSize(): number;
|
|
697
|
+
get concurrency(): number;
|
|
698
|
+
get isFull(): boolean;
|
|
699
|
+
/** Returns the injected hickory binding, or null for the libuv path.
|
|
700
|
+
* No loading happens here — the `'zynor/native'` entry injects (or
|
|
701
|
+
* refuses to construct, if the binary is missing). */
|
|
702
|
+
private rust;
|
|
703
|
+
/**
|
|
704
|
+
* Executes a function through the queue with abort/timeout support.
|
|
705
|
+
*/
|
|
706
|
+
private executeQueued;
|
|
707
|
+
/**
|
|
708
|
+
* @internal Bypasses PQueue and intervalCap. Reserved for the validator
|
|
709
|
+
* hot path. Dispatches to Rust when `useRust` is on (and binary loaded);
|
|
710
|
+
* otherwise to `dns.resolve`. Both paths remain abort-aware.
|
|
711
|
+
*/
|
|
712
|
+
_resolveDirect<T>(hostname: string, type: RecordType, options?: AbortOptions): Promise<T>;
|
|
713
|
+
/**
|
|
714
|
+
* Resolves A records for a hostname. TTL-aware variants stay on libuv.
|
|
715
|
+
*/
|
|
716
|
+
resolve4(hostname: string): Promise<string[]>;
|
|
717
|
+
resolve4(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
|
|
718
|
+
/** Resolves AAAA records for a hostname. TTL-aware variants stay on libuv. */
|
|
719
|
+
resolve6(hostname: string): Promise<string[]>;
|
|
720
|
+
resolve6(hostname: string, options: ResolveWithTtlOptions): Promise<RecordWithTtl[]>;
|
|
721
|
+
/** ANY records — Rust binding's shape doesn't mirror libuv's tagged union,
|
|
722
|
+
* so we always go through libuv. */
|
|
723
|
+
resolveAny(hostname: string, options?: AbortOptions): Promise<AnyRecord[]>;
|
|
724
|
+
resolveCaa(hostname: string, options?: AbortOptions): Promise<CaaRecord[]>;
|
|
725
|
+
resolveCname(hostname: string, options?: AbortOptions): Promise<string[]>;
|
|
726
|
+
resolveMx(hostname: string, options?: AbortOptions): Promise<MxRecord[]>;
|
|
727
|
+
resolveNaptr(hostname: string, options?: AbortOptions): Promise<NaptrRecord[]>;
|
|
728
|
+
resolveNs(hostname: string, options?: AbortOptions): Promise<string[]>;
|
|
729
|
+
resolvePtr(hostname: string, options?: AbortOptions): Promise<string[]>;
|
|
730
|
+
/** SOA. Rust returns `RustSoaRecord | null`; libuv throws on missing.
|
|
731
|
+
* Bridge: if Rust returns null, throw to match libuv contract. */
|
|
732
|
+
resolveSoa(hostname: string, options?: AbortOptions): Promise<SoaRecord>;
|
|
733
|
+
resolveSrv(hostname: string, options?: AbortOptions): Promise<SrvRecord[]>;
|
|
734
|
+
resolveTlsa(hostname: string, options?: AbortOptions): Promise<TlsaRecord[]>;
|
|
735
|
+
resolveTxt(hostname: string, options?: AbortOptions): Promise<string[][]>;
|
|
736
|
+
reverse(ip: string, options?: AbortOptions): Promise<string[]>;
|
|
737
|
+
/**
|
|
738
|
+
* Generic resolve method. Dispatches to the typed methods so that the
|
|
739
|
+
* Rust path is honored consistently — calling `resolve('gmail.com', 'MX')`
|
|
740
|
+
* with `useRust: true` goes through hickory just like `resolveMx` would.
|
|
741
|
+
*/
|
|
742
|
+
resolve(hostname: string): Promise<string[]>;
|
|
743
|
+
resolve(hostname: string, rrtype: "A"): Promise<string[]>;
|
|
744
|
+
resolve(hostname: string, rrtype: "AAAA"): Promise<string[]>;
|
|
745
|
+
resolve(hostname: string, rrtype: "ANY"): Promise<AnyRecord[]>;
|
|
746
|
+
resolve(hostname: string, rrtype: "CAA"): Promise<CaaRecord[]>;
|
|
747
|
+
resolve(hostname: string, rrtype: "CNAME"): Promise<string[]>;
|
|
748
|
+
resolve(hostname: string, rrtype: "MX"): Promise<MxRecord[]>;
|
|
749
|
+
resolve(hostname: string, rrtype: "NAPTR"): Promise<NaptrRecord[]>;
|
|
750
|
+
resolve(hostname: string, rrtype: "NS"): Promise<string[]>;
|
|
751
|
+
resolve(hostname: string, rrtype: "PTR"): Promise<string[]>;
|
|
752
|
+
resolve(hostname: string, rrtype: "SOA"): Promise<SoaRecord>;
|
|
753
|
+
resolve(hostname: string, rrtype: "SRV"): Promise<SrvRecord[]>;
|
|
754
|
+
resolve(hostname: string, rrtype: "TLSA"): Promise<TlsaRecord[]>;
|
|
755
|
+
resolve(hostname: string, rrtype: "TXT"): Promise<string[][]>;
|
|
756
|
+
}
|
|
676
757
|
declare const EmailProviders: readonly [
|
|
677
758
|
{
|
|
678
759
|
readonly name: "Gmail";
|
|
@@ -2468,7 +2549,7 @@ declare const records: readonly [
|
|
|
2468
2549
|
readonly mx: "..................";
|
|
2469
2550
|
}
|
|
2470
2551
|
];
|
|
2471
|
-
type
|
|
2552
|
+
export type EmailProviderName = typeof records[number]["name"] | ProviderNames;
|
|
2472
2553
|
/**
|
|
2473
2554
|
* Logger signature for debug output. Receives one preformatted line per event.
|
|
2474
2555
|
*/
|
|
@@ -2577,6 +2658,18 @@ export declare class EmailValidator {
|
|
|
2577
2658
|
options?: ValidationConfig;
|
|
2578
2659
|
dns?: Omit<ZynorConfig, "cache">;
|
|
2579
2660
|
});
|
|
2661
|
+
/**
|
|
2662
|
+
* @internal Overridable factory for the internal DNS resolver. Base
|
|
2663
|
+
* implementation returns a libuv-backed {@link Zynor} (quad9 off,
|
|
2664
|
+
* cache off). The subclass exported from `'zynor/native'` overrides
|
|
2665
|
+
* this to return a hickory-Rust-backed Zynor instead, so users of
|
|
2666
|
+
* that subpath get the Rust DNS engine without any public config
|
|
2667
|
+
* knob.
|
|
2668
|
+
*
|
|
2669
|
+
* Called from the constructor; JS method dispatch goes through the
|
|
2670
|
+
* actual class of `this`, so subclass overrides fire correctly.
|
|
2671
|
+
*/
|
|
2672
|
+
protected createDns(config?: Omit<ZynorConfig, "cache">): Zynor;
|
|
2580
2673
|
/**
|
|
2581
2674
|
* Creates or returns an existing instance of the EmailValidator (Singleton pattern)
|
|
2582
2675
|
* @param config - Configuration object for the EmailValidator
|
|
@@ -2724,7 +2817,7 @@ export declare class EmailValidator {
|
|
|
2724
2817
|
*
|
|
2725
2818
|
* Unlike {@link validateBulk}, which waits for every input before returning,
|
|
2726
2819
|
* `each` invokes `onBatch` as soon as enough results have accumulated
|
|
2727
|
-
* (`
|
|
2820
|
+
* (`perPage`, default 10) and continues until every input has been
|
|
2728
2821
|
* processed. Designed for very large inputs (millions) where time-to-first
|
|
2729
2822
|
* result matters and holding the entire result array in memory is wasteful.
|
|
2730
2823
|
*
|
|
@@ -2734,7 +2827,7 @@ export declare class EmailValidator {
|
|
|
2734
2827
|
* round-robin per validation.
|
|
2735
2828
|
*
|
|
2736
2829
|
* Backpressure: `onBatch` is awaited serially. If the callback is slow and
|
|
2737
|
-
* the in-memory buffer reaches `10 *
|
|
2830
|
+
* the in-memory buffer reaches `10 * perPage`, workers pause picking
|
|
2738
2831
|
* new emails until the buffer drains below the cap. This keeps memory
|
|
2739
2832
|
* bounded for truly large inputs.
|
|
2740
2833
|
*
|
|
@@ -2752,7 +2845,7 @@ export declare class EmailValidator {
|
|
|
2752
2845
|
* @param emails - The list of email addresses to validate
|
|
2753
2846
|
* @param options - Streaming options
|
|
2754
2847
|
* @param options.concurrency - Max parallel validations (default 500)
|
|
2755
|
-
* @param options.
|
|
2848
|
+
* @param options.perPage - Min results buffered before invoking onBatch (default 10)
|
|
2756
2849
|
* @param options.deep - Enable deep validation per email
|
|
2757
2850
|
* @param options.logo - Fetch provider logo per email
|
|
2758
2851
|
* @param options.signal - AbortSignal to cancel the batch
|
|
@@ -2764,7 +2857,7 @@ export declare class EmailValidator {
|
|
|
2764
2857
|
* ```typescript
|
|
2765
2858
|
* await validator.each(
|
|
2766
2859
|
* emails, // could be millions
|
|
2767
|
-
* { concurrency: 500,
|
|
2860
|
+
* { concurrency: 500, perPage: 50, deep: true },
|
|
2768
2861
|
* async (batch) => {
|
|
2769
2862
|
* await db.insertMany(batch);
|
|
2770
2863
|
* },
|
|
@@ -2773,7 +2866,7 @@ export declare class EmailValidator {
|
|
|
2773
2866
|
*/
|
|
2774
2867
|
each(emails: string[], options: {
|
|
2775
2868
|
concurrency?: number;
|
|
2776
|
-
|
|
2869
|
+
perPage?: number;
|
|
2777
2870
|
deep?: boolean;
|
|
2778
2871
|
logo?: boolean;
|
|
2779
2872
|
signal?: AbortSignal;
|
|
@@ -3023,11 +3116,11 @@ export declare class EmailValidator {
|
|
|
3023
3116
|
* business/enterprise providers, and many others. See the provider list for complete coverage.
|
|
3024
3117
|
*
|
|
3025
3118
|
* @overload
|
|
3026
|
-
* @param {
|
|
3119
|
+
* @param {EmailProviderName} provider - The name of the email provider (e.g., "Gmail", "Yahoo", "Outlook").
|
|
3027
3120
|
* @returns {string | null} The webmail URL for the provider, or `null` if not found.
|
|
3028
3121
|
*
|
|
3029
3122
|
* @overload
|
|
3030
|
-
* @param {
|
|
3123
|
+
* @param {EmailProviderName} provider - The name of the email provider.
|
|
3031
3124
|
* @param {string} domainOrEmail - A domain name (e.g., "example.com") or email address (e.g., "user@example.com").
|
|
3032
3125
|
* Used as a fallback if the provider name doesn't have a direct URL mapping.
|
|
3033
3126
|
* @returns {string | null} The webmail URL for the provider/domain, or `null` if not found.
|
|
@@ -3067,8 +3160,8 @@ export declare class EmailValidator {
|
|
|
3067
3160
|
* validator.getProviderWebmailUrl("CustomProvider", "customdomain.com");
|
|
3068
3161
|
* // May return a URL if the domain is recognized as a free provider
|
|
3069
3162
|
*/
|
|
3070
|
-
getProviderWebmailUrl(provider:
|
|
3071
|
-
getProviderWebmailUrl(provider:
|
|
3163
|
+
getProviderWebmailUrl(provider: EmailProviderName): string | null;
|
|
3164
|
+
getProviderWebmailUrl(provider: EmailProviderName, domainOrEmail: string): string | null;
|
|
3072
3165
|
getProviderWebmailUrl(domainOrEmail: string): string | null;
|
|
3073
3166
|
/**
|
|
3074
3167
|
* Extract and validate email addresses from mixed HTML or plain-text content.
|
|
@@ -3103,7 +3196,7 @@ export declare class EmailValidator {
|
|
|
3103
3196
|
export interface Valid {
|
|
3104
3197
|
success: true;
|
|
3105
3198
|
data: {
|
|
3106
|
-
provider:
|
|
3199
|
+
provider: EmailProviderName;
|
|
3107
3200
|
isFree: boolean;
|
|
3108
3201
|
email: string;
|
|
3109
3202
|
role: boolean;
|
|
@@ -3119,7 +3212,7 @@ export interface Invalid {
|
|
|
3119
3212
|
email: string;
|
|
3120
3213
|
role: boolean;
|
|
3121
3214
|
}
|
|
3122
|
-
interface
|
|
3215
|
+
export interface EmailDisposable {
|
|
3123
3216
|
success: false;
|
|
3124
3217
|
type: "Disposable";
|
|
3125
3218
|
email: string;
|
|
@@ -3137,14 +3230,89 @@ export interface Syntax {
|
|
|
3137
3230
|
email: string;
|
|
3138
3231
|
role: boolean;
|
|
3139
3232
|
}
|
|
3140
|
-
interface
|
|
3233
|
+
export interface EmailError {
|
|
3141
3234
|
success: false;
|
|
3142
3235
|
type: "Error";
|
|
3143
3236
|
email: string;
|
|
3144
3237
|
message: string;
|
|
3145
3238
|
role: boolean;
|
|
3146
3239
|
}
|
|
3147
|
-
export type EmailResponse = Valid | Invalid | Rejected | Syntax |
|
|
3240
|
+
export type EmailResponse = Valid | Invalid | Rejected | Syntax | EmailError | EmailDisposable;
|
|
3241
|
+
export interface RustResolveOptions {
|
|
3242
|
+
/** Hard deadline in milliseconds. Rust task self-cancels at the
|
|
3243
|
+
* boundary; prevents orphan tasks if the JS caller's watchdog gives
|
|
3244
|
+
* up first. `| undefined` is explicit so callers can spread
|
|
3245
|
+
* `{ timeoutMs: options?.timeout }` under exactOptionalPropertyTypes. */
|
|
3246
|
+
timeoutMs?: number | undefined;
|
|
3247
|
+
}
|
|
3248
|
+
export interface RustMxRecord {
|
|
3249
|
+
exchange: string;
|
|
3250
|
+
priority: number;
|
|
3251
|
+
}
|
|
3252
|
+
export interface RustSrvRecord {
|
|
3253
|
+
priority: number;
|
|
3254
|
+
weight: number;
|
|
3255
|
+
port: number;
|
|
3256
|
+
name: string;
|
|
3257
|
+
}
|
|
3258
|
+
export interface RustSoaRecord {
|
|
3259
|
+
nsname: string;
|
|
3260
|
+
hostmaster: string;
|
|
3261
|
+
serial: number;
|
|
3262
|
+
refresh: number;
|
|
3263
|
+
retry: number;
|
|
3264
|
+
expire: number;
|
|
3265
|
+
minttl: number;
|
|
3266
|
+
}
|
|
3267
|
+
export interface RustCaaRecord {
|
|
3268
|
+
/** 128 when issuer-critical bit set, 0 otherwise (mirrors libuv). */
|
|
3269
|
+
critical: number;
|
|
3270
|
+
issue?: string;
|
|
3271
|
+
issuewild?: string;
|
|
3272
|
+
iodef?: string;
|
|
3273
|
+
}
|
|
3274
|
+
export interface RustNaptrRecord {
|
|
3275
|
+
order: number;
|
|
3276
|
+
preference: number;
|
|
3277
|
+
flags: string;
|
|
3278
|
+
service: string;
|
|
3279
|
+
regexp: string;
|
|
3280
|
+
replacement: string;
|
|
3281
|
+
}
|
|
3282
|
+
/** TLSA. Note: field is `matching` (not `match`); the validator-side
|
|
3283
|
+
* adapter renames if needed for the public TS type. */
|
|
3284
|
+
export interface RustTlsaRecord {
|
|
3285
|
+
certUsage: number;
|
|
3286
|
+
selector: number;
|
|
3287
|
+
matching: number;
|
|
3288
|
+
data: Uint8Array;
|
|
3289
|
+
}
|
|
3290
|
+
/** Generic envelope for `resolveAny`. Different shape from node:dns's
|
|
3291
|
+
* tagged union — `kind` is the record-type name ("A", "MX", …) and
|
|
3292
|
+
* `data` is hickory's textual rendering. The validator's hot path
|
|
3293
|
+
* doesn't use ANY, so divergence is acceptable. */
|
|
3294
|
+
export interface RustAnyRecord {
|
|
3295
|
+
kind: string;
|
|
3296
|
+
data: string;
|
|
3297
|
+
ttl: number;
|
|
3298
|
+
}
|
|
3299
|
+
export interface RustBinding {
|
|
3300
|
+
resolveMx(hostname: string, options?: RustResolveOptions | null): Promise<RustMxRecord[]>;
|
|
3301
|
+
resolveA(hostname: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3302
|
+
resolveAaaa(hostname: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3303
|
+
resolveCname(hostname: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3304
|
+
resolveTxt(hostname: string, options?: RustResolveOptions | null): Promise<string[][]>;
|
|
3305
|
+
resolveNs(hostname: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3306
|
+
resolvePtr(hostname: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3307
|
+
resolveSrv(hostname: string, options?: RustResolveOptions | null): Promise<RustSrvRecord[]>;
|
|
3308
|
+
resolveSoa(hostname: string, options?: RustResolveOptions | null): Promise<RustSoaRecord | null>;
|
|
3309
|
+
resolveCaa(hostname: string, options?: RustResolveOptions | null): Promise<RustCaaRecord[]>;
|
|
3310
|
+
resolveNaptr(hostname: string, options?: RustResolveOptions | null): Promise<RustNaptrRecord[]>;
|
|
3311
|
+
resolveTlsa(hostname: string, options?: RustResolveOptions | null): Promise<RustTlsaRecord[]>;
|
|
3312
|
+
resolveAny(hostname: string, options?: RustResolveOptions | null): Promise<RustAnyRecord[]>;
|
|
3313
|
+
reverseLookup(ip: string, options?: RustResolveOptions | null): Promise<string[]>;
|
|
3314
|
+
buildInfo?(): string;
|
|
3315
|
+
}
|
|
3148
3316
|
/**
|
|
3149
3317
|
* Main DNS resolver class that aggregates multiple DNS providers.
|
|
3150
3318
|
*/
|
|
@@ -3155,12 +3323,24 @@ export declare class Zynor {
|
|
|
3155
3323
|
private dnsTtl;
|
|
3156
3324
|
private inflight;
|
|
3157
3325
|
private rrIndex;
|
|
3326
|
+
protected rust: RustBinding | null;
|
|
3158
3327
|
private dnsInFlight;
|
|
3159
3328
|
/** Epoch-ms until which a DoH provider is considered failing and excluded
|
|
3160
3329
|
* from {@link pickFreestProvider}. Native is never paused — libuv errors
|
|
3161
3330
|
* are local concerns, not upstream-health signals. */
|
|
3162
3331
|
private dohPausedUntil;
|
|
3332
|
+
/** Consecutive-failure counters per provider; reset on any success. We only
|
|
3333
|
+
* pause once a provider's streak exceeds {@link DOH_PAUSE_AFTER}, so single
|
|
3334
|
+
* transient errors don't cascade-pause healthy providers under high load. */
|
|
3335
|
+
private dohFailureStreak;
|
|
3163
3336
|
private static readonly DOH_PAUSE_MS;
|
|
3337
|
+
private static readonly DOH_PAUSE_AFTER;
|
|
3338
|
+
/** Native's reported `concurrency` (default 50) is the PQueue limit, which
|
|
3339
|
+
* the validator path bypasses anyway. The *real* parallel ceiling is
|
|
3340
|
+
* libuv's getaddrinfo thread pool — defaults to 4 unless UV_THREADPOOL_SIZE
|
|
3341
|
+
* is set. {@link pickFreestProvider} uses this to weight native correctly
|
|
3342
|
+
* in load balancing instead of dumping 60%+ of traffic on libuv. */
|
|
3343
|
+
private static readonly NATIVE_EFFECTIVE_CONCURRENCY;
|
|
3164
3344
|
/**
|
|
3165
3345
|
* Creates a new Zynor resolver instance.
|
|
3166
3346
|
* @param config - Configuration for all providers
|
|
@@ -3213,6 +3393,18 @@ export declare class Zynor {
|
|
|
3213
3393
|
* Initializes all DNS providers with their configurations.
|
|
3214
3394
|
*/
|
|
3215
3395
|
private initializeProviders;
|
|
3396
|
+
/**
|
|
3397
|
+
* @internal Overridable factory for the `native` provider. Base
|
|
3398
|
+
* implementation returns a libuv-backed NativeProvider. The subclass
|
|
3399
|
+
* exported from `'zynor/native'` overrides this to inject `useRust: true`
|
|
3400
|
+
* so importers of that subpath get the hickory-dns binding.
|
|
3401
|
+
*
|
|
3402
|
+
* Called from {@link initializeProviders} during construction. JS method
|
|
3403
|
+
* dispatch resolves through the *actual* class of `this`, so subclass
|
|
3404
|
+
* overrides fire correctly even though the call site is in the base
|
|
3405
|
+
* constructor's code path.
|
|
3406
|
+
*/
|
|
3407
|
+
protected createNativeProvider(config?: ProviderConfig): NativeProvider;
|
|
3216
3408
|
/**
|
|
3217
3409
|
* Sets configuration for a specific provider.
|
|
3218
3410
|
* @param provider - The provider name
|
|
@@ -3440,15 +3632,20 @@ export declare class Zynor {
|
|
|
3440
3632
|
*/
|
|
3441
3633
|
resolve: IResolver["resolve"];
|
|
3442
3634
|
/**
|
|
3443
|
-
* @internal Validator-only. Picks the enabled provider with the
|
|
3444
|
-
*
|
|
3445
|
-
*
|
|
3446
|
-
*
|
|
3447
|
-
*
|
|
3448
|
-
*
|
|
3449
|
-
*
|
|
3450
|
-
*
|
|
3451
|
-
*
|
|
3635
|
+
* @internal Validator-only. Picks the enabled provider with the lowest
|
|
3636
|
+
* load ratio (`inFlight / effectiveCapacity`), which yields a distribution
|
|
3637
|
+
* proportional to each provider's capacity even when total in-flight far
|
|
3638
|
+
* exceeds total capacity. A simple slack-based picker over-saturates
|
|
3639
|
+
* everyone equally above their cap and effectively ignores weights; the
|
|
3640
|
+
* ratio formulation keeps weights honest at any load level.
|
|
3641
|
+
*
|
|
3642
|
+
* Native is included but its effective cap is clamped to libuv's
|
|
3643
|
+
* getaddrinfo pool ({@link NATIVE_EFFECTIVE_CONCURRENCY}, defaults to
|
|
3644
|
+
* UV_THREADPOOL_SIZE or 4) — otherwise the validator would dump 50+ in-
|
|
3645
|
+
* flight lookups onto a 4-thread pool. Paused DoH providers are excluded;
|
|
3646
|
+
* if every enabled provider is paused, the filter is dropped.
|
|
3647
|
+
*
|
|
3648
|
+
* RR breaks ties so even loads spread.
|
|
3452
3649
|
*/
|
|
3453
3650
|
private pickFreestProvider;
|
|
3454
3651
|
/**
|
|
@@ -3501,24 +3698,24 @@ export declare class Zynor {
|
|
|
3501
3698
|
/**
|
|
3502
3699
|
* Streams validation results as they complete. Forwards to
|
|
3503
3700
|
* {@link EmailValidator.each} on the singleton validator. See `each` for
|
|
3504
|
-
* full semantics — defaults are `concurrency: 500`, `
|
|
3701
|
+
* full semantics — defaults are `concurrency: 500`, `perPage: 10`, and
|
|
3505
3702
|
* all validator-routed DNS calls bypass the per-provider queue.
|
|
3506
3703
|
*
|
|
3507
3704
|
* @param emails - The list of email addresses to validate
|
|
3508
|
-
* @param options - Streaming options (concurrency,
|
|
3705
|
+
* @param options - Streaming options (concurrency, perPage, deep, etc.)
|
|
3509
3706
|
* @param onBatch - Callback invoked with each completed batch
|
|
3510
3707
|
* @returns Resolves once every input has been processed and flushed
|
|
3511
3708
|
*
|
|
3512
3709
|
* @example
|
|
3513
3710
|
* ```typescript
|
|
3514
|
-
* await Zynor.each(emails, {
|
|
3711
|
+
* await Zynor.each(emails, { perPage: 50 }, async (batch) => {
|
|
3515
3712
|
* await db.insertMany(batch);
|
|
3516
3713
|
* });
|
|
3517
3714
|
* ```
|
|
3518
3715
|
*/
|
|
3519
3716
|
static each(emails: string[], options: {
|
|
3520
3717
|
concurrency?: number;
|
|
3521
|
-
|
|
3718
|
+
perPage?: number;
|
|
3522
3719
|
deep?: boolean;
|
|
3523
3720
|
logo?: boolean;
|
|
3524
3721
|
signal?: AbortSignal;
|