npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@push.rocks/smartnetwork

v4.7.3

Published

A toolkit for network diagnostics including speed tests, port availability checks, and more.

Readme

@push.rocks/smartnetwork 🌐

Comprehensive network diagnostics and intelligence for Node.js — speed tests, port scanning, ICMP ping, traceroute, DNS, IP & domain RDAP, ASN lookups, geolocation, and DNS record enrichment in a single, promise-based toolkit.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

🚀 Install

pnpm add @push.rocks/smartnetwork

🎯 Overview

@push.rocks/smartnetwork is your Swiss Army knife for network diagnostics in Node.js. Whether you're building monitoring dashboards, investigating IP/domain ownership, or debugging connectivity — this library has you covered with a clean, async API and zero-config setup.

Under the hood, system-level operations (ICMP ping, traceroute, raw-socket port checks, gateway detection) are powered by a bundled Rust binary for maximum performance and cross-platform reliability. Everything else — speed tests, DNS, public IP discovery, IP & domain intelligence, HTTP health checks — runs in pure TypeScript.

✨ Key Features

| Category | Capabilities | |----------|-------------| | 🏎️ Speed Testing | Download/upload benchmarks via Cloudflare's global infrastructure | | 🔌 Port Management | Local/remote port checks, find free ports (sequential or random), exclusion lists | | 📡 Connectivity | ICMP ping with stats, hop-by-hop traceroute, HTTP/HTTPS health checks | | 🌍 DNS | A, AAAA, MX resolution with system-first + DoH fallback strategy | | 🔍 IP Intelligence | ASN, organization, geolocation, RDAP registration — all from free public sources | | 🏢 Domain Intelligence | RDAP registrar/registrant, nameservers, events, DNSSEC, plus DNS enrichment (A/AAAA/MX/TXT/SOA) | | 🖥️ Network Discovery | Interfaces, default gateway, public IPv4/IPv6 | | ⚡ Caching | Built-in TTL cache for expensive lookups | | 🔧 Extensible | Plugin architecture for custom functionality | | 📝 TypeScript | Full type definitions, ESM-native |

💻 Usage

Basic Setup

import { SmartNetwork } from '@push.rocks/smartnetwork';

const network = new SmartNetwork();

// Start the Rust bridge (auto-started on first use, but explicit start is recommended)
await network.start();

// ... use the network instance ...

// Clean up when done — tears down both the Rust bridge and the smartdns backend
await network.stop();

Enable caching for repeated lookups:

const network = new SmartNetwork({ cacheTtl: 60000 }); // 60s TTL

🕵️ IP Intelligence

Get ASN, organization, geolocation, and RDAP registration data for any IPv4 address. Combines three free public data sources in parallel:

  • RDAP — direct queries to RIRs (RIPE, ARIN, APNIC, LACNIC, AFRINIC) for authoritative registration data
  • Team Cymru DNS — fast ASN resolution via DNS TXT records
  • MaxMind GeoLite2 — in-memory MMDB databases (auto-downloaded from CDN, periodically refreshed)
const intel = await network.getIpIntelligence('8.8.8.8');

console.log(intel);
// {
//   asn: 15169,
//   asnOrg: 'Google LLC',
//   registrantOrg: 'Google LLC',
//   registrantCountry: 'United States',
//   networkRange: '8.8.8.0/24',
//   networkCidrs: ['8.8.8.0/24'],
//   abuseContact: null,
//   country: null,
//   countryCode: 'US',
//   city: null,
//   latitude: 37.751,
//   longitude: -97.822,
//   accuracyRadius: null,
//   timezone: 'America/Chicago'
// }

Works great for your own IP too:

const publicIps = await network.getPublicIps();
if (publicIps.v4) {
  const myIntel = await network.getIpIntelligence(publicIps.v4);
  console.log(`You're on AS${myIntel.asn} (${myIntel.asnOrg}) in ${myIntel.city}, ${myIntel.countryCode}`);
}

The IIpIntelligenceResult interface:

interface IIpIntelligenceResult {
  // ASN (Team Cymru primary, MaxMind fallback)
  asn: number | null;
  asnOrg: string | null;

  // Registration (RDAP)
  registrantOrg: string | null;
  registrantCountry: string | null;
  networkRange: string | null;       // primary CIDR, or legacy start-end range when multiple CIDRs are needed
  networkCidrs: string[] | null;     // canonical CIDR coverage for the RDAP network when available
  abuseContact: string | null;       // abuse email from RDAP

