@rdapify/pro
v0.2.2
Published
Premium Rust-native features for RDAPify — Bulk Monitoring, Change Detection, Analytics & more
Maintainers
Readme
@rdapify/pro
Premium Rust-native features for RDAPify — Bulk Monitoring, Change Detection, Analytics & more
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 rdapifyPre-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 issuanceTypeScript 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
reqwestasync 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] |
