cdk-common 2.0.1259 → 2.0.1261

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.
Files changed (34) hide show
  1. package/.jsii +2 -2
  2. package/lib/main.js +1 -1
  3. package/node_modules/fast-uri/.github/workflows/ci.yml +45 -2
  4. package/node_modules/fast-uri/.github/workflows/package-manager-ci.yml +5 -1
  5. package/node_modules/fast-uri/LICENSE +3 -1
  6. package/node_modules/fast-uri/README.md +37 -24
  7. package/node_modules/fast-uri/benchmark/benchmark.mjs +159 -0
  8. package/node_modules/fast-uri/benchmark/equal.mjs +51 -0
  9. package/node_modules/fast-uri/benchmark/non-simple-domain.mjs +22 -0
  10. package/node_modules/fast-uri/benchmark/package.json +17 -0
  11. package/node_modules/fast-uri/benchmark/string-array-to-hex-stripped.mjs +24 -0
  12. package/node_modules/fast-uri/benchmark/ws-is-secure.mjs +65 -0
  13. package/node_modules/fast-uri/index.js +95 -58
  14. package/node_modules/fast-uri/lib/schemes.js +160 -81
  15. package/node_modules/fast-uri/lib/utils.js +214 -122
  16. package/node_modules/fast-uri/package.json +7 -6
  17. package/node_modules/fast-uri/test/ajv.test.js +7 -3
  18. package/node_modules/fast-uri/test/equal.test.js +7 -2
  19. package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +501 -0
  20. package/node_modules/fast-uri/test/fixtures/uri-js-serialize.json +120 -0
  21. package/node_modules/fast-uri/test/parse.test.js +31 -31
  22. package/node_modules/fast-uri/test/resolve.test.js +52 -49
  23. package/node_modules/fast-uri/test/rfc-3986.test.js +90 -0
  24. package/node_modules/fast-uri/test/serialize.test.js +55 -47
  25. package/node_modules/fast-uri/test/uri-js-compatibility.test.js +33 -0
  26. package/node_modules/fast-uri/test/uri-js.test.js +230 -230
  27. package/node_modules/fast-uri/test/util.test.js +23 -8
  28. package/node_modules/fast-uri/tsconfig.json +9 -0
  29. package/node_modules/fast-uri/types/index.d.ts +7 -0
  30. package/package.json +1 -1
  31. package/node_modules/fast-uri/benchmark.js +0 -105
  32. package/node_modules/fast-uri/lib/scopedChars.js +0 -30
  33. package/node_modules/fast-uri/test/.gitkeep +0 -0
  34. package/node_modules/fast-uri/test/compatibility.test.js +0 -131
@@ -1,28 +1,49 @@
1
1
  'use strict'
2
2
 
3
- const { normalizeIPv6, normalizeIPv4, removeDotSegments, recomposeAuthority, normalizeComponentEncoding } = require('./lib/utils')
4
- const SCHEMES = require('./lib/schemes')
5
-
3
+ const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require('./lib/utils')
4
+ const { SCHEMES, getSchemeHandler } = require('./lib/schemes')
5
+
6
+ /**
7
+ * @template {import('./types/index').URIComponent|string} T
8
+ * @param {T} uri
9
+ * @param {import('./types/index').Options} [options]
10
+ * @returns {T}
11
+ */
6
12
  function normalize (uri, options) {
7
13
  if (typeof uri === 'string') {
8
- uri = serialize(parse(uri, options), options)
14
+ uri = /** @type {T} */ (serialize(parse(uri, options), options))
9
15
  } else if (typeof uri === 'object') {
10
- uri = parse(serialize(uri, options), options)
16
+ uri = /** @type {T} */ (parse(serialize(uri, options), options))
11
17
  }
12
18
  return uri
13
19
  }
14
20
 
