UNPKG

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