Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,25 @@ s.data('level1', 'level2');
// 'data.level1.level2'
```

##### compareToField(field)

Build value as field to facilitate field to field comparison. Can only be used in context of a value in a search dsl
predicate

```js
s.greaterThan('field1', s.compareToField('field2'));
// greaterThan: {field: field1, value: {field: field2}}
```

##### computedField(field)

Prefix field with identifier for a computed field.

```js
s.computedField('computedField');
// ':computedField'
```

##### contains(field, value)

Build a criterion matching `MultiSelectList` and `Collection` fields which contains the provided value.
Expand Down Expand Up @@ -1232,6 +1251,26 @@ Dynamic field names must be prefixed with `data.`.
Build a criterion matching `YesOrNo` fields that are either `true` or `false`.
Dynamic field names must be prefixed with `data.`.

##### greaterThan(field, value)

Build a criterion matching on field greater than provided value.
Dynamic field names must be prefixed with `data.`.

##### greaterThanOrEquals(field, value)

Build a criterion matching on field greater than or equals provided value.
Dynamic field names must be prefixed with `data.`.

##### lessThan(field, value)

Build a criterion matching on field less than provided value.
Dynamic field names must be prefixed with `data.`.

##### lessThanOrEquals(field, value)

Build a criterion matching on field less than or equals provided value.
Dynamic field names must be prefixed with `data.`.

##### sort(...instructions)

Build the top-level `sort` object by combining one or many sorting instructions.
Expand All @@ -1255,6 +1294,19 @@ Build the top-level `page` object.
* `index` is the number of the results page to retrieve and starts at `1`
* `size` is the maximum number of results to retrieve per page and is capped at `100`

#### searchParams(additionalProperties)

Build optional search request parameters

* `additionalProperties` - additional properties to be passed as request parameters

```js
s.searchParams()
.withLinks()
.withComputedFields('computedField')
.build();
```

#### Example

```javascript
Expand All @@ -1273,7 +1325,11 @@ const query = s.query(
s.equalsAny(s.data('field2'), ['VALUE_1', 'VALUE_2']),
s.equalsAnyIgnoreCase(s.data('field2'), ['value_1', 'value_2']),
s.hasValue(s.data('field3'), true),
s.is(s.data('yesOrNoField'), true),
s.is(s.data('yesOrNoField'), true),
s.greaterThan(s.data('numberField1'), 10),
s.greaterThanOrEquals(s.data('numberField2'), s.compareToField('numberField1')),
s.lessThan(s.data('numberField3'), 10),
s.lessThanOrEquals(s.computedField('numberField4'), 10),
)
);

