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

@rdapify/pro

v0.2.2

Published

Premium Rust-native features for RDAPify — Bulk Monitoring, Change Detection, Analytics & more

Readme

@rdapify/pro

Premium Rust-native features for RDAPify — Bulk Monitoring, Change Detection, Analytics & more

npm version License: Proprietary Node.js 20+

Commercial extension for rdapify — adds continuous monitoring, change detection, historical tracking, analytics, and integrations. Entirely Rust-native (via napi-rs) for zero-copy RDAP processing and concurrent change detection.

@rdapify/pro is a plugin — it attaches to an existing RDAPClient instance via the .use() interface and does not modify or replace any core behaviour. All open-source features (SSRF protection, caching, PII redaction, middleware) remain fully operational.


Requirements

| Component | Specification | |-----------|---------------| | Peer dependency | rdapify >= 0.2.0 | | Node.js | >= 20.0.0 (LTS recommended) | | License key | Required — rdapify.com/pricing | | Operating System | Linux, macOS, Windows, FreeBSD |


Installation

npm install @rdapify/pro rdapify

Pre-built Binaries

Platform-specific binaries are automatically selected during installation:

  • Linux (x64, arm64, arm, s390x, riscv64) — glibc & musl variants
  • macOS (x64, arm64, universal)
  • Windows (x64, ia32, arm64) — MSVC
  • FreeBSD (x64)
  • Android (arm64, arm)

Quick Start

1. Initialize the Plugin

import { RDAPClient } from 'rdapify';
import { ProPlugin } from '@rdapify/pro';

const client = new RDAPClient();

// Activate Pro features with your license key
const plugin = await ProPlugin({
  licenseKey: process.env.RDAPIFY_LICENSE_KEY!,
  onlineValidation: true  // Opt-in: verify key status with API (default: false)
});

// Install the plugin
await client.use(plugin);

2. Use Pro Features

// Bulk monitoring
const monitor = new BulkMonitor(['example.com', 'test.org'], { interval: '6h' });
monitor.onChange = (event) => console.log(event);

// Change detection
const changes = detector.diff(previousSnapshot, currentSnapshot);

// Historical tracking
history.record('example.com', 'domain', rdapResponse);
const entries = history.query({ target: 'example.com', limit: 10 });

// Analytics
const report = reporter.generate(snapshots, { format: 'detailed' });

// Webhooks
webhooks.register({ provider: 'slack', url: 'https://...' });

// Export
const csv = exporter.exportCsv(snapshots);

Features

Bulk Monitoring

Automatically monitor thousands of domains or IPs on a configurable schedule.

import { BulkMonitor } from '@rdapify/pro';

const targets = ['example.com', 'example.org', '192.0.2.1'];
const monitor = new BulkMonitor(targets, {
  interval: '6h',        // Check every 6 hours (or '30m', '1h', '24h', '7d')
  concurrency: 10        // Max 10 parallel RDAP queries per cycle
});

// Set up change callback
monitor.onChange = (event) => {
  console.log(`${event.domain} changed:`, event.changes);
};

// Add/remove targets dynamically
monitor.addTargets(['new.example.com']);
monitor.removeTargets(['old.example.com']);

Change Detection

Detects 5 types of RDAP changes automatically:

| Change Type | Description | |-------------|-------------| | nameserver_changed | Nameserver list updated | | status_changed | Domain/IP status flags modified | | registrar_changed | Sponsoring registrar changed | | expiry_changed | Expiration date moved | | dnssec_changed | DNSSEC delegation signer data updated |

import { ChangeDetector } from '@rdapify/pro';

const detector = new ChangeDetector(['example.com']);

const changes = detector.diff(
  JSON.stringify(oldRdapResponse),
  JSON.stringify(newRdapResponse)
);

changes.forEach(change => {
  console.log(`${change.changeType}: ${change.field}`);
  console.log(`  Before: ${change.previousValue}`);
  console.log(`  After: ${change.currentValue}`);
});

Historical Tracking

Store and query RDAP snapshots over time for trend analysis.

import { HistoryTracker } from '@rdapify/pro';

const history = new HistoryTracker();

