UNPKG

connection-string

Version:

Advanced URL Connection String parser + generator.

323 lines (322 loc) 12.7 kB
"use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConnectionString = void 0; var types_1 = require("./types"); var static_1 = require("./static"); var inspect_1 = require("./inspect"); var errInvalidDefaults = "Invalid \"defaults\" parameter: "; var ConnectionString = /** @class */ (function () { /** * Constructor. * * @param cs - connection string (can be empty). * * @param defaults - optional defaults, which can also be set * explicitly, via method setDefaults. */ function ConnectionString(cs, defaults) { var _this = this; if (!(this instanceof ConnectionString)) { throw new TypeError("Class constructor ConnectionString cannot be invoked without 'new'"); } cs = cs !== null && cs !== void 0 ? cs : ''; if (typeof cs !== 'string') { throw new TypeError("Invalid connection string: ".concat(JSON.stringify(cs))); } if (typeof (defaults !== null && defaults !== void 0 ? defaults : {}) !== 'object') { throw new TypeError(errInvalidDefaults + JSON.stringify(defaults)); } cs = cs.trim(); (0, static_1.validateUrl)(cs); // will throw, if failed // Extracting the protocol: var m = cs.match(/^(.*)?:\/\//); if (m) { var p = m[1]; // protocol name if (p) { var m2 = p.match(/^([a-z]+[a-z0-9+-.:]*)/i); if (p && (!m2 || m2[1] !== p)) { throw new Error("Invalid protocol name: ".concat(p)); } this.protocol = p; } cs = cs.substring(m[0].length); } // Extracting user + password: m = cs.match(/^([\w-_.+!*'()$%]*):?([\w-_.+!*'()$%~]*)@/); if (m) { if (m[1]) { this.user = (0, static_1.decode)(m[1]); } if (m[2]) { this.password = (0, static_1.decode)(m[2]); } cs = cs.substring(m[0].length); } // Extracting hosts details: // (if it starts with `/`, it is the first path segment, i.e. no hosts specified) if (cs[0] !== '/') { var endOfHosts = cs.search(/[\/?]/); var hosts = (endOfHosts === -1 ? cs : cs.substring(0, endOfHosts)).split(','); hosts.forEach(function (h) { var host = (0, static_1.parseHost)(h); if (host) { if (!_this.hosts) { _this.hosts = []; } _this.hosts.push(host); } }); if (endOfHosts >= 0) { cs = cs.substring(endOfHosts); } } // Extracting the path: m = cs.match(/\/([\w-_.+!*'()$%]+)/g); if (m) { this.path = m.map(function (s) { return (0, static_1.decode)(s.substring(1)); }); } // Extracting parameters: var idx = cs.indexOf('?'); if (idx !== -1) { cs = cs.substring(idx + 1); m = cs.match(/([\w-_.+!*'()$%]+)=([\w-_.+!*'()$%,]+)/g); if (m) { var params_1 = {}; m.forEach(function (s) { var _a; var a = s.split('='); var prop = (0, static_1.decode)(a[0]); var val = a[1].split(',').map(static_1.decode); if (prop in params_1) { if (Array.isArray(params_1[prop])) { (_a = params_1[prop]).push.apply(_a, val); } else { params_1[prop] = __spreadArray([params_1[prop]], val, true); } } else { params_1[prop] = val.length > 1 ? val : val[0]; } }); this.params = params_1; } } if (defaults) { this.setDefaults(defaults); } } Object.defineProperty(ConnectionString.prototype, "host", { /** * Safe read-accessor to the first host's full name (hostname + port). */ get: function () { var _a; return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].toString(); }, enumerable: false, configurable: true }); Object.defineProperty(ConnectionString.prototype, "hostname", { /** * Safe read-accessor to the first host's name (without port). */ get: function () { var _a; return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].name; }, enumerable: false, configurable: true }); Object.defineProperty(ConnectionString.prototype, "port", { /** * Safe read-accessor to the first host's port. */ get: function () { var _a; return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].port; }, enumerable: false, configurable: true }); Object.defineProperty(ConnectionString.prototype, "type", { /** * Safe read-accessor to the first host's type. */ get: function () { var _a; return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].type; }, enumerable: false, configurable: true }); /** * Parses a host name into an object, which then can be passed into `setDefaults`. * * It returns `null` only when no valid host recognized. */ ConnectionString.parseHost = function (host) { return (0, static_1.parseHost)(host, true); }; /** * Converts this object into a valid connection string. */ ConnectionString.prototype.toString = function (options) { var s = this.protocol ? "".concat(this.protocol, "://") : ""; var opts = options || {}; if (this.user || this.password) { if (this.user) { s += (0, static_1.encode)(this.user, opts); } if (this.password) { s += ':'; var h = opts.passwordHash; if (h) { var code = (typeof h === 'string' && h[0]) || '#'; s += code.repeat(this.password.length); } else { s += (0, static_1.encode)(this.password, opts); } } s += '@'; } if (Array.isArray(this.hosts)) { s += this.hosts.map(function (h) { return (0, static_1.fullHostName)(h, options); }).join(); } if (Array.isArray(this.path)) { this.path.forEach(function (seg) { s += "/".concat((0, static_1.encode)(seg, opts)); }); } if (this.params && typeof this.params === 'object') { var params = []; for (var a in this.params) { var value = this.params[a]; value = Array.isArray(value) ? value : [value]; value = value.map(function (v) { return (0, static_1.encode)(typeof v === 'string' ? v : JSON.stringify(v), opts); }).join(); if (opts.plusForSpace) { value = value.replace(/%20/g, '+'); } params.push("".concat((0, static_1.encode)(a, opts), "=").concat(value)); } if (params.length) { s += "?".concat(params.join('&')); } } return s; }; /** * Applies default parameters, and returns itself. */ ConnectionString.prototype.setDefaults = function (defaults) { if (!defaults || typeof defaults !== 'object') { throw new TypeError(errInvalidDefaults + JSON.stringify(defaults)); } if (!('protocol' in this) && (0, static_1.hasText)(defaults.protocol)) { this.protocol = defaults.protocol && defaults.protocol.trim(); } // Missing default `hosts` are merged with the existing ones: if (Array.isArray(defaults.hosts)) { var hosts_1 = Array.isArray(this.hosts) ? this.hosts : []; var dhHosts = defaults.hosts.filter(function (d) { return d && typeof d === 'object'; }); dhHosts.forEach(function (dh) { var dhName = (0, static_1.hasText)(dh.name) ? dh.name.trim() : undefined; var h = { name: dhName, port: dh.port, type: dh.type }; var found = false; for (var i = 0; i < hosts_1.length; i++) { var thisHost = (0, static_1.fullHostName)(hosts_1[i]), defHost = (0, static_1.fullHostName)(h); if (thisHost.toLowerCase() === defHost.toLowerCase()) { found = true; break; } } if (!found) { var obj_1 = {}; if (h.name) { if (h.type && h.type in types_1.HostType) { obj_1.name = h.name; obj_1.type = h.type; } else { var t = (0, static_1.parseHost)(h.name, true); if (t) { obj_1.name = t.name; obj_1.type = t.type; } } } var p = h.port; if (typeof p === 'number' && p > 0 && p < 65536) { obj_1.port = p; } if (obj_1.name || obj_1.port) { Object.defineProperty(obj_1, 'toString', { value: function (options) { return (0, static_1.fullHostName)(obj_1, options); } }); hosts_1.push(obj_1); } } }); if (hosts_1.length) { this.hosts = hosts_1; } } if (!('user' in this) && (0, static_1.hasText)(defaults.user)) { this.user = defaults.user.trim(); } if (!('password' in this) && (0, static_1.hasText)(defaults.password)) { this.password = defaults.password.trim(); } // Since the order of `path` segments is usually important, we set default // `path` segments as they are, but only when they are missing completely: if (!('path' in this) && Array.isArray(defaults.path)) { var s = defaults.path.filter(static_1.hasText); if (s.length) { this.path = s; } } // Missing default `params` are merged with the existing ones: if (defaults.params && typeof defaults.params === 'object') { var keys = Object.keys(defaults.params); if (keys.length) { if (this.params && typeof this.params === 'object') { for (var a in defaults.params) { if (!(a in this.params)) { this.params[a] = defaults.params[a]; } } } else { this.params = {}; for (var b in defaults.params) { this.params[b] = defaults.params[b]; } } } } return this; }; return ConnectionString; }()); exports.ConnectionString = ConnectionString; (function () { // hiding prototype methods, to keep the type signature clean: ['setDefaults', 'toString'].forEach(function (prop) { var desc = Object.getOwnPropertyDescriptor(ConnectionString.prototype, prop); desc.enumerable = false; Object.defineProperty(ConnectionString.prototype, prop, desc); }); (0, inspect_1.setupCustomInspect)(ConnectionString); })();