Expand All @@ -1284,7 +1340,12 @@ const sort = s.sort(

const page = s.page(1, 30);

const response = await search(searchClient)('CaseType1')(query)(sort)(page);
const params = s.searchParams()
.withLinks()
.withComputedFields('computedField')
.build();

const response = await search(searchClient)('CaseType1')(query)(sort)(page, params);
```

### Redis Gateway
Expand Down
13 changes: 7 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions src/modules/http-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ export const httpClient = (baseUrl, axiosInstance = axios) => (accessTokenProvid
put: bodyRequest(axiosInstance.put)(urlBuilder(baseUrl))(accessTokenProvider),
});

const emptyRequest = (axiosFn) => (url) => (accessTokenProvider) => async (relativeUrl) => axiosFn(url(relativeUrl), headers(await authorization(accessTokenProvider)));
const emptyRequest = (axiosFn) => (url) => (accessTokenProvider) => async (relativeUrl, params) => axiosFn(url(relativeUrl), {
...headers(await authorization(accessTokenProvider)),
params,
});

const bodyRequest = (axiosFn) => (url) => (accessTokenProvider) => async (relativeUrl, body) => axiosFn(url(relativeUrl), body, headers(await authorization(accessTokenProvider)));
const bodyRequest = (axiosFn) => (url) => (accessTokenProvider) => async (relativeUrl, body, params) => axiosFn(url(relativeUrl), body, {
...headers(await authorization(accessTokenProvider)),
params,
});

const urlBuilder = (baseUrl) => (relativeUrl) => baseUrl + relativeUrl;

Expand Down
53 changes: 51 additions & 2 deletions src/modules/http-client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ describe('httpClient', () => {
expect(axios.get).toHaveBeenCalledWith('http://data-store:4452/path/to/resource', {headers: {Authorization: 'Bearer access-token-123'}});
});

test('should get resource with request parameters', async () => {
const expectedResp = {data: {foo: 'bar'}};
axios.get.mockResolvedValue(expectedResp);

const resp = await httpClient(baseUrl)(tokenProviderStub).get('/path/to/resource', {['with-links']: 'true'});

expect(resp).toEqual(expectedResp);
expect(axios.get).toHaveBeenCalledWith('http://data-store:4452/path/to/resource',
{
headers: {Authorization: 'Bearer access-token-123'},
params: {['with-links']: 'true'},
}
);
});

test('should securely post resource', async () => {
const body = {foo: 'bar'};
const expectedResp = {status: 201};
Expand All @@ -25,7 +40,24 @@ describe('httpClient', () => {
const resp = await httpClient(baseUrl)(tokenProviderStub).post('/path/to/resource', body);

expect(resp).toEqual(expectedResp);
expect(axios.post).toHaveBeenCalledWith('http://data-store:4452/path/to/resource', body,{headers: {Authorization: 'Bearer access-token-123'}});
expect(axios.post).toHaveBeenCalledWith('http://data-store:4452/path/to/resource', body, {headers: {Authorization: 'Bearer access-token-123'}});
});

test('should post resource with request parameters', async () => {
const body = {foo: 'bar'};
const expectedResp = {status: 201};
axios.post.mockResolvedValue(expectedResp);

const resp = await httpClient(baseUrl)(tokenProviderStub).post('/path/to/resource', body, {['computed-fields']: ['computedField1']});

expect(resp).toEqual(expectedResp);
expect(axios.post).toHaveBeenCalledWith('http://data-store:4452/path/to/resource',
body,
{
headers: {Authorization: 'Bearer access-token-123'},
params: {['computed-fields']: ['computedField1']},
}
);
});

test('should securely put resource', async () => {
Expand All @@ -36,7 +68,24 @@ describe('httpClient', () => {
const resp = await httpClient(baseUrl)(tokenProviderStub).put('/path/to/resource', body);

expect(resp).toEqual(expectedResp);
expect(axios.put).toHaveBeenCalledWith('http://data-store:4452/path/to/resource', body,{headers: {Authorization: 'Bearer access-token-123'}});
expect(axios.put).toHaveBeenCalledWith('http://data-store:4452/path/to/resource', body, {headers: {Authorization: 'Bearer access-token-123'}});
});

test('should put resource with request parameters', async () => {
const body = {foo: 'bar'};
const expectedResp = {status: 200};
axios.put.mockResolvedValue(expectedResp);

const resp = await httpClient(baseUrl)(tokenProviderStub).put('/path/to/resource', body, {filter: 'test'});

expect(resp).toEqual(expectedResp);
expect(axios.put).toHaveBeenCalledWith('http://data-store:4452/path/to/resource',
body,
{
headers: {Authorization: 'Bearer access-token-123'},
params: {filter: 'test'},
}
);
});

test('should accept custom axios instance', async () => {
Expand Down
55 changes: 53 additions & 2 deletions src/modules/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
* Search
*/

export const search = (http) => (caseTypeId) => (query) => (sort) => async (page) => {
export const search = (http) => (caseTypeId) => (query) => (sort) => async (page, params) => {
const url = `/case-types/${caseTypeId}/cases/search`;
const body = {
...query,
...sort,
...page,
};
const res = await http.post(url, body);
const res = await http.post(url, body, params);
return res.data;
};

Expand All @@ -33,6 +33,10 @@ const hasValue = matcher('hasValue');
const dateRange = matcher('dateRange');
const contains = matcher('contains');
const is = matcher('is');
const greaterThan = matcher('greaterThan');
const greaterThanOrEquals = matcher('greaterThanOrEquals');
const lessThan = matcher('lessThan');
const lessThanOrEquals = matcher('lessThanOrEquals');

const and = (...criteria) => ({
and: criteria,
Expand Down Expand Up @@ -83,9 +87,51 @@ const collectionItem = (field, value) => ({
field, value
});

/**
* Build value as field in field to field comparison. Can only be used in context of value for a given querydsl.
* @param field - field name to compare with
* @returns {{field}} object representing field to be compared
*/
const compareToField = (field) => ({
field,
});

/**
* Return field name with a prefix to identify a computed field in querydsl
* @param computedFieldName - computed field name
* @returns {String} field name prefixed with identifier for computed field
*/
const computedField = (computedFieldName) => ':' + computedFieldName;

/**
* Build optional search request parameters
* @param additionalParams - optional additional parameters to be included in the search query parameters
* @returns object with optional parameters to build
*/
const searchParams = (additionalParams) => {
const params = {...additionalParams};
return {
withLinks: function () {
Object.assign(params, {['with-links']: 'true'});
return this;
},
withComputedFields: function (...computedFields) {
if (computedFields?.length > 0) {
Object.assign(params, {['computed-fields']: computedFields.join(',')});
}
return this;
},
build: function () {
return params;
},
}
};

export const searchDsl = Object.freeze({
not,
and,
compareToField,
computedField,
data,
equals,
equalsIgnoreCase,
Expand All @@ -95,9 +141,14 @@ export const searchDsl = Object.freeze({
dateRange,
contains,
is,
greaterThan,
greaterThanOrEquals,
lessThan,
lessThanOrEquals,
page,
query,
or,
searchParams,
sort,
sortAsc,
sortDesc,
Expand Down
Loading