  // Geolocation (MaxMind GeoLite2)
  country: string | null;
  countryCode: string | null;        // ISO 3166-1 alpha-2
  city: string | null;
  latitude: number | null;
  longitude: number | null;
  accuracyRadius: number | null;     // km
  timezone: string | null;           // IANA timezone
}

💡 The GeoLite2 databases are fetched into memory from jsDelivr CDN on first use (~32 MB total). They auto-refresh in the background every 7 days (configurable via IpIntelligence options). No disk I/O, no API keys, no rate limits.


🏢 Domain Intelligence

Get comprehensive domain registration and DNS data. Runs an RDAP layer and a DNS layer in parallel, then merges results:

  • RDAP — queries the correct registry RDAP server (discovered via the IANA DNS bootstrap) for registrar, registrant, events, status flags, DNSSEC, and abuse contacts
  • DNS — queries A, AAAA, NS, MX, TXT, and SOA records via @push.rocks/smartdns (system resolver first, DoH fallback)

For gTLDs (.com, .org, .net, etc.) you get the full picture from both layers. For ccTLDs without RDAP support (.de, .fr, .nl, etc.), the DNS layer fills in nameservers, resolved IPs, MX, TXT, and SOA — so you still get useful intelligence even when RDAP isn't available.

const info = await network.getDomainIntelligence('google.com');

console.log(info);
// {
//   domain: 'google.com',
//   handle: '2138514_DOMAIN_COM-VRSN',
//   status: ['client delete prohibited', 'server transfer prohibited', ...],
//   registrationDate: '1997-09-15T04:00:00Z',
//   expirationDate: '2028-09-14T04:00:00Z',
//   lastChangedDate: '2019-09-09T15:39:04Z',
//   registrarName: 'MarkMonitor Inc.',
//   registrarIanaId: 292,
//   registrantOrg: null,           // often redacted under GDPR
//   registrantCountry: null,
//   abuseEmail: '[email protected]',
//   abusePhone: '+1.2086851750',
//   nameservers: ['ns1.google.com', 'ns2.google.com', 'ns3.google.com', 'ns4.google.com'],
//   dnssec: false,
//   nameserversSource: 'rdap',
//   resolvedIpv4: ['142.251.20.102', '142.251.20.113', ...],
//   resolvedIpv6: ['2a00:1450:4001:c15::8b', ...],
//   mxRecords: [{ priority: 10, exchange: 'smtp.google.com' }],
//   txtRecords: ['v=spf1 include:_spf.google.com ~all', ...],
//   soaRecord: 'ns1.google.com dns-admin.google.com 895796075 900 900 1800 60'
// }

Works with ccTLDs that don't have RDAP (like .de):

const deInfo = await network.getDomainIntelligence('bund.de');
console.log(deInfo.registrarName);       // null (no .de RDAP)
console.log(deInfo.nameservers);         // ['bamberg.bund.de', 'argon.bund.de', ...]
console.log(deInfo.nameserversSource);   // 'dns' — nameservers came from DNS, not RDAP
console.log(deInfo.resolvedIpv4);        // ['80.245.156.34']
console.log(deInfo.mxRecords);           // [{priority: 10, exchange: 'mx1.bund.de'}, ...]

Handles IDN (internationalized domain names) automatically:

const idn = await network.getDomainIntelligence('münchen.de');
console.log(idn.domain); // 'xn--mnchen-3ya.de' — normalized to punycode

The IDomainIntelligenceResult interface:

interface IDomainIntelligenceResult {
  domain: string | null;              // normalized ASCII form
  handle: string | null;              // registry handle
  status: string[] | null;            // EPP status codes

  // Registration lifecycle (ISO 8601)
  registrationDate: string | null;
  expirationDate: string | null;
  lastChangedDate: string | null;

  // Registrar
  registrarName: string | null;
  registrarIanaId: number | null;

  // Registrant (often redacted under GDPR)
  registrantOrg: string | null;
  registrantCountry: string | null;

  // Abuse contact
  abuseEmail: string | null;
  abusePhone: string | null;

  // Technical
  nameservers: string[] | null;
  dnssec: boolean | null;             // secureDNS.delegationSigned from RDAP
  nameserversSource: 'rdap' | 'dns' | null;

