@rdapify/pro 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +35 -0
- package/README.md +176 -0
- package/index.d.ts +245 -0
- package/index.js +322 -0
- package/package.json +98 -0
- package/wrapper.js +90 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
RDAPify Pro — Commercial License Agreement
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 RDAPify Authors. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is licensed, not sold. By using this software, you agree
|
|
6
|
+
to the following terms:
|
|
7
|
+
|
|
8
|
+
1. GRANT OF LICENSE
|
|
9
|
+
A valid license key is required to use this software. Each license key
|
|
10
|
+
is granted to a single organization and covers the number of developers
|
|
11
|
+
specified in the purchased plan.
|
|
12
|
+
|
|
13
|
+
2. PERMITTED USE
|
|
14
|
+
- Use in commercial and internal applications
|
|
15
|
+
- Use by the number of developers covered by your license
|
|
16
|
+
- Deployment to unlimited production environments
|
|
17
|
+
|
|
18
|
+
3. RESTRICTIONS
|
|
19
|
+
- You may NOT redistribute, sublicense, or share the source code
|
|
20
|
+
- You may NOT reverse engineer, decompile, or disassemble the software
|
|
21
|
+
- You may NOT share, transfer, or publish your license key
|
|
22
|
+
- You may NOT remove or alter any proprietary notices
|
|
23
|
+
|
|
24
|
+
4. SUBSCRIPTION
|
|
25
|
+
This license is valid only during the active subscription period.
|
|
26
|
+
Upon expiration or cancellation, you must cease using the software.
|
|
27
|
+
|
|
28
|
+
5. WARRANTY DISCLAIMER
|
|
29
|
+
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
|
|
30
|
+
|
|
31
|
+
6. LIMITATION OF LIABILITY
|
|
32
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DAMAGES ARISING
|
|
33
|
+
FROM THE USE OF THIS SOFTWARE.
|
|
34
|
+
|
|
35
|
+
For licensing inquiries: licensing@rdapify.dev
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# @rdapify/pro
|
|
2
|
+
|
|
3
|
+
Commercial extension for [rdapify](https://github.com/rdapify/RDAPify) that adds continuous monitoring, change detection, historical tracking, analytics, and integrations on top of the open-source RDAP client.
|
|
4
|
+
|
|
5
|
+
`@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.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
| Dependency | Version |
|
|
10
|
+
|------------|---------|
|
|
11
|
+
| `rdapify` (peer) | `>= 0.2.0` |
|
|
12
|
+
| Node.js | `>= 18` |
|
|
13
|
+
| License key | Required — [rdapify.dev/pricing](https://rdapify.dev/pricing) |
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install rdapify @rdapify/pro
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { RDAPClient } from 'rdapify';
|
|
25
|
+
import { ProPlugin } from '@rdapify/pro';
|
|
26
|
+
|
|
27
|
+
const client = new RDAPClient();
|
|
28
|
+
client.use(ProPlugin({ licenseKey: process.env.RDAPIFY_LICENSE_KEY! }));
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Once activated, six new capabilities are available on the client instance: `monitor`, `detect`, `report`, `history`, `webhooks`, and `export`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Modules
|
|
36
|
+
|
|
37
|
+
### Bulk monitoring
|
|
38
|
+
|
|
39
|
+
Monitor thousands of domains or IP addresses on a recurring schedule. The monitor runs queries at a configurable interval, compares successive snapshots, and fires callbacks when changes are detected.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
client.monitor.start(['example.com', 'example.org'], {
|
|
43
|
+
interval: '6h', // check every 6 hours
|
|
44
|
+
concurrency: 10, // max parallel RDAP queries
|
|
45
|
+
onChange(event) {
|
|
46
|
+
// event.domain — the target that changed
|
|
47
|
+
// event.type — 'created' | 'updated' | 'expired' | 'transferred' | 'deleted'
|
|
48
|
+
// event.changes — list of changed field paths
|
|
49
|
+
// event.previous — previous RDAP snapshot
|
|
50
|
+
// event.current — current RDAP snapshot
|
|
51
|
+
console.log(`${event.domain}: ${event.type}`, event.changes);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Stop monitoring
|
|
56
|
+
client.monitor.stop();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Change detection
|
|
60
|
+
|
|
61
|
+
Compare two RDAP response snapshots and extract a structured diff. Useful for on-demand comparisons without continuous monitoring.
|
|
62
|
+
|
|
63
|
+
Detected change types:
|
|
64
|
+
|
|
65
|
+
| Type | Description |
|
|
66
|
+
|------|-------------|
|
|
67
|
+
| `nameserver_changed` | Nameserver list differs |
|
|
68
|
+
| `status_changed` | Domain/IP status flags changed |
|
|
69
|
+
| `registrar_changed` | Sponsoring registrar changed |
|
|
70
|
+
| `expiry_changed` | Expiration date moved |
|
|
71
|
+
| `contact_changed` | Registrant/admin/tech contact changed |
|
|
72
|
+
| `dnssec_changed` | DNSSEC delegation signer data changed |
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const previous = await client.domain('example.com');
|
|
76
|
+
// ... time passes ...
|
|
77
|
+
const current = await client.domain('example.com');
|
|
78
|
+
|
|
79
|
+
const changes = client.detect.diff(previous, current);
|
|
80
|
+
// → [{ changeType: 'expiry_changed', field: 'events.expiration',
|
|
81
|
+
// previousValue: '2025-03-01', currentValue: '2026-03-01' }]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Historical tracking
|
|
85
|
+
|
|
86
|
+
Record RDAP snapshots over time and query the history for a specific target.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// Record a snapshot (typically called from monitor.onChange)
|
|
90
|
+
client.history.record('example.com', 'domain', currentResponse);
|
|
91
|
+
|
|
92
|
+
// Query stored history
|
|
93
|
+
const entries = client.history.query({
|
|
94
|
+
target: 'example.com',
|
|
95
|
+
from: new Date('2026-01-01'),
|
|
96
|
+
to: new Date('2026-03-21'),
|
|
97
|
+
limit: 50,
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Analytics and reporting
|
|
102
|
+
|
|
103
|
+
Generate summary, detailed, or trend-based reports from collected query data.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const report = client.report.generate({
|
|
107
|
+
format: 'trends', // 'summary' | 'detailed' | 'trends'
|
|
108
|
+
from: new Date('2026-01-01'),
|
|
109
|
+
to: new Date('2026-03-21'),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
console.log(report.totalQueries, report.data);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Webhook integrations
|
|
116
|
+
|
|
117
|
+
Push change notifications to Slack, Discord, Microsoft Teams, or any HTTP endpoint.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
client.webhooks.register({
|
|
121
|
+
provider: 'slack', // 'slack' | 'discord' | 'teams' | 'custom'
|
|
122
|
+
url: process.env.SLACK_WEBHOOK_URL!,
|
|
123
|
+
events: ['status_changed', 'expiry_changed'],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Notifications are sent automatically when monitor detects changes.
|
|
127
|
+
// Manual dispatch:
|
|
128
|
+
await client.webhooks.notify({ domain: 'example.com', type: 'expiry_changed' });
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Data export
|
|
132
|
+
|
|
133
|
+
Export query results or historical snapshots to JSON or CSV.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const csv = client.export.export(entries, {
|
|
137
|
+
format: 'csv',
|
|
138
|
+
fields: ['target', 'capturedAt', 'snapshot.registrar.name'],
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## License key format
|
|
145
|
+
|
|
146
|
+
Keys follow the pattern `RDAP-{plan}-{payload}-{signature}` and support offline validation (the payload is a signed, base64-encoded JSON). Online validation is available as an opt-in:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
client.use(ProPlugin({
|
|
150
|
+
licenseKey: 'RDAP-PRO-...',
|
|
151
|
+
onlineValidation: true, // default: false
|
|
152
|
+
}));
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Plans: **pro** and **enterprise**. Enterprise keys unlock higher concurrency limits and priority support.
|
|
156
|
+
|
|
157
|
+
## Architecture
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
@rdapify/pro
|
|
161
|
+
├── plugin.ts ProPlugin factory — validates license, attaches modules
|
|
162
|
+
├── license/ Offline + online license validation
|
|
163
|
+
├── monitoring/ BulkMonitor, ChangeDetector
|
|
164
|
+
├── analytics/ Reporter (summary / detailed / trends)
|
|
165
|
+
├── history/ HistoryTracker (in-memory snapshot storage)
|
|
166
|
+
└── integrations/ WebhookManager, Exporter (json / csv)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Only `plugin.ts` touches `rdapify` internals. All other modules are self-contained and communicate through the plugin's `install()` hook.
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
Proprietary. A commercial license is required for production use.
|
|
174
|
+
|
|
175
|
+
See [LICENSE](LICENSE) for full terms.
|
|
176
|
+
Purchase at [rdapify.dev/pricing](https://rdapify.dev/pricing).
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
export interface ReportOptions {
|
|
7
|
+
/** "summary" | "detailed" | "trends". Default: "summary". */
|
|
8
|
+
format?: string
|
|
9
|
+
/** ISO-8601 — include only entries captured on or after this timestamp. */
|
|
10
|
+
from?: string
|
|
11
|
+
/** ISO-8601 — include only entries captured on or before this timestamp. */
|
|
12
|
+
to?: string
|
|
13
|
+
}
|
|
14
|
+
export interface TopEntry {
|
|
15
|
+
target: string
|
|
16
|
+
count: number
|
|
17
|
+
}
|
|
18
|
+
export interface ReportOutput {
|
|
19
|
+
generatedAt: string
|
|
20
|
+
format: string
|
|
21
|
+
totalQueries: number
|
|
22
|
+
registrars: Record<string, number>
|
|
23
|
+
statusCounts: Record<string, number>
|
|
24
|
+
queryTypes: Record<string, number>
|
|
25
|
+
topDomains: Array<TopEntry>
|
|
26
|
+
errorRate: number
|
|
27
|
+
}
|
|
28
|
+
export interface HistoryEntry {
|
|
29
|
+
target: string
|
|
30
|
+
queryType: string
|
|
31
|
+
/** JSON-serialised RDAP snapshot string. */
|
|
32
|
+
snapshot: string
|
|
33
|
+
/** ISO-8601 timestamp string. */
|
|
34
|
+
capturedAt: string
|
|
35
|
+
}
|
|
36
|
+
export interface HistoryQuery {
|
|
37
|
+
target: string
|
|
38
|
+
/** Filter: only entries captured on or after this ISO-8601 timestamp. */
|
|
39
|
+
from?: string
|
|
40
|
+
/** Filter: only entries captured on or before this ISO-8601 timestamp. */
|
|
41
|
+
to?: string
|
|
42
|
+
/** Return at most this many entries (most recent first). */
|
|
43
|
+
limit?: number
|
|
44
|
+
}
|
|
45
|
+
export interface WebhookConfig {
|
|
46
|
+
/** "slack" | "discord" | "teams" | "custom" */
|
|
47
|
+
provider: string
|
|
48
|
+
url: string
|
|
49
|
+
/** If set, only fire for these event types. */
|
|
50
|
+
events?: Array<string>
|
|
51
|
+
/** Custom HTTP headers added to the webhook request. */
|
|
52
|
+
headers?: Record<string, string>
|
|
53
|
+
}
|
|
54
|
+
export interface LicenseInfo {
|
|
55
|
+
valid: boolean
|
|
56
|
+
/** Present when `valid` is false. */
|
|
57
|
+
reason?: string
|
|
58
|
+
/** "pro" | "enterprise" | "trial" */
|
|
59
|
+
plan?: string
|
|
60
|
+
organization?: string
|
|
61
|
+
/** Unix timestamp in milliseconds (pass to `new Date(n)` in JS). */
|
|
62
|
+
expiresAt?: number
|
|
63
|
+
maxDevelopers?: number
|
|
64
|
+
}
|
|
65
|
+
export interface ChangeEvent {
|
|
66
|
+
target: string
|
|
67
|
+
/**
|
|
68
|
+
* "nameserver_changed" | "status_changed" | "registrar_changed" |
|
|
69
|
+
* "expiry_changed" | "dnssec_changed"
|
|
70
|
+
*/
|
|
71
|
+
changeType: string
|
|
72
|
+
field: string
|
|
73
|
+
/** JSON-serialised previous value. */
|
|
74
|
+
previousValue: string
|
|
75
|
+
/** JSON-serialised current value. */
|
|
76
|
+
currentValue: string
|
|
77
|
+
/** ISO-8601 timestamp string. */
|
|
78
|
+
detectedAt: string
|
|
79
|
+
}
|
|
80
|
+
export interface MonitorEvent {
|
|
81
|
+
domain: string
|
|
82
|
+
/** "created" | "updated" | "expired" | "transferred" | "deleted" */
|
|
83
|
+
eventType: string
|
|
84
|
+
timestamp: string
|
|
85
|
+
changes: Array<string>
|
|
86
|
+
}
|
|
87
|
+
/** Options passed to `proPlugin()`. */
|
|
88
|
+
export interface ProPluginOptions {
|
|
89
|
+
/** License key — required. Get one at https://rdapify.dev/pricing */
|
|
90
|
+
licenseKey: string
|
|
91
|
+
/** Enable online license validation (default: false). */
|
|
92
|
+
onlineValidation?: boolean
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validated plugin descriptor returned by `proPlugin()`.
|
|
96
|
+
* The JS wrapper calls `install(client)` on this object.
|
|
97
|
+
*/
|
|
98
|
+
export interface ProPluginDescriptor {
|
|
99
|
+
name: string
|
|
100
|
+
version: string
|
|
101
|
+
license: LicenseInfo
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validate the license key and return a plugin descriptor.
|
|
105
|
+
*
|
|
106
|
+
* Throws if the key is missing or invalid.
|
|
107
|
+
* The JS wrapper (`index.js`) attaches Pro modules to the client.
|
|
108
|
+
*/
|
|
109
|
+
export declare function proPlugin(options: ProPluginOptions): Promise<ProPluginDescriptor>
|
|
110
|
+
/** Generates analytics reports from RDAP query data. */
|
|
111
|
+
export declare class Reporter {
|
|
112
|
+
constructor()
|
|
113
|
+
/**
|
|
114
|
+
* Generate a report from a slice of RDAP response objects.
|
|
115
|
+
*
|
|
116
|
+
* `data` — each element must be a JSON string
|
|
117
|
+
* (e.g. `history.query(...).map(e => e.snapshot)`).
|
|
118
|
+
*/
|
|
119
|
+
generate(data: Array<string>, options?: ReportOptions | undefined | null): ReportOutput
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Tracks historical RDAP data for domains/IPs over time.
|
|
123
|
+
* Thread-safe: the inner `Vec` is guarded by a `Mutex` so that the JS
|
|
124
|
+
* `afterQuery` hook and explicit `record()` calls don't race.
|
|
125
|
+
*/
|
|
126
|
+
export declare class HistoryTracker {
|
|
127
|
+
constructor()
|
|
128
|
+
/**
|
|
129
|
+
* Record a new RDAP snapshot for `target`.
|
|
130
|
+
* `data` must be a JSON string (e.g. `JSON.stringify(rdapResponse)`).
|
|
131
|
+
*/
|
|
132
|
+
record(target: string, queryType: string, data: string): void
|
|
133
|
+
/** Query history for a specific target, with optional date range and limit. */
|
|
134
|
+
query(options: HistoryQuery): Array<HistoryEntry>
|
|
135
|
+
/** Return the most recent snapshot for `target`, or `null` if none. */
|
|
136
|
+
latest(target: string): HistoryEntry | null
|
|
137
|
+
/** Total number of stored entries. */
|
|
138
|
+
count(): number
|
|
139
|
+
/** Remove all stored entries. */
|
|
140
|
+
clear(): void
|
|
141
|
+
}
|
|
142
|
+
/** Exports RDAP query results in JSON or CSV format. */
|
|
143
|
+
export declare class Exporter {
|
|
144
|
+
constructor()
|
|
145
|
+
/**
|
|
146
|
+
* Export `data` as a pretty-printed JSON string.
|
|
147
|
+
*
|
|
148
|
+
* `data` — each element must be a JSON string
|
|
149
|
+
* (e.g. `history.query(...).map(e => e.snapshot)`).
|
|
150
|
+
*/
|
|
151
|
+
exportJson(data: Array<string>): string
|
|
152
|
+
/**
|
|
153
|
+
* Export `data` as CSV.
|
|
154
|
+
*
|
|
155
|
+
* `data` — each element must be a JSON string.
|
|
156
|
+
* `fields` — column names to include. If omitted, all top-level string/number
|
|
157
|
+
* keys from the first record are used.
|
|
158
|
+
*/
|
|
159
|
+
exportCsv(data: Array<string>, fields?: Array<string> | undefined | null): string
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Manages webhook integrations for change-event notifications.
|
|
163
|
+
* HTTP is handled by a `reqwest` async client; failures are silently ignored
|
|
164
|
+
* so one bad webhook cannot block the others.
|
|
165
|
+
*/
|
|
166
|
+
export declare class WebhookManager {
|
|
167
|
+
constructor()
|
|
168
|
+
register(config: WebhookConfig): void
|
|
169
|
+
remove(url: string): void
|
|
170
|
+
getWebhooks(): Array<WebhookConfig>
|
|
171
|
+
/**
|
|
172
|
+
* Send `event` to all registered webhooks concurrently.
|
|
173
|
+
* `event` must be a JSON string (e.g. `JSON.stringify(changeEvent)`).
|
|
174
|
+
* Returns the number of webhooks notified (regardless of HTTP status).
|
|
175
|
+
*/
|
|
176
|
+
notify(event: string): Promise<number>
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* License key format: `RDAP-{PLAN}-{base64url-payload}-{signature}`
|
|
180
|
+
*
|
|
181
|
+
* The payload is a base64url-encoded JSON object:
|
|
182
|
+
* `{ org: string, exp: number (ms), maxDev?: number }`
|
|
183
|
+
*
|
|
184
|
+
* The signature segment is reserved for server-side cryptographic verification.
|
|
185
|
+
* Use `validate_online()` for full verification and revocation checks.
|
|
186
|
+
*/
|
|
187
|
+
export declare class LicenseValidator {
|
|
188
|
+
constructor()
|
|
189
|
+
/**
|
|
190
|
+
* Validate a license key offline.
|
|
191
|
+
* Decodes the embedded payload and checks expiry and plan.
|
|
192
|
+
* Does **not** verify the cryptographic signature.
|
|
193
|
+
*/
|
|
194
|
+
static validate(key: string): LicenseInfo
|
|
195
|
+
/**
|
|
196
|
+
* Validate a license key online via the rdapify.dev license API.
|
|
197
|
+
* Falls back to offline validation if the API is unreachable.
|
|
198
|
+
*/
|
|
199
|
+
static validateOnline(key: string): Promise<LicenseInfo>
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Bulk domain/IP monitor.
|
|
203
|
+
*
|
|
204
|
+
* The Rust side manages targets, snapshots, and change detection.
|
|
205
|
+
* The JS wrapper (`index.js`) drives scheduling via `setInterval` and
|
|
206
|
+
* supplies RDAP query results by calling `process_results()`.
|
|
207
|
+
*/
|
|
208
|
+
export declare class BulkMonitor {
|
|
209
|
+
/**
|
|
210
|
+
* Create a new BulkMonitor.
|
|
211
|
+
*
|
|
212
|
+
* `interval` — polling interval string, e.g. `"30m"`, `"1h"`, `"6h"`, `"24h"`.
|
|
213
|
+
* `concurrency` — max parallel queries per poll cycle (default 10).
|
|
214
|
+
*/
|
|
215
|
+
constructor(targets: Array<string>, interval?: string | undefined | null, concurrency?: number | undefined | null)
|
|
216
|
+
/**
|
|
217
|
+
* Process a batch of RDAP results received from the JS side.
|
|
218
|
+
*
|
|
219
|
+
* `results` — map of `{ target → JSON string of rdapResponse }`.
|
|
220
|
+
* Runs change detection against stored snapshots, updates them, and
|
|
221
|
+
* returns monitor events.
|
|
222
|
+
*
|
|
223
|
+
* Called by the JS wrapper on each poll cycle.
|
|
224
|
+
*/
|
|
225
|
+
processResults(results: Record<string, string>): Array<MonitorEvent>
|
|
226
|
+
getTargets(): Array<string>
|
|
227
|
+
getIntervalMs(): number
|
|
228
|
+
getConcurrency(): number
|
|
229
|
+
addTargets(targets: Array<string>): void
|
|
230
|
+
removeTargets(targets: Array<string>): void
|
|
231
|
+
clearSnapshots(): void
|
|
232
|
+
}
|
|
233
|
+
/** Detects specific changes in RDAP records by comparing snapshots. */
|
|
234
|
+
export declare class ChangeDetector {
|
|
235
|
+
constructor(targets: Array<string>)
|
|
236
|
+
/**
|
|
237
|
+
* Compare two RDAP response snapshots and return detected changes.
|
|
238
|
+
*
|
|
239
|
+
* Both `previous` and `current` must be JSON strings
|
|
240
|
+
* (e.g. `JSON.stringify(rdapResponse)`).
|
|
241
|
+
* Checks: nameservers, status flags, registrar name, expiry date, DNSSEC.
|
|
242
|
+
*/
|
|
243
|
+
diff(previous: string, current: string): Array<ChangeEvent>
|
|
244
|
+
getTargets(): Array<string>
|
|
245
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'rdapify-pro.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./rdapify-pro.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@rdapify/pro-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'rdapify-pro.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./rdapify-pro.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@rdapify/pro-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'rdapify-pro.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./rdapify-pro.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@rdapify/pro-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'rdapify-pro.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./rdapify-pro.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@rdapify/pro-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'rdapify-pro.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./rdapify-pro.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@rdapify/pro-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'rdapify-pro.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./rdapify-pro.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@rdapify/pro-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'rdapify-pro.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./rdapify-pro.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@rdapify/pro-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'rdapify-pro.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./rdapify-pro.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@rdapify/pro-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'rdapify-pro.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./rdapify-pro.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@rdapify/pro-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'rdapify-pro.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./rdapify-pro.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@rdapify/pro-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'rdapify-pro.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./rdapify-pro.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@rdapify/pro-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'rdapify-pro.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./rdapify-pro.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@rdapify/pro-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'rdapify-pro.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./rdapify-pro.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@rdapify/pro-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'rdapify-pro.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./rdapify-pro.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@rdapify/pro-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'rdapify-pro.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./rdapify-pro.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@rdapify/pro-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'rdapify-pro.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./rdapify-pro.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@rdapify/pro-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'rdapify-pro.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./rdapify-pro.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@rdapify/pro-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'rdapify-pro.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./rdapify-pro.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@rdapify/pro-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { Reporter, HistoryTracker, Exporter, WebhookManager, LicenseValidator, BulkMonitor, ChangeDetector, proPlugin } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.Reporter = Reporter
|
|
316
|
+
module.exports.HistoryTracker = HistoryTracker
|
|
317
|
+
module.exports.Exporter = Exporter
|
|
318
|
+
module.exports.WebhookManager = WebhookManager
|
|
319
|
+
module.exports.LicenseValidator = LicenseValidator
|
|
320
|
+
module.exports.BulkMonitor = BulkMonitor
|
|
321
|
+
module.exports.ChangeDetector = ChangeDetector
|
|
322
|
+
module.exports.proPlugin = proPlugin
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rdapify/pro",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Premium Rust-native features for RDAPify — Bulk Monitoring, Change Detection, Analytics & more",
|
|
5
|
+
"main": "wrapper.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"napi": {
|
|
8
|
+
"name": "rdapify-pro",
|
|
9
|
+
"triples": {
|
|
10
|
+
"defaults": true,
|
|
11
|
+
"additional": [
|
|
12
|
+
"aarch64-apple-darwin",
|
|
13
|
+
"aarch64-unknown-linux-gnu",
|
|
14
|
+
"aarch64-unknown-linux-musl",
|
|
15
|
+
"x86_64-unknown-linux-musl"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "napi build --platform --release",
|
|
21
|
+
"build:debug": "napi build --platform",
|
|
22
|
+
"artifacts": "napi artifacts",
|
|
23
|
+
"prepublishOnly": "napi prepublish -t npm",
|
|
24
|
+
"universal": "napi universal",
|
|
25
|
+
"version": "napi version",
|
|
26
|
+
"test": "jest --runInBand",
|
|
27
|
+
"clean": "rm -rf *.node target/"
|
|
28
|
+
},
|
|
29
|
+
"jest": {
|
|
30
|
+
"preset": "ts-jest",
|
|
31
|
+
"testEnvironment": "node",
|
|
32
|
+
"testMatch": [
|
|
33
|
+
"**/tests/**/*.test.ts"
|
|
34
|
+
],
|
|
35
|
+
"moduleFileExtensions": [
|
|
36
|
+
"ts",
|
|
37
|
+
"js",
|
|
38
|
+
"json"
|
|
39
|
+
],
|
|
40
|
+
"transform": {
|
|
41
|
+
"^.+\\.ts$": [
|
|
42
|
+
"ts-jest",
|
|
43
|
+
{
|
|
44
|
+
"tsconfig": {
|
|
45
|
+
"strict": false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"rdapify": ">=0.1.9"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@napi-rs/cli": "^2.18.0",
|
|
56
|
+
"rdapify": "file:../rdapify",
|
|
57
|
+
"jest": "^29.7.0",
|
|
58
|
+
"@types/jest": "^29.5.0",
|
|
59
|
+
"ts-jest": "^29.2.0",
|
|
60
|
+
"typescript": "^5.7.0",
|
|
61
|
+
"@types/node": "^22.0.0"
|
|
62
|
+
},
|
|
63
|
+
"optionalDependencies": {
|
|
64
|
+
"@rdapify/pro-win32-x64-msvc": "0.2.0",
|
|
65
|
+
"@rdapify/pro-darwin-x64": "0.2.0",
|
|
66
|
+
"@rdapify/pro-linux-x64-gnu": "0.2.0",
|
|
67
|
+
"@rdapify/pro-darwin-arm64": "0.2.0",
|
|
68
|
+
"@rdapify/pro-linux-arm64-gnu": "0.2.0",
|
|
69
|
+
"@rdapify/pro-linux-arm64-musl": "0.2.0",
|
|
70
|
+
"@rdapify/pro-linux-x64-musl": "0.2.0"
|
|
71
|
+
},
|
|
72
|
+
"files": [
|
|
73
|
+
"index.js",
|
|
74
|
+
"wrapper.js",
|
|
75
|
+
"index.d.ts",
|
|
76
|
+
"rdapify-pro.node",
|
|
77
|
+
"LICENSE",
|
|
78
|
+
"README.md"
|
|
79
|
+
],
|
|
80
|
+
"engines": {
|
|
81
|
+
"node": ">=20.0.0"
|
|
82
|
+
},
|
|
83
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
84
|
+
"repository": {
|
|
85
|
+
"type": "git",
|
|
86
|
+
"url": "https://github.com/rdapify/RDAPify-Pro.git"
|
|
87
|
+
},
|
|
88
|
+
"keywords": [
|
|
89
|
+
"rdap",
|
|
90
|
+
"rdapify",
|
|
91
|
+
"rust",
|
|
92
|
+
"native",
|
|
93
|
+
"monitoring",
|
|
94
|
+
"domain",
|
|
95
|
+
"whois",
|
|
96
|
+
"analytics"
|
|
97
|
+
]
|
|
98
|
+
}
|
package/wrapper.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const native = require('./index.js');
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
Reporter,
|
|
7
|
+
HistoryTracker,
|
|
8
|
+
Exporter,
|
|
9
|
+
WebhookManager,
|
|
10
|
+
LicenseValidator,
|
|
11
|
+
BulkMonitor,
|
|
12
|
+
ChangeDetector,
|
|
13
|
+
proPlugin,
|
|
14
|
+
} = native;
|
|
15
|
+
|
|
16
|
+
module.exports.Reporter = Reporter;
|
|
17
|
+
module.exports.HistoryTracker = HistoryTracker;
|
|
18
|
+
module.exports.Exporter = Exporter;
|
|
19
|
+
module.exports.WebhookManager = WebhookManager;
|
|
20
|
+
module.exports.LicenseValidator = LicenseValidator;
|
|
21
|
+
module.exports.BulkMonitor = BulkMonitor;
|
|
22
|
+
module.exports.ChangeDetector = ChangeDetector;
|
|
23
|
+
module.exports.proPlugin = proPlugin;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* ProPlugin — synchronous factory that validates a license key offline and
|
|
27
|
+
* returns a plugin descriptor with an `install(client)` method.
|
|
28
|
+
*
|
|
29
|
+
* @param {object} options
|
|
30
|
+
* @param {string} options.licenseKey
|
|
31
|
+
* @param {boolean} [options.onlineValidation=false]
|
|
32
|
+
*/
|
|
33
|
+
function ProPlugin(options) {
|
|
34
|
+
if (!options || !options.licenseKey) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
'[@rdapify/pro] License key required. Get one at https://rdapify.dev/pricing'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const license = LicenseValidator.validate(options.licenseKey);
|
|
41
|
+
if (!license.valid) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`[@rdapify/pro] Invalid or expired license key. Reason: ${license.reason}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
name: '@rdapify/pro',
|
|
49
|
+
version: require('./package.json').version,
|
|
50
|
+
license,
|
|
51
|
+
install(client) {
|
|
52
|
+
const history = new HistoryTracker();
|
|
53
|
+
|
|
54
|
+
client.monitor = function (targets, opts) {
|
|
55
|
+
return new BulkMonitor(
|
|
56
|
+
targets,
|
|
57
|
+
(opts && opts.interval) || undefined,
|
|
58
|
+
(opts && opts.concurrency) || undefined
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
client.detect = function (targets) {
|
|
63
|
+
return new ChangeDetector(targets);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
client.report = function () {
|
|
67
|
+
return new Reporter();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
client.history = history;
|
|
71
|
+
client.webhooks = new WebhookManager();
|
|
72
|
+
client.export = new Exporter();
|
|
73
|
+
|
|
74
|
+
if (typeof client.use === 'function') {
|
|
75
|
+
client.use({
|
|
76
|
+
afterQuery(ctx) {
|
|
77
|
+
const result = ctx.result;
|
|
78
|
+
if (result) {
|
|
79
|
+
const queryType = ctx.queryType != null ? String(ctx.queryType) : 'domain';
|
|
80
|
+
const query = ctx.query != null ? String(ctx.query) : '';
|
|
81
|
+
history.record(query, queryType, JSON.stringify(result));
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports.ProPlugin = ProPlugin;
|