source: frontend/node_modules/fast-uri/lib/schemes.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 7.0 KB
Line 
1'use strict'
2
3const { isUUID } = require('./utils')
4const URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu
5
6const 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 */
15function isValidSchemeName (name) {
16 return supportedSchemeNames.indexOf(/** @type {*} */ (name)) !== -1
17}
18
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 */
41function 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
55 }
56}
57
58/** @type {SchemeFn} */
59function httpParse (component) {
60 if (!component.host) {
61 component.error = component.error || 'HTTP URIs must have a host.'
62 }
63
64 return component
65}
66
67/** @type {SchemeFn} */
68function httpSerialize (component) {
69 const secure = String(component.scheme).toLowerCase() === 'https'
70
71 // normalize the default port
72 if (component.port === (secure ? 443 : 80) || component.port === '') {
73 component.port = undefined
74 }
75
76 // normalize the empty path
77 if (!component.path) {
78 component.path = '/'
79 }
80
81 // NOTE: We do not parse query strings for HTTP URIs
82 // as WWW Form Url Encoded query strings are part of the HTML4+ spec,
83 // and not the HTTP spec.
84
85 return component
86}
87
88/** @type {SchemeFn} */
89function wsParse (wsComponent) {
90// indicate if the secure flag is set
91 wsComponent.secure = wsIsSecure(wsComponent)
92
93 // construct resouce name
94 wsComponent.resourceName = (wsComponent.path || '/') + (wsComponent.query ? '?' + wsComponent.query : '')
95 wsComponent.path = undefined
96 wsComponent.query = undefined
97
98 return wsComponent
99}
100
101/** @type {SchemeFn} */
102function wsSerialize (wsComponent) {
103// normalize the default port
104 if (wsComponent.port === (wsIsSecure(wsComponent) ? 443 : 80) || wsComponent.port === '') {
105 wsComponent.port = undefined
106 }
107
108 // ensure scheme matches secure flag
109 if (typeof wsComponent.secure === 'boolean') {
110 wsComponent.scheme = (wsComponent.secure ? 'wss' : 'ws')
111 wsComponent.secure = undefined
112 }
113
114 // reconstruct path from resource name
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
120 }
121
122 // forbid fragment component
123 wsComponent.fragment = undefined
124
125 return wsComponent
126}
127
128/** @type {SchemeFn} */
129function urnParse (urnComponent, options) {
130 if (!urnComponent.path) {
131 urnComponent.error = 'URN can not be parsed'
132 return urnComponent
133 }
134 const matches = urnComponent.path.match(URN_REG)
135 if (matches) {
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
142
143 if (schemeHandler) {
144 urnComponent = schemeHandler.parse(urnComponent, options)
145 }
146 } else {
147 urnComponent.error = urnComponent.error || 'URN can not be parsed.'
148 }
149
150 return urnComponent
151}
152
153/** @type {SchemeFn} */
154function 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()
160 const urnScheme = `${scheme}:${options.nid || nid}`
161 const schemeHandler = getSchemeHandler(urnScheme)
162
163 if (schemeHandler) {
164 urnComponent = schemeHandler.serialize(urnComponent, options)
165 }
166
167 const uriComponent = urnComponent
168 const nss = urnComponent.nss
169 uriComponent.path = `${nid || options.nid}:${nss}`
170
171 options.skipEscape = true
172 return uriComponent
173}
174
175/** @type {SchemeFn} */
176function urnuuidParse (urnComponent, options) {
177 const uuidComponent = urnComponent
178 uuidComponent.uuid = uuidComponent.nss
179 uuidComponent.nss = undefined
180
181 if (!options.tolerant && (!uuidComponent.uuid || !isUUID(uuidComponent.uuid))) {
182 uuidComponent.error = uuidComponent.error || 'UUID is not valid.'
183 }
184
185 return uuidComponent
186}
187
188/** @type {SchemeFn} */
189function urnuuidSerialize (uuidComponent) {
190 const urnComponent = uuidComponent
191 // normalize UUID
192 urnComponent.nss = (uuidComponent.uuid || '').toLowerCase()
193 return urnComponent
194}
195
196const http = /** @type {SchemeHandler} */ ({
197 scheme: 'http',
198 domainHost: true,
199 parse: httpParse,
200 serialize: httpSerialize
201})
202
203const https = /** @type {SchemeHandler} */ ({
204 scheme: 'https',
205 domainHost: http.domainHost,
206 parse: httpParse,
207 serialize: httpSerialize
208})
209
210const ws = /** @type {SchemeHandler} */ ({
211 scheme: 'ws',
212 domainHost: true,
213 parse: wsParse,
214 serialize: wsSerialize
215})
216
217const wss = /** @type {SchemeHandler} */ ({
218 scheme: 'wss',
219 domainHost: ws.domainHost,
220 parse: ws.parse,
221 serialize: ws.serialize
222})
223
224const urn = /** @type {SchemeHandler} */ ({
225 scheme: 'urn',
226 parse: urnParse,
227 serialize: urnSerialize,
228 skipNormalize: true
229})
230
231const urnuuid = /** @type {SchemeHandler} */ ({
232 scheme: 'urn:uuid',
233 parse: urnuuidParse,
234 serialize: urnuuidSerialize,
235 skipNormalize: true
236})
237
238const SCHEMES = /** @type {Record<SchemeName, SchemeHandler>} */ ({
239 http,
240 https,
241 ws,
242 wss,
243 urn,
244 'urn:uuid': urnuuid
245})
246
247Object.setPrototypeOf(SCHEMES, null)
248
249/**
250 * @param {string|undefined} scheme
251 * @returns {SchemeHandler|undefined}
252 */
253function getSchemeHandler (scheme) {
254 return (
255 scheme && (
256 SCHEMES[/** @type {SchemeName} */ (scheme)] ||
257 SCHEMES[/** @type {SchemeName} */(scheme.toLowerCase())])
258 ) ||
259 undefined
260}
261
262module.exports = {
263 wsIsSecure,
264 SCHEMES,
265 isValidSchemeName,
266 getSchemeHandler,
267}
Note: See TracBrowser for help on using the repository browser.