  // DNS enrichment
  resolvedIpv4: string[] | null;      // A records
  resolvedIpv6: string[] | null;      // AAAA records
  mxRecords: { priority: number | null; exchange: string }[] | null;
  txtRecords: string[] | null;        // SPF, DKIM, site verification, etc.
  soaRecord: string | null;           // raw SOA value
}

💡 RDAP vs DNS nameservers: When RDAP is available (most gTLDs), nameservers comes from the registry's authoritative parent-zone delegation (nameserversSource: 'rdap'). When RDAP is unavailable (many ccTLDs), the DNS layer fills in nameservers via NS record resolution (nameserversSource: 'dns'). The nameserversSource field tells you which source won.


🏎️ Speed Testing

Measure network performance via Cloudflare's global infrastructure:

const result = await network.getSpeed();
console.log(`⬇️  Download: ${result.downloadSpeed} Mbps`);
console.log(`⬆️  Upload: ${result.uploadSpeed} Mbps`);

// Advanced: parallel streams + fixed duration
const advanced = await network.getSpeed({
  parallelStreams: 3,
  duration: 5,
});

🔌 Port Management

Check Local Port Availability

Checks both IPv4 and IPv6:

const isUnused = await network.isLocalPortUnused(8080);
console.log(isUnused ? '✅ Port 8080 is free' : '❌ Port 8080 is in use');

Find Free Port in Range

// First available
const port = await network.findFreePort(3000, 3100);

// Random pick (avoids clustering)
const randomPort = await network.findFreePort(3000, 3100, { randomize: true });

// With exclusions
const port2 = await network.findFreePort(3000, 3100, {
  randomize: true,
  exclude: [3000, 3001, 3005],
});

Check Remote Port

// Simple
const isOpen = await network.isRemotePortAvailable('example.com', 443);

// With retries and timeout
const isOpen2 = await network.isRemotePortAvailable('example.com', {
  port: 443,
  retries: 3,
  timeout: 5000,
});

📡 Ping & Traceroute

// Simple ping
const ping = await network.ping('google.com');
console.log(`Alive: ${ping.alive}, RTT: ${ping.time} ms`);

// Multi-ping with statistics
const stats = await network.ping('google.com', { count: 10, timeout: 2000 });
console.log(`📊 min=${stats.min} avg=${stats.avg.toFixed(1)} max=${stats.max} loss=${stats.packetLoss}%`);

// Traceroute
const hops = await network.traceroute('google.com', { maxHops: 20 });
hops.forEach(hop => {
  const rtt = hop.rtt === null ? '*' : `${hop.rtt} ms`;
  console.log(`  ${hop.ttl}\t${hop.ip}\t${rtt}`);
});

⚠️ ICMP ping requires CAP_NET_RAW or appropriate ping_group_range sysctl on Linux.


🌍 DNS Resolution

Uses @push.rocks/smartdns with a system-first strategy and automatic DoH (DNS-over-HTTPS) fallback:

const dns = await network.resolveDns('example.com');
console.log('A records:', dns.A);       // ['93.184.216.34']
console.log('AAAA records:', dns.AAAA); // ['2606:2800:220:1:248:1893:25c8:1946']
dns.MX.forEach(mx => {
  console.log(`📧 ${mx.exchange} (priority ${mx.priority})`);
});

🏥 HTTP/HTTPS Health Checks

const health = await network.checkEndpoint('https://api.example.com/health', {
  timeout: 5000,
  rejectUnauthorized: true,
});
console.log(`Status: ${health.status}, RTT: ${health.rtt.toFixed(0)} ms`);

🖥️ Network Interfaces & Public IPs

// All interfaces
const gateways = await network.getGateways();
Object.entries(gateways).forEach(([name, ifaces]) => {
  console.log(`🔌 ${name}:`);
  ifaces.forEach(i => console.log(`  ${i.family}: ${i.address}`));
});

// Default gateway
const gw = await network.getDefaultGateway();
if (gw) {
  console.log(`🌐 Gateway IPv4: ${gw.ipv4.address}`);
}

// Public IPs (multiple fallback services: ipify, ident.me, seeip, icanhazip)
const publicIps = await network.getPublicIps();
console.log(`🌍 IPv4: ${publicIps.v4 || 'N/A'}`);
console.log(`🌍 IPv6: ${publicIps.v6 || 'N/A'}`);

