feat: added model to represent and construct filters when querying for records

This commit is contained in:
StevanFreeborn
2023-02-12 15:52:47 -06:00
parent abf571f415
commit d2edce6290
4 changed files with 257 additions and 67 deletions
+64 -12
View File
@@ -1,12 +1,64 @@
export enum FilterOperators { /**
Equal = 'eq', * @enum FilterOperators - The operators that can be used in a query filter
NotEqual = 'ne', */
Contains = 'contains', export enum FilterOperators {
IsNull = 'isnull', /**
NotNull = 'notnull', * @constant Equal - The equal operator
GreaterThan = 'gt', * @remarks Can be used with text, auto-number, date, and number fields as well as their formula equivalents.
LessThan = 'lt', */
And = 'and', Equal = 'eq',
Or = 'or',
Not = 'not', /**
} * @constant NotEqual - The not equal operator
* @remarks Can be used with text, auto-number, date, and number fields as well as their formula equivalents.
*/
NotEqual = 'ne',
/**
* @constant Contains - The contains operator
* @remarks Can be used with list fields as well as their formula equivalents.
*/
Contains = 'contains',
/**
* @constant IsNull - The is null operator
* @remarks Can be used with text, date, and number fields as well as their formula equivalents.
*/
IsNull = 'isnull',
/**
* @constant NotNull - The not null operator
* @remarks Can be used with text, date, and number fields as well as their formula equivalents.
*/
NotNull = 'notnull',
/**
* @constant GreaterThan - The greater than operator
* @remarks Can be used with auto-number, date, and number fields as well as their formula equivalents.
*/
GreaterThan = 'gt',
/**
* @constant LessThan - The less than operator
* @remarks Can be used with auto-number, date, and number fields as well as their formula equivalents.
*/
LessThan = 'lt',
/**
* @constant And - The and operator
* @remarks Can be used to create compound filters.
*/
And = 'and',
/**
* @constant Or - The or operator
* @remarks Can be used to create compound filters.
*/
Or = 'or',
/**
* @constant Not - The not operator
* @remarks Can be used to negate a filter and create compound filters.
*/
Not = 'not',
}
+43
View File
@@ -0,0 +1,43 @@
import { FilterOperators } from '../enums/FilterOperators';
export class QueryFilter {
public fieldId: number;
public operator: FilterOperators;
public value: string | number | Date | null;
constructor(
fieldId: number,
operator: FilterOperators,
value: string | number | Date | null
) {
if (
value === null &&
operator !== FilterOperators.IsNull &&
operator !== FilterOperators.NotNull
) {
throw new Error('Value cannot be null for this operator');
}
this.fieldId = fieldId;
this.operator = operator;
this.value = value;
}
public toString(): string {
if (this.value == null) {
return `${this.fieldId} ${this.operator}`;
}
if (this.value instanceof Date) {
return `${this.fieldId} ${
this.operator
} datetime'${this.value.toISOString()}'`;
}
if (typeof this.value === 'string') {
return `${this.fieldId} ${this.operator} '${this.value}'`;
}
return `${this.fieldId} ${this.operator} ${this.value}`;
}
}
+56 -55
View File
@@ -1,55 +1,56 @@
import { DataFormat } from '../enums/DataFormat'; import { DataFormat } from '../enums/DataFormat';
import { PagingRequest } from './PagingRequest'; import { PagingRequest } from './PagingRequest';
import { type QueryFilter } from './QueryFilter';
/**
* @class QueryRecordsRequest - Request to query for records. /**
*/ * @class QueryRecordsRequest - Request to query for records.
export class QueryRecordsRequest { */
/** export class QueryRecordsRequest {
* @property {number} appId - The id of the app the records belong to. /**
*/ * @property {number} appId - The id of the app the records belong to.
appId: number; */
appId: number;
/**
* @property {string} filter - The filter to use to query for records. /**
*/ * @property {string | QueryFilter} filter - The filter to use to query for records.
filter: string; */
filter: string | QueryFilter;
/**
* @property {number[]} fieldIds - The ids of the fields to include in the response. /**
*/ * @property {number[]} fieldIds - The ids of the fields to include in the response.
fieldIds: number[]; */
fieldIds: number[];
/**
* @property {DataFormat} dataFormat - The format of the data in the response. /**
*/ * @property {DataFormat} dataFormat - The format of the data in the response.
dataFormat: DataFormat; */
dataFormat: DataFormat;
/**
* @property {PagingRequest} pagingRequest - The paging request to use to query for records. /**
*/ * @property {PagingRequest} pagingRequest - The paging request to use to query for records.
pagingRequest: PagingRequest; */
pagingRequest: PagingRequest;
/**
* @constructor - Creates a new instance of QueryRecordsRequest /**
* @param {number} appId - The id of the app the records belong to. * @constructor - Creates a new instance of QueryRecordsRequest
* @param {string} filter - The filter to use to query for records. * @param {number} appId - The id of the app the records belong to.
* @param {number[]} fieldIds - The ids of the fields to include in the response. * @param {string | QueryFilter} filter - The filter to use to query for records.
* @param {DataFormat} dataFormat - The format of the data in the response. * @param {number[]} fieldIds - The ids of the fields to include in the response.
* @param {PagingRequest} pagingRequest - The paging request to use to query for records. * @param {DataFormat} dataFormat - The format of the data in the response.
* @returns {QueryRecordsRequest} - A new instance of QueryRecordsRequest * @param {PagingRequest} pagingRequest - The paging request to use to query for records.
*/ * @returns {QueryRecordsRequest} - A new instance of QueryRecordsRequest
constructor( */
appId: number, constructor(
filter: string, appId: number,
fieldIds: number[] = [], filter: string | QueryFilter,
dataFormat: DataFormat = DataFormat.Raw, fieldIds: number[] = [],
pagingRequest: PagingRequest = new PagingRequest(1, 50) dataFormat: DataFormat = DataFormat.Raw,
) { pagingRequest: PagingRequest = new PagingRequest(1, 50)
this.appId = appId; ) {
this.filter = filter; this.appId = appId;
this.fieldIds = fieldIds; this.filter = filter.toString();
this.dataFormat = dataFormat; this.fieldIds = fieldIds;
this.pagingRequest = pagingRequest; this.dataFormat = dataFormat;
} this.pagingRequest = pagingRequest;
} }
}
+94
View File
@@ -0,0 +1,94 @@
import { QueryFilter } from '../src/models/QueryFilter';
import { expect } from 'chai';
import { FilterOperators } from '../src/enums/FilterOperators';
describe('QueryFilter', function () {
it('should be defined', function () {
expect(QueryFilter).to.not.be.undefined;
});
it('should have a constructor', function () {
expect(QueryFilter).to.have.property('constructor');
});
it('should have a constructor that takes 3 parameters', function () {
expect(QueryFilter).to.have.lengthOf(3);
});
it('should have a constructor that throws an error if value is null and operator is not IsNull or NotNull', function () {
expect(() => new QueryFilter(1, FilterOperators.Equal, null)).to.throw(
'Value cannot be null for this operator'
);
});
it('should have a fieldId property', function () {
expect(new QueryFilter(1, FilterOperators.Equal, 'test')).to.have.property(
'fieldId'
);
});
it('should have an operator property', function () {
expect(new QueryFilter(1, FilterOperators.Equal, 'test')).to.have.property(
'operator'
);
});
it('should have a value property', function () {
expect(new QueryFilter(1, FilterOperators.Equal, 'test')).to.have.property(
'value'
);
});
it('should have a constructor that sets its properties correctly', function () {
const fieldId = 1;
const operator = FilterOperators.Equal;
const value = 'test';
const filter = new QueryFilter(fieldId, operator, value);
expect(filter).to.have.property('fieldId', fieldId);
expect(filter).to.have.property('operator', operator);
expect(filter).to.have.property('value', value);
});
describe('toString', function () {
it('should be defined', function () {
expect(QueryFilter.prototype.toString).to.not.be.undefined;
});
it('should be a function', function () {
expect(QueryFilter.prototype.toString).to.be.a('function');
});
it('should return a string', function () {
expect(
new QueryFilter(1, FilterOperators.Equal, 'test').toString()
).to.be.a('string');
});
it('should return a properly constructed filter string if value is null', function () {
expect(
new QueryFilter(1, FilterOperators.IsNull, null).toString()
).to.equal('1 isnull');
});
it('should return a properly constructed filter string if value is a Date', function () {
const date = new Date();
expect(
new QueryFilter(1, FilterOperators.Equal, date).toString()
).to.equal(`1 eq datetime'${date.toISOString()}'`);
});
it('should return a properly constructed filter string if value is a string', function () {
expect(
new QueryFilter(1, FilterOperators.Equal, 'test').toString()
).to.equal("1 eq 'test'");
});
it('should return a properly constructed filter string if value is a number', function () {
expect(new QueryFilter(1, FilterOperators.Equal, 1).toString()).to.equal(
'1 eq 1'
);
});
});
});