mirror of
https://github.com/Xevion/rdap.git
synced 2025-12-16 06:12:56 -06:00
build: migrate to pnpm and add vitest testing infrastructure
- Replace Yarn with pnpm as package manager - Add Vitest with React Testing Library and happy-dom - Configure test setup and add test scripts (test, test:ui, test:run) - Add IPCard component and update lookup components - Remove unused react-ogp dependency - Add type-check script
This commit is contained in:
@@ -40,3 +40,92 @@ export function truncated(input: string, maxLength: number, ellipsis = "...") {
|
||||
export function preventDefault(event: SyntheticEvent | Event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an IPv4 address string to a 32-bit integer
|
||||
*/
|
||||
function ipv4ToInt(ip: string): number {
|
||||
const parts = ip.split('.').map(Number);
|
||||
if (parts.length !== 4) return 0;
|
||||
const [a, b, c, d] = parts;
|
||||
if (a === undefined || b === undefined || c === undefined || d === undefined) return 0;
|
||||
return ((a << 24) | (b << 16) | (c << 8) | d) >>> 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IPv4 address falls within a CIDR range
|
||||
* @param ip The IP address to check (e.g., "192.168.1.1")
|
||||
* @param cidr The CIDR range to check against (e.g., "192.168.0.0/16")
|
||||
* @returns true if the IP is within the CIDR range
|
||||
*/
|
||||
export function ipv4InCIDR(ip: string, cidr: string): boolean {
|
||||
const [rangeIp, prefixLenStr] = cidr.split('/');
|
||||
const prefixLen = parseInt(prefixLenStr ?? '', 10);
|
||||
|
||||
if (!rangeIp || isNaN(prefixLen) || prefixLen < 0 || prefixLen > 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ipInt = ipv4ToInt(ip);
|
||||
const rangeInt = ipv4ToInt(rangeIp);
|
||||
const mask = (0xFFFFFFFF << (32 - prefixLen)) >>> 0;
|
||||
|
||||
return (ipInt & mask) === (rangeInt & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an IPv6 address to a BigInt representation
|
||||
*/
|
||||
function ipv6ToBigInt(ip: string): bigint {
|
||||
// Expand :: notation
|
||||
const expandedIp = expandIPv6(ip);
|
||||
const parts = expandedIp.split(':');
|
||||
|
||||
let result = BigInt(0);
|
||||
for (const part of parts) {
|
||||
result = (result << BigInt(16)) | BigInt(parseInt(part, 16));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand IPv6 address shorthand notation
|
||||
*/
|
||||
function expandIPv6(ip: string): string {
|
||||
if (ip.includes('::')) {
|
||||
const [left, right] = ip.split('::');
|
||||
const leftParts = left ? left.split(':') : [];
|
||||
const rightParts = right ? right.split(':') : [];
|
||||
const missingParts = 8 - leftParts.length - rightParts.length;
|
||||
const middleParts: string[] = Array(missingParts).fill('0') as string[];
|
||||
const allParts = [...leftParts, ...middleParts, ...rightParts];
|
||||
return allParts.map((p: string) => p.padStart(4, '0')).join(':');
|
||||
}
|
||||
return ip.split(':').map((p: string) => p.padStart(4, '0')).join(':');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IPv6 address falls within a CIDR range
|
||||
* @param ip The IPv6 address to check (e.g., "2001:db8::1")
|
||||
* @param cidr The CIDR range to check against (e.g., "2001:db8::/32")
|
||||
* @returns true if the IP is within the CIDR range
|
||||
*/
|
||||
export function ipv6InCIDR(ip: string, cidr: string): boolean {
|
||||
const [rangeIp, prefixLenStr] = cidr.split('/');
|
||||
const prefixLen = parseInt(prefixLenStr ?? '', 10);
|
||||
|
||||
if (!rangeIp || isNaN(prefixLen) || prefixLen < 0 || prefixLen > 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const ipInt = ipv6ToBigInt(ip);
|
||||
const rangeInt = ipv6ToBigInt(rangeIp);
|
||||
const maxMask = BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF');
|
||||
const mask = (maxMask << BigInt(128 - prefixLen)) & maxMask;
|
||||
|
||||
return (ipInt & mask) === (rangeInt & mask);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user