From cde44a62d5c5993a983a1b6f49078ae80f43ce84 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Thu, 29 Aug 2019 01:45:00 +0100 Subject: [PATCH] refactoring static members --- src/index.ts | 2 +- src/main.ts | 134 +++++++++++++++++++++++----------------------- test/main.spec.ts | 3 +- 3 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/index.ts b/src/index.ts index 56cbac4..341630f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ export {ConnectionString} from './main'; -export {IConnectionDefaults} from './types'; +export {IConnectionDefaults, IEncodingOptions, HostType, IHost, IParsedHost} from './types'; diff --git a/src/main.ts b/src/main.ts index a4ce9b8..b4e3663 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,7 +10,7 @@ export class ConnectionString { user?: string; password?: string; path?: string[]; - params?: { [name: string]: string }; + params?: { [name: string]: any }; /** * Virtualized accessor to the first host name. @@ -42,7 +42,7 @@ export class ConnectionString { cs = cs.trim(); - ConnectionString.validateUrl(cs); + validateUrl(cs); // Extracting the protocol: let m = cs.match(/^[\w-_.+!*'()$%:]*:\/\//); @@ -74,7 +74,7 @@ export class ConnectionString { const hosts = (endOfHosts === -1 ? cs : cs.substr(0, endOfHosts)).split(','); hosts.forEach(h => { - const host = ConnectionString.parseInnerHost(h); + const host = parseHost(h); if (host) { if (!this.hosts) { this.hosts = []; @@ -119,70 +119,8 @@ export class ConnectionString { } - private static validateUrl(url: string): void { - const idx = url.search(/[^A-Za-z0-9-._~:/?[\]@!$&'()*+,;=%]/); - if (idx >= 0) { - const s = JSON.stringify(url[idx]).replace(/^"|"$/g, '\''); - throw new Error('Invalid URL character ' + s + ' at position ' + idx); - } - } - static parseHost(host: string): IParsedHost | null { - return ConnectionString.parseInnerHost(host, true); - } - - private static parseInnerHost(host: string, raw?: boolean): IParsedHost | null { - if (raw) { - 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 (raw) { - m = host.match(/(([a-z0-9.$/-]*)(?::(-?[0-9a-z]+))?)/i); - } else { - m = host.match(/(([a-z0-9.$%-]*)(?::(-?[0-9a-z]+))?)/i); - } - } - if (m) { - const h: IHost = {}; - if (m[2]) { - if (isIPv6) { - h.name = m[2]; - h.type = HostType.IPv6; - } else { - if (m[2].match(/([0-9]{1,3}\.){3}[0-9]{1,3}/)) { - h.name = m[2]; - h.type = HostType.IPv4; - } else { - h.name = raw ? m[2] : decode(m[2]); - h.type = h.name.match(/\/|.*\.sock$/i) ? HostType.socket : 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 number: ' + JSON.stringify(p)); - } - } - if (h.name || h.port) { - Object.defineProperty(h, 'toString', { - value: (options: IEncodingOptions) => fullHostName(h, options) - }); - return h; - } - } - return null; + return parseHost(host, true); } toString(options?: IEncodingOptions): string { @@ -269,7 +207,7 @@ export class ConnectionString { obj.name = h.name; obj.type = h.type; } else { - const t = ConnectionString.parseInnerHost(h.name, true); + const t = parseHost(h.name, true); if (t) { obj.name = t.name; obj.type = t.type; @@ -332,6 +270,68 @@ export class ConnectionString { } } +function validateUrl(url: string): void { + const idx = url.search(/[^A-Za-z0-9-._~:/?[\]@!$&'()*+,;=%]/); + if (idx >= 0) { + const s = JSON.stringify(url[idx]).replace(/^"|"$/g, '\''); + throw new Error('Invalid URL character ' + s + ' at position ' + idx); + } +} + +function parseHost(host: string, raw?: boolean): IParsedHost | null { + if (raw) { + 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 (raw) { + m = host.match(/(([a-z0-9.$/-]*)(?::(-?[0-9a-z]+))?)/i); + } else { + m = host.match(/(([a-z0-9.$%-]*)(?::(-?[0-9a-z]+))?)/i); + } + } + if (m) { + const h: IHost = {}; + if (m[2]) { + if (isIPv6) { + h.name = m[2]; + h.type = HostType.IPv6; + } else { + if (m[2].match(/([0-9]{1,3}\.){3}[0-9]{1,3}/)) { + h.name = m[2]; + h.type = HostType.IPv4; + } else { + h.name = raw ? m[2] : decode(m[2]); + h.type = h.name.match(/\/|.*\.sock$/i) ? HostType.socket : 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 number: ' + JSON.stringify(p)); + } + } + if (h.name || h.port) { + Object.defineProperty(h, 'toString', { + value: (options: IEncodingOptions) => fullHostName(h, options) + }); + return h; + } + } + return null; +} + (function () { // hiding prototype members: ['setDefaults', 'toString', 'hostname', 'port'].forEach(prop => { diff --git a/test/main.spec.ts b/test/main.spec.ts index ad401c5..ddfa06e 100644 --- a/test/main.spec.ts +++ b/test/main.spec.ts @@ -1,6 +1,5 @@ import {expect} from './header'; -import {ConnectionString, IConnectionDefaults} from '../src'; -import {HostType, IHost, IParsedHost} from '../src/types'; +import {ConnectionString, IConnectionDefaults, HostType, IHost, IParsedHost} from '../src'; function parse(cs: string, defaults?: IConnectionDefaults): ConnectionString { return new ConnectionString(cs, defaults);