// Record snapshots (auto-called by BulkMonitor)
history.record('example.com', 'domain', JSON.stringify(rdapResponse));

// Query by date range
const entries = history.query({
  target: 'example.com',
  from: '2026-01-01T00:00:00Z',
  to: '2026-03-23T23:59:59Z',
  limit: 100
});

// Get most recent snapshot
const latest = history.latest('example.com');

// Get total recorded entries
const count = history.count();

// Clear history
history.clear();

Advanced Analytics

Generate summary, detailed, or trend reports from collected RDAP data.

import { Reporter } from '@rdapify/pro';

const reporter = new Reporter();

const report = reporter.generate(
  snapshots.map(s => JSON.stringify(s)),
  {
    format: 'detailed',  // 'summary' | 'detailed' | 'trends'
    from: '2026-01-01T00:00:00Z',
    to: '2026-03-23T23:59:59Z'
  }
);

console.log(report);
// Output:
// {
//   generatedAt: '2026-03-23T12:00:00Z',
//   format: 'detailed',
//   totalQueries: 1543,
//   registrars: {
//     'GoDaddy': 420,
//     'Namecheap': 380,
//     'Cloudflare': 215
//   },
//   statusCounts: {
//     'clientTransferProhibited': 890,
//     'autoRenewPeriod': 653
//   },
//   queryTypes: {
//     'domain': 900,
//     'ip': 643
//   },
//   topDomains: [
//     { target: 'example.com', count: 12 },
//     { target: 'example.org', count: 8 }
//   ],
//   errorRate: 0.02
// }

Webhook Integrations

Send real-time change notifications to Slack, Discord, Teams, or custom HTTP endpoints.

import { WebhookManager } from '@rdapify/pro';

const webhooks = new WebhookManager();

// Slack integration
webhooks.register({
  provider: 'slack',
  url: 'https://hooks.slack.com/services/T.../B.../X...',
  events: ['expiry_changed', 'nameserver_changed'],
  headers: { 'X-Custom-Auth': 'token' }
});

// Discord integration
webhooks.register({
  provider: 'discord',
  url: 'https://discord.com/api/webhooks/...'
});

// Microsoft Teams integration
webhooks.register({
  provider: 'teams',
  url: 'https://outlook.webhook.office.com/webhookb2/...'
});

// Custom HTTP endpoint
webhooks.register({
  provider: 'custom',
  url: 'https://my-api.example.com/webhooks',
  headers: { 'X-API-Key': 'secret' }
});

// Send notifications (auto-fired by monitor or manual)
const changeEvent = {
  target: 'example.com',
  changeType: 'nameserver_changed',
  field: 'nameservers',
  previousValue: JSON.stringify(['ns1.example.com']),
  currentValue: JSON.stringify(['ns2.new-provider.com']),
  detectedAt: new Date().toISOString()
};

await webhooks.notify(JSON.stringify(changeEvent));

// List registered webhooks
const registered = webhooks.getWebhooks();

// Remove a webhook
webhooks.remove('https://hooks.slack.com/services/T.../B.../X...');

Data Export

Export RDAP data in JSON (pretty-printed) or CSV format for analysis and reporting.

import { Exporter } from '@rdapify/pro';

const exporter = new Exporter();

// JSON export (pretty-printed)
const jsonOutput = exporter.exportJson(
  snapshots.map(s => JSON.stringify(s))
);

// CSV export (RFC 4180 compliant)
const csvOutput = exporter.exportCsv(
  snapshots.map(s => JSON.stringify(s)),
  ['target', 'registrar', 'status', 'expirationDate']  // Optional: filter columns
);

// Save to file
const fs = require('fs');
fs.writeFileSync('report.json', jsonOutput);
fs.writeFileSync('report.csv', csvOutput);

Pricing & Plans

Unlock Pro features with a license key. Plans and pricing as of March 2026:

