Skip to content

Commit

Permalink
Merge pull request #39 from vitaly-t/plus
Browse files Browse the repository at this point in the history
Plus
  • Loading branch information
vitaly-t committed Aug 9, 2020
2 parents 10621d0 + 8bf8b6f commit 75bfffc
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 32 deletions.
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "connection-string",
"version": "3.4.2",
"version": "4.0.0",
"description": "Advanced URL Connection String parser + generator.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -34,20 +34,20 @@
},
"license": "MIT",
"engines": {
"node": ">=4.5",
"npm": ">=2.15"
"node": ">=12",
"npm": ">=6"
},
"devDependencies": {
"@types/chai": "4.2.12",
"@types/mocha": "8.0.0",
"@types/node": "14.0.25",
"@types/mocha": "8.0.1",
"@types/node": "14.0.27",
"chai": "4.2.0",
"coveralls": "3.1.0",
"mocha": "8.0.1",
"mocha": "8.1.1",
"mocha-lcov-reporter": "1.3.0",
"nyc": "15.1.0",
"ts-node": "8.10.2",
"tslint": "6.1.2",
"tslint": "6.1.3",
"typescript": "3.9.7"
}
}
21 changes: 11 additions & 10 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class ConnectionString {

cs = cs ?? '';

if (typeof cs !== 'string') {
if (typeof cs as any !== 'string') {
throw new TypeError(`Invalid connection string: ${JSON.stringify(cs)}`);
}

Expand All @@ -93,11 +93,15 @@ export class ConnectionString {
validateUrl(cs); // will throw, if failed

// Extracting the protocol:
let m = cs.match(/^[\w-_.+!*'()$%:]*:\/\//);
let m = cs.match(/^(.*)?:\/\//);
if (m) {
const protocol = m[0].replace(/:\/\//, '');
if (protocol) {
this.protocol = decode(protocol);
const p = m[1]; // protocol name
if (p) {
const m2 = p.match(/^([a-z]+[a-z0-9+-.]*)/i);
if (p && (!m2 || m2[1] !== p)) {
throw new Error(`Invalid protocol name: ${p}`);
}
this.protocol = p;
}
cs = cs.substr(m[0].length);
}
Expand Down Expand Up @@ -180,12 +184,9 @@ export class ConnectionString {
* Converts this object into a valid connection string.
*/
toString(options?: IEncodingOptions): string {
let s = '';
let s = this.protocol ? `${this.protocol}://` : ``;
const opts = <IEncodingOptions>options || {};

if (this.protocol) {
s += encode(this.protocol, opts).replace(/%3A/g, ':') + '://';
}
if (this.user || this.password) {
if (this.user) {
s += encode(this.user, opts);
Expand Down Expand Up @@ -239,7 +240,7 @@ export class ConnectionString {
}

if (!('protocol' in this) && hasText(defaults.protocol)) {
this.protocol = defaults.protocol!.trim();
this.protocol = defaults.protocol?.trim();
}

// Missing default `hosts` are merged with the existing ones:
Expand Down
4 changes: 2 additions & 2 deletions src/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function hasText(txt?: string): boolean {
}

export function validateUrl(url: string): void {
const idx = url.search(/[^A-Za-z0-9-._:/?[\]@!$&'()*+,;=%]/);
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}`);
Expand All @@ -38,7 +38,7 @@ export function validateUrl(url: string): void {

export function parseHost(host: string, direct?: boolean): IParsedHost | null {
if (direct) {
if (typeof host !== 'string') {
if (typeof host as any !== 'string') {
throw new TypeError(`Invalid "host" parameter: ${JSON.stringify(host)}`);
}
host = host.trim();
Expand Down
32 changes: 19 additions & 13 deletions test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,30 @@ describe('constructor', () => {

describe('protocol', () => {
it('must recognize standard format', () => {
expect(parse('abc://')).to.eql({protocol: 'abc'});
expect(parse('abc123://')).to.eql({protocol: 'abc123'});
});
it('must allow sub-protocols', () => {
expect(parse('one:two:three://')).to.eql({protocol: 'one:two:three'});
it('must allow special symbols', () => {
expect(parse('one+two-three.four://')).to.eql({protocol: 'one+two-three.four'});
});
it('must ignore incomplete format', () => {
expect(parse('abc:/')).to.eql({hosts: [{name: 'abc', type: 'domain'}]});
expect(parse('://')).to.eql({});
});
it('must decode URL-encoded characters', () => {
expect(parse('a%20b%3F://')).to.eql({protocol: 'a b?'});
it('must throw on invalid symbols', () => {
expect(() => {
parse('a$b://');
}).to.throw('Invalid protocol name: a$b');
expect(() => {
parse('a%://');
}).to.throw('Invalid protocol name: a%');
});
it('must support special symbols', () => {
expect(parse('A9z$-_.+!*\'()://')).to.eql({protocol: 'A9z$-_. !*\'()'});
it('must throw on leading digits', () => {
expect(() => {
parse('123://');
}).to.throw('Invalid protocol name: 123');
expect(() => {
parse('1a://');
}).to.throw('Invalid protocol name: 1a');
});
});

Expand Down Expand Up @@ -394,10 +404,6 @@ describe('complex', () => {
});

describe('toString', () => {
it('must encode protocol', () => {
expect(create({protocol: 'abc 123?456'})).to.eq('abc%20123%3F456://');
expect(create({protocol: 'one:two:three'})).to.eq('one:two:three://');
});
it('must encode user', () => {
expect(create({user: 'user 1?2'})).to.eq('user%201%3F2@');
});
Expand Down Expand Up @@ -452,8 +458,8 @@ describe('toString', () => {
expect(a.toString()).to.eq('');
});
it('must encode dollar symbol when required', () => {
expect(parse('abc%20$://user$:pa$$@host$name.com/seg$?par$=1$2').toString()).to.eq('abc%20$://user$:pa$$@host$name.com/seg$?par$=1$2');
expect(parse('abc%20$://user$:pa$$@host$name.com/seg$?par$=1$2').toString({encodeDollar: true})).to.eq('abc%20%24://user%24:pa%24%24@host%24name.com/seg%24?par%24=1%242');
expect(parse('abc://user$:pa$$@host$name.com/seg$?par$=1$2').toString()).to.eq('abc://user$:pa$$@host$name.com/seg$?par$=1$2');
expect(parse('abc://user$:pa$$@host$name.com/seg$?par$=1$2').toString({encodeDollar: true})).to.eq('abc://user%24:pa%24%24@host%24name.com/seg%24?par%24=1%242');
});
it('must use plus for params when required', () => {
expect(parse('?a=+1++2').toString()).to.eq('?a=%201%20%202');
Expand Down

0 comments on commit 75bfffc

Please sign in to comment.