parse-domain 3.0.4 → 6.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 +17 -20
- package/README.md +181 -112
- package/bin/update.js +12 -15
- package/{build-cjs/src → build}/config.d.ts +0 -0
- package/{build-esm/src → build}/config.js +0 -0
- package/build/config.js.map +1 -0
- package/{build-cjs/src → build}/from-url.d.ts +0 -0
- package/{build-esm/src → build}/from-url.js +1 -1
- package/build/from-url.js.map +1 -0
- package/build/main.d.ts +3 -0
- package/build/main.js +6 -0
- package/build/main.js.map +1 -0
- package/{build-cjs/src → build}/parse-domain.d.ts +9 -3
- package/{build-esm/src → build}/parse-domain.js +6 -6
- package/build/parse-domain.js.map +1 -0
- package/build/psl/build-tries.d.ts +4 -0
- package/{build-esm/src → build}/psl/build-tries.js +5 -20
- package/build/psl/build-tries.js.map +1 -0
- package/{build-cjs/src → build}/psl/fetch-psl.d.ts +0 -0
- package/{build-esm/src → build}/psl/fetch-psl.js +1 -1
- package/build/psl/fetch-psl.js.map +1 -0
- package/build/punycode.d.ts +1 -0
- package/build/punycode.js +4 -0
- package/build/punycode.js.map +1 -0
- package/{build-cjs/src → build}/sanitize.d.ts +28 -6
- package/build/sanitize.js +194 -0
- package/build/sanitize.js.map +1 -0
- package/{build-cjs/src → build}/scripts/update-psl-fixture.d.ts +0 -0
- package/build/scripts/update-psl-fixture.js +20 -0
- package/build/scripts/update-psl-fixture.js.map +1 -0
- package/{build-cjs/src → build}/scripts/update-tries.d.ts +0 -0
- package/{build-cjs/src → build}/scripts/update-tries.js +15 -23
- package/build/scripts/update-tries.js.map +1 -0
- package/build/serialized-tries.d.ts +3 -0
- package/build/serialized-tries.js +4 -0
- package/build/serialized-tries.js.map +1 -0
- package/{build-cjs/src → build}/smoke-test.d.ts +0 -0
- package/{build-esm/src → build}/smoke-test.js +6 -8
- package/build/smoke-test.js.map +1 -0
- package/{build-cjs/src → build}/trie/characters.d.ts +0 -0
- package/{build-esm/src → build}/trie/characters.js +0 -0
- package/build/trie/characters.js.map +1 -0
- package/build/trie/create-trie.d.ts +1 -0
- package/{build-esm/src → build}/trie/create-trie.js +1 -1
- package/build/trie/create-trie.js.map +1 -0
- package/build/trie/look-up.d.ts +3 -0
- package/{build-esm/src → build}/trie/look-up.js +1 -1
- package/build/trie/look-up.js.map +1 -0
- package/{build-cjs/src → build}/trie/nodes.d.ts +0 -0
- package/{build-esm/src → build}/trie/nodes.js +0 -0
- package/build/trie/nodes.js.map +1 -0
- package/{build-cjs/src → build}/trie/parse-trie.d.ts +1 -1
- package/{build-esm/src → build}/trie/parse-trie.js +2 -2
- package/build/trie/parse-trie.js.map +1 -0
- package/{build-cjs/src → build}/trie/serialize-trie.d.ts +1 -1
- package/{build-esm/src → build}/trie/serialize-trie.js +1 -1
- package/build/trie/serialize-trie.js.map +1 -0
- package/build/type-util.d.ts +3 -0
- package/build/type-util.js +2 -0
- package/{build-cjs/src → build}/type-util.js.map +1 -1
- package/{build-cjs/src → build}/update-tries.d.ts +0 -0
- package/{build-esm/src → build}/update-tries.js +3 -3
- package/build/update-tries.js.map +1 -0
- package/package.json +83 -85
- package/serialized-tries/icann.d.ts +3 -0
- package/serialized-tries/icann.js +1 -0
- package/serialized-tries/info.json +1 -0
- package/serialized-tries/private.d.ts +3 -0
- package/serialized-tries/private.js +1 -0
- package/build-cjs/serialized-tries/icann.json +0 -1
- package/build-cjs/serialized-tries/info.json +0 -1
- package/build-cjs/serialized-tries/private.json +0 -1
- package/build-cjs/src/config.js +0 -9
- package/build-cjs/src/config.js.map +0 -1
- package/build-cjs/src/from-url.js +0 -30
- package/build-cjs/src/from-url.js.map +0 -1
- package/build-cjs/src/main.d.ts +0 -3
- package/build-cjs/src/main.js +0 -11
- package/build-cjs/src/main.js.map +0 -1
- package/build-cjs/src/main.mjs +0 -11
- package/build-cjs/src/parse-domain.js +0 -95
- package/build-cjs/src/parse-domain.js.map +0 -1
- package/build-cjs/src/psl/build-tries.d.ts +0 -4
- package/build-cjs/src/psl/build-tries.js +0 -57
- package/build-cjs/src/psl/build-tries.js.map +0 -1
- package/build-cjs/src/psl/fetch-psl.js +0 -25
- package/build-cjs/src/psl/fetch-psl.js.map +0 -1
- package/build-cjs/src/sanitize.js +0 -131
- package/build-cjs/src/sanitize.js.map +0 -1
- package/build-cjs/src/scripts/update-psl-fixture.js +0 -28
- package/build-cjs/src/scripts/update-psl-fixture.js.map +0 -1
- package/build-cjs/src/scripts/update-tries.js.map +0 -1
- package/build-cjs/src/serialized-tries.d.ts +0 -3
- package/build-cjs/src/serialized-tries.js +0 -10
- package/build-cjs/src/serialized-tries.js.map +0 -1
- package/build-cjs/src/smoke-test.js +0 -61
- package/build-cjs/src/smoke-test.js.map +0 -1
- package/build-cjs/src/trie/characters.js +0 -10
- package/build-cjs/src/trie/characters.js.map +0 -1
- package/build-cjs/src/trie/create-trie.d.ts +0 -1
- package/build-cjs/src/trie/create-trie.js +0 -14
- package/build-cjs/src/trie/create-trie.js.map +0 -1
- package/build-cjs/src/trie/look-up.d.ts +0 -2
- package/build-cjs/src/trie/look-up.js +0 -34
- package/build-cjs/src/trie/look-up.js.map +0 -1
- package/build-cjs/src/trie/nodes.js +0 -24
- package/build-cjs/src/trie/nodes.js.map +0 -1
- package/build-cjs/src/trie/parse-trie.js +0 -56
- package/build-cjs/src/trie/parse-trie.js.map +0 -1
- package/build-cjs/src/trie/serialize-trie.js +0 -29
- package/build-cjs/src/trie/serialize-trie.js.map +0 -1
- package/build-cjs/src/type-util.d.ts +0 -3
- package/build-cjs/src/type-util.js +0 -3
- package/build-cjs/src/update-tries.js +0 -25
- package/build-cjs/src/update-tries.js.map +0 -1
- package/build-esm/serialized-tries/icann.json +0 -1
- package/build-esm/serialized-tries/info.json +0 -1
- package/build-esm/serialized-tries/private.json +0 -1
- package/build-esm/src/config.d.ts +0 -6
- package/build-esm/src/config.js.map +0 -1
- package/build-esm/src/from-url.d.ts +0 -2
- package/build-esm/src/from-url.js.map +0 -1
- package/build-esm/src/main.d.ts +0 -3
- package/build-esm/src/main.js +0 -4
- package/build-esm/src/main.js.map +0 -1
- package/build-esm/src/parse-domain.d.ts +0 -79
- package/build-esm/src/parse-domain.js.map +0 -1
- package/build-esm/src/psl/build-tries.d.ts +0 -4
- package/build-esm/src/psl/build-tries.js.map +0 -1
- package/build-esm/src/psl/fetch-psl.d.ts +0 -1
- package/build-esm/src/psl/fetch-psl.js.map +0 -1
- package/build-esm/src/sanitize.d.ts +0 -36
- package/build-esm/src/sanitize.js +0 -126
- package/build-esm/src/sanitize.js.map +0 -1
- package/build-esm/src/serialized-tries.d.ts +0 -3
- package/build-esm/src/serialized-tries.js +0 -4
- package/build-esm/src/serialized-tries.js.map +0 -1
- package/build-esm/src/smoke-test.d.ts +0 -1
- package/build-esm/src/smoke-test.js.map +0 -1
- package/build-esm/src/trie/characters.d.ts +0 -6
- package/build-esm/src/trie/characters.js.map +0 -1
- package/build-esm/src/trie/create-trie.d.ts +0 -1
- package/build-esm/src/trie/create-trie.js.map +0 -1
- package/build-esm/src/trie/look-up.d.ts +0 -2
- package/build-esm/src/trie/look-up.js.map +0 -1
- package/build-esm/src/trie/nodes.d.ts +0 -15
- package/build-esm/src/trie/nodes.js.map +0 -1
- package/build-esm/src/trie/parse-trie.d.ts +0 -1
- package/build-esm/src/trie/parse-trie.js.map +0 -1
- package/build-esm/src/trie/serialize-trie.d.ts +0 -2
- package/build-esm/src/trie/serialize-trie.js.map +0 -1
- package/build-esm/src/type-util.d.ts +0 -3
- package/build-esm/src/type-util.js +0 -1
- package/build-esm/src/type-util.js.map +0 -1
- package/build-esm/src/update-tries.d.ts +0 -4
- package/build-esm/src/update-tries.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
distribute this software, either in source code form or as a compiled
|
|
5
|
-
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
-
means.
|
|
3
|
+
Copyright (c) 2021 Peerigon GmbH
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
of this software
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
software under copyright law.
|
|
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:
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
-
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
-
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
-
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
23
14
|
|
|
24
|
-
|
|
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
CHANGED
|
@@ -7,36 +7,32 @@
|
|
|
7
7
|
[](https://www.npmjs.com/package/parse-domain)<br>
|
|
8
8
|
[](https://bundlephobia.com/result?p=parse-domain)
|
|
9
9
|
[](https://bundlephobia.com/result?p=parse-domain)<br>
|
|
10
|
-
[](https://snyk.io/test/github/peerigon/parse-domain)<br>
|
|
12
|
-

|
|
13
|
-
[](https://coveralls.io/github/peerigon/parse-domain?branch=master)
|
|
14
|
-
[](https://unlicense.org/)
|
|
10
|
+
[](./LICENSE)
|
|
15
11
|
|
|
16
12
|
Since domain name registrars organize their namespaces in different ways, it's not straight-forward to split a hostname into subdomains, the domain and top-level domains. In order to do that **parse-domain** uses a [large list of known top-level domains](https://publicsuffix.org/list/public_suffix_list.dat) from [publicsuffix.org](https://publicsuffix.org/):
|
|
17
13
|
|
|
18
14
|
```javascript
|
|
19
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
15
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
20
16
|
|
|
21
17
|
const parseResult = parseDomain(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
// This should be a string with basic latin letters only.
|
|
19
|
+
// More information below.
|
|
20
|
+
"www.some.example.co.uk"
|
|
25
21
|
);
|
|
26
22
|
|
|
27
23
|
// Check if the domain is listed in the public suffix list
|
|
28
24
|
if (parseResult.type === ParseResultType.Listed) {
|
|
29
|
-
|
|
25
|
+
const { subDomains, domain, topLevelDomains } = parseResult;
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
console.log(subDomains); // ["www", "some"]
|
|
28
|
+
console.log(domain); // "example"
|
|
29
|
+
console.log(topLevelDomains); // ["co", "uk"]
|
|
34
30
|
} else {
|
|
35
|
-
|
|
31
|
+
// Read more about other parseResult types below...
|
|
36
32
|
}
|
|
37
33
|
```
|
|
38
34
|
|
|
39
|
-
This package has been designed for modern Node and browser environments, supporting both CommonJS and ECMAScript modules. It assumes an ES2015 environment with [`Symbol()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)
|
|
35
|
+
This package has been designed for modern Node and browser environments, supporting both CommonJS and ECMAScript modules. It assumes an ES2015 environment with [`Symbol()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), [`URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL) and [`TextDecoder()](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) globally available. You need to transpile it down to ES5 (e.g. by using [Babel](https://babeljs.io/)) if you need to support older environments.
|
|
40
36
|
|
|
41
37
|
The list of top-level domains is stored in a [trie](https://en.wikipedia.org/wiki/Trie) data structure and serialization format to ensure the fastest lookup and the smallest possible library size. The library is side-effect free (this is important for proper [tree-shaking](https://webpack.js.org/guides/tree-shaking/)).
|
|
42
38
|
|
|
@@ -67,10 +63,10 @@ npm install parse-domain
|
|
|
67
63
|
There is the utility function [`fromUrl`](#api-js-fromUrl) which tries to extract the hostname from a (partial) URL and puny-encodes it:
|
|
68
64
|
|
|
69
65
|
```javascript
|
|
70
|
-
import {parseDomain, fromUrl} from "parse-domain";
|
|
66
|
+
import { parseDomain, fromUrl } from "parse-domain";
|
|
71
67
|
|
|
72
|
-
const {subDomains, domain, topLevelDomains} = parseDomain(
|
|
73
|
-
|
|
68
|
+
const { subDomains, domain, topLevelDomains } = parseDomain(
|
|
69
|
+
fromUrl("https://www.münchen.de?query")
|
|
74
70
|
);
|
|
75
71
|
|
|
76
72
|
console.log(subDomains); // ["www"]
|
|
@@ -78,7 +74,7 @@ console.log(domain); // "xn--mnchen-3ya"
|
|
|
78
74
|
console.log(topLevelDomains); // ["de"]
|
|
79
75
|
|
|
80
76
|
// You can use the 'punycode' NPM package to decode the domain again
|
|
81
|
-
import {toUnicode} from "punycode";
|
|
77
|
+
import { toUnicode } from "punycode";
|
|
82
78
|
|
|
83
79
|
console.log(toUnicode(domain)); // "münchen"
|
|
84
80
|
```
|
|
@@ -100,10 +96,10 @@ When parsing a hostname there are 5 possible results:
|
|
|
100
96
|
|
|
101
97
|
### 👉 Invalid domains
|
|
102
98
|
|
|
103
|
-
The given input is first validated against [RFC
|
|
99
|
+
The given input is first validated against [RFC 3696](https://datatracker.ietf.org/doc/html/rfc3696#section-2) (the domain labels are limited to basic latin letters, numbers and hyphens). If the validation fails, `parseResult.type` will be `ParseResultType.Invalid`:
|
|
104
100
|
|
|
105
101
|
```javascript
|
|
106
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
102
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
107
103
|
|
|
108
104
|
const parseResult = parseDomain("münchen.de");
|
|
109
105
|
|
|
@@ -112,12 +108,26 @@ console.log(parseResult.type === ParseResultType.Invalid); // true
|
|
|
112
108
|
|
|
113
109
|
Check out the [API](#api-ts-ValidationError) if you need more information about the validation error.
|
|
114
110
|
|
|
111
|
+
If you don't want the characters to be validated (e.g. because you need to allow underscores in hostnames), there's also a more relaxed validation mode (according to [RFC 2181](https://www.rfc-editor.org/rfc/rfc2181#section-11)).
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import { parseDomain, ParseResultType, Validation } from "parse-domain";
|
|
115
|
+
|
|
116
|
+
const parseResult = parseDomain("_jabber._tcp.gmail.com", {
|
|
117
|
+
validation: Validation.Lax,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(parseResult.type === ParseResultType.Listed); // true
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
See also [#134](https://github.com/peerigon/parse-domain/issues/134) for the discussion.
|
|
124
|
+
|
|
115
125
|
### 👉 IP addresses
|
|
116
126
|
|
|
117
127
|
If the given input is an IP address, `parseResult.type` will be `ParseResultType.Ip`:
|
|
118
128
|
|
|
119
129
|
```javascript
|
|
120
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
130
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
121
131
|
|
|
122
132
|
const parseResult = parseDomain("192.168.2.1");
|
|
123
133
|
|
|
@@ -140,7 +150,7 @@ There are 5 top-level domains that are not listed in the public suffix list but
|
|
|
140
150
|
In these cases, `parseResult.type` will be `ParseResultType.Reserved`:
|
|
141
151
|
|
|
142
152
|
```javascript
|
|
143
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
153
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
144
154
|
|
|
145
155
|
const parseResult = parseDomain("pecorino.local");
|
|
146
156
|
|
|
@@ -153,7 +163,7 @@ console.log(parseResult.labels); // ["pecorino", "local"]
|
|
|
153
163
|
If the given hostname is valid, but not listed in the downloaded public suffix list, `parseResult.type` will be `ParseResultType.NotListed`:
|
|
154
164
|
|
|
155
165
|
```javascript
|
|
156
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
166
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
157
167
|
|
|
158
168
|
const parseResult = parseDomain("this.is.not-listed");
|
|
159
169
|
|
|
@@ -179,7 +189,7 @@ Some examples for public suffixes:
|
|
|
179
189
|
If the hostname is listed in the public suffix list, the `parseResult.type` will be `ParseResultType.Listed`:
|
|
180
190
|
|
|
181
191
|
```javascript
|
|
182
|
-
import {parseDomain, ParseResultType} from "parse-domain";
|
|
192
|
+
import { parseDomain, ParseResultType } from "parse-domain";
|
|
183
193
|
|
|
184
194
|
const parseResult = parseDomain("example.co.uk");
|
|
185
195
|
|
|
@@ -190,7 +200,7 @@ console.log(parseResult.labels); // ["example", "co", "uk"]
|
|
|
190
200
|
Now `parseResult` will also provide a `subDomains`, `domain` and `topLevelDomains` property:
|
|
191
201
|
|
|
192
202
|
```javascript
|
|
193
|
-
const {subDomains, domain, topLevelDomains} = parseResult;
|
|
203
|
+
const { subDomains, domain, topLevelDomains } = parseResult;
|
|
194
204
|
|
|
195
205
|
console.log(subDomains); // []
|
|
196
206
|
console.log(domain); // "example"
|
|
@@ -203,21 +213,21 @@ We recommend switching over the `parseResult.type`:
|
|
|
203
213
|
|
|
204
214
|
```javascript
|
|
205
215
|
switch (parseResult.type) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
216
|
+
case ParseResultType.Listed: {
|
|
217
|
+
const { hostname, topLevelDomains } = parseResult;
|
|
218
|
+
|
|
219
|
+
console.log(`${hostname} belongs to ${topLevelDomains.join(".")}`);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case ParseResultType.Reserved:
|
|
223
|
+
case ParseResultType.NotListed: {
|
|
224
|
+
const { hostname } = parseResult;
|
|
225
|
+
|
|
226
|
+
console.log(`${hostname} is a reserved or unknown domain`);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
default:
|
|
230
|
+
throw new Error(`${hostname} is an ip address or invalid domain`);
|
|
221
231
|
}
|
|
222
232
|
```
|
|
223
233
|
|
|
@@ -226,8 +236,8 @@ switch (parseResult.type) {
|
|
|
226
236
|
What's surprising to a lot of people is that the definition of public suffix means that regular user domains can become effective top-level domains:
|
|
227
237
|
|
|
228
238
|
```javascript
|
|
229
|
-
const {subDomains, domain, topLevelDomains} = parseDomain(
|
|
230
|
-
|
|
239
|
+
const { subDomains, domain, topLevelDomains } = parseDomain(
|
|
240
|
+
"parse-domain.github.io"
|
|
231
241
|
);
|
|
232
242
|
|
|
233
243
|
console.log(subDomains); // []
|
|
@@ -241,7 +251,7 @@ If you want to deviate from the browser's understanding of a top-level domain an
|
|
|
241
251
|
|
|
242
252
|
```javascript
|
|
243
253
|
const parseResult = parseDomain("parse-domain.github.io");
|
|
244
|
-
const {subDomains, domain, topLevelDomains} = parseResult.icann;
|
|
254
|
+
const { subDomains, domain, topLevelDomains } = parseResult.icann;
|
|
245
255
|
|
|
246
256
|
console.log(subDomains); // ["parse-domain"]
|
|
247
257
|
console.log(domain); // "github"
|
|
@@ -251,7 +261,7 @@ console.log(topLevelDomains); // ["io"]
|
|
|
251
261
|
### ⚠️ `domain` can also be `undefined`
|
|
252
262
|
|
|
253
263
|
```javascript
|
|
254
|
-
const {subDomains, domain, topLevelDomains} = parseDomain("co.uk");
|
|
264
|
+
const { subDomains, domain, topLevelDomains } = parseDomain("co.uk");
|
|
255
265
|
|
|
256
266
|
console.log(subDomains); // []
|
|
257
267
|
console.log(domain); // undefined
|
|
@@ -263,7 +273,7 @@ console.log(topLevelDomains); // ["co", "uk"]
|
|
|
263
273
|
The empty string `""` represents the [DNS root](https://en.wikipedia.org/wiki/DNS_root_zone) and is considered to be valid. `parseResult.type` will be `ParseResultType.Reserved` in that case:
|
|
264
274
|
|
|
265
275
|
```javascript
|
|
266
|
-
const {type, subDomains, domain, topLevelDomains} = parseDomain("");
|
|
276
|
+
const { type, subDomains, domain, topLevelDomains } = parseDomain("");
|
|
267
277
|
|
|
268
278
|
console.log(type === ParseResultType.Reserved); // true
|
|
269
279
|
console.log(subDomains); // []
|
|
@@ -277,17 +287,27 @@ console.log(topLevelDomains); // []
|
|
|
277
287
|
🧬 = TypeScript export
|
|
278
288
|
|
|
279
289
|
<h3 id="api-js-parseDomain">
|
|
280
|
-
🧩 <code>export parseDomain(hostname: string | typeof <a href="#api-js-NO_HOSTNAME">NO_HOSTNAME</a>): <a href="#api-ts-ParseResult">ParseResult</a></code>
|
|
290
|
+
🧩 <code>export parseDomain(hostname: string | typeof <a href="#api-js-NO_HOSTNAME">NO_HOSTNAME</a>, options?: <a href="#api-ts-ParseDomainOptions">ParseDomainOptions</a>): <a href="#api-ts-ParseResult">ParseResult</a></code>
|
|
281
291
|
</h3>
|
|
282
292
|
|
|
283
|
-
Takes a hostname (e.g. `"www.example.com"`) and returns a [`ParseResult`](#api-ts-ParseResult). The hostname must only contain basic latin
|
|
293
|
+
Takes a hostname (e.g. `"www.example.com"`) and returns a [`ParseResult`](#api-ts-ParseResult). The hostname must only contain basic latin letters, digits, hyphens and dots. International hostnames must be puny-encoded. Does not throw an error, even with invalid input.
|
|
284
294
|
|
|
285
295
|
```javascript
|
|
286
|
-
import {parseDomain} from "parse-domain";
|
|
296
|
+
import { parseDomain } from "parse-domain";
|
|
287
297
|
|
|
288
298
|
const parseResult = parseDomain("www.example.com");
|
|
289
299
|
```
|
|
290
300
|
|
|
301
|
+
Use `Validation.Lax` if you want to allow all characters:
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
import { parseDomain, Validation } from "parse-domain";
|
|
305
|
+
|
|
306
|
+
const parseResult = parseDomain("_jabber._tcp.gmail.com", {
|
|
307
|
+
validation: Validation.Lax,
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
291
311
|
<h3 id="api-js-fromUrl">
|
|
292
312
|
🧩 <code>export fromUrl(input: string): string | typeof <a href="#api-js-NO_HOSTNAME">NO_HOSTNAME</a></code>
|
|
293
313
|
</h3>
|
|
@@ -300,6 +320,54 @@ Takes a URL-like string and tries to extract the hostname. Requires the global [
|
|
|
300
320
|
|
|
301
321
|
`NO_HOSTNAME` is a symbol that is returned by [`fromUrl`](#api-js-fromUrl) when it was not able to extract a hostname from the given string. When passed to [`parseDomain`](#api-js-parseDomain), it will always yield a [`ParseResultInvalid`](#api-ts-ParseResultInvalid).
|
|
302
322
|
|
|
323
|
+
<h3 id="api-ts-ParseDomainOptions">
|
|
324
|
+
🧬 <code>export type ParseDomainOptions</code>
|
|
325
|
+
</h3>
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
export type ParseDomainOptions = {
|
|
329
|
+
/**
|
|
330
|
+
* If no validation is specified, Validation.Strict will be used.
|
|
331
|
+
**/
|
|
332
|
+
validation?: Validation;
|
|
333
|
+
};
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
<h3 id="api-js-Validation">
|
|
337
|
+
🧩 <code>export Validation</code>
|
|
338
|
+
</h3>
|
|
339
|
+
|
|
340
|
+
An object that holds all possible [Validation](#api-ts-Validation) `validation` values:
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
export const Validation = {
|
|
344
|
+
/**
|
|
345
|
+
* Allows any octets as labels
|
|
346
|
+
* but still restricts the length of labels and the overall domain.
|
|
347
|
+
*
|
|
348
|
+
* @see https://www.rfc-editor.org/rfc/rfc2181#section-11
|
|
349
|
+
**/
|
|
350
|
+
Lax: "LAX",
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Only allows ASCII letters, digits and hyphens (aka LDH),
|
|
354
|
+
* forbids hyphens at the beginning or end of a label
|
|
355
|
+
* and requires top-level domain names not to be all-numeric.
|
|
356
|
+
*
|
|
357
|
+
* This is the default if no validation is configured.
|
|
358
|
+
*
|
|
359
|
+
* @see https://datatracker.ietf.org/doc/html/rfc3696#section-2
|
|
360
|
+
*/
|
|
361
|
+
Strict: "STRICT",
|
|
362
|
+
};
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
<h3 id="api-ts-Validation">
|
|
366
|
+
🧬 <code>export Validation</code>
|
|
367
|
+
</h3>
|
|
368
|
+
|
|
369
|
+
This type represents all possible `validation` values.
|
|
370
|
+
|
|
303
371
|
<h3 id="api-ts-ParseResult">
|
|
304
372
|
🧬 <code>export ParseResult</code>
|
|
305
373
|
</h3>
|
|
@@ -318,11 +386,11 @@ An object that holds all possible [ParseResult](#api-ts-ParseResult) `type` valu
|
|
|
318
386
|
|
|
319
387
|
```javascript
|
|
320
388
|
const ParseResultType = {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
389
|
+
Invalid: "INVALID",
|
|
390
|
+
Ip: "IP",
|
|
391
|
+
Reserved: "RESERVED",
|
|
392
|
+
NotListed: "NOT_LISTED",
|
|
393
|
+
Listed: "LISTED",
|
|
326
394
|
};
|
|
327
395
|
```
|
|
328
396
|
|
|
@@ -346,17 +414,17 @@ Describes the shape of the parse result that is returned when the given hostname
|
|
|
346
414
|
|
|
347
415
|
```ts
|
|
348
416
|
type ParseResultInvalid = {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
417
|
+
type: ParseResultType.INVALID;
|
|
418
|
+
hostname: string | typeof NO_HOSTNAME;
|
|
419
|
+
errors: Array<ValidationError>;
|
|
352
420
|
};
|
|
353
421
|
|
|
354
422
|
// Example
|
|
355
423
|
|
|
356
424
|
{
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
425
|
+
type: "INVALID",
|
|
426
|
+
hostname: ".com",
|
|
427
|
+
errors: [...]
|
|
360
428
|
}
|
|
361
429
|
```
|
|
362
430
|
|
|
@@ -368,17 +436,17 @@ Describes the shape of a validation error as returned by [`parseDomain`](#api-js
|
|
|
368
436
|
|
|
369
437
|
```ts
|
|
370
438
|
type ValidationError = {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
439
|
+
type: ValidationErrorType;
|
|
440
|
+
message: string;
|
|
441
|
+
column: number;
|
|
374
442
|
};
|
|
375
443
|
|
|
376
444
|
// Example
|
|
377
445
|
|
|
378
446
|
{
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
447
|
+
type: "LABEL_MIN_LENGTH",
|
|
448
|
+
message: `Label "" is too short. Label is 0 octets long but should be at least 1.`,
|
|
449
|
+
column: 1,
|
|
382
450
|
}
|
|
383
451
|
```
|
|
384
452
|
|
|
@@ -390,11 +458,12 @@ An object that holds all possible [ValidationError](#api-ts-ValidationError) `ty
|
|
|
390
458
|
|
|
391
459
|
```javascript
|
|
392
460
|
const ValidationErrorType = {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
461
|
+
NoHostname: "NO_HOSTNAME",
|
|
462
|
+
DomainMaxLength: "DOMAIN_MAX_LENGTH",
|
|
463
|
+
LabelMinLength: "LABEL_MIN_LENGTH",
|
|
464
|
+
LabelMaxLength: "LABEL_MAX_LENGTH",
|
|
465
|
+
LabelInvalidCharacter: "LABEL_INVALID_CHARACTER",
|
|
466
|
+
LastLabelInvalid: "LAST_LABEL_INVALID",
|
|
398
467
|
};
|
|
399
468
|
```
|
|
400
469
|
|
|
@@ -412,17 +481,17 @@ This type describes the shape of the parse result that is returned when the give
|
|
|
412
481
|
|
|
413
482
|
```ts
|
|
414
483
|
type ParseResultIp = {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
484
|
+
type: ParseResultType.Ip;
|
|
485
|
+
hostname: string;
|
|
486
|
+
ipVersion: 4 | 6;
|
|
418
487
|
};
|
|
419
488
|
|
|
420
489
|
// Example
|
|
421
490
|
|
|
422
491
|
{
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
492
|
+
type: "IP",
|
|
493
|
+
hostname: "192.168.0.1",
|
|
494
|
+
ipVersion: 4
|
|
426
495
|
}
|
|
427
496
|
```
|
|
428
497
|
|
|
@@ -447,17 +516,17 @@ This type describes the shape of the parse result that is returned when the give
|
|
|
447
516
|
|
|
448
517
|
```ts
|
|
449
518
|
type ParseResultReserved = {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
519
|
+
type: ParseResultType.Reserved;
|
|
520
|
+
hostname: string;
|
|
521
|
+
labels: Array<string>;
|
|
453
522
|
};
|
|
454
523
|
|
|
455
524
|
// Example
|
|
456
525
|
|
|
457
526
|
{
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
527
|
+
type: "RESERVED",
|
|
528
|
+
hostname: "pecorino.local",
|
|
529
|
+
labels: ["pecorino", "local"]
|
|
461
530
|
}
|
|
462
531
|
```
|
|
463
532
|
|
|
@@ -471,17 +540,17 @@ Describes the shape of the parse result that is returned when the given hostname
|
|
|
471
540
|
|
|
472
541
|
```ts
|
|
473
542
|
type ParseResultNotListed = {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
543
|
+
type: ParseResultType.NotListed;
|
|
544
|
+
hostname: string;
|
|
545
|
+
labels: Array<string>;
|
|
477
546
|
};
|
|
478
547
|
|
|
479
548
|
// Example
|
|
480
549
|
|
|
481
550
|
{
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
551
|
+
type: "NOT_LISTED",
|
|
552
|
+
hostname: "this.is.not-listed",
|
|
553
|
+
labels: ["this", "is", "not-listed"]
|
|
485
554
|
}
|
|
486
555
|
```
|
|
487
556
|
|
|
@@ -493,39 +562,39 @@ Describes the shape of the parse result that is returned when the given hostname
|
|
|
493
562
|
|
|
494
563
|
```ts
|
|
495
564
|
type ParseResultListed = {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
565
|
+
type: ParseResultType.Listed;
|
|
566
|
+
hostname: string;
|
|
567
|
+
labels: Array<string>;
|
|
568
|
+
subDomains: Array<string>;
|
|
569
|
+
domain: string | undefined;
|
|
570
|
+
topLevelDomains: Array<string>;
|
|
571
|
+
icann: {
|
|
572
|
+
subDomains: Array<string>;
|
|
573
|
+
domain: string | undefined;
|
|
574
|
+
topLevelDomains: Array<string>;
|
|
575
|
+
};
|
|
507
576
|
};
|
|
508
577
|
|
|
509
578
|
// Example
|
|
510
579
|
|
|
511
580
|
{
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
581
|
+
type: "LISTED",
|
|
582
|
+
hostname: "parse-domain.github.io",
|
|
583
|
+
labels: ["parse-domain", "github", "io"]
|
|
584
|
+
subDomains: [],
|
|
585
|
+
domain: "parse-domain",
|
|
586
|
+
topLevelDomains: ["github", "io"],
|
|
587
|
+
icann: {
|
|
588
|
+
subDomains: ["parse-domain"],
|
|
589
|
+
domain: "github",
|
|
590
|
+
topLevelDomains: ["io"]
|
|
591
|
+
}
|
|
523
592
|
}
|
|
524
593
|
```
|
|
525
594
|
|
|
526
595
|
## License
|
|
527
596
|
|
|
528
|
-
|
|
597
|
+
MIT
|
|
529
598
|
|
|
530
599
|
## Sponsors
|
|
531
600
|
|
package/bin/update.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const {EOL} = require("os");
|
|
3
|
+
import { EOL } from "os";
|
|
6
4
|
|
|
7
5
|
(async () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
process.argv.push("--", "../../serialized-tries");
|
|
7
|
+
|
|
8
|
+
const updateTries = await import("../build/scripts/update-tries.js");
|
|
9
|
+
|
|
10
|
+
await updateTries.done;
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
process.stderr.write("Running smoke test... ");
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
const smokeTest = await import("../build/smoke-test.js");
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
smokeTest.runSmokeTest();
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
process.stdout.write("ok" + EOL);
|
|
21
19
|
})().catch((error) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
process.exit(1);
|
|
20
|
+
console.error(`parse-domain update failed: ${error}`);
|
|
21
|
+
process.exit(1);
|
|
25
22
|
});
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAC5B,sDAAsD,CAAC;AACzD,MAAM,CAAC,MAAM,gCAAgC,GAAG,8BAA8B,CAAC;AAC/E,MAAM,CAAC,MAAM,8BAA8B,GAAG,4BAA4B,CAAC;AAC3E,MAAM,CAAC,MAAM,kCAAkC,GAC7C,gCAAgC,CAAC;AACnC,MAAM,CAAC,MAAM,gCAAgC,GAAG,8BAA8B,CAAC;AAC/E,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"from-url.js","sourceRoot":"","sources":["../src/from-url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAE5C,MAAM,CAAC,MAAM,WAAW,GAAkB,MAAM,CAAC,aAAa,CAAC,CAAC;AAEhE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;IACzC,0BAA0B;IAC1B,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;QAC7B,MAAM,IAAI,KAAK,CACb,yHAAyH,CAC1H,CAAC;KACH;IAED,uCAAuC;IACvC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC/B,OAAO,WAAW,CAAC;KACpB;IAED,gDAAgD;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAClC,CAAC,CAAC,QAAQ,OAAO,EAAE;QACnB,CAAC,CAAC,wDAAwD;YAC1D,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;gBACvB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;oBAC1B,CAAC,CAAC,OAAO;oBACT,CAAC,CAAC,UAAU,OAAO,EAAE,CAAC;IAExB,IAAI;QACF,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;KAC9B;IAAC,WAAM;QACN,OAAO,WAAW,CAAC;KACpB;AACH,CAAC,CAAC"}
|
package/build/main.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { parseDomain, ParseResult, ParseResultType, ParseResultInvalid, ParseResultReserved, ParseResultNotListed, ParseResultListed, } from "./parse-domain.js";
|
|
2
|
+
export { fromUrl, NO_HOSTNAME } from "./from-url.js";
|
|
3
|
+
export { Validation, ValidationError, ValidationErrorType, } from "./sanitize.js";
|
package/build/main.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
// Jest will report function coverage errors here otherwise
|
|
3
|
+
export { parseDomain, ParseResultType, } from "./parse-domain.js";
|
|
4
|
+
export { fromUrl, NO_HOSTNAME } from "./from-url.js";
|
|
5
|
+
export { Validation, ValidationErrorType, } from "./sanitize.js";
|
|
6
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,2DAA2D;AAC3D,OAAO,EACL,WAAW,EAEX,eAAe,GAKhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,UAAU,EAEV,mBAAmB,GACpB,MAAM,eAAe,CAAC"}
|