21
+ /**
22
+ * @param {string} baseURI
23
+ * @param {string} relativeURI
24
+ * @param {import('./types/index').Options} [options]
25
+ * @returns {string}
26
+ */
15
27
  function resolve (baseURI, relativeURI, options) {
16
- const schemelessOptions = Object.assign({ scheme: 'null' }, options)
17
- const resolved = resolveComponents(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true)
18
- return serialize(resolved, { ...schemelessOptions, skipEscape: true })
28
+ const schemelessOptions = options ? Object.assign({ scheme: 'null' }, options) : { scheme: 'null' }
29
+ const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true)
30
+ schemelessOptions.skipEscape = true
31
+ return serialize(resolved, schemelessOptions)
19
32
  }
20
33
 
21
- function resolveComponents (base, relative, options, skipNormalization) {
34
+ /**
35
+ * @param {import ('./types/index').URIComponent} base
36
+ * @param {import ('./types/index').URIComponent} relative
37
+ * @param {import('./types/index').Options} [options]
38
+ * @param {boolean} [skipNormalization=false]
39
+ * @returns {import ('./types/index').URIComponent}
40
+ */
41
+ function resolveComponent (base, relative, options, skipNormalization) {
42
+ /** @type {import('./types/index').URIComponent} */
22
43
  const target = {}
23
44
  if (!skipNormalization) {
24
- base = parse(serialize(base, options), options) // normalize base components
25
- relative = parse(serialize(relative, options), options) // normalize relative components
45
+ base = parse(serialize(base, options), options) // normalize base component
46
+ relative = parse(serialize(relative, options), options) // normalize relative component
26
47
  }
27
48
  options = options || {}
28
49
 
@@ -51,7 +72,7 @@ function resolveComponents (base, relative, options, skipNormalization) {
51
72
  target.query = base.query
52
73
  }
53
74
  } else {
54
- if (relative.path.charAt(0) === '/') {
75
+ if (relative.path[0] === '/') {
55
76
  target.path = removeDotSegments(relative.path)
56
77
  } else {
57
78
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
@@ -78,6 +99,12 @@ function resolveComponents (base, relative, options, skipNormalization) {
78
99
  return target
79
100
  }
80
101
 
102
+ /**
103
+ * @param {import ('./types/index').URIComponent|string} uriA
104
+ * @param {import ('./types/index').URIComponent|string} uriB
105
+ * @param {import ('./types/index').Options} options
106
+ * @returns {boolean}
107
+ */
81
108
  function equal (uriA, uriB, options) {
82
109
  if (typeof uriA === 'string') {
83
110
  uriA = unescape(uriA)
@@ -96,8 +123,13 @@ function equal (uriA, uriB, options) {
96
123
  return uriA.toLowerCase() === uriB.toLowerCase()
97
124
  }
98
125
 
126
+ /**
127
+ * @param {Readonly<import('./types/index').URIComponent>} cmpts
128
+ * @param {import('./types/index').Options} [opts]
129
+ * @returns {string}
130
+ */
99
131
  function serialize (cmpts, opts) {
100
- const components = {
132
+ const component = {
101
133
  host: cmpts.host,
102
134
  scheme: cmpts.scheme,
103
135
  userinfo: cmpts.userinfo,
@@ -117,28 +149,28 @@ function serialize (cmpts, opts) {
117
149
  const uriTokens = []
118
150
 
119
151
  // find scheme handler
120
- const schemeHandler = SCHEMES[(options.scheme || components.scheme || '').toLowerCase()]
152
+ const schemeHandler = getSchemeHandler(options.scheme || component.scheme)
121
153
 
122
154
  // perform scheme specific serialization
123
- if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(components, options)
155
+ if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options)
124
156
 
125
- if (components.path !== undefined) {
157
+ if (component.path !== undefined) {
126
158
  if (!options.skipEscape) {
127
- components.path = escape(components.path)
159
+ component.path = escape(component.path)
128
160
 
129
- if (components.scheme !== undefined) {
130
- components.path = components.path.split('%3A').join(':')
161
+ if (component.scheme !== undefined) {
162
+ component.path = component.path.split('%3A').join(':')
131
163
  }
132
164
  } else {
133
- components.path = unescape(components.path)
165
+ component.path = unescape(component.path)
134
166
  }
135
167
  }
136
168
 
137
- if (options.reference !== 'suffix' && components.scheme) {
138
- uriTokens.push(components.scheme, ':')
169
+ if (options.reference !== 'suffix' && component.scheme) {
170
+ uriTokens.push(component.scheme, ':')
139
171
  }
140
172
 
141
- const authority = recomposeAuthority(components)
173
+ const authority = recomposeAuthority(component)
142
174
  if (authority !== undefined) {
143
175
  if (options.reference !== 'suffix') {
144
176
  uriTokens.push('//')
@@ -146,51 +178,49 @@ function serialize (cmpts, opts) {
146
178
 
147
179
  uriTokens.push(authority)
148
180
 
149
- if (components.path && components.path.charAt(0) !== '/') {
181
+ if (component.path && component.path[0] !== '/') {
150
182
  uriTokens.push('/')
151
183
  }
152
184
  }
153
- if (components.path !== undefined) {
154
- let s = components.path
185
+ if (component.path !== undefined) {
186
+ let s = component.path
155
187
 
156
188
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
157
189
  s = removeDotSegments(s)
158
190
  }
159
191
 
160
- if (authority === undefined) {
161
- s = s.replace(/^\/\//u, '/%2F') // don't allow the path to start with "//"
192
+ if (
193
+ authority === undefined &&
194
+ s[0] === '/' &&
195
+ s[1] === '/'
196
+ ) {
197
+ // don't allow the path to start with "//"
198
+ s = '/%2F' + s.slice(2)
162
199
  }
163
200
 
164
201
  uriTokens.push(s)
165
202
  }
166
203
 
167
- if (components.query !== undefined) {
168
- uriTokens.push('?', components.query)
204
+ if (component.query !== undefined) {
205
+ uriTokens.push('?', component.query)
169
206
  }
170
207
 
171
- if (components.fragment !== undefined) {
172
- uriTokens.push('#', components.fragment)
208
+ if (component.fragment !== undefined) {
209
+ uriTokens.push('#', component.fragment)
173
210
  }
174
211
  return uriTokens.join('')
175
212
  }
176
213
 
177
- const hexLookUp = Array.from({ length: 127 }, (_v, k) => /[^!"$&'()*+,\-.;=_`a-z{}~]/u.test(String.fromCharCode(k)))
178
-
179
- function nonSimpleDomain (value) {
180
- let code = 0
181
- for (let i = 0, len = value.length; i < len; ++i) {
182
- code = value.charCodeAt(i)
183
- if (code > 126 || hexLookUp[code]) {
184
- return true
185
- }
186
- }
187
- return false
188
- }
189
-
190
214
  const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u
191
215
 
216
+ /**
217
+ * @param {string} uri
218
+ * @param {import('./types/index').Options} [opts]
219
+ * @returns
220
+ */
192
221
  function parse (uri, opts) {
193
222
  const options = Object.assign({}, opts)
223
+ /** @type {import('./types/index').URIComponent} */
194
224
  const parsed = {
195
225
  scheme: undefined,
196
226
  userinfo: undefined,
@@ -200,9 +230,15 @@ function parse (uri, opts) {
200
230
  query: undefined,
201
231
  fragment: undefined
202
232
  }
203
- const gotEncoding = uri.indexOf('%') !== -1
233
+
204
234
  let isIP = false
205
- if (options.reference === 'suffix') uri = (options.scheme ? options.scheme + ':' : '') + '//' + uri
235
+ if (options.reference === 'suffix') {
236
+ if (options.scheme) {
237
+ uri = options.scheme + ':' + uri
238
+ } else {
239
+ uri = '//' + uri
240
+ }
241
+ }
206
242
 
207
243
  const matches = uri.match(URI_PARSE)
208
244
 
@@ -221,13 +257,12 @@ function parse (uri, opts) {
221
257
  parsed.port = matches[5]
222
258
  }
223
259
  if (parsed.host) {
224
- const ipv4result = normalizeIPv4(parsed.host)
225
- if (ipv4result.isIPV4 === false) {
226
- const ipv6result = normalizeIPv6(ipv4result.host)
260
+ const ipv4result = isIPv4(parsed.host)
261
+ if (ipv4result === false) {
262
+ const ipv6result = normalizeIPv6(parsed.host)
227
263
  parsed.host = ipv6result.host.toLowerCase()
228
264
  isIP = ipv6result.isIPV6
229
265
  } else {
230
- parsed.host = ipv4result.host
231
266
  isIP = true
232
267
  }
233
268
  }
@@ -247,7 +282,7 @@ function parse (uri, opts) {
247
282
  }
248
283
 
249
284
  // find scheme handler
250
- const schemeHandler = SCHEMES[(options.scheme || parsed.scheme || '').toLowerCase()]
285
+ const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme)
251
286
 
252
287
  // check if scheme can't handle IRIs
253
288
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
@@ -264,11 +299,13 @@ function parse (uri, opts) {
264
299
  }
265
300
 
266
301
  if (!schemeHandler || (schemeHandler && !schemeHandler.skipNormalize)) {
267
- if (gotEncoding && parsed.scheme !== undefined) {
268
- parsed.scheme = unescape(parsed.scheme)
269
- }
270
- if (gotEncoding && parsed.host !== undefined) {
271
- parsed.host = unescape(parsed.host)
302
+ if (uri.indexOf('%') !== -1) {
303
+ if (parsed.scheme !== undefined) {
304
+ parsed.scheme = unescape(parsed.scheme)
305
+ }
306
+ if (parsed.host !== undefined) {
307
+ parsed.host = unescape(parsed.host)
308
+ }
272
309
  }
273
310
  if (parsed.path) {
274
311
  parsed.path = escape(unescape(parsed.path))
@@ -292,7 +329,7 @@ const fastUri = {
292
329
  SCHEMES,
293
330
  normalize,
294
331
  resolve,
295
- resolveComponents,
332
+ resolveComponent,
296
333
  equal,
297
334
  serialize,
298
335
  parse
@@ -1,188 +1,267 @@
1
1
  'use strict'
2
2
 
3
- const UUID_REG = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu
3
+ const { isUUID } = require('./utils')
4
4
  const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu
5
5
 
6
- function isSecure (wsComponents) {
7
- return typeof wsComponents.secure === 'boolean' ? wsComponents.secure : String(wsComponents.scheme).toLowerCase() === 'wss'
6
+ const supportedSchemeNames = /** @type {const} */ (['http', 'https', 'ws',
7
+ 'wss', 'urn', 'urn:uuid'])
8
+
9
+ /** @typedef {supportedSchemeNames[number]} SchemeName */
10
+
11
+ /**
12
+ * @param {string} name
13
+ * @returns {name is SchemeName}
14
+ */
15
+ function isValidSchemeName (name) {
16
+ return supportedSchemeNames.indexOf(/** @type {*} */ (name)) !== -1
8
17
  }
9
18
 
10
- function httpParse (components) {
11
- if (!components.host) {
12
- components.error = components.error || 'HTTP URIs must have a host.'
19
+ /**
20
+ * @callback SchemeFn
21
+ * @param {import('../types/index').URIComponent} component
22
+ * @param {import('../types/index').Options} options
23
+ * @returns {import('../types/index').URIComponent}
24
+ */
25
+
26
+ /**
27
+ * @typedef {Object} SchemeHandler
28
+ * @property {SchemeName} scheme - The scheme name.
29
+ * @property {boolean} [domainHost] - Indicates if the scheme supports domain hosts.
30
+ * @property {SchemeFn} parse - Function to parse the URI component for this scheme.
31
+ * @property {SchemeFn} serialize - Function to serialize the URI component for this scheme.
32
+ * @property {boolean} [skipNormalize] - Indicates if normalization should be skipped for this scheme.
33
+ * @property {boolean} [absolutePath] - Indicates if the scheme uses absolute paths.
34
+ * @property {boolean} [unicodeSupport] - Indicates if the scheme supports Unicode.
35
+ */
36
+
37
+ /**
38
+ * @param {import('../types/index').URIComponent} wsComponent
39
+ * @returns {boolean}
40
+ */
41
+ function wsIsSecure (wsComponent) {
42
+ if (wsComponent.secure === true) {
43
+ return true
44
+ } else if (wsComponent.secure === false) {
45
+ return false
46
+ } else if (wsComponent.scheme) {
47
+ return (
48
+ wsComponent.scheme.length === 3 &&
49
+ (wsComponent.scheme[0] === 'w' || wsComponent.scheme[0] === 'W') &&
50
+ (wsComponent.scheme[1] === 's' || wsComponent.scheme[1] === 'S') &&
51
+ (wsComponent.scheme[2] === 's' || wsComponent.scheme[2] === 'S')
52
+ )
53
+ } else {
54
+ return false
13
55
  }
56
+ }
14
57
 
15
- return components
58
+ /** @type {SchemeFn} */
59
+ function httpParse (component) {
60
+ if (!component.host) {
61
+ component.error = component.error || 'HTTP URIs must have a host.'
62
+ }
63
+
64
+ return component
16
65
  }
17
66
 
18
- function httpSerialize (components) {
19
- const secure = String(components.scheme).toLowerCase() === 'https'
67
+ /** @type {SchemeFn} */
68
+ function httpSerialize (component) {
69
+ const secure = String(component.scheme).toLowerCase() === 'https'
20
70
 
21
71
  // normalize the default port
22
- if (components.port === (secure ? 443 : 80) || components.port === '') {
23
- components.port = undefined
72
+ if (component.port === (secure ? 443 : 80) || component.port === '') {
73
+ component.port = undefined
24
74
  }
25
75
 
26
76
  // normalize the empty path
27
- if (!components.path) {
28
- components.path = '/'
77
+ if (!component.path) {
78
+ component.path = '/'
29
79
  }
30
80
 
31
81
  // NOTE: We do not parse query strings for HTTP URIs
32
82
  // as WWW Form Url Encoded query strings are part of the HTML4+ spec,
33
83
  // and not the HTTP spec.
34
84
 
35
- return components
85
+ return component
36
86
  }
37
87
 
38
- function wsParse (wsComponents) {
88
+ /** @type {SchemeFn} */
89
+ function wsParse (wsComponent) {
39
90
  // indicate if the secure flag is set
40
- wsComponents.secure = isSecure(wsComponents)
91
+ wsComponent.secure = wsIsSecure(wsComponent)
41
92
 
42
93
  // construct resouce name
43
- wsComponents.resourceName = (wsComponents.path || '/') + (wsComponents.query ? '?' + wsComponents.query : '')
44
- wsComponents.path = undefined
45
- wsComponents.query = undefined
94
+ wsComponent.resourceName = (wsComponent.path || '/') + (wsComponent.query ? '?' + wsComponent.query : '')
95
+ wsComponent.path = undefined
96
+ wsComponent.query = undefined
46
97
 
47
- return wsComponents
98
+ return wsComponent
48
99
  }
49
100
 
50
- function wsSerialize (wsComponents) {
101
+ /** @type {SchemeFn} */
102
+ function wsSerialize (wsComponent) {
51
103
  // normalize the default port
52
- if (wsComponents.port === (isSecure(wsComponents) ? 443 : 80) || wsComponents.port === '') {
53
- wsComponents.port = undefined
104
+ if (wsComponent.port === (wsIsSecure(wsComponent) ? 443 : 80) || wsComponent.port === '') {
105
+ wsComponent.port = undefined
54
106
  }
55
107
 
56
108
  // ensure scheme matches secure flag
57
- if (typeof wsComponents.secure === 'boolean') {
58
- wsComponents.scheme = (wsComponents.secure ? 'wss' : 'ws')
59
- wsComponents.secure = undefined
109
+ if (typeof wsComponent.secure === 'boolean') {
110
+ wsComponent.scheme = (wsComponent.secure ? 'wss' : 'ws')
111
+ wsComponent.secure = undefined
60
112
  }
61
113
 
62
114
  // reconstruct path from resource name
63
- if (wsComponents.resourceName) {
64
- const [path, query] = wsComponents.resourceName.split('?')
65
- wsComponents.path = (path && path !== '/' ? path : undefined)
66
- wsComponents.query = query
67
- wsComponents.resourceName = undefined
115
+ if (wsComponent.resourceName) {
116
+ const [path, query] = wsComponent.resourceName.split('?')
117
+ wsComponent.path = (path && path !== '/' ? path : undefined)
118
+ wsComponent.query = query
119
+ wsComponent.resourceName = undefined
68
120
  }
69
121
 
70
122
  // forbid fragment component
71
- wsComponents.fragment = undefined
123
+ wsComponent.fragment = undefined
72
124
 
73
- return wsComponents
125
+ return wsComponent
74
126
  }
75
127
 
76
- function urnParse (urnComponents, options) {
77
- if (!urnComponents.path) {
78
- urnComponents.error = 'URN can not be parsed'
79
- return urnComponents
128
+ /** @type {SchemeFn} */
129
+ function urnParse (urnComponent, options) {
130
+ if (!urnComponent.path) {
131
+ urnComponent.error = 'URN can not be parsed'
132
+ return urnComponent
80
133
  }
81
- const matches = urnComponents.path.match(URN_REG)
134
+ const matches = urnComponent.path.match(URN_REG)
82
135
  if (matches) {
83
- const scheme = options.scheme || urnComponents.scheme || 'urn'
84
- urnComponents.nid = matches[1].toLowerCase()
85
- urnComponents.nss = matches[2]
86
- const urnScheme = `${scheme}:${options.nid || urnComponents.nid}`
87
- const schemeHandler = SCHEMES[urnScheme]
88
- urnComponents.path = undefined
136
+ const scheme = options.scheme || urnComponent.scheme || 'urn'
137
+ urnComponent.nid = matches[1].toLowerCase()
138
+ urnComponent.nss = matches[2]
139
+ const urnScheme = `${scheme}:${options.nid || urnComponent.nid}`
140
+ const schemeHandler = getSchemeHandler(urnScheme)
141
+ urnComponent.path = undefined
89
142
 
90
143
  if (schemeHandler) {
91
- urnComponents = schemeHandler.parse(urnComponents, options)
144
+ urnComponent = schemeHandler.parse(urnComponent, options)
92
145
  }
93
146
  } else {
94
- urnComponents.error = urnComponents.error || 'URN can not be parsed.'
147
+ urnComponent.error = urnComponent.error || 'URN can not be parsed.'
95
148
  }
96
149
 
97
- return urnComponents
150
+ return urnComponent
98
151
  }
99
152
 
100
- function urnSerialize (urnComponents, options) {
101
- const scheme = options.scheme || urnComponents.scheme || 'urn'
102
- const nid = urnComponents.nid.toLowerCase()
153
+ /** @type {SchemeFn} */
154
+ function urnSerialize (urnComponent, options) {
155
+ if (urnComponent.nid === undefined) {
156
+ throw new Error('URN without nid cannot be serialized')
157
+ }
158
+ const scheme = options.scheme || urnComponent.scheme || 'urn'
159
+ const nid = urnComponent.nid.toLowerCase()
103
160
  const urnScheme = `${scheme}:${options.nid || nid}`
104
- const schemeHandler = SCHEMES[urnScheme]
161
+ const schemeHandler = getSchemeHandler(urnScheme)
105
162
 
106
163
  if (schemeHandler) {
107
- urnComponents = schemeHandler.serialize(urnComponents, options)
164
+ urnComponent = schemeHandler.serialize(urnComponent, options)
108
165
  }
109
166
 
110
- const uriComponents = urnComponents
111
- const nss = urnComponents.nss
112
- uriComponents.path = `${nid || options.nid}:${nss}`
167
+ const uriComponent = urnComponent
168
+ const nss = urnComponent.nss
169
+ uriComponent.path = `${nid || options.nid}:${nss}`
113
170
 
114
171
  options.skipEscape = true
115
- return uriComponents
172
+ return uriComponent
116
173
  }
117
174
 
118
- function urnuuidParse (urnComponents, options) {
119
- const uuidComponents = urnComponents
120
- uuidComponents.uuid = uuidComponents.nss
121
- uuidComponents.nss = undefined
175
+ /** @type {SchemeFn} */
176
+ function urnuuidParse (urnComponent, options) {
177
+ const uuidComponent = urnComponent
178
+ uuidComponent.uuid = uuidComponent.nss
179
+ uuidComponent.nss = undefined
122
180
 
123
- if (!options.tolerant && (!uuidComponents.uuid || !UUID_REG.test(uuidComponents.uuid))) {
124
- uuidComponents.error = uuidComponents.error || 'UUID is not valid.'
181
+ if (!options.tolerant && (!uuidComponent.uuid || !isUUID(uuidComponent.uuid))) {
182
+ uuidComponent.error = uuidComponent.error || 'UUID is not valid.'
125
183
  }
126
184
 
127
- return uuidComponents
185
+ return uuidComponent
128
186
  }
129
187
 
130
- function urnuuidSerialize (uuidComponents) {
131
- const urnComponents = uuidComponents
188
+ /** @type {SchemeFn} */
189
+ function urnuuidSerialize (uuidComponent) {
190
+ const urnComponent = uuidComponent
132
191
  // normalize UUID
133
- urnComponents.nss = (uuidComponents.uuid || '').toLowerCase()
134
- return urnComponents
192
+ urnComponent.nss = (uuidComponent.uuid || '').toLowerCase()
193
+ return urnComponent
135
194
  }
136
195
 
137
- const http = {
196
+ const http = /** @type {SchemeHandler} */ ({
138
197
  scheme: 'http',
139
198
  domainHost: true,
140
199
  parse: httpParse,
141
200
  serialize: httpSerialize
142
- }
201
+ })
143
202
 
144
- const https = {
203
+ const https = /** @type {SchemeHandler} */ ({
145
204
  scheme: 'https',
146
205
  domainHost: http.domainHost,
147
206
  parse: httpParse,
148
207
  serialize: httpSerialize
149
- }
208
+ })
150
209
 
151
- const ws = {
210
+ const ws = /** @type {SchemeHandler} */ ({
152
211
  scheme: 'ws',
153
212
  domainHost: true,
154
213
  parse: wsParse,
155
214
  serialize: wsSerialize
156
- }
215
+ })
157
216
 
158
- const wss = {
217
+ const wss = /** @type {SchemeHandler} */ ({
159
218
  scheme: 'wss',
160
219
  domainHost: ws.domainHost,
161
220
  parse: ws.parse,
162
221
  serialize: ws.serialize
163
- }
222
+ })
164
223
 
165
- const urn = {
224
+ const urn = /** @type {SchemeHandler} */ ({
166
225
  scheme: 'urn',
167
226
  parse: urnParse,
168
227
  serialize: urnSerialize,
169
228
  skipNormalize: true
170
- }
229
+ })
171
230
 
172
- const urnuuid = {
231
+ const urnuuid = /** @type {SchemeHandler} */ ({
173
232
  scheme: 'urn:uuid',
174
233
  parse: urnuuidParse,
175
234
  serialize: urnuuidSerialize,
176
235
  skipNormalize: true
177
- }
236
+ })
178
237
 
179
- const SCHEMES = {
238
+ const SCHEMES = /** @type {Record<SchemeName, SchemeHandler>} */ ({
180
239
  http,
181
240
  https,
182
241
  ws,
183
242
  wss,
184
243
  urn,
185
244
  'urn:uuid': urnuuid
245
+ })
246
+
247
+ Object.setPrototypeOf(SCHEMES, null)
248
+
249
+ /**
250
+ * @param {string|undefined} scheme
251
+ * @returns {SchemeHandler|undefined}
252
+ */
253
+ function getSchemeHandler (scheme) {
254
+ return (
255
+ scheme && (
256
+ SCHEMES[/** @type {SchemeName} */ (scheme)] ||
257
+ SCHEMES[/** @type {SchemeName} */(scheme.toLowerCase())])
258
+ ) ||
259
+ undefined
186
260
  }
187
261
 
188
- module.exports = SCHEMES
262
+ module.exports = {
263
+ wsIsSecure,
264
+ SCHEMES,
265
+ isValidSchemeName,
266
+ getSchemeHandler,
267
+ }