plevinjs 0.1.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/README.md +283 -0
- package/dist/address.d.ts +28 -0
- package/dist/address.d.ts.map +1 -0
- package/dist/address.js +242 -0
- package/dist/address.js.map +1 -0
- package/dist/countries.d.ts +3 -0
- package/dist/countries.d.ts.map +1 -0
- package/dist/countries.js +255 -0
- package/dist/countries.js.map +1 -0
- package/dist/derive.d.ts +13 -0
- package/dist/derive.d.ts.map +1 -0
- package/dist/derive.js +124 -0
- package/dist/derive.js.map +1 -0
- package/dist/extra.d.ts +9 -0
- package/dist/extra.d.ts.map +1 -0
- package/dist/extra.js +217 -0
- package/dist/extra.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +282 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +148 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +3 -0
- package/dist/models.js.map +1 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +12 -0
- package/dist/node.js.map +1 -0
- package/dist/reader.d.ts +85 -0
- package/dist/reader.d.ts.map +1 -0
- package/dist/reader.js +461 -0
- package/dist/reader.js.map +1 -0
- package/dist/zones.d.ts +3 -0
- package/dist/zones.d.ts.map +1 -0
- package/dist/zones.js +373 -0
- package/dist/zones.js.map +1 -0
- package/dist/zstd.d.ts +31 -0
- package/dist/zstd.d.ts.map +1 -0
- package/dist/zstd.js +574 -0
- package/dist/zstd.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://www.npmjs.com/package/plevinjs">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tn3w/plevin/master/.github/title-dark.png">
|
|
5
|
+
<img src="https://raw.githubusercontent.com/tn3w/plevin/master/.github/title-light.png" width="320" alt="plevin">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
|
|
9
|
+
**Location, network and abuse information for any IP address in one offline file.**<br>
|
|
10
|
+
No API, no rate limit, no lookup leaving the machine — or the browser tab.
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+

|
|
16
|
+

