UNPKG

connection-string

Version:

Advanced URL Connection String parser + generator.

102 lines (101 loc) 3.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fullHostName = fullHostName; exports.encode = encode; exports.decode = decode; exports.hasText = hasText; exports.validateUrl = validateUrl; exports.parseHost = parseHost; const types_1 = require("./types"); function fullHostName(obj, options) { let a = ''; if (obj.name) { const skipEncoding = obj.type === types_1.HostType.IPv4 || obj.type === types_1.HostType.IPv6; a = skipEncoding ? obj.name : encode(obj.name, options ?? {}); } if (obj.port) { a += `:${obj.port}`; } return a; } function encode(text, options) { text = encodeURIComponent(text); if (options.plusForSpace) { text = text.replace(/%20/g, '+'); } return options.encodeDollar ? text : text.replace(/%24/g, '$'); } function decode(text) { return decodeURIComponent(text.replace(/\+/g, '%20')); } function hasText(txt) { return typeof txt === 'string' && /\S/.test(txt); } function validateUrl(url) { const idx = url.search(/[^a-z0-9-._:\/?[\]@!$&'()*+,;=%~]/i); if (idx >= 0) { const s = JSON.stringify(url[idx]).replace(/^"|"$/g, `'`); throw new Error(`Invalid URL character ${s} at position ${idx}`); } } function parseHost(host, direct) { if (direct) { if (typeof host !== 'string') { throw new TypeError(`Invalid "host" parameter: ${JSON.stringify(host)}`); } host = host.trim(); } let m, isIPv6; if (host[0] === '[') { // This is IPv6, with [::] being the shortest possible m = host.match(/((\[[0-9a-z:%_]{2,45}])(?::(-?[0-9a-z]+))?)/i); isIPv6 = true; } else { // It is either IPv4 or domain/socket if (direct) { // Allowed directly: ForwardSlash + Space m = host.match(/(([a-z0-9.$/\- _]*)(?::(-?[0-9a-z]+))?)/i); } else { // Allow when indirectly: + and % m = host.match(/(([a-z0-9.+$%\-_]*)(?::(-?[0-9a-z]+))?)/i); } } if (m) { const h = {}; if (m[2]) { if (isIPv6) { h.name = m[2]; h.type = types_1.HostType.IPv6; } else { if (m[2].match(/([0-9]{1,3}\.){3}[0-9]{1,3}/)) { h.name = m[2]; h.type = types_1.HostType.IPv4; } else { h.name = direct ? m[2] : decode(m[2]); h.type = h.name.match(/\/|.*\.sock$/i) ? types_1.HostType.socket : types_1.HostType.domain; } } } if (m[3]) { const p = m[3], port = parseInt(p); if (port > 0 && port < 65536 && port.toString() === p) { h.port = port; } else { throw new Error(`Invalid port: ${JSON.stringify(p)}. Valid port range is: [1...65535]`); } } if (h.name || h.port) { Object.defineProperty(h, 'toString', { value: (options) => fullHostName(h, options), enumerable: false }); return h; } } return null; }