Skip to content

Commit

Permalink
feat: add connection string builder
Browse files Browse the repository at this point in the history
  • Loading branch information
dhensby committed Aug 8, 2023
1 parent 813ad83 commit 369a63f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/builder/index.ts
@@ -0,0 +1,49 @@
type ValidDataTypes = string | boolean | number | null | undefined | { toString(): string };

function isQuoted(val: string): boolean {
if (val[0] !== '{') {
return false;
}
for (let i = 1; i < val.length; i++) {
if (val[i] === '}') {
if (i + 1 === val.length) {
// if last char, then it's quoted properly
return true;
} else if (val[i + 1] !== '}') {
// the next char is no a `}` so there is no valid escaping here
return false;
} else {
// we are seeing an escaped `}`, so skip ahead
i++;
}
}
}
return false;
}

function needsQuotes(val: string): boolean {
return !isQuoted(val) && !!val.match(/\[|]|{|}|\|\(|\)|,|;|\?|\*|=|!|@/)?.length;
}

function encodeTuple(key: string, value: ValidDataTypes): [string, string] {
if (value === null || value === undefined) {
return [key, ''];
}
switch (typeof value) {
case 'boolean':
return [key, value ? 'Yes' : 'No'];
default: {
const strVal = (value as { toString(): string }).toString();
if (needsQuotes(strVal)) {
return [key, `{${strVal.replace(/}/g, '}}')}}`];
}
return [key, strVal];
}
}
}

export function buildConnectionString(data: Record<string, ValidDataTypes>): string {
return Object.entries(data).map(([key, value]) => {
return encodeTuple(key.trim(), value).join('=');
}).join(';');
}
2 changes: 2 additions & 0 deletions src/index.ts
@@ -1,6 +1,8 @@
import parseConnectionString from './parser/connection-string';
import parseSqlConnectionString from './parser/sql-connection-string';

export * from './builder';

export {
parseConnectionString,
parseSqlConnectionString,
Expand Down
21 changes: 21 additions & 0 deletions test/builder/connection-string.ts
@@ -0,0 +1,21 @@
import { buildConnectionString } from '../../src/builder';
import { expect } from 'chai';

describe('builder', () => {
it('builds a connection string', () => {
const built = buildConnectionString({
strkey: 'value',
booltrue: true,
boolfalse: false,
numkey: 123,
needsquote: 'a}test',
quotedquote: '{quoted}}value}',
quoted: '{regular value}',
badlyquoted: '{no closing quote',
badclose: '{close}early',
nullkey: null,
undefinedkey: undefined,
});
expect(built).to.equal('strkey=value;booltrue=Yes;boolfalse=No;numkey=123;needsquote={a}}test};quotedquote={quoted}}value};quoted={regular value};badlyquoted={{no closing quote};badclose={{close}}early};nullkey=;undefinedkey=');
});
});

0 comments on commit 369a63f

Please sign in to comment.