|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install plevinjs
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { Plevin, open } from "plevinjs";
|
|
27
|
+
|
|
28
|
+
const db = await open("https://plevin.tn3w.dev/db/plevin.plv");
|
|
29
|
+
const found = db.lookup("1.1.1.1"); // string, number, bigint or packed bytes
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Always a `Result`, never `undefined`; it throws for anything that is not an address, and
|
|
33
|
+
a number reads as v6 only above `0xffffffff`, so `lookup(1)` is `0.0.0.1`.
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
found.place.city.name; // 'Brisbane'
|
|
37
|
+
found.place.city.region.name; // 'Queensland'
|
|
38
|
+
found.place.country.name; // 'Australia'
|
|
39
|
+
found.place.time.local; // '2026-08-13T23:27:58+10:00'
|
|
40
|
+
|
|
41
|
+
found.network.asn; // 13335
|
|
42
|
+
found.network.operator.brand; // 'Cloudflare'
|
|
43
|
+
found.network.cidr; // '1.1.1.0/24'
|
|
44
|
+
|
|
45
|
+
const exit = db.lookup("185.220.101.1");
|
|
46
|
+
exit.abuse.service; // 'tor_exit_node'
|
|
47
|
+
exit.abuse.risk; // 0.97
|
|
48
|
+
exit.abuse.is_tor_exit_node; // true
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Pure ESM with no dependencies, so it runs wherever fetch does: Node, Deno, Bun,
|
|
52
|
+
Cloudflare Workers, and any browser off a CDN.
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<script type="module">
|
|
56
|
+
import { open } from "https://cdn.jsdelivr.net/npm/plevinjs";
|
|
57
|
+
|
|
58
|
+
const db = await open("https://plevin.tn3w.dev/db/plevin.plv");
|
|
59
|
+
document.title = db.lookup("8.8.8.8").place.country.flag;
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`https://esm.sh/plevinjs` serves the same thing. Every database is rehosted with open
|
|
64
|
+
CORS at [plevin.tn3w.dev/db](https://plevin.tn3w.dev/db/), because GitHub release
|
|
65
|
+
downloads send no CORS header.
|
|
66
|
+
|
|
67
|
+
## Where the file comes from
|
|
68
|
+
|
|
69
|
+
| where it runs | how to open it |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| browser, worker | `await open(url)`, or `await open(response)` |
|
|
72
|
+
| Node, Deno, Bun | `import { openFile } from "plevinjs/node"`, then `await openFile(path)` |
|
|
73
|
+
| bytes you hold | `new Plevin(bytes)`, taking a `Uint8Array` |
|
|
74
|
+
|
|
75
|
+
`openFile()` reads `PLEVIN_DB` where no path is given. Nothing is downloaded for you
|
|
76
|
+
and nothing is cached for you: hand the same `Plevin` to every lookup and the file is
|
|
77
|
+
read once.
|
|
78
|
+
|
|
79
|
+
| file | size | carries |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `plevin.plv` | 16.9 MB | every field |
|
|
82
|
+
| `plevin.metro-place.plv` | 6.3 MB | city, region, postal, coordinates, metro |
|
|
83
|
+
| `plevin.abuse-network.plv` | 10.3 MB | ASN, operator, routing, abuse |
|
|
84
|
+
| `plevin.place-country-code.plv` | 423 KB | the country code |
|
|
85
|
+
|
|
86
|
+
## Every field
|
|
87
|
+
|
|
88
|
+
<picture>
|
|
89
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tn3w/plevin/master/.github/fields-dark.png">
|
|
90
|
+
<img src="https://raw.githubusercontent.com/tn3w/plevin/master/.github/fields-light.png" width="840" alt="address to place, network and abuse">
|
|
91
|
+
</picture>
|
|
92
|
+
|
|
93
|
+
`found.place` is where the address is, `found.network` who announces it, `found.abuse`
|
|
94
|
+
what has been seen from it. Any of the three is `null` where the build carries none of
|
|
95
|
+
it, and every leaf is `null` rather than `""` or `0` where a source says nothing. The
|
|
96
|
+
shapes and the field names are the ones the
|
|
97
|
+
[Python package](https://github.com/tn3w/plevin/blob/master/python/README.md#every-field)
|
|
98
|
+
answers with, to the letter.
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
{
|
|
102
|
+
lat: -27.4675, lon: 153.0281, accuracy: 200, confidence: 36,
|
|
103
|
+
granularity: 'city',
|
|
104
|
+
city: {
|
|
105
|
+
id: 2174003, name: 'Brisbane', ascii: 'Brisbane', country: 'AU',
|
|
106
|
+
population: 2780063, elevation: 27, postal: '4000', postal_partial: null,
|
|
107
|
+
timezone: 'Australia/Brisbane', type: 'regional capital', capital: 'region',
|
|
108
|
+
region: { id: 2152274, code: '04', iso: 'AU-QLD', name: 'Queensland',
|
|
109
|
+
type: 'State' },
|
|
110
|
+
district: { id: 7839562, code: '31000', name: 'Brisbane' },
|
|
111
|
+
metro: null,
|
|
112
|
+
},
|
|
113
|
+
country: {
|
|
114
|
+
code: 'AU', name: 'Australia', official: null, common: null, iso3: 'AUS',
|
|
115
|
+
numeric: '036', flag: '🇦🇺', european_union: false, driving_side: 'left',
|
|
116
|
+
},
|
|
117
|
+
time: {
|
|
118
|
+
timezone: 'Australia/Brisbane', abbreviation: 'AEST',
|
|
119
|
+
local: '2026-08-13T19:20:00+10:00', utc_offset: '+10:00', is_dst: false,
|
|
120
|
+
dst_start: null, dst_end: null,
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`country` and `time` are derived, not stored: `country` out of an ISO 3166 table in the
|
|
126
|
+
package, `time` out of the runtime's own `Intl` zone data, so neither needs an install
|
|
127
|
+
and neither is a network call. Where the host's zone data is older or newer than the
|
|
128
|
+
one the Python package reads, a daylight boundary may move by a transition.
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
{
|
|
132
|
+
asn: 13335, handle: 'CLOUDFLARENET', prefix: 24, cidr: '1.1.1.0/24',
|
|
133
|
+
start: '1.1.1.0', end: '1.1.1.255', rpki: 'valid', roas: 1,
|
|
134
|
+
operator: {
|
|
135
|
+
company: 'Cloudflare, Inc.', brand: 'Cloudflare', domain: 'cloudflare.com',
|
|
136
|
+
website: 'https://www.cloudflare.com', category: 'content', tier: 2,
|
|
137
|
+
peering: 356, scope: 'Global', rir: 'arin', since: 2010,
|
|
138
|
+
street: '101 Townsend St', state: 'CA', postal: '94107-1934', country: 'US',
|
|
139
|
+
abuse_email: 'abuse@cloudflare.com', city: { name: 'San Francisco', ... },
|
|
140
|
+
},
|
|
141
|
+
carrier: { user_type: 'hosting', user_count: 19, mcc: null, mnc: null,
|
|
142
|
+
is_mobile: false },
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`cidr` is the announcement the address falls in, masked out of the address itself.
|
|
147
|
+
`rpki` is `valid`, `invalid` or `unknown` and `roas` how many ROAs agree. `brand` drops
|
|
148
|
+
the legal form and the words every network carries, so `GOOGLE` and `Google LLC` both
|
|
149
|
+
read `Google`.
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
db.lookup("185.220.101.1").abuse;
|
|
153
|
+
{
|
|
154
|
+
name: 'Tor', service: 'tor_exit_node', evidence: 'measured', risk: 0.97,
|
|
155
|
+
network_risk: null, last_seen_days: 1, is_anycast: false, is_satellite: false,
|
|
156
|
+
is_hosting_provider: true, is_proxy: false, is_public_proxy: false,
|
|
157
|
+
is_residential_proxy: false, is_anonymous_vpn: false, is_tor_exit_node: true,
|
|
158
|
+
is_private_relay: false, is_anonymous: true,
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`risk` is 0 to 1 for the address, `network_risk` the same for the whole ASN, `null`
|
|
163
|
+
where nothing has ever been seen — which is not a risk of zero.
|
|
164
|
+
|
|
165
|
+
## What an address says on its own
|
|
166
|
+
|
|
167
|
+
Answered without the database, so they hold for every address:
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
const found = db.lookup("2606:4700::1111");
|
|
171
|
+
found.number; // 50543257672059871404715951523469725969n
|
|
172
|
+
found.compressed // '2606:4700::1111'
|
|
173
|
+
found.expanded; // '2606:4700:0000:0000:0000:0000:0000:1111'
|
|
174
|
+
found.arpa; // '1.1.1.1.0.0.….0.7.4.6.0.6.2.ip6.arpa'
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`number` is a `bigint` for v6 and a `number` for v4, so `JSON.stringify` needs a
|
|
178
|
+
replacer where you hand a v6 result on. Then `is_global` and `is_bogon`, `is_private`,
|
|
179
|
+
`is_loopback`, `is_multicast`, `is_reserved`, `is_link_local`, `is_unique_local`,
|
|
180
|
+
`is_documentation`, `is_shared` (100.64/10) and `is_benchmark` (198.18/15), bisected
|
|
181
|
+
out of the IANA special-purpose registries.
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
db.lookup("::ffff:8.8.8.8").tunnel; // 'ipv4-mapped'
|
|
185
|
+
db.lookup("::ffff:8.8.8.8").embedded_ipv4; // '8.8.8.8'
|
|
186
|
+
db.lookup("2002:808:808::1").is_6to4; // true
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`tunnel` is `ipv4-mapped`, `6to4`, `teredo`, `nat64` or `null`.
|
|
190
|
+
|
|
191
|
+
## In a browser
|
|
192
|
+
|
|
193
|
+
No build step and no install: the package is plain ESM with no dependencies, so any npm
|
|
194
|
+
CDN serves it as it is.
|
|
195
|
+
|
|
196
|
+
```html
|
|
197
|
+
<script type="module">
|
|
198
|
+
import { open } from "https://cdn.jsdelivr.net/npm/plevinjs";
|
|
199
|
+
|
|
200
|
+
const db = await open("https://plevin.tn3w.dev/db/plevin.plv");
|
|
201
|
+
document.title = db.lookup("1.1.1.1").place.country.flag;
|
|
202
|
+
</script>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| | |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| `https://cdn.jsdelivr.net/npm/plevinjs` | the published files, as they are |
|
|
208
|
+
| `https://esm.sh/plevinjs` | the same, imports rewritten |
|
|
209
|
+
| `https://unpkg.com/plevinjs` | the same as jsDelivr |
|
|
210
|
+
| `https://plevin.tn3w.dev/plevin/` | the reader beside the databases |
|
|
211
|
+
|
|
212
|
+
Every module is fetched as published, `./reader.js` and all, so the browser loads the
|
|
213
|
+
ten it needs and nothing more. Pin a version for anything that ships:
|
|
214
|
+
`cdn.jsdelivr.net/npm/plevinjs@0.1.0`. `plevinjs/node` is the only entry that touches
|
|
215
|
+
Node, so a CDN import never reaches for `node:fs`.
|
|
216
|
+
|
|
217
|
+
18 MB crosses the wire once, so keep it out of the critical path and out of the next
|
|
218
|
+
visit's way:
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
const store = await caches.open("plevin");
|
|
222
|
+
const url = "https://plevin.tn3w.dev/db/plevin.plv";
|
|
223
|
+
if (!(await store.match(url))) await store.add(url);
|
|
224
|
+
|
|
225
|
+
const held = await store.match(url);
|
|
226
|
+
const db = new Plevin(new Uint8Array(await held.arrayBuffer()));
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
`plevin.place-country-code.plv` is 423 KB where the country code is all a page needs.
|
|
230
|
+
[The lookup page](https://plevin.tn3w.dev/) is the whole idea in one file of
|
|
231
|
+
plain JavaScript: it reads the database in the tab and calls out only for the visitor's
|
|
232
|
+
own address and for hostnames.
|
|
233
|
+
|
|
234
|
+
## Speed
|
|
235
|
+
|
|
236
|
+
Measured on the full file, Node 26, one core:
|
|
237
|
+
|
|
238
|
+
| | |
|
|
239
|
+
| --- | --- |
|
|
240
|
+
| open | 14 ms, the header only |
|
|
241
|
+
| first answer | 44 ms, the blocks it lands in |
|
|
242
|
+
| repeats | 4,600,000/s |
|
|
243
|
+
| uniformly random v4 | 13,000/s cold, 200,000/s over the same log again |
|
|
244
|
+
|
|
245
|
+
Blocks decode on reach and stay decoded, so a real log lands between the two. Memory is
|
|
246
|
+
the file plus whatever it decoded, around 120 MB of heap with the whole world touched.
|
|
247
|
+
|
|
248
|
+
## Zstandard
|
|
249
|
+
|
|
250
|
+
The file is Zstandard with trained dictionaries, which no runtime decompresses on its
|
|
251
|
+
own — `DecompressionStream` has no zstd and Node's `zlib` takes no dictionary. So the
|
|
252
|
+
package carries one, condensed from [fzstd](https://github.com/101arrowz/fzstd) (MIT)
|
|
253
|
+
with the dictionary support it leaves out, and verified block for block against
|
|
254
|
+
libzstd over the whole database.
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
import { decompress, loadDictionary } from "plevin/zstd";
|
|
258
|
+
|
|
259
|
+
decompress(frame); // one frame
|
|
260
|
+
decompress(frame, loadDictionary(trained)); // with a trained dictionary
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Development
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
cd js
|
|
267
|
+
npm ci
|
|
268
|
+
npm test # node --test, no database needed for most of it
|
|
269
|
+
npm run lint # biome
|
|
270
|
+
npm run typecheck # tsc, strict
|
|
271
|
+
npm run build # dist/, ESM and .d.ts
|
|
272
|
+
|
|
273
|
+
node test/compare.ts ../plevin.plv sample.json # field for field against Python
|
|
274
|
+
node test/blocks.ts ../plevin.plv 100000 # every block against libzstd
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
Apache 2.0, see [LICENSE](https://github.com/tn3w/plevin/blob/master/LICENSE). The
|
|
280
|
+
database carries the licenses of the sources it was built from, listed in
|
|
281
|
+
[`builder/README.md`](https://github.com/tn3w/plevin/blob/master/builder/README.md#sources).
|
|
282
|
+
|
|
283
|
+
<!-- brand: Noto Sans 800, wordmark bar #1868f2 place, #6f42c1 network, #2ea043 abuse; #7d8894 address, ink #0b1220 light, #f0f6fc dark -->
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** What an address is before any database is opened. */
|
|
2
|
+
export type Value = string | number | bigint | Uint8Array;
|
|
3
|
+
export declare const PRIVATE = 1;
|
|
4
|
+
export declare const LOOPBACK = 2;
|
|
5
|
+
export declare const MULTICAST = 4;
|
|
6
|
+
export declare const RESERVED = 8;
|
|
7
|
+
export declare const LINK_LOCAL = 16;
|
|
8
|
+
export declare const UNIQUE_LOCAL = 32;
|
|
9
|
+
export declare const DOCUMENTATION = 64;
|
|
10
|
+
export declare const SHARED = 128;
|
|
11
|
+
export declare const BENCHMARK = 256;
|
|
12
|
+
export declare const MAPPED = "ipv4-mapped";
|
|
13
|
+
export declare const SIXTOFOUR = "6to4";
|
|
14
|
+
export declare const TEREDO = "teredo";
|
|
15
|
+
export declare const NAT64 = "nat64";
|
|
16
|
+
/** An address however it is written; an integer reads as v6 only above 0xffffffff. */
|
|
17
|
+
export declare const parse: (value: Value) => [number | bigint, boolean];
|
|
18
|
+
/** How the address reads short and in full, and the name a resolver asks by. */
|
|
19
|
+
export declare const spelled: (value: number | bigint, wide: boolean) => [string, string, string];
|
|
20
|
+
/** An address as text: v4 from its octets, v6 through the shortening rules. */
|
|
21
|
+
export declare const written: (value: number | bigint, wide: boolean) => string;
|
|
22
|
+
/** What an address is where it is not the internet, bisected out of the table. */
|
|
23
|
+
export declare const purpose: (value: number | bigint, wide: boolean) => number;
|
|
24
|
+
/** The v4 address a v6 one carries, and the tunnel that puts it there. */
|
|
25
|
+
export declare const tunnel: (value: number | bigint, wide: boolean) => [string | null, string | null];
|
|
26
|
+
/** The announcement the address falls in, masked out of the address itself. */
|
|
27
|
+
export declare const span: (value: number | bigint, wide: boolean, prefix: number) => [string, string, string];
|
|
28
|
+
//# sourceMappingURL=address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../src/address.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1D,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,eAAO,MAAM,MAAM,MAAM,CAAC;AAC1B,eAAO,MAAM,SAAS,MAAM,CAAC;AAE7B,eAAO,MAAM,MAAM,gBAAgB,CAAC;AACpC,eAAO,MAAM,SAAS,SAAS,CAAC;AAChC,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,eAAO,MAAM,KAAK,UAAU,CAAC;AAuF7B,sFAAsF;AACtF,eAAO,MAAM,KAAK,UAAW,KAAK,KAAG,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CA6B7D,CAAC;AA2BF,gFAAgF;AAChF,eAAO,MAAM,OAAO,UACX,MAAM,GAAG,MAAM,QAChB,OAAO,KACZ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CA4BzB,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,OAAO,UAAW,MAAM,GAAG,MAAM,QAAQ,OAAO,KAAG,MACvC,CAAC;AAc1B,kFAAkF;AAClF,eAAO,MAAM,OAAO,UAAW,MAAM,GAAG,MAAM,QAAQ,OAAO,KAAG,MAa/D,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,MAAM,UACV,MAAM,GAAG,MAAM,QAChB,OAAO,KACZ,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,CAW/B,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,IAAI,UACR,MAAM,GAAG,MAAM,QAChB,OAAO,UACL,MAAM,KACb,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAOzB,CAAC"}
|
package/dist/address.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/** What an address is before any database is opened. */
|
|
2
|
+
export const PRIVATE = 1;
|
|
3
|
+
export const LOOPBACK = 2;
|
|
4
|
+
export const MULTICAST = 4;
|
|
5
|
+
export const RESERVED = 8;
|
|
6
|
+
export const LINK_LOCAL = 16;
|
|
7
|
+
export const UNIQUE_LOCAL = 32;
|
|
8
|
+
export const DOCUMENTATION = 64;
|
|
9
|
+
export const SHARED = 128;
|
|
10
|
+
export const BENCHMARK = 256;
|
|
11
|
+
export const MAPPED = "ipv4-mapped";
|
|
12
|
+
export const SIXTOFOUR = "6to4";
|
|
13
|
+
export const TEREDO = "teredo";
|
|
14
|
+
export const NAT64 = "nat64";
|
|
15
|
+
const V4_MAX = 0xffffffff;
|
|
16
|
+
const V6_MAX = (1n << 128n) - 1n;
|
|
17
|
+
const SPECIAL_V4 = [
|
|
18
|
+
["0.0.0.0/8", RESERVED],
|
|
19
|
+
["10.0.0.0/8", PRIVATE],
|
|
20
|
+
["100.64.0.0/10", PRIVATE | SHARED],
|
|
21
|
+
["127.0.0.0/8", PRIVATE | LOOPBACK],
|
|
22
|
+
["169.254.0.0/16", PRIVATE | LINK_LOCAL],
|
|
23
|
+
["172.16.0.0/12", PRIVATE],
|
|
24
|
+
["192.0.0.0/24", RESERVED],
|
|
25
|
+
["192.0.2.0/24", RESERVED | DOCUMENTATION],
|
|
26
|
+
["192.88.99.0/24", RESERVED],
|
|
27
|
+
["192.168.0.0/16", PRIVATE],
|
|
28
|
+
["198.18.0.0/15", RESERVED | BENCHMARK],
|
|
29
|
+
["198.51.100.0/24", RESERVED | DOCUMENTATION],
|
|
30
|
+
["203.0.113.0/24", RESERVED | DOCUMENTATION],
|
|
31
|
+
["224.0.0.0/4", MULTICAST],
|
|
32
|
+
["240.0.0.0/4", RESERVED],
|
|
33
|
+
];
|
|
34
|
+
const SPECIAL_V6 = [
|
|
35
|
+
["::/128", RESERVED],
|
|
36
|
+
["::1/128", PRIVATE | LOOPBACK],
|
|
37
|
+
["::ffff:0:0/96", RESERVED],
|
|
38
|
+
["64:ff9b::/96", RESERVED],
|
|
39
|
+
["64:ff9b:1::/48", RESERVED],
|
|
40
|
+
["100::/64", RESERVED],
|
|
41
|
+
["2001::/23", RESERVED],
|
|
42
|
+
["2001:db8::/32", RESERVED | DOCUMENTATION],
|
|
43
|
+
["2002::/16", RESERVED],
|
|
44
|
+
["3fff::/20", RESERVED | DOCUMENTATION],
|
|
45
|
+
["fc00::/7", PRIVATE | UNIQUE_LOCAL],
|
|
46
|
+
["fe80::/10", PRIVATE | LINK_LOCAL],
|
|
47
|
+
["ff00::/8", MULTICAST],
|
|
48
|
+
];
|
|
49
|
+
const OCTET = /^(0|[1-9][0-9]{0,2})$/;
|
|
50
|
+
const GROUP = /^[0-9a-fA-F]{1,4}$/;
|
|
51
|
+
const parseV4 = (text) => {
|
|
52
|
+
const parts = text.split(".");
|
|
53
|
+
if (parts.length !== 4)
|
|
54
|
+
return null;
|
|
55
|
+
let value = 0;
|
|
56
|
+
for (const part of parts) {
|
|
57
|
+
if (!OCTET.test(part))
|
|
58
|
+
return null;
|
|
59
|
+
const octet = Number(part);
|
|
60
|
+
if (octet > 255)
|
|
61
|
+
return null;
|
|
62
|
+
value = value * 256 + octet;
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
};
|
|
66
|
+
const groups = (text, expected) => {
|
|
67
|
+
if (text === "")
|
|
68
|
+
return [];
|
|
69
|
+
const parts = text.split(":");
|
|
70
|
+
const held = [];
|
|
71
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
72
|
+
const part = parts[index];
|
|
73
|
+
if (index === parts.length - 1 && part.includes(".")) {
|
|
74
|
+
const embedded = parseV4(part);
|
|
75
|
+
if (embedded === null)
|
|
76
|
+
return null;
|
|
77
|
+
held.push(embedded >>> 16, embedded & 0xffff);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (!GROUP.test(part))
|
|
81
|
+
return null;
|
|
82
|
+
held.push(Number.parseInt(part, 16));
|
|
83
|
+
}
|
|
84
|
+
return held.length <= expected ? held : null;
|
|
85
|
+
};
|
|
86
|
+
const parseV6 = (text) => {
|
|
87
|
+
const sides = text.split("::");
|
|
88
|
+
if (sides.length > 2)
|
|
89
|
+
return null;
|
|
90
|
+
const head = groups(sides[0], 8);
|
|
91
|
+
const tail = sides.length === 2 ? groups(sides[1], 8) : [];
|
|
92
|
+
if (head === null || tail === null)
|
|
93
|
+
return null;
|
|
94
|
+
const held = head.length + tail.length;
|
|
95
|
+
if (sides.length === 1 ? held !== 8 : held > 7)
|
|
96
|
+
return null;
|
|
97
|
+
const all = [...head, ...Array(8 - held).fill(0), ...tail];
|
|
98
|
+
let value = 0n;
|
|
99
|
+
for (const group of all)
|
|
100
|
+
value = (value << 16n) | BigInt(group);
|
|
101
|
+
return value;
|
|
102
|
+
};
|
|
103
|
+
/** An address however it is written; an integer reads as v6 only above 0xffffffff. */
|
|
104
|
+
export const parse = (value) => {
|
|
105
|
+
if (typeof value === "string") {
|
|
106
|
+
if (value.includes(":")) {
|
|
107
|
+
const wide = parseV6(value);
|
|
108
|
+
if (wide === null)
|
|
109
|
+
throw new Error(`${value} is not an address`);
|
|
110
|
+
return [wide, true];
|
|
111
|
+
}
|
|
112
|
+
const narrow = parseV4(value);
|
|
113
|
+
if (narrow === null)
|
|
114
|
+
throw new Error(`${value} is not an address`);
|
|
115
|
+
return [narrow, false];
|
|
116
|
+
}
|
|
117
|
+
if (value instanceof Uint8Array) {
|
|
118
|
+
if (value.length === 4) {
|
|
119
|
+
return [
|
|
120
|
+
((value[0] << 24) >>> 0) + (value[1] << 16) + (value[2] << 8) + value[3],
|
|
121
|
+
false,
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
if (value.length !== 16)
|
|
125
|
+
throw new Error("packed addresses are 4 or 16 bytes");
|
|
126
|
+
let held = 0n;
|
|
127
|
+
for (const byte of value)
|
|
128
|
+
held = (held << 8n) | BigInt(byte);
|
|
129
|
+
return [held, true];
|
|
130
|
+
}
|
|
131
|
+
if (typeof value !== "bigint" && !Number.isInteger(value)) {
|
|
132
|
+
throw new Error(`${String(value)} is not an address`);
|
|
133
|
+
}
|
|
134
|
+
const number = typeof value === "bigint" ? value : BigInt(value);
|
|
135
|
+
if (number < 0n || number > V6_MAX)
|
|
136
|
+
throw new Error(`${value} is not an address`);
|
|
137
|
+
return number > BigInt(V4_MAX) ? [number, true] : [Number(number), false];
|
|
138
|
+
};
|
|
139
|
+
const hextets = (value) => Array.from({ length: 8 }, (_, index) => Number((value >> BigInt(112 - index * 16)) & 0xffffn));
|
|
140
|
+
const dotted = (value) => [24, 16, 8, 0].map((shift) => (value >>> shift) & 255).join(".");
|
|
141
|
+
const shortest = (parts, held) => {
|
|
142
|
+
let bestAt = -1;
|
|
143
|
+
let bestRun = 1;
|
|
144
|
+
let at = -1;
|
|
145
|
+
for (let index = 0; index <= held.length; index += 1) {
|
|
146
|
+
if (held[index] === 0 && at < 0)
|
|
147
|
+
at = index;
|
|
148
|
+
if ((held[index] !== 0 || index === held.length) && at >= 0) {
|
|
149
|
+
if (index - at > bestRun)
|
|
150
|
+
[bestAt, bestRun] = [at, index - at];
|
|
151
|
+
at = -1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (bestAt < 0)
|
|
155
|
+
return parts.join(":");
|
|
156
|
+
const head = parts.slice(0, bestAt).join(":");
|
|
157
|
+
const tail = parts.slice(bestAt + bestRun).join(":");
|
|
158
|
+
return `${head}::${tail}`;
|
|
159
|
+
};
|
|
160
|
+
/** How the address reads short and in full, and the name a resolver asks by. */
|
|
161
|
+
export const spelled = (value, wide) => {
|
|
162
|
+
if (!wide) {
|
|
163
|
+
const text = dotted(value);
|
|
164
|
+
const octets = text.split(".");
|
|
165
|
+
return [text, text, `${[...octets].reverse().join(".")}.in-addr.arpa`];
|
|
166
|
+
}
|
|
167
|
+
const held = hextets(value);
|
|
168
|
+
const nibbles = value.toString(16).padStart(32, "0");
|
|
169
|
+
const arpa = `${[...nibbles].reverse().join(".")}.ip6.arpa`;
|
|
170
|
+
const mapped = held.slice(0, 5).every((group) => group === 0) && held[5] === 0xffff;
|
|
171
|
+
if (mapped) {
|
|
172
|
+
const quad = dotted(Number(value & 0xffffffffn));
|
|
173
|
+
const parts = held.slice(0, 6).map((group) => group.toString(16));
|
|
174
|
+
const full = held.slice(0, 6).map((group) => group.toString(16).padStart(4, "0"));
|
|
175
|
+
return [
|
|
176
|
+
`${shortest(parts, held.slice(0, 6))}:${quad}`,
|
|
177
|
+
`${full.join(":")}:${quad}`,
|
|
178
|
+
arpa,
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
return [
|
|
182
|
+
shortest(held.map((group) => group.toString(16)), held),
|
|
183
|
+
held.map((group) => group.toString(16).padStart(4, "0")).join(":"),
|
|
184
|
+
arpa,
|
|
185
|
+
];
|
|
186
|
+
};
|
|
187
|
+
/** An address as text: v4 from its octets, v6 through the shortening rules. */
|
|
188
|
+
export const written = (value, wide) => spelled(value, wide)[0];
|
|
189
|
+
const table = (rows, wide) => rows
|
|
190
|
+
.map(([text, marks]) => {
|
|
191
|
+
const [network, bits] = text.split("/");
|
|
192
|
+
const first = BigInt(parse(network)[0]);
|
|
193
|
+
const spare = BigInt((wide ? 128 : 32) - Number(bits));
|
|
194
|
+
return [first, first + ((1n << spare) - 1n), marks];
|
|
195
|
+
})
|
|
196
|
+
.sort((left, right) => (left[0] < right[0] ? -1 : 1));
|
|
197
|
+
const SPECIAL = [table(SPECIAL_V4, false), table(SPECIAL_V6, true)];
|
|
198
|
+
/** What an address is where it is not the internet, bisected out of the table. */
|
|
199
|
+
export const purpose = (value, wide) => {
|
|
200
|
+
const rows = SPECIAL[wide ? 1 : 0];
|
|
201
|
+
const held = BigInt(value);
|
|
202
|
+
let low = 0;
|
|
203
|
+
let high = rows.length;
|
|
204
|
+
while (low < high) {
|
|
205
|
+
const middle = (low + high) >> 1;
|
|
206
|
+
if (rows[middle][0] <= held)
|
|
207
|
+
low = middle + 1;
|
|
208
|
+
else
|
|
209
|
+
high = middle;
|
|
210
|
+
}
|
|
211
|
+
const found = rows[low - 1];
|
|
212
|
+
if (found && held <= found[1])
|
|
213
|
+
return found[2];
|
|
214
|
+
return wide && held >> 125n !== 1n ? RESERVED : 0;
|
|
215
|
+
};
|
|
216
|
+
/** The v4 address a v6 one carries, and the tunnel that puts it there. */
|
|
217
|
+
export const tunnel = (value, wide) => {
|
|
218
|
+
if (!wide)
|
|
219
|
+
return [null, null];
|
|
220
|
+
const held = value;
|
|
221
|
+
const low = Number(held & 0xffffffffn);
|
|
222
|
+
if (held >> 32n === 0xffffn)
|
|
223
|
+
return [MAPPED, dotted(low)];
|
|
224
|
+
if (held >> 112n === 0x2002n) {
|
|
225
|
+
return [SIXTOFOUR, dotted(Number((held >> 80n) & 0xffffffffn))];
|
|
226
|
+
}
|
|
227
|
+
if (held >> 96n === 0x20010000n)
|
|
228
|
+
return [TEREDO, dotted(~low >>> 0)];
|
|
229
|
+
if (held >> 32n === 0x0064ff9bn << 64n)
|
|
230
|
+
return [NAT64, dotted(low)];
|
|
231
|
+
return [null, null];
|
|
232
|
+
};
|
|
233
|
+
/** The announcement the address falls in, masked out of the address itself. */
|
|
234
|
+
export const span = (value, wide, prefix) => {
|
|
235
|
+
const spare = BigInt((wide ? 128 : 32) - prefix);
|
|
236
|
+
const held = BigInt(value);
|
|
237
|
+
const first = (held >> spare) << spare;
|
|
238
|
+
const last = held | ((1n << spare) - 1n);
|
|
239
|
+
const start = written(wide ? first : Number(first), wide);
|
|
240
|
+
return [`${start}/${prefix}`, start, written(wide ? last : Number(last), wide)];
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../src/address.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"countries.d.ts","sourceRoot":"","sources":["../src/countries.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAEzF,eAAO,MAAM,SAAS,UA4PR,CAAC"}
|