| Feature | Community | Pro | Team | Enterprise | |---------|-----------|-----|------|-----------| | RDAP Queries (domain, IP, ASN, etc.) | ✓ | ✓ | ✓ | ✓ | | In-Memory Cache | ✓ | ✓ | ✓ | ✓ | | SSRF Protection | ✓ | ✓ | ✓ | ✓ | | Bulk Monitoring | — | ✓ | ✓ | ✓ | | Change Detection | — | ✓ | ✓ | ✓ | | History Tracking | — | ✓ | ✓ | ✓ | | Analytics | — | ✓ | ✓ | ✓ | | Webhooks (up to 3) | — | ✓ | ✓ | ✓ | | Webhooks (unlimited) | — | — | ✓ | ✓ | | Export (JSON/CSV) | — | ✓ | ✓ | ✓ | | Dedicated Support | — | — | ✓ | ✓ | | SLA (99.9% uptime) | — | — | — | ✓ | | Monthly Cost | $0 | $19 | $49 | Custom |

Get your license: https://rdapify.com/pricing


License Key Validation

Key Format

RDAP-{PLAN}-{base64url-payload}-{signature}

Example:
RDAP-PRO-eyJvcmciOiJNeSBDb21wYW55IiwiZXhwIjoxNzEwODk1OTk5OTk5LCJtYXhEZXYiOjV9-HMAC256Signature...

Payload structure (base64url-decoded):

{
  "org": "My Company",
  "exp": 1710895999999,
  "maxDev": 5
}
  • org — Organization name
  • exp — Expiration timestamp (milliseconds)
  • maxDev — Maximum developers (trial: 1, pro: 5, team: 10, enterprise: unlimited)

Offline Validation

import { LicenseValidator } from '@rdapify/pro';

const info = LicenseValidator.validate(licenseKey);

console.log(info);
// {
//   valid: true,
//   plan: 'pro',
//   organization: 'My Company',
//   expiresAt: 1710895999999,
//   maxDevelopers: 5
// }

Online Validation

Checks the API for key status, revocations, and seat usage:

const onlineInfo = await LicenseValidator.validateOnline(licenseKey);

Trial Licenses

30-day trial licenses use the TRIAL plan:

RDAP-TRIAL-{payload}-{signature}

Issued with:
- maxDevelopers: 1
- Expires: 30 days from issuance

TypeScript API Reference

ProPlugin

// Factory function
const plugin = await ProPlugin(options: ProPluginOptions): Promise<ProPluginDescriptorFull>

interface ProPluginOptions {
  licenseKey: string;           // Required license key
  onlineValidation?: boolean;   // Verify with API (default: false)
}

interface ProPluginDescriptor {
  name: string;
  version: string;
  license: LicenseInfo;
  install(client: unknown): void;
}

BulkMonitor

class BulkMonitor {
  constructor(targets: string[], interval?: string, concurrency?: number)
  processResults(results: Record<string, string>): MonitorEvent[]
  getTargets(): string[]
  getIntervalMs(): number
  getConcurrency(): number
  addTargets(targets: string[]): void
  removeTargets(targets: string[]): void
  clearSnapshots(): void
}

interface MonitorEvent {
  domain: string;
  eventType: 'created' | 'updated' | 'expired' | 'transferred' | 'deleted'
  timestamp: string;
  changes: string[];
}

ChangeDetector

class ChangeDetector {
  constructor(targets: string[])
  diff(previous: string, current: string): ChangeEvent[]
  getTargets(): string[]
}

interface ChangeEvent {
  target: string;
  changeType: 'nameserver_changed' | 'status_changed' | 'registrar_changed'
            | 'expiry_changed' | 'dnssec_changed'
  field: string;
  previousValue: string;      // JSON-serialized
  currentValue: string;       // JSON-serialized
  detectedAt: string;         // ISO-8601
}

HistoryTracker

class HistoryTracker {
  constructor()
  record(target: string, queryType: string, data: string): void
  query(options: HistoryQuery): HistoryEntry[]
  latest(target: string): HistoryEntry | null
  count(): number
  clear(): void
}

interface HistoryEntry {
  target: string;
  queryType: string;
  snapshot: string;           // JSON-serialized RDAP
  capturedAt: string;         // ISO-8601
}

interface HistoryQuery {
  target: string;
  from?: string;              // ISO-8601
  to?: string;                // ISO-8601
  limit?: number;
}

Reporter

