@@ -251,10 +251,12 @@ export async function resolveAll(domain: string): Promise<DnsResolveResult> {
251251 isCloudflare : r . isCloudflare ?? undefined ,
252252 } ) ) ,
253253 ) ;
254- const merged = sortDnsRecordsByType (
255- [ ...cachedFresh , ...fetchedStale ] ,
256- types ,
257- ) ;
254+ // Deduplicate before sorting to prevent duplicates in merged results
255+ const deduplicated = deduplicateDnsRecords ( [
256+ ...cachedFresh ,
257+ ...fetchedStale ,
258+ ] ) ;
259+ const merged = sortDnsRecordsByType ( deduplicated , types ) ;
258260 const counts = ( types as DnsType [ ] ) . reduce (
259261 ( acc , t ) => {
260262 acc [ t ] = merged . filter ( ( r ) => r . type === t ) . length ;
@@ -370,8 +372,10 @@ export async function resolveAll(domain: string): Promise<DnsResolveResult> {
370372 console . info (
371373 `[dns] ok ${ registrable } counts=${ JSON . stringify ( counts ) } resolver=${ resolverUsed } durations=${ JSON . stringify ( durationByProvider ) } ` ,
372374 ) ;
375+ // Deduplicate records before returning (same logic as replaceDns uses for DB persistence)
376+ const deduplicated = deduplicateDnsRecords ( flat ) ;
373377 // Sort records deterministically to match cache-path ordering
374- const sorted = sortDnsRecordsByType ( flat , types ) ;
378+ const sorted = sortDnsRecordsByType ( deduplicated , types ) ;
375379 return { records : sorted , resolver : resolverUsed } as DnsResolveResult ;
376380 } catch ( err ) {
377381 console . warn (
@@ -466,6 +470,29 @@ function trimQuotes(s: string) {
466470 return s . replace ( / ^ " | " $ / g, "" ) ;
467471}
468472
473+ /**
474+ * Deduplicate DNS records using the same logic as replaceDns.
475+ * Records are considered duplicates if they have the same type, name, value, and priority.
476+ * Case-insensitive comparison for name and value.
477+ */
478+ function deduplicateDnsRecords ( records : DnsRecord [ ] ) : DnsRecord [ ] {
479+ const seen = new Set < string > ( ) ;
480+ const deduplicated : DnsRecord [ ] = [ ] ;
481+
482+ for ( const r of records ) {
483+ // Use case-insensitive comparison, same as replaceDns
484+ const priorityPart = r . priority != null ? `|${ r . priority } ` : "" ;
485+ const key = `${ r . type } |${ r . name . trim ( ) . toLowerCase ( ) } |${ r . value . trim ( ) . toLowerCase ( ) } ${ priorityPart } ` ;
486+
487+ if ( ! seen . has ( key ) ) {
488+ seen . add ( key ) ;
489+ deduplicated . push ( r ) ;
490+ }
491+ }
492+
493+ return deduplicated ;
494+ }
495+
469496function sortDnsRecordsByType (
470497 records : DnsRecord [ ] ,
471498 order : readonly DnsType [ ] ,
0 commit comments