UNPKG

12.2 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ConnectionString = void 0;
4var util_1 = require("util");
5var os_1 = require("os");
6var types_1 = require("./types");
7var static_1 = require("./static");
8var errInvalidDefaults = "Invalid \"defaults\" parameter: ";
9var ConnectionString = /** @class */ (function () {
10 /**
11 * Constructor.
12 *
13 * @param cs - connection string (can be empty).
14 *
15 * @param defaults - optional defaults, which can also be set
16 * explicitly, via method setDefaults.
17 */
18 function ConnectionString(cs, defaults) {
19 var _this = this;
20 if (!(this instanceof ConnectionString)) {
21 throw new TypeError("Class constructor ConnectionString cannot be invoked without 'new'");
22 }
23 if (typeof cs !== 'string') {
24 throw new TypeError("Invalid connection string: " + JSON.stringify(cs));
25 }
26 if (typeof (defaults !== null && defaults !== void 0 ? defaults : {}) !== 'object') {
27 throw new TypeError(errInvalidDefaults + JSON.stringify(defaults));
28 }
29 cs = cs.trim();
30 static_1.validateUrl(cs); // will throw, if failed
31 // Extracting the protocol:
32 var m = cs.match(/^[\w-_.+!*'()$%:]*:\/\//);
33 if (m) {
34 var protocol = m[0].replace(/:\/\//, '');
35 if (protocol) {
36 this.protocol = static_1.decode(protocol);
37 }
38 cs = cs.substr(m[0].length);
39 }
40 // Extracting user + password:
41 m = cs.match(/^([\w-_.+!*'()$%]*):?([\w-_.+!*'()$%]*)@/);
42 if (m) {
43 if (m[1]) {
44 this.user = static_1.decode(m[1]);
45 }
46 if (m[2]) {
47 this.password = static_1.decode(m[2]);
48 }
49 cs = cs.substr(m[0].length);
50 }
51 // Extracting hosts details:
52 // (if it starts with `/`, it is the first path segment, i.e. no hosts specified)
53 if (cs[0] !== '/') {
54 var endOfHosts = cs.search(/[\/?]/);
55 var hosts = (endOfHosts === -1 ? cs : cs.substr(0, endOfHosts)).split(',');
56 hosts.forEach(function (h) {
57 var host = static_1.parseHost(h);
58 if (host) {
59 if (!_this.hosts) {
60 _this.hosts = [];
61 }
62 _this.hosts.push(host);
63 }
64 });
65 if (endOfHosts >= 0) {
66 cs = cs.substr(endOfHosts);
67 }
68 }
69 // Extracting the path:
70 m = cs.match(/\/([\w-_.+!*'()$%]+)/g);
71 if (m) {
72 this.path = m.map(function (s) { return static_1.decode(s.substr(1)); });
73 }
74 // Extracting parameters:
75 var idx = cs.indexOf('?');
76 if (idx !== -1) {
77 cs = cs.substr(idx + 1);
78 m = cs.match(/([\w-_.+!*'()$%]+)=([\w-_.+!*'()$%]+)/g);
79 if (m) {
80 var params_1 = {};
81 m.forEach(function (s) {
82 var a = s.split('=');
83 var prop = static_1.decode(a[0]);
84 if (prop in params_1) {
85 throw new Error("Parameter \"" + prop + "\" repeated.");
86 }
87 params_1[prop] = static_1.decode(a[1]);
88 });
89 this.params = params_1;
90 }
91 }
92 if (defaults) {
93 this.setDefaults(defaults);
94 }
95 }
96 Object.defineProperty(ConnectionString.prototype, "hostname", {
97 /**
98 * Safe read-accessor to the first host's name.
99 */
100 get: function () {
101 var _a;
102 return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].name;
103 },
104 enumerable: false,
105 configurable: true
106 });
107 Object.defineProperty(ConnectionString.prototype, "port", {
108 /**
109 * Safe read-accessor to the first host's port.
110 */
111 get: function () {
112 var _a;
113 return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].port;
114 },
115 enumerable: false,
116 configurable: true
117 });
118 Object.defineProperty(ConnectionString.prototype, "type", {
119 /**
120 * Safe read-accessor to the first host's type.
121 */
122 get: function () {
123 var _a;
124 return (_a = this.hosts) === null || _a === void 0 ? void 0 : _a[0].type;
125 },
126 enumerable: false,
127 configurable: true
128 });
129 /**
130 * Parses a host name into an object, which then can be passed into `setDefaults`.
131 *
132 * It returns `null` only when no valid host recognized.
133 */
134 ConnectionString.parseHost = function (host) {
135 return static_1.parseHost(host, true);
136 };
137 /**
138 * Converts this object into a valid connection string.
139 */
140 ConnectionString.prototype.toString = function (options) {
141 var s = '';
142 var opts = options || {};
143 if (this.protocol) {
144 s += static_1.encode(this.protocol, opts).replace(/%3A/g, ':') + '://';
145 }
146 if (this.user || this.password) {
147 if (this.user) {
148 s += static_1.encode(this.user, opts);
149 }
150 if (this.password) {
151 s += ':';
152 var h = opts.passwordHash;
153 if (h) {
154 var code = (typeof h === 'string' && h[0]) || '#';
155 s += code.repeat(this.password.length);
156 }
157 else {
158 s += static_1.encode(this.password, opts);
159 }
160 }
161 s += '@';
162 }
163 if (Array.isArray(this.hosts)) {
164 s += this.hosts.map(function (h) { return static_1.fullHostName(h, options); }).join();
165 }
166 if (Array.isArray(this.path)) {
167 this.path.forEach(function (seg) {
168 s += '/' + static_1.encode(seg, opts);
169 });
170 }
171 if (this.params && typeof this.params === 'object') {
172 var params = [];
173 for (var a in this.params) {
174 var value = this.params[a];
175 if (typeof value !== 'string') {
176 value = JSON.stringify(value);
177 }
178 value = static_1.encode(value, opts);
179 if (opts.plusForSpace) {
180 value = value.replace(/%20/g, '+');
181 }
182 params.push(static_1.encode(a, opts) + "=" + value);
183 }
184 if (params.length) {
185 s += "?" + params.join('&');
186 }
187 }
188 return s;
189 };
190 /**
191 * Applies default parameters, and returns itself.
192 */
193 ConnectionString.prototype.setDefaults = function (defaults) {
194 if (!defaults || typeof defaults !== 'object') {
195 throw new TypeError(errInvalidDefaults + JSON.stringify(defaults));
196 }
197 if (!('protocol' in this) && static_1.hasText(defaults.protocol)) {
198 this.protocol = defaults.protocol.trim();
199 }
200 // Missing default `hosts` are merged with the existing ones:
201 if (Array.isArray(defaults.hosts)) {
202 var hosts_1 = Array.isArray(this.hosts) ? this.hosts : [];
203 var dhHosts = defaults.hosts.filter(function (d) { return d && typeof d === 'object'; });
204 dhHosts.forEach(function (dh) {
205 var dhName = static_1.hasText(dh.name) ? dh.name.trim() : undefined;
206 var h = { name: dhName, port: dh.port, type: dh.type };
207 var found = false;
208 for (var i = 0; i < hosts_1.length; i++) {
209 var thisHost = static_1.fullHostName(hosts_1[i]), defHost = static_1.fullHostName(h);
210 if (thisHost.toLowerCase() === defHost.toLowerCase()) {
211 found = true;
212 break;
213 }
214 }
215 if (!found) {
216 var obj_1 = {};
217 if (h.name) {
218 if (h.type && h.type in types_1.HostType) {
219 obj_1.name = h.name;
220 obj_1.type = h.type;
221 }
222 else {
223 var t = static_1.parseHost(h.name, true);
224 if (t) {
225 obj_1.name = t.name;
226 obj_1.type = t.type;
227 }
228 }
229 }
230 var p = h.port;
231 if (typeof p === 'number' && p > 0 && p < 65536) {
232 obj_1.port = p;
233 }
234 if (obj_1.name || obj_1.port) {
235 Object.defineProperty(obj_1, 'toString', {
236 value: function (options) { return static_1.fullHostName(obj_1, options); }
237 });
238 hosts_1.push(obj_1);
239 }
240 }
241 });
242 if (hosts_1.length) {
243 this.hosts = hosts_1;
244 }
245 }
246 if (!('user' in this) && static_1.hasText(defaults.user)) {
247 this.user = defaults.user.trim();
248 }
249 if (!('password' in this) && static_1.hasText(defaults.password)) {
250 this.password = defaults.password.trim();
251 }
252 // Since the order of `path` segments is usually important, we set default
253 // `path` segments as they are, but only when they are missing completely:
254 if (!('path' in this) && Array.isArray(defaults.path)) {
255 var s = defaults.path.filter(static_1.hasText);
256 if (s.length) {
257 this.path = s;
258 }
259 }
260 // Missing default `params` are merged with the existing ones:
261 if (defaults.params && typeof defaults.params === 'object') {
262 var keys = Object.keys(defaults.params);
263 if (keys.length) {
264 if (this.params && typeof (this.params) === 'object') {
265 for (var a in defaults.params) {
266 if (!(a in this.params)) {
267 this.params[a] = defaults.params[a];
268 }
269 }
270 }
271 else {
272 this.params = {};
273 for (var b in defaults.params) {
274 this.params[b] = defaults.params[b];
275 }
276 }
277 }
278 }
279 return this;
280 };
281 return ConnectionString;
282}());
283exports.ConnectionString = ConnectionString;
284(function () {
285 // hiding prototype members, to keep the type signature clean:
286 ['setDefaults', 'toString', 'hostname', 'port', 'type'].forEach(function (prop) {
287 var desc = Object.getOwnPropertyDescriptor(ConnectionString.prototype, prop);
288 desc.enumerable = false;
289 Object.defineProperty(ConnectionString.prototype, prop, desc);
290 });
291 var inspecting = false;
292 // istanbul ignore else
293 if (util_1.inspect.custom) {
294 Object.defineProperty(ConnectionString.prototype, util_1.inspect.custom, {
295 value: function () {
296 if (inspecting) {
297 return this;
298 }
299 inspecting = true;
300 var options = { colors: process.stdout.isTTY };
301 var src = util_1.inspect(this, options);
302 var _a = this, hostname = _a.hostname, port = _a.port, type = _a.type;
303 var vp = util_1.inspect({ hostname: hostname, port: port, type: type }, options);
304 inspecting = false;
305 return "" + src + os_1.EOL + "Virtual Properties: " + vp;
306 }
307 });
308 }
309})();