class Reporter {
  constructor()
  generate(data: string[], options?: ReportOptions): ReportOutput
}

interface ReportOptions {
  format?: 'summary' | 'detailed' | 'trends'
  from?: string;              // ISO-8601
  to?: string;                // ISO-8601
}

interface ReportOutput {
  generatedAt: string;
  format: string;
  totalQueries: number;
  registrars: Record<string, number>;
  statusCounts: Record<string, number>;
  queryTypes: Record<string, number>;
  topDomains: TopEntry[];
  errorRate: number;
}

interface TopEntry {
  target: string;
  count: number;
}

WebhookManager

class WebhookManager {
  constructor()
  register(config: WebhookConfig): void
  remove(url: string): void
  getWebhooks(): WebhookConfig[]
  notify(event: string): Promise<number>
}

interface WebhookConfig {
  provider: 'slack' | 'discord' | 'teams' | 'custom'
  url: string;
  events?: string[];          // Event type filter
  headers?: Record<string, string>;
}

Exporter

class Exporter {
  constructor()
  exportJson(data: string[]): string
  exportCsv(data: string[], fields?: string[]): string
}

LicenseValidator

class LicenseValidator {
  static validate(key: string): LicenseInfo
  static validateOnline(key: string): Promise<LicenseInfo>
}

interface LicenseInfo {
  valid: boolean;
  plan?: 'pro' | 'enterprise' | 'trial'
  organization?: string;
  expiresAt?: number;         // Milliseconds
  maxDevelopers?: number;
  reason?: string;            // Error details if invalid
}

Architecture

Rust-native implementation (via napi-rs) for performance and safety:

┌──────────────────────────────────────────────────┐
│  JavaScript / TypeScript Application             │
├──────────────────────────────────────────────────┤
│  index.js (platform detection, native binding)   │
├──────────────────────────────────────────────────┤
│  Rust Native Module (.node binary)               │
│  ├─ lib.rs            (napi root, ProPlugin)     │
│  ├─ license/mod.rs    (LicenseValidator)         │
│  ├─ monitoring/mod.rs (BulkMonitor, detector)    │
│  ├─ history/mod.rs    (HistoryTracker)           │
│  ├─ analytics/mod.rs  (Reporter)                 │
│  └─ integrations/     (WebhookManager, Exporter) │
├──────────────────────────────────────────────────┤
│  rdapify Library                                 │
└──────────────────────────────────────────────────┘

All computation is performed in Rust:

  • Zero-copy RDAP processing
  • Thread-safe history with Arc<Mutex<Vec<>>>
  • Concurrent webhooks via reqwest async client
  • Timing-safe license validation (HMAC constant-time comparison)

Environment Variables

| Variable | Purpose | Default | |----------|---------|---------| | RDAPIFY_PRO_LICENSE_KEY | License key injection (optional) | None | | RDAPIFY_PRO_ONLINE_VALIDATION | Enable API validation | true |


Troubleshooting

| Issue | Solution | |-------|----------| | "Failed to load native binding" | Reinstall: npm install --force @rdapify/pro | | "License key not found" | Set licenseKey in ProPlugin options or env var | | "License expired" | Renew at https://rdapify.com/pricing | | "Invalid license format" | Key must match RDAP-{PLAN}-{payload}-{signature} | | "Webhook failed silently" | Check logs; failures don't block other webhooks |


System Requirements

  • Node.js: 20.0.0 or later (LTS recommended)
  • Memory: 64 MB minimum (scales with history size)
  • Network: Optional for online license validation

Changelog & Migration

See CHANGELOG.md for version history and breaking changes. See MIGRATION.md for upgrade guides.


License

Proprietary — NOT open source. A valid license key is required for production use.

Copyright © 2024–2026 RDAPify. All rights reserved.

See LICENSE for full terms.


Support & Links

| Resource | URL | |----------|-----| | Pricing | https://rdapify.com/pricing | | Documentation | https://rdapify.com/docs | | GitHub (Private) | https://github.com/rdapify/RDAPify-Pro | | Issues | https://github.com/rdapify/RDAPify-Pro/issues | | Email | [email protected] |