exacturi 1.0.0 → 1.0.1
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 +1 -0
- package/dist/cjs/errors.d.ts.map +1 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/exacturi.d.ts +10 -13
- package/dist/cjs/exacturi.d.ts.map +1 -1
- package/dist/cjs/exacturi.js +10 -13
- package/dist/cjs/exacturi.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -4
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/parts.d.ts +1 -3
- package/dist/cjs/parts.d.ts.map +1 -1
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/exacturi.d.ts +10 -13
- package/dist/esm/exacturi.d.ts.map +1 -1
- package/dist/esm/exacturi.js +10 -13
- package/dist/esm/exacturi.js.map +1 -1
- package/dist/esm/index.d.ts +6 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/package.json +1 -0
- package/dist/esm/parts.d.ts +1 -3
- package/dist/esm/parts.d.ts.map +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/errors.ts +8 -8
- package/src/exacturi.ts +158 -161
- package/src/index.ts +15 -13
- package/src/parts.ts +10 -12
- package/src/utils.ts +16 -16
- package/dist/cjs/reuri.d.ts +0 -92
- package/dist/cjs/reuri.d.ts.map +0 -1
- package/dist/cjs/reuri.js +0 -345
- package/dist/cjs/reuri.js.map +0 -1
- package/dist/esm/reuri.d.ts +0 -92
- package/dist/esm/reuri.d.ts.map +0 -1
- package/dist/esm/reuri.js +0 -341
- package/dist/esm/reuri.js.map +0 -1
- package/dist/lib/errors.d.ts +0 -14
- package/dist/lib/errors.d.ts.map +0 -1
- package/dist/lib/errors.js +0 -52
- package/dist/lib/index.d.ts +0 -31
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js +0 -20
- package/dist/lib/parts.d.ts +0 -18
- package/dist/lib/parts.d.ts.map +0 -1
- package/dist/lib/parts.js +0 -3
- package/dist/lib/payload.d.ts +0 -17
- package/dist/lib/payload.d.ts.map +0 -1
- package/dist/lib/payload.js +0 -126
- package/dist/lib/reuri.d.ts +0 -127
- package/dist/lib/reuri.d.ts.map +0 -1
- package/dist/lib/reuri.js +0 -457
- package/dist/lib/utils.d.ts +0 -2
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/utils.js +0 -26
- package/dist/test/basic.test.js +0 -319
- package/dist/test/basic.test.js.map +0 -1
- package/dist/test/extras.test.js +0 -77
- package/dist/test/extras.test.js.map +0 -1
- package/dist/test/matching.test.js +0 -80
- package/dist/test/matching.test.js.map +0 -1
package/src/errors.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
export class ExactUriError extends Error {
|
|
2
|
-
name = "ExactUriError"
|
|
2
|
+
name = "ExactUriError"
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function badInputError(input: any, reason: string) {
|
|
6
|
-
return new ExactUriError(`Received bad input ${input}. ${reason}`)
|
|
6
|
+
return new ExactUriError(`Received bad input ${input}. ${reason}`)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function inputMustBeString(input: unknown) {
|
|
10
|
-
return badInputError(input, `Input must be a string, but was a ${typeof input}`)
|
|
10
|
+
return badInputError(input, `Input must be a string, but was a ${typeof input}`)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function cantSerializeArtificialUrl(url: string) {
|
|
14
|
-
return new ExactUriError(`This URL is artificial and can't be serialized. Looks like: ${url}`)
|
|
14
|
+
return new ExactUriError(`This URL is artificial and can't be serialized. Looks like: ${url}`)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function invalidCharacter(input: string, char: string, reason: string) {
|
|
18
|
-
return badInputError(input, `The character ${char} was unexpected because ${reason}.`)
|
|
18
|
+
return badInputError(input, `The character ${char} was unexpected because ${reason}.`)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function portMustBeNumeric(input: string) {
|
|
22
|
-
return badInputError(input, "Port must be numeric.")
|
|
22
|
+
return badInputError(input, "Port must be numeric.")
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function inputMustBeUrl(input: string) {
|
|
26
|
-
return badInputError(input, "Input failed to parse.")
|
|
26
|
+
return badInputError(input, "Input failed to parse.")
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function cantCompareType(value: unknown) {
|
|
30
|
-
return new ExactUriError(`Can't compare this URI to a value ${value}`)
|
|
30
|
+
return new ExactUriError(`Can't compare this URI to a value ${value}`)
|
|
31
31
|
}
|
package/src/exacturi.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ExactUriError, inputMustBeString, inputMustBeUrl, portMustBeNumeric } from "./errors.js"
|
|
2
|
-
import { hostnameContains } from "./utils.js";
|
|
1
|
+
import { ExactUriError, inputMustBeString, inputMustBeUrl, portMustBeNumeric } from "./errors.js"
|
|
3
2
|
import {
|
|
4
3
|
ExactUri_CompoundNames,
|
|
5
4
|
ExactUri_Parts,
|
|
6
5
|
ExactUri_PathKey,
|
|
7
6
|
ExactUri_Protocol
|
|
8
|
-
} from "./parts.js"
|
|
7
|
+
} from "./parts.js"
|
|
8
|
+
import { hostnameContains } from "./utils.js"
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Represents a URI and allows performing operations and inspecting it.
|
|
@@ -26,25 +26,25 @@ export class ExactUri {
|
|
|
26
26
|
) {}
|
|
27
27
|
|
|
28
28
|
static is(other: unknown): other is ExactUri {
|
|
29
|
-
return !!(other && typeof other === "object" && other.constructor === ExactUri)
|
|
29
|
+
return !!(other && typeof other === "object" && other.constructor === ExactUri)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
segments(): string[]
|
|
33
|
-
segments(overwrite: string[]): ExactUri
|
|
32
|
+
segments(): string[]
|
|
33
|
+
segments(overwrite: string[]): ExactUri
|
|
34
34
|
segments(overwrite?: string[]) {
|
|
35
35
|
if (arguments.length === 0) {
|
|
36
|
-
return this._path.split("/")
|
|
36
|
+
return this._path.split("/")
|
|
37
37
|
}
|
|
38
|
-
const clone = this._noCopyClone()
|
|
39
|
-
clone._path = overwrite!.join("/")
|
|
40
|
-
return clone
|
|
38
|
+
const clone = this._noCopyClone()
|
|
39
|
+
clone._path = overwrite!.join("/")
|
|
40
|
+
return clone
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
merge(other: string): ExactUri
|
|
44
|
-
merge(other: ExactUri): ExactUri
|
|
43
|
+
merge(other: string): ExactUri
|
|
44
|
+
merge(other: ExactUri): ExactUri
|
|
45
45
|
merge(other: ExactUri | string): ExactUri {
|
|
46
46
|
if (typeof other === "string") {
|
|
47
|
-
return this.merge(ExactUri.parse(other))
|
|
47
|
+
return this.merge(ExactUri.parse(other))
|
|
48
48
|
}
|
|
49
49
|
return this.parts({
|
|
50
50
|
hash: other._hash || this._hash,
|
|
@@ -53,19 +53,19 @@ export class ExactUri {
|
|
|
53
53
|
port: other._port || this._port,
|
|
54
54
|
protocol: other._protocol || this._protocol,
|
|
55
55
|
query: other._query || this._query
|
|
56
|
-
})
|
|
56
|
+
})
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
pick(...keys: ExactUri_PathKey[]): ExactUri {
|
|
60
|
-
let result = ExactUri.empty()
|
|
60
|
+
let result = ExactUri.empty()
|
|
61
61
|
for (const key of keys) {
|
|
62
|
-
result = result.part(key, this.part(key as ExactUri_CompoundNames))
|
|
62
|
+
result = result.part(key, this.part(key as ExactUri_CompoundNames))
|
|
63
63
|
}
|
|
64
|
-
return result
|
|
64
|
+
return result
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
parts(): ExactUri_Parts
|
|
68
|
-
parts(overwrite: Partial<ExactUri_Parts>): ExactUri
|
|
67
|
+
parts(): ExactUri_Parts
|
|
68
|
+
parts(overwrite: Partial<ExactUri_Parts>): ExactUri
|
|
69
69
|
parts(overwrite?: Partial<ExactUri_Parts>): any {
|
|
70
70
|
if (arguments.length === 0) {
|
|
71
71
|
return {
|
|
@@ -75,194 +75,194 @@ export class ExactUri {
|
|
|
75
75
|
path: this._path,
|
|
76
76
|
query: this._query,
|
|
77
77
|
hash: this._hash
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
79
|
}
|
|
80
80
|
if (!overwrite) {
|
|
81
|
-
return this
|
|
82
|
-
}
|
|
83
|
-
const clone = this._noCopyClone()
|
|
84
|
-
clone._protocol = "protocol" in overwrite ? overwrite.protocol : clone._protocol
|
|
85
|
-
clone._hostname = "hostname" in overwrite ? overwrite.hostname : clone._hostname
|
|
86
|
-
clone._port = "port" in overwrite ? overwrite.port : clone._port
|
|
87
|
-
clone._path = "path" in overwrite ? (overwrite.path as any) : clone._path
|
|
88
|
-
clone._query = "query" in overwrite ? overwrite.query : clone._query
|
|
89
|
-
clone._hash = "hash" in overwrite ? overwrite.hash : clone._hash
|
|
90
|
-
return clone
|
|
81
|
+
return this
|
|
82
|
+
}
|
|
83
|
+
const clone = this._noCopyClone()
|
|
84
|
+
clone._protocol = "protocol" in overwrite ? overwrite.protocol : clone._protocol
|
|
85
|
+
clone._hostname = "hostname" in overwrite ? overwrite.hostname : clone._hostname
|
|
86
|
+
clone._port = "port" in overwrite ? overwrite.port : clone._port
|
|
87
|
+
clone._path = "path" in overwrite ? (overwrite.path as any) : clone._path
|
|
88
|
+
clone._query = "query" in overwrite ? overwrite.query : clone._query
|
|
89
|
+
clone._hash = "hash" in overwrite ? overwrite.hash : clone._hash
|
|
90
|
+
return clone
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
part(key: ExactUri_PathKey): string | undefined
|
|
94
|
-
part(key: ExactUri_PathKey, value: string | undefined): ExactUri
|
|
93
|
+
part(key: ExactUri_PathKey): string | undefined
|
|
94
|
+
part(key: ExactUri_PathKey, value: string | undefined): ExactUri
|
|
95
95
|
part(key: ExactUri_PathKey, value?: string): any {
|
|
96
96
|
if (arguments.length === 1) {
|
|
97
|
-
const result = (this as any)[key]()
|
|
98
|
-
return result != null ? String(result) : undefined
|
|
97
|
+
const result = (this as any)[key]()
|
|
98
|
+
return result != null ? String(result) : undefined
|
|
99
99
|
}
|
|
100
|
-
return (this as any)[key](value as any)
|
|
100
|
+
return (this as any)[key](value as any)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
address(address: string | undefined | null): ExactUri
|
|
104
|
-
address(): string | undefined
|
|
103
|
+
address(address: string | undefined | null): ExactUri
|
|
104
|
+
address(): string | undefined
|
|
105
105
|
address(address?: string): string | ExactUri | undefined {
|
|
106
106
|
if (arguments.length === 1) {
|
|
107
|
-
const parsed = ExactUri.parse(address!)
|
|
107
|
+
const parsed = ExactUri.parse(address!)
|
|
108
108
|
return parsed.parts({
|
|
109
109
|
protocol: this._protocol
|
|
110
|
-
})
|
|
110
|
+
})
|
|
111
111
|
}
|
|
112
112
|
return this.parts({
|
|
113
113
|
protocol: undefined
|
|
114
|
-
}).href
|
|
114
|
+
}).href
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
resource(resource: string | undefined | null): ExactUri
|
|
118
|
-
resource(): string | undefined
|
|
117
|
+
resource(resource: string | undefined | null): ExactUri
|
|
118
|
+
resource(): string | undefined
|
|
119
119
|
resource(resource?: string): string | ExactUri | undefined {
|
|
120
120
|
if (arguments.length === 1) {
|
|
121
|
-
const parsed = ExactUri.parse(resource!)
|
|
121
|
+
const parsed = ExactUri.parse(resource!)
|
|
122
122
|
return parsed.parts({
|
|
123
123
|
protocol: this._protocol,
|
|
124
124
|
hostname: this._hostname,
|
|
125
125
|
port: this._port
|
|
126
|
-
})
|
|
126
|
+
})
|
|
127
127
|
}
|
|
128
128
|
return this.parts({
|
|
129
129
|
protocol: undefined,
|
|
130
130
|
hostname: undefined,
|
|
131
131
|
port: undefined
|
|
132
|
-
}).href
|
|
132
|
+
}).href
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
origin(origin: string | undefined | null): ExactUri
|
|
136
|
-
origin(): string | undefined
|
|
135
|
+
origin(origin: string | undefined | null): ExactUri
|
|
136
|
+
origin(): string | undefined
|
|
137
137
|
origin(origin?: string): string | ExactUri | undefined {
|
|
138
138
|
if (arguments.length === 1) {
|
|
139
|
-
const parsed = ExactUri.parse(origin!)
|
|
139
|
+
const parsed = ExactUri.parse(origin!)
|
|
140
140
|
return this.parts({
|
|
141
141
|
protocol: parsed._protocol,
|
|
142
142
|
hostname: parsed._hostname,
|
|
143
143
|
port: parsed._port
|
|
144
|
-
})
|
|
144
|
+
})
|
|
145
145
|
}
|
|
146
|
-
const parts = this.parts()
|
|
146
|
+
const parts = this.parts()
|
|
147
147
|
return (
|
|
148
148
|
ExactUri.empty().parts({
|
|
149
149
|
protocol: parts.protocol,
|
|
150
150
|
hostname: parts.hostname,
|
|
151
151
|
port: parts.port
|
|
152
152
|
}).href || undefined
|
|
153
|
-
)
|
|
153
|
+
)
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
segment(index: number): string
|
|
157
|
-
segment(index: number, value: string): ExactUri
|
|
156
|
+
segment(index: number): string
|
|
157
|
+
segment(index: number, value: string): ExactUri
|
|
158
158
|
segment(index: number, value?: string) {
|
|
159
159
|
if (arguments.length === 0) {
|
|
160
|
-
throw new ExactUriError(`You must provide an index.`)
|
|
160
|
+
throw new ExactUriError(`You must provide an index.`)
|
|
161
161
|
}
|
|
162
162
|
if (arguments.length === 1) {
|
|
163
|
-
return this._path.split("/")[index]
|
|
163
|
+
return this._path.split("/")[index]
|
|
164
164
|
}
|
|
165
|
-
const segments = this.segments()
|
|
166
|
-
segments[index] = value
|
|
167
|
-
return this.segments(segments)
|
|
165
|
+
const segments = this.segments()
|
|
166
|
+
segments[index] = value!
|
|
167
|
+
return this.segments(segments)
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
// Gets the path. It can't be nullish.
|
|
171
|
-
path(): string
|
|
171
|
+
path(): string
|
|
172
172
|
// Sets the path to `path`. Null is converted to `""`.
|
|
173
|
-
path(path: string | undefined | null): ExactUri
|
|
173
|
+
path(path: string | undefined | null): ExactUri
|
|
174
174
|
path(path?: string) {
|
|
175
175
|
if (arguments.length === 0) {
|
|
176
|
-
return this._path
|
|
176
|
+
return this._path
|
|
177
177
|
}
|
|
178
|
-
const clone = this._noCopyClone()
|
|
179
|
-
clone._path = path ?? ""
|
|
180
|
-
return clone
|
|
178
|
+
const clone = this._noCopyClone()
|
|
179
|
+
clone._path = path ?? ""
|
|
180
|
+
return clone
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
port(): number | undefined
|
|
184
|
-
port(raw: true): string | undefined
|
|
185
|
-
port(port: number | undefined | string | null): ExactUri
|
|
183
|
+
port(): number | undefined
|
|
184
|
+
port(raw: true): string | undefined
|
|
185
|
+
port(port: number | undefined | string | null): ExactUri
|
|
186
186
|
port(port?: number | true | string | null) {
|
|
187
187
|
if (arguments.length === 0) {
|
|
188
|
-
return this._port != null ? Number(this._port) : undefined
|
|
188
|
+
return this._port != null ? Number(this._port) : undefined
|
|
189
189
|
}
|
|
190
190
|
if (port === true) {
|
|
191
|
-
return this._port
|
|
191
|
+
return this._port
|
|
192
192
|
}
|
|
193
|
-
const clone = this._noCopyClone()
|
|
194
|
-
clone._port = port != null ? String(port) : undefined
|
|
195
|
-
return clone
|
|
193
|
+
const clone = this._noCopyClone()
|
|
194
|
+
clone._port = port != null ? String(port) : undefined
|
|
195
|
+
return clone
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
// Gets the protocol.
|
|
199
|
-
protocol(): ExactUri_Protocol | undefined
|
|
199
|
+
protocol(): ExactUri_Protocol | undefined
|
|
200
200
|
// Sets the protocol to `proto`.
|
|
201
|
-
protocol(proto: ExactUri_Protocol | null | undefined): ExactUri
|
|
201
|
+
protocol(proto: ExactUri_Protocol | null | undefined): ExactUri
|
|
202
202
|
protocol(proto?: ExactUri_Protocol | null | undefined) {
|
|
203
203
|
if (arguments.length === 0) {
|
|
204
|
-
return this._protocol
|
|
204
|
+
return this._protocol
|
|
205
205
|
}
|
|
206
|
-
const clone = this._noCopyClone()
|
|
207
|
-
clone._protocol = proto ?? undefined
|
|
208
|
-
return clone
|
|
206
|
+
const clone = this._noCopyClone()
|
|
207
|
+
clone._protocol = proto ?? undefined
|
|
208
|
+
return clone
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
// Gets the hostname and port.
|
|
212
|
-
host(): string | undefined
|
|
212
|
+
host(): string | undefined
|
|
213
213
|
// Sets the hostname and port.
|
|
214
|
-
host(host: string | undefined | null): ExactUri
|
|
214
|
+
host(host: string | undefined | null): ExactUri
|
|
215
215
|
host(host?: string): any {
|
|
216
216
|
if (arguments.length === 0) {
|
|
217
217
|
return (
|
|
218
218
|
ExactUri.empty().hostname(this._hostname).port(this._port).href.slice(2) ||
|
|
219
219
|
undefined
|
|
220
|
-
)
|
|
220
|
+
)
|
|
221
221
|
}
|
|
222
222
|
if (host == null) {
|
|
223
|
-
return this.hostname(null).port(null)
|
|
223
|
+
return this.hostname(null).port(null)
|
|
224
224
|
}
|
|
225
|
-
const parsed = ExactUri.parse(`//${host}`)
|
|
226
|
-
return this.hostname(parsed._hostname).port(parsed._port)
|
|
225
|
+
const parsed = ExactUri.parse(`//${host}`)
|
|
226
|
+
return this.hostname(parsed._hostname).port(parsed._port)
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
// Gets the hostname, which is the domain without the port.
|
|
230
|
-
hostname(): string | undefined
|
|
230
|
+
hostname(): string | undefined
|
|
231
231
|
// Sets the hostname to `hostname`.
|
|
232
|
-
hostname(hostname: string | undefined | null): ExactUri
|
|
232
|
+
hostname(hostname: string | undefined | null): ExactUri
|
|
233
233
|
hostname(hostname?: string) {
|
|
234
234
|
if (arguments.length === 0) {
|
|
235
|
-
return this._hostname
|
|
235
|
+
return this._hostname
|
|
236
236
|
}
|
|
237
|
-
const clone = this._noCopyClone()
|
|
238
|
-
clone._hostname = hostname ?? undefined
|
|
239
|
-
return clone
|
|
237
|
+
const clone = this._noCopyClone()
|
|
238
|
+
clone._hostname = hostname ?? undefined
|
|
239
|
+
return clone
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
// Gets the query string.
|
|
243
|
-
query(): string | undefined
|
|
243
|
+
query(): string | undefined
|
|
244
244
|
// Sets the query string to `query`.
|
|
245
|
-
query(query: string | null | undefined): ExactUri
|
|
245
|
+
query(query: string | null | undefined): ExactUri
|
|
246
246
|
query(query?: string) {
|
|
247
247
|
if (arguments.length === 0) {
|
|
248
|
-
return this._query
|
|
248
|
+
return this._query
|
|
249
249
|
}
|
|
250
|
-
const clone = this._noCopyClone()
|
|
251
|
-
clone._query = query ?? undefined
|
|
252
|
-
return clone
|
|
250
|
+
const clone = this._noCopyClone()
|
|
251
|
+
clone._query = query ?? undefined
|
|
252
|
+
return clone
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
// Gets the hash, aka the fragment, without the #.
|
|
256
|
-
hash(): string
|
|
256
|
+
hash(): string
|
|
257
257
|
// Sets the hash of this to `hash`, and returns `this`.
|
|
258
|
-
hash(hash: string | null | undefined): ExactUri
|
|
258
|
+
hash(hash: string | null | undefined): ExactUri
|
|
259
259
|
hash(hash?: string) {
|
|
260
260
|
if (arguments.length === 0) {
|
|
261
|
-
return this._hash
|
|
261
|
+
return this._hash
|
|
262
262
|
}
|
|
263
|
-
const clone = this._noCopyClone()
|
|
264
|
-
clone._hash = hash ?? undefined
|
|
265
|
-
return clone
|
|
263
|
+
const clone = this._noCopyClone()
|
|
264
|
+
clone._hash = hash ?? undefined
|
|
265
|
+
return clone
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
private _noCopyClone() {
|
|
@@ -274,17 +274,15 @@ export class ExactUri {
|
|
|
274
274
|
this._hash,
|
|
275
275
|
this._parsed,
|
|
276
276
|
this._port
|
|
277
|
-
)
|
|
277
|
+
)
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// Does this URL have a web protocol?
|
|
281
281
|
get isWeb() {
|
|
282
|
-
return !!this._protocol && webProtocols.has(this._protocol)
|
|
282
|
+
return !!this._protocol && webProtocols.has(this._protocol)
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
/**
|
|
286
|
-
* Gets a clone of this instance.
|
|
287
|
-
*/
|
|
285
|
+
/** Gets a clone of this instance. */
|
|
288
286
|
clone(): ExactUri {
|
|
289
287
|
return new ExactUri(
|
|
290
288
|
this._protocol,
|
|
@@ -294,37 +292,37 @@ export class ExactUri {
|
|
|
294
292
|
this._hash,
|
|
295
293
|
this._parsed,
|
|
296
294
|
this._port
|
|
297
|
-
)
|
|
295
|
+
)
|
|
298
296
|
}
|
|
299
297
|
|
|
300
298
|
static empty() {
|
|
301
|
-
return new ExactUri(undefined, undefined, "", undefined, undefined, undefined, undefined)
|
|
299
|
+
return new ExactUri(undefined, undefined, "", undefined, undefined, undefined, undefined)
|
|
302
300
|
}
|
|
303
301
|
|
|
304
302
|
// Parses `input` as a URI. Errors on bad input.
|
|
305
|
-
static parse(input: null | undefined): ExactUri
|
|
306
|
-
static parse(input: string | ExactUri | Partial<ExactUri_Parts>): ExactUri
|
|
303
|
+
static parse(input: null | undefined): ExactUri
|
|
304
|
+
static parse(input: string | ExactUri | Partial<ExactUri_Parts>): ExactUri
|
|
307
305
|
static parse(input: any) {
|
|
308
306
|
if (input == null) {
|
|
309
|
-
return ExactUri.empty()
|
|
307
|
+
return ExactUri.empty()
|
|
310
308
|
}
|
|
311
309
|
if (input instanceof ExactUri) {
|
|
312
|
-
return input
|
|
310
|
+
return input
|
|
313
311
|
}
|
|
314
312
|
if (typeof input === "object") {
|
|
315
|
-
return ExactUri.empty().parts(input)
|
|
313
|
+
return ExactUri.empty().parts(input)
|
|
316
314
|
}
|
|
317
315
|
if (typeof input !== "string") {
|
|
318
|
-
throw inputMustBeString(input)
|
|
316
|
+
throw inputMustBeString(input)
|
|
319
317
|
}
|
|
320
|
-
const r = urlRegexp.exec(input)
|
|
318
|
+
const r = urlRegexp.exec(input)
|
|
321
319
|
if (!r) {
|
|
322
|
-
throw inputMustBeUrl(input)
|
|
320
|
+
throw inputMustBeUrl(input)
|
|
323
321
|
}
|
|
324
322
|
|
|
325
|
-
const [, proto, hostname, port, path, query, fragment] = r
|
|
323
|
+
const [, proto, hostname, port, path, query, fragment] = r
|
|
326
324
|
if (port != null && (Number.isNaN(+port) || port === "")) {
|
|
327
|
-
throw portMustBeNumeric(input)
|
|
325
|
+
throw portMustBeNumeric(input)
|
|
328
326
|
}
|
|
329
327
|
return new ExactUri(
|
|
330
328
|
proto?.trim(),
|
|
@@ -334,111 +332,110 @@ export class ExactUri {
|
|
|
334
332
|
fragment?.trim(),
|
|
335
333
|
input,
|
|
336
334
|
port
|
|
337
|
-
)
|
|
335
|
+
)
|
|
338
336
|
}
|
|
339
337
|
|
|
340
338
|
/**
|
|
341
|
-
* Checks if this URI (CHILD) matches another URI (PARENT). The parent can be a string,
|
|
342
|
-
*
|
|
339
|
+
* Checks if this URI (CHILD) matches another URI (PARENT). The parent can be a string, an
|
|
340
|
+
* {@link ExactUri}, or an object describing the parts of a URI -- an {@link ExactUri_Parts}.
|
|
343
341
|
*
|
|
344
342
|
* CHILD is considered to be a child of PARENT if:
|
|
343
|
+
*
|
|
345
344
|
* 1. If PARENT has a protocol, it must equal CHILD protocol.
|
|
346
345
|
* 2. If PARENT has a hostname, it must be a parent of CHILD's hostname.
|
|
347
346
|
* 3. If PARENT has a port, it must equal CHILD's port.
|
|
348
347
|
* 4. If PARENT has a path, it must be a parent of CHILD's path.
|
|
349
348
|
* 5. If PARENT has a query, it must equal CHILD's query.
|
|
350
349
|
* 6. If PARENT has a hash, it must equal CHILD's hash.
|
|
350
|
+
*
|
|
351
351
|
* @param parent The parent URI to check against.
|
|
352
352
|
*/
|
|
353
353
|
matches(parent: Partial<ExactUri_Parts> | ExactUri | string): boolean {
|
|
354
|
-
parent = ExactUri.parse(parent)
|
|
354
|
+
parent = ExactUri.parse(parent)
|
|
355
355
|
if (parent._protocol && parent._protocol !== this._protocol) {
|
|
356
|
-
return false
|
|
356
|
+
return false
|
|
357
357
|
}
|
|
358
358
|
if (parent._hostname && !hostnameContains(this._hostname, parent._hostname)) {
|
|
359
|
-
return false
|
|
359
|
+
return false
|
|
360
360
|
}
|
|
361
361
|
|
|
362
362
|
if (parent._port && parent._port !== this._port) {
|
|
363
|
-
return false
|
|
363
|
+
return false
|
|
364
364
|
}
|
|
365
365
|
if (parent._query && parent._query !== this._query) {
|
|
366
|
-
return false
|
|
366
|
+
return false
|
|
367
367
|
}
|
|
368
368
|
if (parent._hash && parent._hash !== this._hash) {
|
|
369
|
-
return false
|
|
369
|
+
return false
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
const parentSegments = parent.segments()
|
|
373
|
-
const childSegments = this.segments()
|
|
372
|
+
const parentSegments = parent.segments()
|
|
373
|
+
const childSegments = this.segments()
|
|
374
374
|
for (let i = 0; i < parentSegments.length; i++) {
|
|
375
375
|
if (parentSegments[i] !== childSegments[i]) {
|
|
376
|
-
return false
|
|
376
|
+
return false
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
|
-
return true
|
|
379
|
+
return true
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
/**
|
|
383
|
-
* Checks if this URI equals another URI, which can be given as a string, an
|
|
384
|
-
*
|
|
383
|
+
* Checks if this URI equals another URI, which can be given as a string, an {@link ExactUri}, or
|
|
384
|
+
* an object describing the parts of a URI -- an {@link ExactUri_Parts}.
|
|
385
|
+
*
|
|
385
386
|
* @param other The other URI to check against.
|
|
386
387
|
*/
|
|
387
388
|
equal(other: string | ExactUri | Partial<ExactUri_Parts>): boolean {
|
|
388
389
|
if (this === other) {
|
|
389
|
-
return true
|
|
390
|
+
return true
|
|
390
391
|
}
|
|
391
|
-
other = ExactUri.parse(other)
|
|
392
|
-
const myParts = this.parts()
|
|
393
|
-
const otherParts = other.parts()
|
|
392
|
+
other = ExactUri.parse(other)
|
|
393
|
+
const myParts = this.parts()
|
|
394
|
+
const otherParts = other.parts()
|
|
394
395
|
for (const key of ["protocol", "hostname", "port", "path", "query", "hash"] as const) {
|
|
395
396
|
if (myParts[key] !== otherParts[key]) {
|
|
396
|
-
return false
|
|
397
|
+
return false
|
|
397
398
|
}
|
|
398
399
|
}
|
|
399
|
-
return true
|
|
400
|
+
return true
|
|
400
401
|
}
|
|
401
402
|
|
|
402
403
|
// An artificial URI is one that can't have been parsed from a string due to an invalid combination of components.
|
|
403
404
|
get isArtificial(): boolean {
|
|
404
|
-
return !ExactUri.parse(this._print()).equal(this)
|
|
405
|
+
return !ExactUri.parse(this._print()).equal(this)
|
|
405
406
|
}
|
|
406
407
|
|
|
407
|
-
/**
|
|
408
|
-
* Does this URL have a non-web protocol?
|
|
409
|
-
*/
|
|
408
|
+
/** Does this URL have a non-web protocol? */
|
|
410
409
|
get isNonWeb() {
|
|
411
|
-
return !!this._protocol && !webProtocols.has(this._protocol)
|
|
410
|
+
return !!this._protocol && !webProtocols.has(this._protocol)
|
|
412
411
|
}
|
|
413
412
|
|
|
414
|
-
/**
|
|
415
|
-
* Gets the full URI.
|
|
416
|
-
*/
|
|
413
|
+
/** Gets the full URI. */
|
|
417
414
|
get href() {
|
|
418
|
-
return this._print()
|
|
415
|
+
return this._print()
|
|
419
416
|
}
|
|
420
417
|
|
|
421
418
|
private _print() {
|
|
422
|
-
let { _protocol, _hostname, _query, _hash } = this
|
|
423
|
-
const { _port } = this
|
|
424
|
-
_protocol = _protocol != null ? `${_protocol}:` : _protocol
|
|
425
|
-
_hostname = _hostname != null ? `//${_hostname}` : ""
|
|
426
|
-
_query = _query != null ? `?${_query}` : ""
|
|
427
|
-
_hash = _hash != null ? `#${_hash}` : ""
|
|
428
|
-
const strPort = _port != null ? `:${_port}` : ""
|
|
429
|
-
return [_protocol, _hostname, strPort, this._path, _query, _hash].join("")
|
|
419
|
+
let { _protocol, _hostname, _query, _hash } = this
|
|
420
|
+
const { _port } = this
|
|
421
|
+
_protocol = _protocol != null ? `${_protocol}:` : _protocol
|
|
422
|
+
_hostname = _hostname != null ? `//${_hostname}` : ""
|
|
423
|
+
_query = _query != null ? `?${_query}` : ""
|
|
424
|
+
_hash = _hash != null ? `#${_hash}` : ""
|
|
425
|
+
const strPort = _port != null ? `:${_port}` : ""
|
|
426
|
+
return [_protocol, _hostname, strPort, this._path, _query, _hash].join("")
|
|
430
427
|
}
|
|
431
428
|
|
|
432
429
|
get [Symbol.toStringTag]() {
|
|
433
|
-
return this.href
|
|
430
|
+
return this.href
|
|
434
431
|
}
|
|
435
432
|
|
|
436
433
|
toString() {
|
|
437
|
-
return this.href
|
|
434
|
+
return this.href
|
|
438
435
|
}
|
|
439
436
|
}
|
|
440
437
|
|
|
441
438
|
const urlRegexp =
|
|
442
|
-
/^(?:([a-zA-Z][A-Za-z\d+-.]*):)?(?:\/\/([^/?#:]*)(?::([^/?#]*))?)?([^?#]*)?(?:\?([^#]*))?(?:#(.*))
|
|
439
|
+
/^(?:([a-zA-Z][A-Za-z\d+-.]*):)?(?:\/\/([^/?#:]*)(?::([^/?#]*))?)?([^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/
|
|
443
440
|
|
|
444
|
-
const webProtocols = new Set(["http", "ws", "https", "wss"])
|
|
441
|
+
const webProtocols = new Set(["http", "ws", "https", "wss"])
|
package/src/index.ts
CHANGED
|
@@ -1,37 +1,39 @@
|
|
|
1
|
-
import { ExactUri } from "./exacturi.js"
|
|
1
|
+
import { ExactUri } from "./exacturi.js"
|
|
2
2
|
|
|
3
|
-
import { ExactUri_Parts } from "./parts.js"
|
|
3
|
+
import { ExactUri_Parts } from "./parts.js"
|
|
4
4
|
|
|
5
|
-
export { ExactUri } from "./exacturi.js"
|
|
5
|
+
export { ExactUri } from "./exacturi.js"
|
|
6
|
+
export { ExactUri_Protocol } from "./parts.js"
|
|
6
7
|
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export function exacturi(): ExactUri;
|
|
8
|
+
/** Creates an empty ExactUri object. */
|
|
9
|
+
export function exacturi(): ExactUri
|
|
11
10
|
/**
|
|
12
11
|
* Creates an ExactUri object from an {@link ExactUri_Parts} describing the parts of the URI.
|
|
12
|
+
*
|
|
13
13
|
* @param parts The parts of the URI.
|
|
14
14
|
*/
|
|
15
|
-
export function exacturi(parts: Partial<ExactUri_Parts>): ExactUri
|
|
15
|
+
export function exacturi(parts: Partial<ExactUri_Parts>): ExactUri
|
|
16
16
|
/**
|
|
17
17
|
* Returns the same ExactUri object that was passed in.
|
|
18
|
+
*
|
|
18
19
|
* @param uri
|
|
19
20
|
*/
|
|
20
|
-
export function exacturi(uri: ExactUri): ExactUri
|
|
21
|
+
export function exacturi(uri: ExactUri): ExactUri
|
|
21
22
|
/**
|
|
22
23
|
* Parses a string into an ExactUri object.
|
|
24
|
+
*
|
|
23
25
|
* @param uri The string to parse.
|
|
24
26
|
*/
|
|
25
|
-
export function exacturi(uri: string): ExactUri
|
|
27
|
+
export function exacturi(uri: string): ExactUri
|
|
26
28
|
export function exacturi(uri?: ExactUri | string | Partial<ExactUri_Parts>): ExactUri {
|
|
27
|
-
return ExactUri.parse(uri as any)
|
|
29
|
+
return ExactUri.parse(uri as any)
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Returns true if the given value is an ExactUri object.
|
|
34
|
+
*
|
|
32
35
|
* @param uri The value to check.
|
|
33
36
|
*/
|
|
34
37
|
export function isExactUri(uri: unknown): uri is ExactUri {
|
|
35
|
-
return ExactUri.is(uri)
|
|
38
|
+
return ExactUri.is(uri)
|
|
36
39
|
}
|
|
37
|
-
export { ExactUri_Protocol } from "./parts.js";
|