47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
export type DomainAgeResult = {
|
|
domain: string;
|
|
registeredAt: string | null;
|
|
ageDays: number | null;
|
|
source: 'rdap' | 'unavailable';
|
|
};
|
|
|
|
type RdapEvent = { eventAction?: string; eventDate?: string };
|
|
|
|
async function fetchRdap(domain: string): Promise<DomainAgeResult> {
|
|
const response = await fetch(`https://rdap.org/domain/${encodeURIComponent(domain)}`, {
|
|
headers: { Accept: 'application/rdap+json' },
|
|
});
|
|
|
|
if (!response.ok) {
|
|
return { domain, registeredAt: null, ageDays: null, source: 'unavailable' };
|
|
}
|
|
|
|
const data = (await response.json()) as { events?: RdapEvent[] };
|
|
const registration = data.events?.find((event) => event.eventAction === 'registration');
|
|
|
|
if (!registration?.eventDate) {
|
|
return { domain, registeredAt: null, ageDays: null, source: 'unavailable' };
|
|
}
|
|
|
|
const registeredAt = new Date(registration.eventDate);
|
|
if (Number.isNaN(registeredAt.getTime())) {
|
|
return { domain, registeredAt: null, ageDays: null, source: 'unavailable' };
|
|
}
|
|
|
|
const ageDays = Math.floor((Date.now() - registeredAt.getTime()) / (1000 * 60 * 60 * 24));
|
|
|
|
return {
|
|
domain,
|
|
registeredAt: registeredAt.toISOString(),
|
|
ageDays,
|
|
source: 'rdap',
|
|
};
|
|
}
|
|
|
|
export async function checkDomainAge(emailOrDomain: string): Promise<DomainAgeResult> {
|
|
const domain = emailOrDomain.includes('@')
|
|
? emailOrDomain.split('@')[1]!.toLowerCase()
|
|
: emailOrDomain.toLowerCase();
|
|
|
|
return fetchRdap(domain);
|
|
}
|