vpndetection 1.0.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 +21 -0
- package/README.md +158 -0
- package/dist/bogon.d.ts +19 -0
- package/dist/bogon.js +130 -0
- package/dist/bogon.js.map +1 -0
- package/dist/bogons.gen.d.ts +2 -0
- package/dist/bogons.gen.js +62 -0
- package/dist/bogons.gen.js.map +1 -0
- package/dist/client.d.ts +97 -0
- package/dist/client.js +201 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +69 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/client/client.gen.d.ts +2 -0
- package/dist/generated/client/client.gen.js +217 -0
- package/dist/generated/client/client.gen.js.map +1 -0
- package/dist/generated/client/index.d.ts +10 -0
- package/dist/generated/client/index.js +7 -0
- package/dist/generated/client/index.js.map +1 -0
- package/dist/generated/client/types.gen.d.ts +120 -0
- package/dist/generated/client/types.gen.js +3 -0
- package/dist/generated/client/types.gen.js.map +1 -0
- package/dist/generated/client/utils.gen.d.ts +37 -0
- package/dist/generated/client/utils.gen.js +229 -0
- package/dist/generated/client/utils.gen.js.map +1 -0
- package/dist/generated/client.gen.d.ts +12 -0
- package/dist/generated/client.gen.js +4 -0
- package/dist/generated/client.gen.js.map +1 -0
- package/dist/generated/core/auth.gen.d.ts +25 -0
- package/dist/generated/core/auth.gen.js +15 -0
- package/dist/generated/core/auth.gen.js.map +1 -0
- package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
- package/dist/generated/core/bodySerializer.gen.js +58 -0
- package/dist/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/generated/core/params.gen.d.ts +43 -0
- package/dist/generated/core/params.gen.js +110 -0
- package/dist/generated/core/params.gen.js.map +1 -0
- package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
- package/dist/generated/core/pathSerializer.gen.js +107 -0
- package/dist/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/generated/core/queryKeySerializer.gen.js +93 -0
- package/dist/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/generated/core/serverSentEvents.gen.js +133 -0
- package/dist/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/generated/core/types.gen.d.ts +83 -0
- package/dist/generated/core/types.gen.js +3 -0
- package/dist/generated/core/types.gen.js.map +1 -0
- package/dist/generated/core/utils.gen.d.ts +19 -0
- package/dist/generated/core/utils.gen.js +88 -0
- package/dist/generated/core/utils.gen.js.map +1 -0
- package/dist/generated/index.d.ts +2 -0
- package/dist/generated/index.js +3 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/generated/sdk.gen.d.ts +51 -0
- package/dist/generated/sdk.gen.js +111 -0
- package/dist/generated/sdk.gen.js.map +1 -0
- package/dist/generated/types.gen.d.ts +466 -0
- package/dist/generated/types.gen.js +3 -0
- package/dist/generated/types.gen.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.js +39 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mslm Dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# [<img src="https://s3.vpndetection.io/vpndetection-public/brand/mark.svg" alt="VPNDetection" width="24"/>](https://vpndetection.io/) VPNDetection Node.js Client Library
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/vpndetection)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
The official Node.js client library for the [VPNDetection](https://vpndetection.io) API.
|
|
7
|
+
|
|
8
|
+
The library helps you query VPNDetection's APIs for anonymity detection including VPNs, residential proxies, Tor nodes, hosting servers, CDNs, relays and more.
|
|
9
|
+
|
|
10
|
+
## Getting Started
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install vpndetection
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires Node.js 22 or newer. TypeScript types are included.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
**No API key needed to start.** The free tier answers `ip` and `is_vpn`, and allows 1000 requests per day per source address.
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { VPNDetection } from 'vpndetection';
|
|
24
|
+
|
|
25
|
+
const client = new VPNDetection();
|
|
26
|
+
|
|
27
|
+
const result = await client.lookup('45.83.91.1');
|
|
28
|
+
console.log(result.isVpn); // true
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### With an API key
|
|
32
|
+
|
|
33
|
+
An API key raises your quota, and raises your features on a paid plan. Create one in the [console](https://app.vpndetection.io), then pass it in:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
const client = new VPNDetection({ apiKey: process.env.VPNDETECTION_API_KEY });
|
|
37
|
+
|
|
38
|
+
const result = await client.lookup('45.83.91.1');
|
|
39
|
+
console.log(result.isVpn); // true
|
|
40
|
+
console.log(result.vpn?.provider); // 'mullvad'
|
|
41
|
+
console.log(result.isHosting); // true
|
|
42
|
+
console.log(result.hosting?.provider);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Batch lookup
|
|
46
|
+
|
|
47
|
+
You can do batch lookups with a list, which parallelizes requests for you efficiently:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const results = await client.lookupBatch(['45.83.91.1', '8.8.8.8', '1.1.1.1']);
|
|
51
|
+
|
|
52
|
+
for (const [ip, result] of results) {
|
|
53
|
+
if (result instanceof Error) {
|
|
54
|
+
console.error(`${ip}: ${result.message}`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
console.log(`${ip}: ${result.isVpn}`);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Results are keyed by address, so duplicates in your list collapse into a single request and one address failing never loses the rest.
|
|
62
|
+
|
|
63
|
+
Concurrency and other variables are configurable per-call:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
const results = await client.lookupBatch(manyIps, { concurrency: 32, retries: 4 });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Caching
|
|
70
|
+
|
|
71
|
+
Answers are cached by default, so repeat lookups of the same address are free:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const client = new VPNDetection();
|
|
75
|
+
|
|
76
|
+
const result = await client.lookup('45.83.91.1');
|
|
77
|
+
console.log(result.isVpn); // true, API request
|
|
78
|
+
|
|
79
|
+
const result2 = await client.lookup('45.83.91.1');
|
|
80
|
+
console.log(result2.isVpn); // true, no API request, result was cached
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
You can change the default cache variables (max size, TTL, etc) on initialization, or even disable it:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const client = new VPNDetection({ cache: { max: 50_000, ttlMs: 6 * 60 * 60 * 1000 } });
|
|
87
|
+
const clientNoCache = new VPNDetection({ cache: false });
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Private and reserved addresses
|
|
91
|
+
|
|
92
|
+
Private, loopback, link-local, documentation and multicast addresses (and their IPv6 equivalents, including the 6to4 and Teredo ranges) can never be VPN or proxy infrastructure. The library answers them locally, so they cost no request and no quota:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
const result = await client.lookup('192.168.1.1');
|
|
96
|
+
result.isBogon; // true, this answer was computed rather than served
|
|
97
|
+
result.isVpn; // false
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The check is available on the client, which is handy when your inputs are addresses anyway:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
client.isBogon('10.0.0.1'); // true
|
|
104
|
+
client.isBogon('8.8.8.8'); // false
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
It is also importable on its own, if you want it without a client:
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
import { isBogon } from 'vpndetection';
|
|
111
|
+
|
|
112
|
+
isBogon('10.0.0.1'); // true
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Errors
|
|
116
|
+
|
|
117
|
+
Failures throw a `VPNDetectionError` carrying a `kind` and a `retryable` flag:
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
import { VPNDetectionError } from 'vpndetection';
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await client.lookup('1.1.1.1');
|
|
124
|
+
} catch (err) {
|
|
125
|
+
if (err instanceof VPNDetectionError) {
|
|
126
|
+
console.error(err.kind, err.retryable);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`kind` is one of `bad_request`, `unauthorized`, `forbidden`, `rate_limited`, `quota_exceeded`, `server_error` or `network`.
|
|
132
|
+
|
|
133
|
+
Note that `rate_limited` and `quota_exceeded` both arrive as HTTP 429 and are not the same thing. A rate limit is when the API faces extreme traffic bursts and so retrying later works; but a spent quota needs your allowance raised or the window to roll over. The library retries rate limits for you, but not if your quota is exceeded.
|
|
134
|
+
|
|
135
|
+
### Database downloads
|
|
136
|
+
|
|
137
|
+
If your key carries the `db.download` scope, the licensed datasets are available through `client.database`:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
const datasets = await client.database.list();
|
|
141
|
+
const url = await client.database.downloadUrl('vpn_ip_extended_v1', 'mmdb');
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`downloadUrl` returns a time-limited link rather than the bytes, so you choose how to transfer a file that can run to gigabytes.
|
|
145
|
+
|
|
146
|
+
## Other Libraries
|
|
147
|
+
|
|
148
|
+
There are official VPNDetection client libraries available for many languages including PHP, Python, Go, Java, Ruby, and many popular frameworks such as Django, Rails, and Laravel. See our GitHub at https://github.com/vpndetection-io for more.
|
|
149
|
+
|
|
150
|
+
## About VPNDetection
|
|
151
|
+
|
|
152
|
+
VPN Detection API: Accurate anonymity detection identifying VPNs, residential proxies, hosting servers, Tor nodes, CDNs, relays and more.
|
|
153
|
+
|
|
154
|
+
[<img src="https://s3.vpndetection.io/vpndetection-public/brand/mark.svg" alt="VPNDetection" width="96"/>](https://vpndetection.io/)
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
This project is licensed under the [MIT License](LICENSE).
|
package/dist/bogon.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Result } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether an address is a bogon: private, loopback, link-local, documentation,
|
|
4
|
+
* multicast or otherwise not routable on the public internet, including the
|
|
5
|
+
* IPv6 equivalents and the 6to4 and Teredo ranges that wrap them.
|
|
6
|
+
*
|
|
7
|
+
* These can never be VPN or proxy infrastructure, so the client answers them
|
|
8
|
+
* itself and they never cost a request.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isBogon(ip: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The answer a bogon gets, in the full shape the API serves at its widest plan:
|
|
13
|
+
* every flag present and false, every detail object present and empty.
|
|
14
|
+
*
|
|
15
|
+
* `isBogon` is set so a caller can always tell a locally computed answer from a
|
|
16
|
+
* served one. Note this is deliberately the WIDEST shape regardless of your
|
|
17
|
+
* plan, so do not infer which fields your plan includes from a bogon answer.
|
|
18
|
+
*/
|
|
19
|
+
export declare function bogonResult(ip: string): Result;
|
package/dist/bogon.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { BOGON_V4, BOGON_V6 } from './bogons.gen.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether an address is a bogon: private, loopback, link-local, documentation,
|
|
4
|
+
* multicast or otherwise not routable on the public internet, including the
|
|
5
|
+
* IPv6 equivalents and the 6to4 and Teredo ranges that wrap them.
|
|
6
|
+
*
|
|
7
|
+
* These can never be VPN or proxy infrastructure, so the client answers them
|
|
8
|
+
* itself and they never cost a request.
|
|
9
|
+
*/
|
|
10
|
+
export function isBogon(ip) {
|
|
11
|
+
if (ip.includes(':')) {
|
|
12
|
+
const a = v6ToInt(ip);
|
|
13
|
+
return a === null ? false : v6().some((r) => (a & r.mask) === r.net);
|
|
14
|
+
}
|
|
15
|
+
const a = v4ToInt(ip);
|
|
16
|
+
return a === null ? false : v4().some((r) => (a & r.mask) >>> 0 === r.net);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The answer a bogon gets, in the full shape the API serves at its widest plan:
|
|
20
|
+
* every flag present and false, every detail object present and empty.
|
|
21
|
+
*
|
|
22
|
+
* `isBogon` is set so a caller can always tell a locally computed answer from a
|
|
23
|
+
* served one. Note this is deliberately the WIDEST shape regardless of your
|
|
24
|
+
* plan, so do not infer which fields your plan includes from a bogon answer.
|
|
25
|
+
*/
|
|
26
|
+
export function bogonResult(ip) {
|
|
27
|
+
return {
|
|
28
|
+
ip: ip,
|
|
29
|
+
isBogon: true,
|
|
30
|
+
isVpn: false,
|
|
31
|
+
isHosting: false,
|
|
32
|
+
isRelay: false,
|
|
33
|
+
isTor: false,
|
|
34
|
+
isCdn: false,
|
|
35
|
+
isResproxy: false,
|
|
36
|
+
isDcproxy: false,
|
|
37
|
+
isMobproxy: false,
|
|
38
|
+
vpn: {},
|
|
39
|
+
hosting: {},
|
|
40
|
+
relay: {},
|
|
41
|
+
tor: {},
|
|
42
|
+
cdn: {},
|
|
43
|
+
resproxy: {},
|
|
44
|
+
dcproxy: {},
|
|
45
|
+
mobproxy: {},
|
|
46
|
+
raw: {},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Parsed once on first use rather than at import: a consumer that never looks
|
|
50
|
+
// up an address should not pay for the table, and module-scope work is what
|
|
51
|
+
// makes a library expensive to import.
|
|
52
|
+
let v4Cache = null;
|
|
53
|
+
let v6Cache = null;
|
|
54
|
+
function v4() {
|
|
55
|
+
if (!v4Cache) {
|
|
56
|
+
v4Cache = BOGON_V4.map((c) => {
|
|
57
|
+
const [net, bits] = c.split('/');
|
|
58
|
+
const mask = bits === '0' ? 0 : (~0 << (32 - Number(bits))) >>> 0;
|
|
59
|
+
return { net: (v4ToInt(net) & mask) >>> 0, mask: mask };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return v4Cache;
|
|
63
|
+
}
|
|
64
|
+
function v6() {
|
|
65
|
+
if (!v6Cache) {
|
|
66
|
+
v6Cache = BOGON_V6.map((c) => {
|
|
67
|
+
const [net, bits] = c.split('/');
|
|
68
|
+
const mask = bits === '0' ? 0n : (~0n << BigInt(128 - Number(bits))) & MAX128;
|
|
69
|
+
return { net: v6ToInt(net) & mask, mask: mask };
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return v6Cache;
|
|
73
|
+
}
|
|
74
|
+
const MAX128 = (1n << 128n) - 1n;
|
|
75
|
+
function v4ToInt(ip) {
|
|
76
|
+
const p = ip.split('.');
|
|
77
|
+
if (p.length !== 4) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
let n = 0;
|
|
81
|
+
for (const part of p) {
|
|
82
|
+
const b = Number(part);
|
|
83
|
+
if (!Number.isInteger(b) || b < 0 || b > 255 || part === '') {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
n = ((n << 8) | b) >>> 0;
|
|
87
|
+
}
|
|
88
|
+
return n;
|
|
89
|
+
}
|
|
90
|
+
// Handles the `::` run and a trailing IPv4 literal (::ffff:1.2.3.4), which
|
|
91
|
+
// several of the canonical ranges use.
|
|
92
|
+
function v6ToInt(ip) {
|
|
93
|
+
let a = ip;
|
|
94
|
+
const v4Tail = a.match(/(\d+\.\d+\.\d+\.\d+)$/);
|
|
95
|
+
if (v4Tail) {
|
|
96
|
+
const n = v4ToInt(v4Tail[1]);
|
|
97
|
+
if (n === null) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const hi = (n >>> 16).toString(16).padStart(4, '0');
|
|
101
|
+
const lo = (n & 0xffff).toString(16).padStart(4, '0');
|
|
102
|
+
a = `${a.slice(0, v4Tail.index)}${hi}:${lo}`;
|
|
103
|
+
}
|
|
104
|
+
const dbl = a.indexOf('::');
|
|
105
|
+
let groups;
|
|
106
|
+
if (dbl === -1) {
|
|
107
|
+
groups = a.split(':');
|
|
108
|
+
if (groups.length !== 8) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const head = a.slice(0, dbl).split(':').filter((g) => g !== '');
|
|
114
|
+
const tail = a.slice(dbl + 2).split(':').filter((g) => g !== '');
|
|
115
|
+
const fill = 8 - head.length - tail.length;
|
|
116
|
+
if (fill < 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
groups = [...head, ...Array(fill).fill('0'), ...tail];
|
|
120
|
+
}
|
|
121
|
+
let n = 0n;
|
|
122
|
+
for (const g of groups) {
|
|
123
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(g)) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
n = (n << 16n) | BigInt(parseInt(g, 16));
|
|
127
|
+
}
|
|
128
|
+
return n;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=bogon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bogon.js","sourceRoot":"","sources":["../src/bogon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Generated by sdk/common. Do not edit.
|
|
2
|
+
// The canonical list lives in the monorepo and is checked against both
|
|
3
|
+
// upstream definitions on every regeneration.
|
|
4
|
+
export const BOGON_V4 = [
|
|
5
|
+
'0.0.0.0/8',
|
|
6
|
+
'10.0.0.0/8',
|
|
7
|
+
'100.64.0.0/10',
|
|
8
|
+
'127.0.0.0/8',
|
|
9
|
+
'169.254.0.0/16',
|
|
10
|
+
'172.16.0.0/12',
|
|
11
|
+
'192.0.0.0/24',
|
|
12
|
+
'192.0.2.0/24',
|
|
13
|
+
'192.168.0.0/16',
|
|
14
|
+
'198.18.0.0/15',
|
|
15
|
+
'198.51.100.0/24',
|
|
16
|
+
'203.0.113.0/24',
|
|
17
|
+
'224.0.0.0/4',
|
|
18
|
+
'240.0.0.0/4',
|
|
19
|
+
'255.255.255.255/32',
|
|
20
|
+
];
|
|
21
|
+
export const BOGON_V6 = [
|
|
22
|
+
'::/128',
|
|
23
|
+
'::1/128',
|
|
24
|
+
'::ffff:0:0/96',
|
|
25
|
+
'::/96',
|
|
26
|
+
'100::/64',
|
|
27
|
+
'2001:10::/28',
|
|
28
|
+
'2001:db8::/32',
|
|
29
|
+
'fc00::/7',
|
|
30
|
+
'fe80::/10',
|
|
31
|
+
'fec0::/10',
|
|
32
|
+
'ff00::/8',
|
|
33
|
+
'2002::/24',
|
|
34
|
+
'2002:a00::/24',
|
|
35
|
+
'2002:7f00::/24',
|
|
36
|
+
'2002:a9fe::/32',
|
|
37
|
+
'2002:ac10::/28',
|
|
38
|
+
'2002:c000::/40',
|
|
39
|
+
'2002:c000:200::/40',
|
|
40
|
+
'2002:c0a8::/32',
|
|
41
|
+
'2002:c612::/31',
|
|
42
|
+
'2002:c633:6400::/40',
|
|
43
|
+
'2002:cb00:7100::/40',
|
|
44
|
+
'2002:e000::/20',
|
|
45
|
+
'2002:f000::/20',
|
|
46
|
+
'2002:ffff:ffff::/48',
|
|
47
|
+
'2001::/40',
|
|
48
|
+
'2001:0:a00::/40',
|
|
49
|
+
'2001:0:7f00::/40',
|
|
50
|
+
'2001:0:a9fe::/48',
|
|
51
|
+
'2001:0:ac10::/44',
|
|
52
|
+
'2001:0:c000::/56',
|
|
53
|
+
'2001:0:c000:200::/56',
|
|
54
|
+
'2001:0:c0a8::/48',
|
|
55
|
+
'2001:0:c612::/47',
|
|
56
|
+
'2001:0:c633:6400::/56',
|
|
57
|
+
'2001:0:cb00:7100::/56',
|
|
58
|
+
'2001:0:e000::/36',
|
|
59
|
+
'2001:0:f000::/36',
|
|
60
|
+
'2001:0:ffff:ffff::/64',
|
|
61
|
+
];
|
|
62
|
+
//# sourceMappingURL=bogons.gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bogons.gen.js","sourceRoot":"","sources":["../src/bogons.gen.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,uEAAuE;AACvE,8CAA8C;AAE9C,MAAM,CAAC,MAAM,QAAQ,GAAsB;IACvC,WAAW;IACX,YAAY;IACZ,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,eAAe;IACf,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,aAAa;IACb,oBAAoB;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAsB;IACvC,QAAQ;IACR,SAAS;IACT,eAAe;IACf,OAAO;IACP,UAAU;IACV,cAAc;IACd,eAAe;IACf,UAAU;IACV,WAAW;IACX,WAAW;IACX,UAAU;IACV,WAAW;IACX,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,oBAAoB;IACpB,gBAAgB;IAChB,gBAAgB;IAChB,qBAAqB;IACrB,qBAAqB;IACrB,gBAAgB;IAChB,gBAAgB;IAChB,qBAAqB;IACrB,WAAW;IACX,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,sBAAsB;IACtB,kBAAkB;IAClB,kBAAkB;IAClB,uBAAuB;IACvB,uBAAuB;IACvB,kBAAkB;IAClB,kBAAkB;IAClB,uBAAuB;CAC1B,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Client } from './generated/client/index.js';
|
|
2
|
+
import type { DatasetMetadata, Download, LicensedDataset } from './generated/types.gen.js';
|
|
3
|
+
import { VPNDetectionError } from './errors.js';
|
|
4
|
+
import { type Result } from './types.js';
|
|
5
|
+
export declare const DEFAULT_BASE_URL = "https://api.vpndetection.io";
|
|
6
|
+
export interface CacheOptions {
|
|
7
|
+
/** Maximum number of addresses held. Default 10000. */
|
|
8
|
+
max?: number;
|
|
9
|
+
/** How long an answer stays fresh, in milliseconds. Default 1 hour. */
|
|
10
|
+
ttlMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Options {
|
|
13
|
+
/**
|
|
14
|
+
* Your API key. Omit it entirely to use the free tier, which answers
|
|
15
|
+
* `ip` and `is_vpn` and allows 1000 requests per day per source address.
|
|
16
|
+
*/
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
/** Pass `false` to disable caching. */
|
|
20
|
+
cache?: CacheOptions | false;
|
|
21
|
+
/** Concurrent in-flight requests during a batch. Default 8. */
|
|
22
|
+
concurrency?: number;
|
|
23
|
+
/** Retry attempts for a transient failure. Default 2. */
|
|
24
|
+
retries?: number;
|
|
25
|
+
/** Override the HTTP implementation, mostly for tests. */
|
|
26
|
+
fetch?: typeof globalThis.fetch;
|
|
27
|
+
}
|
|
28
|
+
/** Per-call overrides for a single lookup. Anything omitted falls back to the client's setting. */
|
|
29
|
+
export interface LookupOptions {
|
|
30
|
+
/** Retry attempts for a transient failure. */
|
|
31
|
+
retries?: number;
|
|
32
|
+
}
|
|
33
|
+
/** Per-call overrides for one batch. Anything omitted falls back to the client's setting. */
|
|
34
|
+
export interface BatchOptions extends LookupOptions {
|
|
35
|
+
/** Concurrent in-flight requests for THIS batch only. */
|
|
36
|
+
concurrency?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A client for the VPNDetection API.
|
|
40
|
+
*
|
|
41
|
+
* The cache is per instance, so an answer is never shared between two clients
|
|
42
|
+
* holding different API keys and therefore entitled to different fields.
|
|
43
|
+
*/
|
|
44
|
+
export declare class VPNDetection {
|
|
45
|
+
private readonly client;
|
|
46
|
+
private readonly cache;
|
|
47
|
+
private readonly limit;
|
|
48
|
+
private readonly retries;
|
|
49
|
+
/** The licensed dataset downloads, for keys that carry the `db.download` scope. */
|
|
50
|
+
readonly database: DatabaseApi;
|
|
51
|
+
constructor(options?: Options);
|
|
52
|
+
/**
|
|
53
|
+
* Whether an address is private, loopback, link-local, documentation,
|
|
54
|
+
* multicast or otherwise not routable, including the IPv6 equivalents and
|
|
55
|
+
* the 6to4 and Teredo ranges.
|
|
56
|
+
*
|
|
57
|
+
* These are the addresses `lookup` answers locally. Exposed here so the
|
|
58
|
+
* check is reachable from the client you already hold; the same function is
|
|
59
|
+
* also importable on its own.
|
|
60
|
+
*/
|
|
61
|
+
isBogon(ip: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Classify one address.
|
|
64
|
+
*
|
|
65
|
+
* A bogon is answered locally and never reaches the network. Everything
|
|
66
|
+
* else is served, then cached for this instance.
|
|
67
|
+
*/
|
|
68
|
+
lookup(ip: string, options?: LookupOptions): Promise<Result>;
|
|
69
|
+
/**
|
|
70
|
+
* Classify many addresses concurrently.
|
|
71
|
+
*
|
|
72
|
+
* Keyed by address rather than positional, so duplicates in the input
|
|
73
|
+
* collapse to a single request and the caller never has to line two lists
|
|
74
|
+
* up. An address that fails carries its error as its value, so one bad
|
|
75
|
+
* entry cannot lose the rest of the answers.
|
|
76
|
+
*/
|
|
77
|
+
lookupBatch(ips: Iterable<string>, options?: BatchOptions): Promise<Map<string, Result | VPNDetectionError>>;
|
|
78
|
+
}
|
|
79
|
+
/** The licensed dataset downloads. Access is granted by contract, not self-serve. */
|
|
80
|
+
export declare class DatabaseApi {
|
|
81
|
+
private readonly client;
|
|
82
|
+
private readonly retries;
|
|
83
|
+
constructor(client: Client, retries: number);
|
|
84
|
+
list(): Promise<LicensedDataset[]>;
|
|
85
|
+
metadata(id: string): Promise<DatasetMetadata>;
|
|
86
|
+
checksum(id: string, format: 'csvgz' | 'mmdb'): Promise<string>;
|
|
87
|
+
downloads(): Promise<Download[]>;
|
|
88
|
+
/**
|
|
89
|
+
* The time-limited URL for one dataset file.
|
|
90
|
+
*
|
|
91
|
+
* The API answers `302` to object storage. The URL is returned rather than
|
|
92
|
+
* the bytes so the caller decides how to transfer a file that routinely
|
|
93
|
+
* runs to gigabytes; the link authorizes the START of a transfer, so one
|
|
94
|
+
* already running is not interrupted when it lapses.
|
|
95
|
+
*/
|
|
96
|
+
downloadUrl(id: string, format: 'csvgz' | 'mmdb'): Promise<string>;
|
|
97
|
+
}
|