⚡ Caching

Caching applies to getGateways(), getPublicIps(), getIpIntelligence(), and getDomainIntelligence():

const network = new SmartNetwork({ cacheTtl: 60000 }); // 60s

const ips1 = await network.getPublicIps();  // fetches
const ips2 = await network.getPublicIps();  // cache hit ⚡

🚨 Error Handling

import { SmartNetwork, NetworkError, TimeoutError } from '@push.rocks/smartnetwork';

try {
  await network.isRemotePortAvailable('example.com', { protocol: 'udp' });
} catch (error) {
  if (error instanceof NetworkError) {
    console.error(`${error.message} (code: ${error.code})`); // ENOTSUP
  }
}

Error codes: EINVAL (invalid argument), ENOTSUP (not supported), ETIMEOUT (timeout).


🔧 Plugin Architecture

class MyPlugin {
  constructor(private network: SmartNetwork) {}
  async doStuff() { /* ... */ }
}

SmartNetwork.registerPlugin('myPlugin', MyPlugin);

const PluginClass = SmartNetwork.pluginsRegistry.get('myPlugin');
const plugin = new PluginClass(network);
await plugin.doStuff();

SmartNetwork.unregisterPlugin('myPlugin');

📝 Custom Logging

Replace the default console logger:

import { setLogger } from '@push.rocks/smartnetwork';

setLogger({
  debug: (msg) => myLogger.debug(msg),
  info: (msg) => myLogger.info(msg),
  warn: (msg) => myLogger.warn(msg),
  error: (msg) => myLogger.error(msg),
});

🛠️ Advanced Example: Network Monitor

const monitor = async () => {
  const network = new SmartNetwork({ cacheTtl: 30000 });

  // Check critical services
  const services = [
    { name: 'Web', host: 'example.com', port: 443 },
    { name: 'DB', host: 'db.internal', port: 5432 },
  ];

  for (const svc of services) {
    const up = await network.isRemotePortAvailable(svc.host, svc.port);
    console.log(`${svc.name}: ${up ? '✅ UP' : '❌ DOWN'}`);
  }

  // Internet connectivity + latency
  const ping = await network.ping('8.8.8.8');
  console.log(`Internet: ${ping.alive ? '✅' : '❌'} (${ping.time} ms)`);

  // Speed
  const speed = await network.getSpeed();
  console.log(`Speed: ⬇️ ${speed.downloadSpeed} / ⬆️ ${speed.uploadSpeed} Mbps`);

  // Who am I?
  const ips = await network.getPublicIps();
  if (ips.v4) {
    const intel = await network.getIpIntelligence(ips.v4);
    console.log(`AS${intel.asn} (${intel.asnOrg}) — ${intel.city || intel.countryCode}`);
  }

  // Domain recon
  const domain = await network.getDomainIntelligence('example.com');
  console.log(`Registrar: ${domain.registrarName}, expires: ${domain.expirationDate}`);
  console.log(`Nameservers (${domain.nameserversSource}):`, domain.nameservers);

  await network.stop();
};

📋 Full API Reference

| Method | Description | Requires Rust | |--------|-------------|:---:| | start() / stop() | Start/stop the Rust bridge and smartdns backend | — | | getSpeed(opts?) | Cloudflare speed test (download + upload) | No | | ping(host, opts?) | ICMP ping with optional multi-ping stats | Yes | | traceroute(host, opts?) | Hop-by-hop network path analysis | Yes | | isLocalPortUnused(port) | Check if local port is free (IPv4+IPv6) | Yes | | findFreePort(start, end, opts?) | Find available port in range | Yes | | isRemotePortAvailable(target, opts?) | TCP port check on remote host | Yes | | getGateways() | List all network interfaces | No | | getDefaultGateway() | Get default gateway info | Yes | | getPublicIps() | Discover public IPv4/IPv6 (4 fallback services) | No | | resolveDns(host) | Resolve A, AAAA, MX records | No | | checkEndpoint(url, opts?) | HTTP/HTTPS health check with RTT | No | | getIpIntelligence(ip) | ASN + org + geo + RDAP registration | No | | getDomainIntelligence(domain) | Registrar, nameservers, events, DNS records, DNSSEC | No |

License and Legal Information

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at [email protected].

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.