lesgo 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lesgo-scripts.sh +31 -26
- package/package.json +2 -1
- package/src/middlewares/__tests__/errorHttpResponseMiddleware.spec.js +33 -16
- package/src/middlewares/__tests__/normalizeHttpRequestMiddleware.spec.js +24 -0
- package/src/middlewares/__tests__/successHttpResponseMiddleware.spec.js +28 -12
- package/src/middlewares/errorHttpResponseMiddleware.js +10 -3
- package/src/middlewares/gzipHttpResponse.js +1 -1
- package/src/middlewares/normalizeHttpRequestMiddleware.js +5 -2
- package/src/middlewares/successHttpResponseMiddleware.js +9 -2
- package/src/middlewares/verifyJwtMiddleware.js +4 -2
- package/src/services/AuroraDbRDSProxyService.js +183 -0
- package/src/services/AuroraDbService.js +13 -5
- package/src/services/DynamoDbService.js +10 -8
- package/src/services/FirebaseAdminService.js +10 -7
- package/src/services/__tests__/AuroraDbRDSProxyService.spec.js +278 -0
- package/src/services/__tests__/AuroraDbService.spec.js +10 -0
- package/src/services/pagination/LengthAwarePaginator.js +3 -2
- package/src/services/pagination/Paginator.js +12 -3
- package/src/utils/__tests__/db.spec.js +40 -1
- package/src/utils/__tests__/validateFields.spec.js +61 -5
- package/src/utils/db.js +13 -2
- package/src/utils/logger.js +1 -4
- package/src/utils/validateFields.js +26 -8
|
@@ -12,13 +12,14 @@ export default class Paginator {
|
|
|
12
12
|
* @param sqlParams
|
|
13
13
|
* @param options
|
|
14
14
|
*/
|
|
15
|
-
constructor(db, sql, sqlParams, options = {}) {
|
|
15
|
+
constructor(db, sql, sqlParams, options = {}, connection = {}) {
|
|
16
16
|
const validFields = [
|
|
17
17
|
{ key: 'db', type: 'object', required: true },
|
|
18
18
|
{ key: 'sql', type: 'string', required: true },
|
|
19
19
|
{ key: 'sqlParams', type: 'object', required: true },
|
|
20
20
|
{ key: 'perPage', type: 'number', required: false },
|
|
21
21
|
{ key: 'currentPage', type: 'number', required: false },
|
|
22
|
+
{ key: 'connection', type: 'object', required: false },
|
|
22
23
|
];
|
|
23
24
|
|
|
24
25
|
let validated = {};
|
|
@@ -29,6 +30,7 @@ export default class Paginator {
|
|
|
29
30
|
sql,
|
|
30
31
|
sqlParams,
|
|
31
32
|
...options,
|
|
33
|
+
connection,
|
|
32
34
|
},
|
|
33
35
|
validFields
|
|
34
36
|
);
|
|
@@ -56,6 +58,8 @@ export default class Paginator {
|
|
|
56
58
|
|
|
57
59
|
this.response = [];
|
|
58
60
|
this.totalProp = false;
|
|
61
|
+
|
|
62
|
+
this.connection = connection;
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
/**
|
|
@@ -215,7 +219,8 @@ export default class Paginator {
|
|
|
215
219
|
async executeQuery() {
|
|
216
220
|
this.response = await this.dbProp.select(
|
|
217
221
|
this.generatePaginationSqlSnippet(),
|
|
218
|
-
this.sqlParamsProp
|
|
222
|
+
this.sqlParamsProp,
|
|
223
|
+
this.connection
|
|
219
224
|
);
|
|
220
225
|
|
|
221
226
|
this.hasNext = this.response.length > this.perPage();
|
|
@@ -232,7 +237,11 @@ export default class Paginator {
|
|
|
232
237
|
* @returns {Promise<number>}
|
|
233
238
|
*/
|
|
234
239
|
async countTotalItems() {
|
|
235
|
-
const resp = await this.dbProp.select(
|
|
240
|
+
const resp = await this.dbProp.select(
|
|
241
|
+
this.sqlProp,
|
|
242
|
+
this.sqlParamsProp,
|
|
243
|
+
this.connection
|
|
244
|
+
);
|
|
236
245
|
this.totalProp = Object.keys(resp).length;
|
|
237
246
|
|
|
238
247
|
return this.totalProp;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import config from 'Config/db'; // eslint-disable-line import/no-unresolved
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
let db;
|
|
4
|
+
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
jest.isolateModules(() => {
|
|
7
|
+
db = require('../db').default; // eslint-disable-line global-require
|
|
8
|
+
});
|
|
9
|
+
});
|
|
3
10
|
|
|
4
11
|
describe('test db utils instantiate', () => {
|
|
5
12
|
it('should not throw error on instantiating AuroraDbService', () => {
|
|
@@ -29,4 +36,36 @@ describe('test db utils instantiate', () => {
|
|
|
29
36
|
},
|
|
30
37
|
});
|
|
31
38
|
});
|
|
39
|
+
|
|
40
|
+
it('should update AuroraDb credentials on connect based on dataApi config', () => {
|
|
41
|
+
config.default = 'dataApi';
|
|
42
|
+
let thisDb;
|
|
43
|
+
jest.isolateModules(() => {
|
|
44
|
+
thisDb = require('../db').default; // eslint-disable-line global-require
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return expect(thisDb.client).toMatchObject({
|
|
48
|
+
mocked: {
|
|
49
|
+
database: config.connections.dataApi.database,
|
|
50
|
+
resourceArn: config.connections.dataApi.resourceArn,
|
|
51
|
+
secretArn: config.connections.dataApi.secretArn,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should update AuroraDb credentials on connect based on rdsProxy config', () => {
|
|
57
|
+
config.default = 'rdsProxy';
|
|
58
|
+
let thisDb;
|
|
59
|
+
jest.isolateModules(() => {
|
|
60
|
+
thisDb = require('../db').default; // eslint-disable-line global-require
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return expect(thisDb.clientOpts).toMatchObject({
|
|
64
|
+
database: config.connections.rdsProxy.database,
|
|
65
|
+
host: config.connections.rdsProxy.host,
|
|
66
|
+
user: config.connections.rdsProxy.user,
|
|
67
|
+
password: config.connections.rdsProxy.password,
|
|
68
|
+
persists: config.connections.rdsProxy.persists,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
32
71
|
});
|
|
@@ -11,6 +11,7 @@ const params = {
|
|
|
11
11
|
listItem: ['apple', 'banana'],
|
|
12
12
|
status: 'active',
|
|
13
13
|
decimalCheck: 1.99,
|
|
14
|
+
totalRecord: 99,
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
const validFields = [
|
|
@@ -25,11 +26,8 @@ const validFields = [
|
|
|
25
26
|
enumValues: ['active', 'inactive'],
|
|
26
27
|
required: true,
|
|
27
28
|
},
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
type: 'decimal',
|
|
31
|
-
required: true,
|
|
32
|
-
},
|
|
29
|
+
{ key: 'decimalCheck', type: 'decimal', required: true },
|
|
30
|
+
{ key: 'totalRecord', type: 'number', required: true },
|
|
33
31
|
];
|
|
34
32
|
|
|
35
33
|
describe('test Utils/validateFields', () => {
|
|
@@ -93,6 +91,28 @@ describe('test Utils/validateFields', () => {
|
|
|
93
91
|
);
|
|
94
92
|
});
|
|
95
93
|
|
|
94
|
+
it('should throw required when array value is empty but required', () => {
|
|
95
|
+
const newParams = { ...params, listItem: [] };
|
|
96
|
+
|
|
97
|
+
expect(() => validateFields(newParams, validFields)).toThrow(
|
|
98
|
+
new LesgoException(
|
|
99
|
+
`Missing required 'listItem'`,
|
|
100
|
+
`${FILE}::MISSING_REQUIRED_LISTITEM`
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should not throw invalid type when array value is empty and not required', () => {
|
|
106
|
+
const newParams = { ...params, listItem: [] };
|
|
107
|
+
const newValidFields = [
|
|
108
|
+
{ key: 'listItem', type: 'array', required: false },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
expect(validateFields(newParams, newValidFields)).toMatchObject({
|
|
112
|
+
listItem: [],
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
96
116
|
it('should throw invalid type when non-enum value check', async () => {
|
|
97
117
|
const newParams = { ...params, status: 'private' };
|
|
98
118
|
|
|
@@ -123,5 +143,41 @@ describe('test Utils/validateFields', () => {
|
|
|
123
143
|
expect(validated).toMatchObject(newParams);
|
|
124
144
|
expect(validated.Id).toBeDefined();
|
|
125
145
|
expect(validated.listItem).toBeUndefined();
|
|
146
|
+
|
|
147
|
+
validFields[4].required = true;
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should return success with validated data for 0 number', () => {
|
|
151
|
+
const newParams = { ...params, totalRecord: 0 };
|
|
152
|
+
const validated = validateFields(newParams, validFields);
|
|
153
|
+
|
|
154
|
+
expect(validated).toMatchObject(newParams);
|
|
155
|
+
expect(validated.totalRecord).toBeDefined();
|
|
156
|
+
expect(validated.totalRecord).toEqual(0);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should return success with validated data for number without required', () => {
|
|
160
|
+
const newParams = { ...params };
|
|
161
|
+
validFields[7].required = false;
|
|
162
|
+
|
|
163
|
+
const validated = validateFields(newParams, validFields);
|
|
164
|
+
|
|
165
|
+
expect(validated).toMatchObject(newParams);
|
|
166
|
+
expect(validated.totalRecord).toBeDefined();
|
|
167
|
+
expect(validated.totalRecord).toEqual(99);
|
|
168
|
+
|
|
169
|
+
validFields[7].required = true;
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should return error with missing required number', () => {
|
|
173
|
+
const newParams = { ...params };
|
|
174
|
+
delete newParams.totalRecord;
|
|
175
|
+
|
|
176
|
+
expect(() => validateFields(newParams, validFields)).toThrow(
|
|
177
|
+
new LesgoException(
|
|
178
|
+
`Missing required 'totalRecord'`,
|
|
179
|
+
`${FILE}::MISSING_REQUIRED_TOTALRECORD`
|
|
180
|
+
)
|
|
181
|
+
);
|
|
126
182
|
});
|
|
127
183
|
});
|
package/src/utils/db.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import dbConfig from 'Config/db'; // eslint-disable-line import/no-unresolved
|
|
2
|
+
import AuroraDbRDSProxyService from '../services/AuroraDbRDSProxyService';
|
|
2
3
|
import AuroraDbService from '../services/AuroraDbService';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/* eslint-disable-next-line import/no-mutable-exports */
|
|
6
|
+
let db;
|
|
7
|
+
|
|
8
|
+
if (dbConfig.default === 'rdsProxy' || dbConfig.default === 'rdsProxyRead') {
|
|
9
|
+
db = new AuroraDbRDSProxyService(dbConfig.connections[dbConfig.default]);
|
|
10
|
+
} else if (dbConfig.default === 'dataApi') {
|
|
11
|
+
db = new AuroraDbService(dbConfig.connections[dbConfig.default]);
|
|
12
|
+
} else {
|
|
13
|
+
// @deprecated
|
|
14
|
+
db = new AuroraDbService(dbConfig);
|
|
15
|
+
}
|
|
5
16
|
|
|
6
17
|
export default db;
|
package/src/utils/logger.js
CHANGED
|
@@ -4,10 +4,7 @@ import LoggerService from '../services/LoggerService';
|
|
|
4
4
|
const transports = [
|
|
5
5
|
{
|
|
6
6
|
logType: 'console',
|
|
7
|
-
level:
|
|
8
|
-
app.env === 'local' && /* istanbul ignore next */ app.debug
|
|
9
|
-
? /* istanbul ignore next */ 'debug'
|
|
10
|
-
: 'info',
|
|
7
|
+
level: /* istanbul ignore next */ app.debug ? 'debug' : 'info',
|
|
11
8
|
config: {
|
|
12
9
|
getCreatedAt: true,
|
|
13
10
|
tags: {
|
|
@@ -8,13 +8,31 @@ export default (params, validFields) => {
|
|
|
8
8
|
const validated = {};
|
|
9
9
|
|
|
10
10
|
validFields.forEach(field => {
|
|
11
|
-
if (field.required
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{
|
|
17
|
-
|
|
11
|
+
if (field.required) {
|
|
12
|
+
if (typeof params[field.key] === 'object') {
|
|
13
|
+
if (
|
|
14
|
+
Array.isArray(params[field.key]) &&
|
|
15
|
+
params[field.key].length === 0
|
|
16
|
+
) {
|
|
17
|
+
throw new LesgoException(
|
|
18
|
+
`Missing required '${field.key}'`,
|
|
19
|
+
`${FILE}::MISSING_REQUIRED_${field.key.toUpperCase()}`,
|
|
20
|
+
500,
|
|
21
|
+
{ field }
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!params[field.key]) {
|
|
27
|
+
if (typeof params[field.key] !== 'number') {
|
|
28
|
+
throw new LesgoException(
|
|
29
|
+
`Missing required '${field.key}'`,
|
|
30
|
+
`${FILE}::MISSING_REQUIRED_${field.key.toUpperCase()}`,
|
|
31
|
+
500,
|
|
32
|
+
{ field }
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
18
36
|
}
|
|
19
37
|
|
|
20
38
|
if (
|
|
@@ -35,7 +53,7 @@ export default (params, validFields) => {
|
|
|
35
53
|
!isEmail(params[field.key])) ||
|
|
36
54
|
(field.type === 'array' &&
|
|
37
55
|
typeof params[field.key] !== 'undefined' &&
|
|
38
|
-
|
|
56
|
+
!Array.isArray(params[field.key])) ||
|
|
39
57
|
(field.type === 'enum' &&
|
|
40
58
|
typeof params[field.key] !== 'undefined' &&
|
|
41
59
|
!field.enumValues.includes(params[field.key]))
|