mirror of
https://github.com/Xevion/rdap.git
synced 2025-12-06 01:16:00 -06:00
feat: implement Entity and Nameserver cards with type safety improvements
- Add EntityCard component to display entity information with handle, roles, and public IDs - Add NameserverCard component to display nameserver details - Integrate new cards into Generic component for proper object rendering - Remove unused dependencies (immutability-helper, type-fest) - Enhance type safety in LookupInput with Zod validation - Replace console.log statements with appropriate comments - Initialize registryDataRef with proper typed default values - Remove unused code and debug logging from rdap.ts and useLookup hook - Update Object.entries type definition without external dependency
This commit is contained in:
@@ -27,7 +27,6 @@
|
||||
"@swc/helpers": "^0.5.11",
|
||||
"clsx": "^2.1.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"immutability-helper": "^3.1.1",
|
||||
"next": "^15.5.6",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
@@ -64,7 +63,6 @@
|
||||
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||
"semantic-release": "^24.0.0",
|
||||
"tailwindcss": "^4.1.15",
|
||||
"type-fest": "^5.1.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
|
||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@@ -29,9 +29,6 @@ importers:
|
||||
date-fns:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
immutability-helper:
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1
|
||||
next:
|
||||
specifier: ^15.5.6
|
||||
version: 15.5.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2)
|
||||
@@ -135,9 +132,6 @@ importers:
|
||||
tailwindcss:
|
||||
specifier: ^4.1.15
|
||||
version: 4.1.15
|
||||
type-fest:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
@@ -2372,9 +2366,6 @@ packages:
|
||||
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
immutability-helper@3.1.1:
|
||||
resolution: {integrity: sha512-Q0QaXjPjwIju/28TsugCHNEASwoCcJSyJV3uO1sOIQGI0jKgm9f41Lvz0DZj3n46cNCyAZTsEYoY4C2bVRUzyQ==}
|
||||
|
||||
immutable@5.1.4:
|
||||
resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==}
|
||||
|
||||
@@ -3712,10 +3703,6 @@ packages:
|
||||
tabbable@6.2.0:
|
||||
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||
|
||||
tagged-tag@1.0.0:
|
||||
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
tailwind-merge@3.3.1:
|
||||
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
|
||||
|
||||
@@ -3824,10 +3811,6 @@ packages:
|
||||
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
type-fest@5.1.0:
|
||||
resolution: {integrity: sha512-wQ531tuWvB6oK+pchHIu5lHe5f5wpSCqB8Kf4dWQRbOYc9HTge7JL0G4Qd44bh6QuJCccIzL3bugb8GI0MwHrg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
typed-array-buffer@1.0.3:
|
||||
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -6413,8 +6396,6 @@ snapshots:
|
||||
|
||||
ignore@7.0.5: {}
|
||||
|
||||
immutability-helper@3.1.1: {}
|
||||
|
||||
immutable@5.1.4: {}
|
||||
|
||||
import-fresh@3.3.1:
|
||||
@@ -7674,8 +7655,6 @@ snapshots:
|
||||
|
||||
tabbable@6.2.0: {}
|
||||
|
||||
tagged-tag@1.0.0: {}
|
||||
|
||||
tailwind-merge@3.3.1: {}
|
||||
|
||||
tailwindcss@4.1.15: {}
|
||||
@@ -7762,10 +7741,6 @@ snapshots:
|
||||
|
||||
type-fest@4.41.0: {}
|
||||
|
||||
type-fest@5.1.0:
|
||||
dependencies:
|
||||
tagged-tag: 1.0.0
|
||||
|
||||
typed-array-buffer@1.0.3:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
|
||||
@@ -47,7 +47,7 @@ const AbstractCard: FunctionComponent<AbstractCardProps> = ({
|
||||
.writeText(JSON.stringify(data, null, 4))
|
||||
.then(
|
||||
() => {
|
||||
console.log("Copied to clipboard.");
|
||||
// Successfully copied to clipboard
|
||||
},
|
||||
(err) => {
|
||||
if (err instanceof Error)
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { FunctionComponent } from "react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { onPromise, preventDefault } from "@/helpers";
|
||||
import type { SimplifiedTargetType, SubmitProps, TargetType } from "@/types";
|
||||
import { TargetTypeEnum } from "@/schema";
|
||||
import {
|
||||
CheckIcon,
|
||||
ChevronUpDownIcon,
|
||||
@@ -109,7 +110,9 @@ const LookupInput: FunctionComponent<LookupInputProps> = ({
|
||||
// 'auto' means 'do whatever' so we return null.
|
||||
if (value == "auto") return null;
|
||||
|
||||
return value as TargetType;
|
||||
// Validate the value is a valid TargetType
|
||||
const result = TargetTypeEnum.safeParse(value);
|
||||
return result.success ? result.data : null;
|
||||
}
|
||||
|
||||
const searchIcon = (
|
||||
@@ -250,7 +253,7 @@ const LookupInput: FunctionComponent<LookupInputProps> = ({
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
console.log("TODO: Show Help Explanation");
|
||||
// TODO: Show Help Explanation
|
||||
}}
|
||||
className="absolute inset-y-0 left-0 flex items-center pl-4 text-lg font-bold opacity-20 hover:animate-pulse"
|
||||
>
|
||||
|
||||
50
src/components/lookup/EntityCard.tsx
Normal file
50
src/components/lookup/EntityCard.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import type { FunctionComponent } from "react";
|
||||
import React from "react";
|
||||
import type { Entity } from "@/types";
|
||||
import Property from "@/components/common/Property";
|
||||
import PropertyList from "@/components/common/PropertyList";
|
||||
import AbstractCard from "@/components/common/AbstractCard";
|
||||
|
||||
export type EntityCardProps = {
|
||||
data: Entity;
|
||||
url?: string;
|
||||
};
|
||||
|
||||
const EntityCard: FunctionComponent<EntityCardProps> = ({ data, url }: EntityCardProps) => {
|
||||
return (
|
||||
<AbstractCard
|
||||
data={data}
|
||||
url={url}
|
||||
header={
|
||||
<>
|
||||
<span className="font-mono tracking-tighter">ENTITY</span>
|
||||
<span className="font-mono tracking-wide">
|
||||
{data.handle || data.roles.join(", ")}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<dl>
|
||||
{data.handle && <Property title="Handle">{data.handle}</Property>}
|
||||
<PropertyList title="Roles">
|
||||
{data.roles.map((role, index) => (
|
||||
<PropertyList.Item key={index} title={role}>
|
||||
{role}
|
||||
</PropertyList.Item>
|
||||
))}
|
||||
</PropertyList>
|
||||
{data.publicIds && data.publicIds.length > 0 && (
|
||||
<PropertyList title="Public IDs">
|
||||
{data.publicIds.map((publicId, index) => (
|
||||
<PropertyList.Item key={index} title={publicId.type}>
|
||||
{`${publicId.identifier} (${publicId.type})`}
|
||||
</PropertyList.Item>
|
||||
))}
|
||||
</PropertyList>
|
||||
)}
|
||||
</dl>
|
||||
</AbstractCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default EntityCard;
|
||||
@@ -2,6 +2,8 @@ import type { FunctionComponent } from "react";
|
||||
import DomainCard from "@/components/lookup/DomainCard";
|
||||
import IPCard from "@/components/lookup/IPCard";
|
||||
import AutnumCard from "@/components/lookup/AutnumCard";
|
||||
import EntityCard from "@/components/lookup/EntityCard";
|
||||
import NameserverCard from "@/components/lookup/NameserverCard";
|
||||
import type { Domain, AutonomousNumber, Entity, Nameserver, IpNetwork } from "@/types";
|
||||
import AbstractCard from "@/components/common/AbstractCard";
|
||||
|
||||
@@ -13,7 +15,9 @@ export type ObjectProps = {
|
||||
};
|
||||
|
||||
const Generic: FunctionComponent<ObjectProps> = ({ data, url }: ObjectProps) => {
|
||||
switch (data.objectClassName) {
|
||||
const objectClassName = data.objectClassName;
|
||||
|
||||
switch (objectClassName) {
|
||||
case "domain":
|
||||
return <DomainCard url={url} data={data} />;
|
||||
case "ip network":
|
||||
@@ -21,11 +25,13 @@ const Generic: FunctionComponent<ObjectProps> = ({ data, url }: ObjectProps) =>
|
||||
case "autnum":
|
||||
return <AutnumCard url={url} data={data} />;
|
||||
case "entity":
|
||||
return <EntityCard url={url} data={data} />;
|
||||
case "nameserver":
|
||||
return <NameserverCard url={url} data={data} />;
|
||||
default:
|
||||
return (
|
||||
<AbstractCard url={url}>
|
||||
Not implemented. (<pre>{data.objectClassName ?? "null"}</pre>)
|
||||
Not implemented. (<pre>{objectClassName ?? "null"}</pre>)
|
||||
</AbstractCard>
|
||||
);
|
||||
}
|
||||
|
||||
34
src/components/lookup/NameserverCard.tsx
Normal file
34
src/components/lookup/NameserverCard.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { FunctionComponent } from "react";
|
||||
import React from "react";
|
||||
import type { Nameserver } from "@/types";
|
||||
import Property from "@/components/common/Property";
|
||||
import AbstractCard from "@/components/common/AbstractCard";
|
||||
|
||||
export type NameserverCardProps = {
|
||||
data: Nameserver;
|
||||
url?: string;
|
||||
};
|
||||
|
||||
const NameserverCard: FunctionComponent<NameserverCardProps> = ({
|
||||
data,
|
||||
url,
|
||||
}: NameserverCardProps) => {
|
||||
return (
|
||||
<AbstractCard
|
||||
data={data}
|
||||
url={url}
|
||||
header={
|
||||
<>
|
||||
<span className="font-mono tracking-tighter">NAMESERVER</span>
|
||||
<span className="font-mono tracking-wide">{data.ldhName}</span>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<dl>
|
||||
<Property title="LDH Name">{data.ldhName}</Property>
|
||||
</dl>
|
||||
</AbstractCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default NameserverCard;
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { SyntheticEvent } from "react";
|
||||
import type { Entries } from "type-fest";
|
||||
|
||||
declare global {
|
||||
interface ObjectConstructor {
|
||||
entries<T extends object>(o: T): Entries<T>;
|
||||
entries<T extends object>(o: T): [keyof T, T[keyof T]][];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,13 @@ const useLookup = (warningHandler?: WarningHandler) => {
|
||||
* A reference to the registry data, which is used to cache the registry data in memory.
|
||||
* This uses TargetType as the key, meaning v4/v6 IP/CIDR lookups are differentiated.
|
||||
*/
|
||||
const registryDataRef = useRef<Record<RootRegistryType, Register | null>>(
|
||||
{} as Record<RootRegistryType, Register>
|
||||
);
|
||||
const registryDataRef = useRef<Record<RootRegistryType, Register | null>>({
|
||||
autnum: null,
|
||||
domain: null,
|
||||
ip4: null,
|
||||
ip6: null,
|
||||
entity: null,
|
||||
});
|
||||
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [target, setTarget] = useState<string>("");
|
||||
@@ -175,12 +179,6 @@ const useLookup = (warningHandler?: WarningHandler) => {
|
||||
|
||||
const registryUri = RootRegistryEnum.safeParse(uriType.value);
|
||||
if (!registryUri.success) return;
|
||||
|
||||
console.log({
|
||||
uriType: uriType.value,
|
||||
registryData: registryDataRef.current,
|
||||
registryUri: registryUri.data,
|
||||
});
|
||||
if (registryDataRef.current[registryUri.data] != null) return;
|
||||
|
||||
try {
|
||||
@@ -211,8 +209,6 @@ const useLookup = (warningHandler?: WarningHandler) => {
|
||||
return `${path}: ${issue.message}`;
|
||||
});
|
||||
|
||||
console.log(flatErrors);
|
||||
|
||||
// combine them all, wrap them in a new error, and return it
|
||||
return Result.err(
|
||||
new Error(
|
||||
|
||||
740
src/rdap.ts
740
src/rdap.ts
@@ -1,14 +1,6 @@
|
||||
import type { Register, RootRegistryType, TargetType } from "@/types";
|
||||
import { Result } from "true-myth";
|
||||
|
||||
// const cardTitles = {
|
||||
// domain: "Domain Name",
|
||||
// "ip network": "IP Network",
|
||||
// nameserver: "Nameserver",
|
||||
// entity: "Entity",
|
||||
// autnum: "AS Number",
|
||||
// };
|
||||
|
||||
export function domainMatchPredicate(domain: string): (tld: string) => boolean {
|
||||
return (tld) => domainMatch(tld, domain);
|
||||
}
|
||||
@@ -17,30 +9,6 @@ export function domainMatch(tld: string, domain: string): boolean {
|
||||
return domain.toUpperCase().endsWith(`.${tld.toUpperCase()}`);
|
||||
}
|
||||
|
||||
/*
|
||||
export function asnMatch(range, asn) {
|
||||
let [min, max] = range.split('-', 2);
|
||||
min = parseInt(min);
|
||||
max = parseInt(max);
|
||||
|
||||
return (asn >= min && asn <= max);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function entityMatch(tag: string, handle: string) {
|
||||
return handle.toUpperCase().endsWith('-' + tag.toUpperCase());
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function ipMatch(prefix: string, ip: string) {
|
||||
const parsedIp = ipaddr.parse(ip);
|
||||
const cidr = ipaddr.parseCIDR(prefix);
|
||||
return (parsedIp.kind() == cidr[0].kind() && parsedIp.match(cidr));
|
||||
}
|
||||
*/
|
||||
|
||||
// return the first HTTPS url, or the first URL
|
||||
export function getBestURL(urls: [string, ...string[]]): string {
|
||||
urls.forEach((url) => {
|
||||
@@ -49,714 +17,6 @@ export function getBestURL(urls: [string, ...string[]]): string {
|
||||
return urls[0];
|
||||
}
|
||||
|
||||
// given a URL, injects that URL into the query input,
|
||||
// and initiates an RDAP query
|
||||
/*
|
||||
export function runQuery(url) {
|
||||
const type = document.getElementById('type');
|
||||
|
||||
for (let i = 0; i < type.options.length; i++) if ('url' == type.options[i].value) type.selectedIndex = i;
|
||||
document.getElementById('object').value = url;
|
||||
doQuery();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function showSpinner(msg) {
|
||||
msg = msg ? msg : 'Loading...';
|
||||
|
||||
const div = document.getElementById('output-div');
|
||||
div.innerHTML = '';
|
||||
|
||||
const spinner = document.createElement('div');
|
||||
spinner.classList.add('spinner-border');
|
||||
spinner.role = 'status';
|
||||
const span = spinner.appendChild(document.createElement('span'));
|
||||
span.classList.add('sr-only');
|
||||
span.appendChild(document.createTextNode(msg));
|
||||
|
||||
div.appendChild(spinner);
|
||||
|
||||
const msgDiv = document.createElement('div');
|
||||
msgDiv.id = 'spinner-msg';
|
||||
msgDiv.appendChild(document.createTextNode(msg));
|
||||
div.appendChild(msgDiv);
|
||||
}
|
||||
*/
|
||||
|
||||
// export function handleError(error) {
|
||||
// var div = document.getElementById('output-div');
|
||||
// div.innerHTML = '';
|
||||
// div.appendChild(createErrorNode(error));
|
||||
// }
|
||||
|
||||
/*
|
||||
export function createErrorNode(error) {
|
||||
el = document.createElement('p');
|
||||
el.classList.add('error', 'alert', 'alert-warning');
|
||||
el.appendChild(document.createTextNode(error));
|
||||
|
||||
return el;
|
||||
}
|
||||
*/
|
||||
|
||||
// process an RDAP object. Argument is a JSON object, return
|
||||
// value is an element that can be inserted into the page
|
||||
/*
|
||||
export function processObject(object, toplevel, followReferral = true) {
|
||||
if (!object) {
|
||||
console.log(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
const dl = document.createElement('dl');
|
||||
|
||||
switch (object.objectClassName) {
|
||||
case 'domain':
|
||||
processDomain(object, dl, toplevel);
|
||||
break;
|
||||
|
||||
case 'nameserver':
|
||||
processNameserver(object, dl, toplevel);
|
||||
break;
|
||||
|
||||
case 'entity':
|
||||
processEntity(object, dl, toplevel);
|
||||
break;
|
||||
|
||||
case 'autnum':
|
||||
processAutnum(object, dl, toplevel);
|
||||
break;
|
||||
|
||||
case 'ip network':
|
||||
processIp(object, dl, toplevel);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (object.errorCode) {
|
||||
return createErrorNode(object.errorCode + ' error: ' + object.title);
|
||||
|
||||
} else {
|
||||
processUnknown(object, dl, toplevel);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const card = document.createElement('div');
|
||||
card.classList.add('card');
|
||||
|
||||
let titleText = '';
|
||||
if (object.unicodeName) {
|
||||
titleText = object.unicodeName.toUpperCase();
|
||||
|
||||
} else if (object.ldhName) {
|
||||
titleText = object.ldhName.toUpperCase();
|
||||
|
||||
} else if (object.handle) {
|
||||
titleText = object.handle.toUpperCase();
|
||||
|
||||
}
|
||||
|
||||
if (object.handle && object.handle != titleText) titleText += ' (' + object.handle + ')';
|
||||
|
||||
if (titleText.length > 0) {
|
||||
titleText = cardTitles[object.objectClassName] + ' ' + titleText;
|
||||
|
||||
} else if (!toplevel) {
|
||||
titleText = cardTitles[object.objectClassName];
|
||||
|
||||
} else {
|
||||
titleText = 'Response';
|
||||
|
||||
}
|
||||
|
||||
const title = document.createElement('div');
|
||||
title.classList.add('card-header', 'font-weight-bold');
|
||||
title.appendChild(document.createTextNode(titleText));
|
||||
card.appendChild(title);
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.classList.add('card-body');
|
||||
|
||||
body.appendChild(dl);
|
||||
|
||||
card.appendChild(body);
|
||||
return card;
|
||||
}
|
||||
*/
|
||||
|
||||
// simplify the process of adding a name => value to a definition list
|
||||
/*
|
||||
export function addProperty(dl, name, value) {
|
||||
|
||||
const dt = document.createElement('dt');
|
||||
dt.classList.add('rdap-property-name');
|
||||
dt.appendChild(document.createTextNode(name));
|
||||
dl.appendChild(dt);
|
||||
|
||||
const dd = document.createElement('dd');
|
||||
dd.classList.add('rdap-property-value');
|
||||
if (value instanceof Node) {
|
||||
dd.appendChild(value);
|
||||
|
||||
} else {
|
||||
dd.appendChild(document.createTextNode(String(value)));
|
||||
|
||||
}
|
||||
dl.appendChild(dd);
|
||||
}
|
||||
*/
|
||||
|
||||
// called by the individual object processors, since all RDAP objects have a similar set of
|
||||
// properties. the first argument is the RDAP object and the second is the <dl> element
|
||||
// being used to display that object.
|
||||
/*
|
||||
export function processCommonObjectProperties(object, dl) {
|
||||
// if (object.objectClassName) addProperty(dl, 'Object Type:', object.objectClassName);
|
||||
// if (object.handle) addProperty(dl, 'Handle:', object.handle);
|
||||
if (object.status) processStatus(object.status, dl);
|
||||
if (object.events) processEvents(object.events, dl);
|
||||
if (object.entities) processEntities(object.entities, dl);
|
||||
if (object.remarks) processRemarks(object.remarks, dl);
|
||||
if (object.notices) processNotices(object.notices, dl);
|
||||
if (object.links) processLinks(object.links, dl);
|
||||
if (object.lang) addProperty(dl, 'Language:', object.lang);
|
||||
if (object.port43) addProperty(dl, 'Whois Server:', object.port43);
|
||||
if (object.rdapConformance) processRdapConformance(object.rdapConformance, dl);
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.id = 'element-' + ++elementCounter;
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.classList.add('btn', 'btn-secondary');
|
||||
button.appendChild(document.createTextNode('Show'));
|
||||
button.onclick = new Function('showRawData("' + div.id + '");return false');
|
||||
div.appendChild(button);
|
||||
|
||||
const pre = document.createElement('pre');
|
||||
pre.style = 'display:none;visibility:hidden';
|
||||
pre.appendChild(document.createTextNode(JSON.stringify(object, null, 2)));
|
||||
div.appendChild(pre);
|
||||
|
||||
addProperty(dl, 'Raw Data:', div);
|
||||
}
|
||||
*/
|
||||
|
||||
// call back for "Show Raw Data" button
|
||||
/*
|
||||
export function showRawData(id) {
|
||||
const div = document.getElementById(id);
|
||||
div.childNodes[0].style = 'display:none;visibility:hidden';
|
||||
div.childNodes[1].style = 'display:block;visibility:visible';
|
||||
}
|
||||
*/
|
||||
|
||||
// convert an array into a bulleted list
|
||||
/*
|
||||
export function createList(list) {
|
||||
const ul = document.createElement('ul');
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const li = document.createElement('li');
|
||||
if (list[i] instanceof Node) {
|
||||
li.appendChild(list[i]);
|
||||
|
||||
} else {
|
||||
li.appendChild(document.createTextNode(list[i]));
|
||||
|
||||
}
|
||||
ul.appendChild(li);
|
||||
}
|
||||
|
||||
return ul;
|
||||
}
|
||||
*/
|
||||
|
||||
// add the RDAP conformance of the response
|
||||
/*
|
||||
export function processRdapConformance(rdapConformance, dl) {
|
||||
addProperty(dl, 'Conformance:', createList(rdapConformance));
|
||||
}
|
||||
*/
|
||||
|
||||
// add the object's status codes
|
||||
/*
|
||||
export function processStatus(status, dl) {
|
||||
const s = [];
|
||||
for (let i = 0; i < status.length; i++) {
|
||||
const span = document.createElement('span');
|
||||
span.classList.add('rdap-status-code');
|
||||
span.appendChild(document.createTextNode(status[i]));
|
||||
span.setAttribute("title", rdapStatusInfo[status[i]]);
|
||||
s.push(span);
|
||||
}
|
||||
addProperty(dl, 'Status:', createList(s));
|
||||
}
|
||||
*/
|
||||
|
||||
// add the object's events
|
||||
/*
|
||||
export function processEvents(events, dl) {
|
||||
const sdl = document.createElement('dl');
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const span1 = document.createElement('span');
|
||||
span1.appendChild(document.createTextNode(new Date(events[i].eventDate).toLocaleString()));
|
||||
span1.classList.add('rdap-event-time');
|
||||
span1.setAttribute('title', events[i].eventDate);
|
||||
|
||||
const span2 = document.createElement('span');
|
||||
span2.appendChild(span1);
|
||||
|
||||
if (events[i].eventActor) {
|
||||
span2.appendChild(document.createTextNode(' (by ' + events[i].eventActor + ')'));
|
||||
}
|
||||
addProperty(sdl, events[i].eventAction + ':', span2);
|
||||
}
|
||||
|
||||
addProperty(dl, 'Event:', sdl);
|
||||
}
|
||||
*/
|
||||
|
||||
// add the object's links
|
||||
/*
|
||||
export function processLinks(links, dl) {
|
||||
const ul = document.createElement('ul');
|
||||
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
li = document.createElement('li');
|
||||
|
||||
const title = (links[i].title ? links[i].title : links[i].href);
|
||||
|
||||
var link;
|
||||
if (links[i].type && 0 == links[i].type.indexOf('application/rdap+json')) {
|
||||
link = createRDAPLink(links[i].href, title);
|
||||
|
||||
} else {
|
||||
link = document.createElement('a');
|
||||
link.rel = 'noopener';
|
||||
link.title = link.href = links[i].href;
|
||||
link.target = '_new';
|
||||
link.appendChild(document.createTextNode(title));
|
||||
|
||||
}
|
||||
|
||||
li.appendChild(link);
|
||||
|
||||
if (links[i].rel) li.appendChild(document.createTextNode(' (' + links[i].rel + ')'));
|
||||
|
||||
ul.appendChild(li);
|
||||
}
|
||||
|
||||
addProperty(dl, 'Links:', ul);
|
||||
}
|
||||
*/
|
||||
|
||||
// add the object's entities
|
||||
/*
|
||||
export function processEntities(entities, dl) {
|
||||
const div = document.createElement('div');
|
||||
|
||||
for (let i = 0; i < entities.length; i++) div.appendChild(processObject(entities[i]));
|
||||
|
||||
addProperty(dl, 'Entities:', div);
|
||||
}
|
||||
*/
|
||||
|
||||
// add the object's remarks
|
||||
/*
|
||||
export function processRemarks(remarks, dl) {
|
||||
addProperty(dl, 'Remarks:', processRemarksOrNotices(remarks));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
// add the responses's notices
|
||||
/*
|
||||
export function processNotices(notices, dl) {
|
||||
addProperty(dl, 'Notices:', processRemarksOrNotices(notices));
|
||||
}
|
||||
*/
|
||||
|
||||
// command handler for remarks and notices
|
||||
/*
|
||||
export function processRemarksOrNotices(things) {
|
||||
const div = document.createElement('div');
|
||||
|
||||
for (let i = 0; i < things.length; i++) {
|
||||
const section = document.createElement('section');
|
||||
section.classList.add('card');
|
||||
div.appendChild(section);
|
||||
|
||||
const title = document.createElement('header');
|
||||
title.classList.add('card-header', 'font-weight-bold');
|
||||
title.appendChild(document.createTextNode(things[i].title));
|
||||
section.appendChild(title);
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.classList.add('card-body');
|
||||
section.appendChild(body);
|
||||
|
||||
if (things[i].description) for (let j = 0; j < things[i].description.length; j++) {
|
||||
const p = document.createElement('p');
|
||||
p.innerHTML = convertUrlsToLinks(things[i].description[j]);
|
||||
body.appendChild(p);
|
||||
}
|
||||
|
||||
if (things[i].links) {
|
||||
const ldl = document.createElement('dl');
|
||||
processLinks(things[i].links, ldl);
|
||||
body.appendChild(ldl);
|
||||
}
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
*/
|
||||
|
||||
// naively match URLs in plain text and convert to links
|
||||
/*
|
||||
export function convertUrlsToLinks(str) {
|
||||
return str.replace(
|
||||
/(https?:\/\/[^\s]+[^\.])/g,
|
||||
'<a href="$1" target="_new" rel="noopener">$1</a>'
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
// process a domain
|
||||
/*
|
||||
export function processDomain(object, dl, toplevel = false) {
|
||||
|
||||
if (toplevel) document.title = 'Domain ' + (object.unicodeName ? object.unicodeName : object.ldhName).toUpperCase() + ' - RDAP Lookup';
|
||||
|
||||
if (object.unicodeName) {
|
||||
addProperty(dl, 'Name:', object.unicodeName);
|
||||
addProperty(dl, 'ASCII Name:', object.ldhName);
|
||||
|
||||
} else {
|
||||
addProperty(dl, 'Name:', object.ldhName);
|
||||
|
||||
}
|
||||
|
||||
if (object.handle) addProperty(dl, 'Handle:', object.handle);
|
||||
|
||||
// process events, status and entities here, then set them to null so processCommonObjectProperties()
|
||||
// doesn't process them again. this makes the output look more like a traditional whois record:
|
||||
if (object.events) processEvents(object.events, dl);
|
||||
if (object.status) processStatus(object.status, dl);
|
||||
if (object.entities) processEntities(object.entities, dl);
|
||||
|
||||
object.events = object.status = object.entities = null;
|
||||
|
||||
if (object.nameservers) {
|
||||
const div = document.createElement('div');
|
||||
|
||||
for (let i = 0; i < object.nameservers.length; i++) div.appendChild(processObject(object.nameservers[i]));
|
||||
|
||||
addProperty(dl, 'Nameservers:', div);
|
||||
}
|
||||
|
||||
addProperty(dl, 'DNSSEC:', object.secureDNS && object.secureDNS.delegationSigned ? 'Secure' : 'Insecure');
|
||||
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
// process a nameserver
|
||||
/*
|
||||
export function processNameserver(object, dl, toplevel = false) {
|
||||
|
||||
if (toplevel) document.title = 'Nameserver ' + object.ldhName + ' - RDAP Lookup';
|
||||
|
||||
addProperty(dl, 'Host Name:', object.ldhName);
|
||||
if (object.unicodeName) addProperty(dl, 'Internationalized Domain Name:', object.unicodeName);
|
||||
if (object.handle) addProperty(dl, 'Handle:', object.handle);
|
||||
|
||||
if (object.ipAddresses) {
|
||||
if (object.ipAddresses.v4) {
|
||||
for (var i = 0; i < object.ipAddresses.v4.length; i++) {
|
||||
addProperty(dl, 'IP Address:', createRDAPLink('https://rdap.org/ip/' + object.ipAddresses.v4[i], object.ipAddresses.v4[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (object.ipAddresses.v6) {
|
||||
for (var i = 0; i < object.ipAddresses.v6.length; i++) {
|
||||
addProperty(dl, 'IP Address:', createRDAPLink('https://rdap.org/ip/' + object.ipAddresses.v6[i], object.ipAddresses.v6[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
// process an entity
|
||||
/*
|
||||
export function processEntity(object, dl, toplevel = false) {
|
||||
|
||||
if (toplevel) document.title = 'Entity ' + object.handle + ' - RDAP Lookup';
|
||||
|
||||
if (object.handle) addProperty(dl, 'Handle:', object.handle);
|
||||
|
||||
if (object.publicIds) {
|
||||
for (let i = 0; i < object.publicIds.length; i++) addProperty(dl, object.publicIds[i].type + ':', object.publicIds[i].identifier);
|
||||
}
|
||||
|
||||
if (object.roles) addProperty(dl, 'Roles:', createList(object.roles));
|
||||
|
||||
if (object.jscard) {
|
||||
addProperty(dl, 'Contact Information:', processJSCard(object.jscard));
|
||||
|
||||
} else if (object.jscard_0) {
|
||||
addProperty(dl, 'Contact Information:', processJSCard(object.jscard_0));
|
||||
|
||||
} else if (object.vcardArray && object.vcardArray[1]) {
|
||||
addProperty(dl, 'Contact Information:', processVCardArray(object.vcardArray[1]));
|
||||
}
|
||||
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
// process an entity's vCard
|
||||
/*
|
||||
export function processVCardArray(vcard) {
|
||||
const vdl = document.createElement('dl');
|
||||
|
||||
for (let i = 0; i < vcard.length; i++) {
|
||||
const node = vcard[i];
|
||||
|
||||
let type = node[0];
|
||||
let value = node[3];
|
||||
|
||||
if ('version' == type) {
|
||||
continue;
|
||||
|
||||
} else if ('fn' == type) {
|
||||
type = 'Name';
|
||||
|
||||
} else if ('n' == type) {
|
||||
continue;
|
||||
|
||||
} else if ('org' == type) {
|
||||
type = 'Organization';
|
||||
|
||||
} else if ('tel' == type) {
|
||||
type = 'Phone';
|
||||
|
||||
if (node[1].type) for (var j = 0; j < node[1].type; j++) if ('fax' == node[1].type[j]) {
|
||||
type = 'Fax';
|
||||
break;
|
||||
}
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = (0 == value.indexOf('tel:') ? '' : 'tel:') + value;
|
||||
link.appendChild(document.createTextNode(value));
|
||||
|
||||
value = link;
|
||||
|
||||
} else if ('adr' == type) {
|
||||
type = 'Address';
|
||||
|
||||
if (node[1].label) {
|
||||
var div = document.createElement('div');
|
||||
strings = node[1].label.split("\n");
|
||||
for (var j = 0; j < strings.length; j++) {
|
||||
div.appendChild(document.createTextNode(strings[j]));
|
||||
if (j < strings.length - 1) div.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
value = div;
|
||||
|
||||
} else if (value) {
|
||||
var div = document.createElement('div');
|
||||
|
||||
for (var j = 0; j < value.length; j++) {
|
||||
if (value[j] && value[j].length > 0) {
|
||||
div.appendChild(document.createTextNode(value[j]));
|
||||
div.appendChild(document.createElement('br'));
|
||||
}
|
||||
}
|
||||
|
||||
value = div;
|
||||
}
|
||||
|
||||
} else if ('email' == type) {
|
||||
type = 'Email';
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = 'mailto:' + value;
|
||||
link.appendChild(document.createTextNode(value));
|
||||
|
||||
value = link;
|
||||
|
||||
} else if ('contact-uri' == type) {
|
||||
type = 'Contact URL';
|
||||
|
||||
var link = document.createElement('a');
|
||||
link.href = value;
|
||||
link.appendChild(document.createTextNode(value));
|
||||
|
||||
value = link;
|
||||
}
|
||||
|
||||
if (value) addProperty(vdl, type + ':', value);
|
||||
}
|
||||
|
||||
addProperty(vdl, 'Contact format:', 'jCard');
|
||||
|
||||
return vdl;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function processJSCard(jscard) {
|
||||
const vdl = document.createElement('dl');
|
||||
|
||||
if (jscard.fullName) addProperty(vdl, 'Name:', jscard.fullName);
|
||||
|
||||
if (jscard.organizations) {
|
||||
for (const k in jscard.organizations) {
|
||||
addProperty(vdl, 'Organization:', jscard.organizations[k].name);
|
||||
}
|
||||
}
|
||||
|
||||
if (jscard.addresses) {
|
||||
for (const k in jscard.addresses) {
|
||||
addProperty(vdl, 'Address:', processJSCardAddress(jscard.addresses[k]));
|
||||
}
|
||||
}
|
||||
|
||||
if (jscard.emails) {
|
||||
for (const k in jscard.emails) {
|
||||
var link = document.createElement('a');
|
||||
link.href = 'mailto:' + jscard.emails[k].email;
|
||||
link.appendChild(document.createTextNode(jscard.emails[k].email));
|
||||
|
||||
addProperty(vdl, 'Email Address:', link);
|
||||
}
|
||||
}
|
||||
|
||||
if (jscard.phones) {
|
||||
for (const k in jscard.phones) {
|
||||
var link = document.createElement('a');
|
||||
link.href = jscard.phones[k].phone;
|
||||
link.appendChild(document.createTextNode(jscard.phones[k].phone));
|
||||
|
||||
addProperty(vdl, (jscard.phones[k].features.fax ? 'Fax:' : 'Phone:'), link);
|
||||
}
|
||||
}
|
||||
|
||||
addProperty(vdl, 'Contact format:', 'JSContact');
|
||||
|
||||
return vdl;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function processJSCardAddress(address) {
|
||||
const dl = document.createElement('dl');
|
||||
for (k in address) {
|
||||
v = address[k];
|
||||
if ('street' == k) {
|
||||
const addr = document.createElement('span');
|
||||
for (let i = 0; i < v.length; i++) {
|
||||
if (i > 1) addr.appendChild(document.createElement('br'));
|
||||
addr.appendChild(document.createTextNode(v[i]));
|
||||
}
|
||||
addProperty(dl, 'Street:', addr);
|
||||
|
||||
} else if ('locality' == k) {
|
||||
addProperty(dl, 'City:', v);
|
||||
|
||||
} else if ('region' == k) {
|
||||
addProperty(dl, 'State/Province:', v);
|
||||
|
||||
} else if ('postcode' == k) {
|
||||
addProperty(dl, 'Postal Code:', v);
|
||||
|
||||
} else if ('countryCode' == k) {
|
||||
addProperty(dl, 'Country:', v);
|
||||
|
||||
}
|
||||
}
|
||||
return dl;
|
||||
}
|
||||
*/
|
||||
|
||||
// process an AS number
|
||||
/*
|
||||
export function processAutnum(object, dl, toplevel = false) {
|
||||
|
||||
if (toplevel) document.title = 'AS Number ' + object.handle + ' - RDAP Lookup';
|
||||
|
||||
if (object.name) addProperty(dl, 'Network Name:', object.name);
|
||||
if (object.type) addProperty(dl, 'Network Type:', object.type);
|
||||
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
// process an IP or IP block
|
||||
/*
|
||||
export function processIp(object, dl, toplevel = false) {
|
||||
|
||||
if (toplevel) document.title = 'IP Network ' + object.handle + ' - RDAP Lookup';
|
||||
|
||||
if (object.ipVersion) addProperty(dl, 'IP Version:', object.ipVersion);
|
||||
if (object.startAddress && object.endAddress) addProperty(dl, 'Address Range:', object.startAddress + ' - ' + object.endAddress);
|
||||
if (object.name) addProperty(dl, 'Network Name:', object.name);
|
||||
if (object.type) addProperty(dl, 'Network Type:', object.type);
|
||||
if (object.country) addProperty(dl, 'Country:', object.country);
|
||||
if (object.parentHandle) addProperty(dl, 'Parent Network:', object.parentHandle);
|
||||
if (object.cidr0_cidrs) addProperty(dl, 'CIDR Prefix(es):', processCIDRs(object.cidr0_cidrs));
|
||||
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function processCIDRs(cidrs) {
|
||||
const list = document.createElement('ul');
|
||||
for (i = 0; i < cidrs.length; i++) {
|
||||
const cidr = (cidrs[i].v6prefix ? cidrs[i].v6prefix : cidrs[i].v4prefix) + '/' + cidrs[i].length;
|
||||
list.appendChild(document.createElement('li')).appendChild(createRDAPLink('https://rdap.org/ip/' + cidr, cidr));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
export function processUnknown(object, dl, toplevel = false) {
|
||||
processCommonObjectProperties(object, dl);
|
||||
}
|
||||
*/
|
||||
|
||||
// given an object, return the "self" URL (if any)
|
||||
/*
|
||||
export function getSelfLink(object) {
|
||||
if (object.links) for (let i = 0; i < object.links.length; i++) if ('self' == object.links[i].rel) return object.links[i].href;
|
||||
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
// create an RDAP link: a link pointing to an RDAP URL
|
||||
// that when clicked, causes an RDAP query to be made
|
||||
/*
|
||||
export function createRDAPLink(url, title) {
|
||||
const link = document.createElement('a');
|
||||
|
||||
link.href = 'javascript:void(0)';
|
||||
link.title = url;
|
||||
link.onclick = new Function("runQuery('" + url + "')");
|
||||
link.appendChild(document.createTextNode(title));
|
||||
|
||||
return link;
|
||||
}
|
||||
*/
|
||||
|
||||
type ValidatorArgs = {
|
||||
value: string;
|
||||
getRegistry: (type: RootRegistryType) => Promise<Register>;
|
||||
|
||||
Reference in New Issue
Block a user