Skip to content

Commit

Permalink
Merge pull request #5 from xiadevisser/issue/3-escaping-quotes
Browse files Browse the repository at this point in the history
Escaping quotes
  • Loading branch information
xiadevisser authored Feb 16, 2022
2 parents 4e29c27 + dd50765 commit 0cdafdc
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "query-builder-odata",
"version": "1.1.1",
"version": "1.2.0",
"keywords": [
"odata",
"odata v4",
Expand Down
5 changes: 3 additions & 2 deletions src/filter-builder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LogicalOperator, ComparisonOperator, StringOperator } from './constants';
import { replaceSpecialCharacters } from './helper';

export class FilterBuilder {
private filter: string[] = [];
Expand Down Expand Up @@ -62,13 +63,13 @@ export class FilterBuilder {
this.filter.push(`${property} ${op} ${value}`);
return this;
}
private stringFunction(op: string, property: StringOperator, value: string | number): FilterBuilder {
private stringFunction(op: StringOperator, property: string, value: string | number): FilterBuilder {
value = this.stringify(value);
this.filter.push(`${op}(${property}, ${value})`);
return this;
}
private stringify(...values: (string | number)[]): string {
values = values.map(v => typeof v === 'string' ? `'${v}'` : v);
values = values.map(v => typeof v === 'string' ? `'${replaceSpecialCharacters(v)}'` : v);
const value = values.join(',');
return values.length > 1 ? `(${value})` : value;
}
Expand Down
12 changes: 12 additions & 0 deletions src/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function replaceSpecialCharacters(field: string): string {
field = field.replace(/'/g, '\'\'');

field = field.replace(/%/g, '%25');
field = field.replace(/\+/g, '%2B');
field = field.replace(/\//g, '%2F');
field = field.replace(/\?/g, '%3F');

field = field.replace(/#/g, '%23');
field = field.replace(/&/g, '%26');
return field;
}
4 changes: 4 additions & 0 deletions src/query-builder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { QueryType, LogicalOperator } from './constants';
import { FilterBuilder } from './filter-builder';
import { replaceSpecialCharacters } from './helper';

export class QueryBuilder {
public query: { [key: string]: QueryType } = {};
Expand All @@ -17,14 +18,17 @@ export class QueryBuilder {
return this;
}
public select(...fields: string[]): QueryBuilder {
fields = fields.map(f => replaceSpecialCharacters(f));
this.addQuery(QueryType.select, fields.join(','), ',');
return this;
}
public orderBy(...fields: string[]): QueryBuilder {
fields = fields.map(f => replaceSpecialCharacters(f));
this.addQuery(QueryType.orderBy, fields.join(','), ',');
return this;
}
public expand(field: string, ...callbacks: ((builder: QueryBuilder) => void)[]): QueryBuilder {
field = replaceSpecialCharacters(field);
const q: string[] = [field];
if (callbacks.length > 0) {
const b = new QueryBuilder();
Expand Down
26 changes: 26 additions & 0 deletions test/query-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,29 @@ it('should return query from the readme', () => {
const expected = '?$top=10&$skip=10&$count=true&$select=name&$orderby=name&$expand=Books($select=title)&$filter=name eq \'John Doe\'';
expect(query).toEqual(expected);
});

describe('special charachters', () => {
it('should escape special charachters', () => {
const query = new QueryBuilder()
.select('name\'s')
.orderBy('name+s')
.expand('Book/s', e => e.select('title?s'))
.filter(f => f.or(o => o
.eq('name', 'John Doe%s')
.eq('name', 'John Doe#s')
.eq('name', 'John Doe&s')
))
.toQuery();
const expected = '?$select=name\'\'s&$orderby=name%2Bs&$expand=Book%2Fs($select=title%3Fs)&$filter=name eq \'John Doe%25s\' or name eq \'John Doe%23s\' or name eq \'John Doe%26s\'';
expect(query).toEqual(expected);
});
it('should escape double special charachters', () => {
const query = new QueryBuilder()
.select('name+s')
.orderBy('name+s')
.toQuery();
const expected = '?$select=name%2Bs&$orderby=name%2Bs';
expect(query).toEqual(expected);
});
});

0 comments on commit 0cdafdc

Please sign in to comment.