Skip to content

Commit f20dcb0

Browse files
authored
feat: filtering on GET /api/logs
2 parents 9ae9884 + 3b9b126 commit f20dcb0

30 files changed

Lines changed: 615 additions & 132 deletions

.validaterc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"parameters": {
1919
"no_parameter_description": "error",
2020
"param_name_case_convention": [
21-
"error",
22-
"lower_snake_case"
21+
"warning",
22+
"lower_camel_case"
2323
],
2424
"invalid_type_format_pair": "error",
2525
"content_type_parameter": "error",
@@ -33,7 +33,7 @@
3333
"snake_case_only": "off",
3434
"paths_case_convention": [
3535
"error",
36-
"lower_snake_case"
36+
"lower_camel_case"
3737
]
3838
},
3939
"responses": {
@@ -56,12 +56,12 @@
5656
"inconsistent_property_type": "error",
5757
"property_case_convention": [
5858
"error",
59-
"lower_snake_case"
59+
"lower_camel_case"
6060
],
6161
"property_case_collision": "error",
6262
"enum_case_convention": [
6363
"error",
64-
"lower_snake_case"
64+
"lower_camel_case"
6565
]
6666
},
6767
"walker": {

lib/database/adapters/LogAdapter.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ class LogAdapter {
2525
*/
2626
static toEntity(databaseObject) {
2727
return Object.assign(new Log(), {
28-
entryID: databaseObject.id,
28+
entryId: databaseObject.id,
2929
authorID: 'Batman',
3030
title: databaseObject.title,
3131
creationTime: new Date(databaseObject.createdAt).getTime(),
3232
tags: [`Tag${databaseObject.id}`, `Tag${++databaseObject.id}`],
33+
origin: databaseObject.origin,
3334
content: [
3435
{ content: 'Batman wrote this...', sender: 'Batman' },
3536
{ content: 'Nightwing wrote this...', sender: 'Nightwing' },
@@ -46,7 +47,7 @@ class LogAdapter {
4647
*/
4748
static toDatabase(entityObject) {
4849
return {
49-
id: entityObject.entryID,
50+
id: entityObject.entryId,
5051
title: entityObject.title,
5152
subtype: 'run',
5253
origin: 'process',

lib/database/repositories/LogRepository.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ class LogRepository {
3030
/**
3131
* Returns all entities.
3232
*
33+
* @param {Object} queryBuilder The QueryBuilder to use.
3334
* @returns {Promise} Promise object representing the full mock data
3435
*/
35-
async findAll() {
36-
return Log.findAll().map(LogAdapter.toEntity);
36+
async findAll(queryBuilder) {
37+
return Log.findAll(queryBuilder.toImplementation()).map(LogAdapter.toEntity);
3738
}
3839

3940
/**
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
/**
15+
* Sequelize implementation of the QueryBuilder.
16+
*/
17+
class QueryBuilder {
18+
/**
19+
* Creates a new `QueryBuilder` instance.
20+
*/
21+
constructor() {
22+
this.options = {};
23+
}
24+
25+
/**
26+
* The numbers of items to return.
27+
*
28+
* @param {Number} number The numbers of items to return.
29+
* @returns {Object} The current QueryBuilder instance.
30+
*/
31+
limit(number) {
32+
this.options.limit = number;
33+
return this;
34+
}
35+
36+
/**
37+
* The number of items to skip before starting to collect the result set.
38+
*
39+
* @param {Number} number The number of items to skip.
40+
* @returns {Object} The current QueryBuilder instance.
41+
*/
42+
offset(number) {
43+
this.options.offset = number;
44+
return this;
45+
}
46+
47+
/**
48+
* Set the order of elements.
49+
*
50+
* @param {String|Array} order Either a string or an array of strings.
51+
* @returns {Object} The current QueryBuilder instance.
52+
*/
53+
orderBy(order) {
54+
if (Array.isArray(order)) {
55+
for (const orderElement of order) {
56+
this.orderBy(orderElement);
57+
}
58+
return this;
59+
}
60+
61+
if (!this.options.order) {
62+
this.options.order = [];
63+
}
64+
65+
if (order.startsWith('-')) {
66+
this.options.order.push([order.substr(1), 'DESC']);
67+
} else {
68+
this.options.order.push([order, 'ASC']);
69+
}
70+
}
71+
72+
/**
73+
* Returns the implementation specific query.
74+
*
75+
* @returns {Object} Implementation specific query.
76+
*/
77+
toImplementation() {
78+
return this.options;
79+
}
80+
81+
/**
82+
* Adds a filter on the given column value pair.
83+
*
84+
* @param {*} column The target column.
85+
* @param {*} value The required value.
86+
* @returns {Object} The current QueryBuilder instance.
87+
*/
88+
where(column, value) {
89+
if (!this.options.where) {
90+
this.options.where = {};
91+
}
92+
93+
this.options.where[column] = value;
94+
return this;
95+
}
96+
}
97+
98+
module.exports = QueryBuilder;

lib/database/utilities/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14+
const QueryBuilder = require('./QueryBuilder');
1415
const TransactionHelper = require('./TransactionHelper');
1516

1617
module.exports = (sequelize) => ({
18+
QueryBuilder,
1719
TransactionHelper: TransactionHelper(sequelize),
1820
});

lib/domain/dtos/CreateLogDto.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14-
const { attributes } = require('structure');
14+
const Joi = require('@hapi/joi');
1515

16-
const BodyDto = attributes({
17-
title: {
18-
type: String,
19-
required: true,
20-
minLength: 3,
21-
},
22-
})(class BodyDto {});
16+
const BodyDto = Joi.object({
17+
title: Joi.string()
18+
.required()
19+
.min(3),
20+
});
2321

24-
const CreateLogDto = attributes({
22+
const CreateLogDto = Joi.object({
23+
query: Joi.object({}),
2524
body: BodyDto,
26-
})(class CreateLogDto {});
25+
params: Joi.object({}),
26+
});
2727

2828
module.exports = CreateLogDto;

lib/domain/dtos/GetAllLogsDto.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
const Joi = require('@hapi/joi');
15+
const PaginationDto = require('./PaginationDto');
16+
17+
const CustomJoi = Joi.extend({
18+
base: Joi.array(),
19+
type: 'stringArray',
20+
coerce: (value) => ({ value: value.split ? value.split(',') : value }),
21+
});
22+
23+
const FilterDto = Joi.object({
24+
origin: Joi.string()
25+
.valid('human', 'process'),
26+
});
27+
28+
const QueryDto = Joi.object({
29+
filter: FilterDto,
30+
page: PaginationDto,
31+
sort: CustomJoi.stringArray()
32+
.items(Joi.string()
33+
.valid('id', '-id')
34+
.valid('title', '-title')),
35+
token: Joi.string(),
36+
});
37+
38+
const GetAllLogsDto = Joi.object({
39+
body: Joi.object({}),
40+
params: Joi.object({}),
41+
query: QueryDto,
42+
});
43+
44+
module.exports = GetAllLogsDto;

lib/domain/dtos/GetLogDto.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,22 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14-
const { attributes } = require('structure');
14+
const Joi = require('@hapi/joi');
1515

16-
const ParamsDto = attributes({
17-
id: {
18-
type: Number,
19-
required: true,
20-
integer: true,
21-
positive: true,
22-
},
23-
})(class ParamsDto {});
16+
const ParamsDto = Joi.object({
17+
id: Joi.number()
18+
.integer()
19+
.positive(),
20+
});
2421

25-
const GetLogDto = attributes({
22+
const QueryDto = Joi.object({
23+
token: Joi.string(),
24+
});
25+
26+
const GetLogDto = Joi.object({
27+
body: Joi.object({}),
2628
params: ParamsDto,
27-
})(class GetLogDto {});
29+
query: QueryDto,
30+
});
2831

2932
module.exports = GetLogDto;
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,16 @@
1111
* or submit itself to any jurisdiction.
1212
*/
1313

14-
const HttpSuite = require('./http');
14+
const Joi = require('@hapi/joi');
1515

16-
module.exports = () => {
17-
describe('HTTP', HttpSuite);
18-
};
16+
const PaginationDto = Joi.object({
17+
limit: Joi.number()
18+
.integer()
19+
.min(1)
20+
.max(100),
21+
offset: Joi.number()
22+
.integer()
23+
.min(0),
24+
});
25+
26+
module.exports = PaginationDto;

lib/domain/dtos/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
*/
1313

1414
const CreateLogDto = require('./CreateLogDto');
15+
const GetAllLogsDto = require('./GetAllLogsDto');
1516
const GetLogDto = require('./GetLogDto');
17+
const PaginationDto = require('./PaginationDto');
1618

1719
module.exports = {
1820
CreateLogDto,
21+
GetAllLogsDto,
1922
GetLogDto,
23+
PaginationDto,
2024
};

0 commit comments

Comments
 (0)