lesgo 0.6.2 → 0.7.2
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/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
|
@@ -4,6 +4,8 @@ import LesgoException from '../exceptions/LesgoException';
|
|
|
4
4
|
import LengthAwarePaginator from './pagination/LengthAwarePaginator';
|
|
5
5
|
import Paginator from './pagination/Paginator';
|
|
6
6
|
|
|
7
|
+
const FILE = 'Lesgo/services/AuroraDbService';
|
|
8
|
+
|
|
7
9
|
export default class AuroraDbService {
|
|
8
10
|
constructor(opts = {}) {
|
|
9
11
|
this.client = null;
|
|
@@ -11,20 +13,26 @@ export default class AuroraDbService {
|
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
connect(opts) {
|
|
14
|
-
const { secretArn, resourceArn, database } = opts;
|
|
16
|
+
const { secretArn, resourceArn, database, region } = opts;
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const clientOpts = {
|
|
17
19
|
secretArn,
|
|
18
20
|
resourceArn,
|
|
19
21
|
database,
|
|
20
|
-
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (region) {
|
|
25
|
+
clientOpts.region = region;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.client = dataApiClient(clientOpts);
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
async query(sql, sqlParams) {
|
|
24
32
|
try {
|
|
25
|
-
logger.
|
|
33
|
+
logger.debug(`${FILE}::QUERYING_DB`, { sql, sqlParams });
|
|
26
34
|
const resp = await this.client.query(sql, sqlParams);
|
|
27
|
-
logger.
|
|
35
|
+
logger.debug(`${FILE}::DB_RESPONSE`, { resp });
|
|
28
36
|
|
|
29
37
|
return resp;
|
|
30
38
|
} catch (err) {
|
|
@@ -2,6 +2,8 @@ import { DocumentClient } from 'aws-sdk/clients/dynamodb'; // eslint-disable-lin
|
|
|
2
2
|
import LesgoException from '../exceptions/LesgoException';
|
|
3
3
|
import logger from '../utils/logger';
|
|
4
4
|
|
|
5
|
+
const FILE = 'Lesgo/services/DynamoDbService';
|
|
6
|
+
|
|
5
7
|
export default class DynamoDb {
|
|
6
8
|
constructor(opts = {}) {
|
|
7
9
|
this.client = null;
|
|
@@ -35,11 +37,11 @@ export default class DynamoDb {
|
|
|
35
37
|
projectionExpression
|
|
36
38
|
);
|
|
37
39
|
|
|
38
|
-
logger.
|
|
40
|
+
logger.debug(`${FILE}::PREPARING_QUERY`, { params });
|
|
39
41
|
|
|
40
42
|
try {
|
|
41
43
|
const data = await this.client.query(params).promise();
|
|
42
|
-
logger.
|
|
44
|
+
logger.debug(`${FILE}::RECEIVED_QUERY_RESPONSE`, { data });
|
|
43
45
|
return data.Items;
|
|
44
46
|
} catch (err) {
|
|
45
47
|
throw new LesgoException(
|
|
@@ -62,11 +64,11 @@ export default class DynamoDb {
|
|
|
62
64
|
expressionAttributeValues
|
|
63
65
|
);
|
|
64
66
|
|
|
65
|
-
logger.
|
|
67
|
+
logger.debug(`${FILE}::PREPARING_QUERY_COUNT`, { params });
|
|
66
68
|
|
|
67
69
|
try {
|
|
68
70
|
const data = await this.client.query(params).promise();
|
|
69
|
-
logger.
|
|
71
|
+
logger.debug(`${FILE}::RECEIVED_QUERY_COUNT_RESPONSE`, { data });
|
|
70
72
|
return data.Count;
|
|
71
73
|
} catch (err) {
|
|
72
74
|
throw new LesgoException(
|
|
@@ -81,11 +83,11 @@ export default class DynamoDb {
|
|
|
81
83
|
async put(tableName, item) {
|
|
82
84
|
const params = this.preparePutPayload(tableName, item);
|
|
83
85
|
|
|
84
|
-
logger.
|
|
86
|
+
logger.debug(`${FILE}::PREPARING_PUT`, { params });
|
|
85
87
|
|
|
86
88
|
try {
|
|
87
89
|
const data = await this.client.put(params).promise();
|
|
88
|
-
logger.
|
|
90
|
+
logger.debug(`${FILE}::RECEIVED_PUT_RESPONSE`, { data });
|
|
89
91
|
return data;
|
|
90
92
|
} catch (err) {
|
|
91
93
|
throw new LesgoException(
|
|
@@ -105,11 +107,11 @@ export default class DynamoDb {
|
|
|
105
107
|
expressionAttributeValues
|
|
106
108
|
);
|
|
107
109
|
|
|
108
|
-
logger.
|
|
110
|
+
logger.debug(`${FILE}::PREPARING_UPDATE`, { params });
|
|
109
111
|
|
|
110
112
|
try {
|
|
111
113
|
const data = await this.client.update(params).promise();
|
|
112
|
-
logger.
|
|
114
|
+
logger.debug(`${FILE}::RECEIVED_UPDATE_RESPONSE`, { data });
|
|
113
115
|
return data;
|
|
114
116
|
} catch (err) {
|
|
115
117
|
throw new LesgoException(
|
|
@@ -3,6 +3,8 @@ import logger from '../utils/logger';
|
|
|
3
3
|
import isEmpty from '../utils/isEmpty';
|
|
4
4
|
import LesgoException from '../exceptions/LesgoException';
|
|
5
5
|
|
|
6
|
+
const FILE = 'Lesgo/services/FirebaseAdminService';
|
|
7
|
+
|
|
6
8
|
export default class FirebaseAdmin {
|
|
7
9
|
constructor(opts = {}) {
|
|
8
10
|
this.app = null;
|
|
@@ -30,13 +32,13 @@ export default class FirebaseAdmin {
|
|
|
30
32
|
const max = !isEmpty(maxResults) ? maxResults : 25;
|
|
31
33
|
|
|
32
34
|
try {
|
|
33
|
-
logger.
|
|
35
|
+
logger.debug(`${FILE}::FETCHING_USERS`, {
|
|
34
36
|
max,
|
|
35
37
|
maxResults,
|
|
36
38
|
nextPageToken,
|
|
37
39
|
});
|
|
38
40
|
const users = await this.app.auth().listUsers(max, nextPageToken);
|
|
39
|
-
logger.
|
|
41
|
+
logger.debug(`${FILE}::USERS_FETCHED`, { users });
|
|
40
42
|
return users.users;
|
|
41
43
|
} catch (err) {
|
|
42
44
|
throw new LesgoException(
|
|
@@ -58,9 +60,9 @@ export default class FirebaseAdmin {
|
|
|
58
60
|
displayName: username,
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
logger.
|
|
63
|
+
logger.debug(`${FILE}::CREATING_USER`, { userData, data });
|
|
62
64
|
const user = await this.app.auth().createUser(userData);
|
|
63
|
-
logger.
|
|
65
|
+
logger.debug(`${FILE}::USER_CREATED`, { user });
|
|
64
66
|
return user;
|
|
65
67
|
} catch (err) {
|
|
66
68
|
throw new LesgoException(
|
|
@@ -74,9 +76,9 @@ export default class FirebaseAdmin {
|
|
|
74
76
|
|
|
75
77
|
async deleteUser(uid) {
|
|
76
78
|
try {
|
|
77
|
-
logger.
|
|
79
|
+
logger.debug(`${FILE}::DELETING_USER`);
|
|
78
80
|
const deleted = await this.app.auth().deleteUser(uid);
|
|
79
|
-
logger.
|
|
81
|
+
logger.debug(`${FILE}::USER_DELETED`, { deleted, uid });
|
|
80
82
|
return deleted;
|
|
81
83
|
} catch (err) {
|
|
82
84
|
throw new LesgoException(
|
|
@@ -90,8 +92,9 @@ export default class FirebaseAdmin {
|
|
|
90
92
|
|
|
91
93
|
async delete() {
|
|
92
94
|
try {
|
|
93
|
-
logger.
|
|
95
|
+
logger.debug(`${FILE}::DELETING_APP`);
|
|
94
96
|
const resp = await this.app.delete();
|
|
97
|
+
logger.debug(`${FILE}::APP_DELETED`, { resp });
|
|
95
98
|
return resp;
|
|
96
99
|
} catch (err) {
|
|
97
100
|
throw new LesgoException(
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import mysql from 'mysql2/promise';
|
|
2
|
+
import AuroraDbRDSProxyService from '../AuroraDbRDSProxyService';
|
|
3
|
+
import LesgoException from '../../exceptions/LesgoException';
|
|
4
|
+
|
|
5
|
+
const auroraConfig = {
|
|
6
|
+
host: 'some-fake-host',
|
|
7
|
+
user: 'fakeUsername',
|
|
8
|
+
password: 'fakePassword',
|
|
9
|
+
database: 'fakeDbName',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const customConfig = {
|
|
13
|
+
host: 'some-fake-host-2',
|
|
14
|
+
user: 'fakeUsername2',
|
|
15
|
+
password: 'fakePassword2',
|
|
16
|
+
database: 'fakeDbName2',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('test AuroraDbRDSProxyService instantiate', () => {
|
|
20
|
+
it('should not throw exception when instantiating', () => {
|
|
21
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
22
|
+
expect(db.clientOpts).toMatchObject(auroraConfig);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should allow for empty config', () => {
|
|
26
|
+
const db = new AuroraDbRDSProxyService();
|
|
27
|
+
expect(db.clientOpts).toMatchObject({});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('test AuroraDbRDSProxyService connect', () => {
|
|
32
|
+
it('should be able to connect without custom config', async () => {
|
|
33
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
34
|
+
const conn = await db.connect();
|
|
35
|
+
|
|
36
|
+
expect(conn.mocked).toMatchObject(auroraConfig);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should be able to connect with custom config', async () => {
|
|
40
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
41
|
+
const conn = await db.connect(customConfig);
|
|
42
|
+
|
|
43
|
+
expect(conn.mocked).toMatchObject(customConfig);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('test AuroraDbRDSProxyService query', () => {
|
|
48
|
+
it('should return results object when calling query function', async () => {
|
|
49
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
50
|
+
const resp = await db.query('SELECT_QUERY', {});
|
|
51
|
+
|
|
52
|
+
expect(resp).toMatchObject({
|
|
53
|
+
results: [
|
|
54
|
+
{
|
|
55
|
+
id: 1,
|
|
56
|
+
uid: 'some-uid-1',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 2,
|
|
60
|
+
uid: 'some-uid-2',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
expect(mysql.createConnection).toHaveBeenCalled();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return results object when calling querying with connection options passed', async () => {
|
|
69
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
70
|
+
const resp = await db.query('SELECT_QUERY', {}, auroraConfig);
|
|
71
|
+
|
|
72
|
+
expect(resp).toMatchObject({
|
|
73
|
+
results: [
|
|
74
|
+
{
|
|
75
|
+
id: 1,
|
|
76
|
+
uid: 'some-uid-1',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 2,
|
|
80
|
+
uid: 'some-uid-2',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(mysql.createConnection).toHaveBeenCalled();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return results object when calling querying with no connection options passed and persistent conn', async () => {
|
|
89
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
90
|
+
await db.pConnect();
|
|
91
|
+
const resp = await db.query('SELECT_QUERY', {});
|
|
92
|
+
|
|
93
|
+
expect(resp).toMatchObject({
|
|
94
|
+
results: [
|
|
95
|
+
{
|
|
96
|
+
id: 1,
|
|
97
|
+
uid: 'some-uid-1',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 2,
|
|
101
|
+
uid: 'some-uid-2',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(mysql.createConnection).toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('test AuroraDbRDSProxyService select', () => {
|
|
111
|
+
it('should return array results when calling select function', async () => {
|
|
112
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
113
|
+
return expect(db.select('SELECT_QUERY', {})).resolves.toMatchObject([
|
|
114
|
+
{
|
|
115
|
+
id: 1,
|
|
116
|
+
uid: 'some-uid-1',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 2,
|
|
120
|
+
uid: 'some-uid-2',
|
|
121
|
+
},
|
|
122
|
+
]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should throw an exception when writing with invalid query', async () => {
|
|
126
|
+
const error = new LesgoException(
|
|
127
|
+
'Exception caught executing SQL Statement',
|
|
128
|
+
'AURORADBSERVICE_QUERY_EXCEPTION',
|
|
129
|
+
500,
|
|
130
|
+
{
|
|
131
|
+
err: {
|
|
132
|
+
code: 'BadRequestException',
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
138
|
+
return expect(db.select('INVALID_QUERY', {})).rejects.toMatchObject(error);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should throw an exception when calling select with invalid query parameters', async () => {
|
|
142
|
+
const error = new LesgoException(
|
|
143
|
+
'Exception caught executing SQL Statement',
|
|
144
|
+
'AURORADBSERVICE_QUERY_EXCEPTION',
|
|
145
|
+
500,
|
|
146
|
+
{
|
|
147
|
+
err: {
|
|
148
|
+
code: 'BadRequestException',
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
154
|
+
return expect(
|
|
155
|
+
db.select('RANDOM_QUERY', 'INVALID_QUERY_PARAMETERS')
|
|
156
|
+
).rejects.toMatchObject(error);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('test AuroraDbRDSProxyService selectPaginate', () => {
|
|
161
|
+
it('should return paginated results when calling selectPaginate function', async () => {
|
|
162
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
163
|
+
return expect(db.selectPaginate('SELECT_QUERY', {})).resolves.toMatchObject(
|
|
164
|
+
{
|
|
165
|
+
count: 2,
|
|
166
|
+
previous_page: false,
|
|
167
|
+
current_page: 1,
|
|
168
|
+
next_page: false,
|
|
169
|
+
per_page: 10,
|
|
170
|
+
items: [
|
|
171
|
+
{
|
|
172
|
+
id: 1,
|
|
173
|
+
uid: 'some-uid-1',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 2,
|
|
177
|
+
uid: 'some-uid-2',
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should return paginated results when calling selectPaginate with defined total', async () => {
|
|
185
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
186
|
+
return expect(
|
|
187
|
+
db.selectPaginate('SELECT_QUERY', {}, 1, 2, 1)
|
|
188
|
+
).resolves.toMatchObject({
|
|
189
|
+
count: 1,
|
|
190
|
+
previous_page: 1,
|
|
191
|
+
current_page: 2,
|
|
192
|
+
next_page: 3,
|
|
193
|
+
per_page: 1,
|
|
194
|
+
items: [
|
|
195
|
+
{
|
|
196
|
+
id: 1,
|
|
197
|
+
uid: 'some-uid-1',
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe('test AuroraDbRDSProxyService selectFirst', () => {
|
|
205
|
+
it('should only return the first record when calling selectFirst', async () => {
|
|
206
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
207
|
+
return expect(db.selectFirst('SELECT_QUERY', {})).resolves.toMatchObject({
|
|
208
|
+
id: 1,
|
|
209
|
+
uid: 'some-uid-1',
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('test AuroraDbRDSProxyService insert', () => {
|
|
215
|
+
it('should return recordId when inserting record', async () => {
|
|
216
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
217
|
+
return expect(db.insert('INSERT_QUERY', {})).resolves.toEqual(20);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should throw exception when calling insert with invalid query', async () => {
|
|
221
|
+
const error = new LesgoException(
|
|
222
|
+
'No records inserted from INSERT query',
|
|
223
|
+
'AURORADBSERVICE_NO_RECORDS_INSERTED',
|
|
224
|
+
400
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
228
|
+
return expect(db.insert('INVALID_INSERT_QUERY', {})).rejects.toMatchObject(
|
|
229
|
+
error
|
|
230
|
+
);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe('test AuroraDbRDSProxyService update', () => {
|
|
235
|
+
it('should return success when making update query', async () => {
|
|
236
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
237
|
+
return expect(db.update('UPDATE_QUERY', {})).resolves.not.toThrow();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should throw not exception when caliing update with invalid query', async () => {
|
|
241
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
242
|
+
return expect(db.update('INVALID_UPDATE_QUERY', {})).resolves.not.toThrow();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('test AuroraDbRDSProxyService pConnect', () => {
|
|
247
|
+
it('should be able to connect without custom config', async () => {
|
|
248
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
249
|
+
await db.pConnect();
|
|
250
|
+
|
|
251
|
+
expect(db.conn.mocked).toMatchObject(auroraConfig);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should be able to connect with custom config', async () => {
|
|
255
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
256
|
+
await db.pConnect(customConfig);
|
|
257
|
+
|
|
258
|
+
expect(db.conn.mocked).toMatchObject(customConfig);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('test AuroraDbRDSProxyService end', () => {
|
|
263
|
+
it('should end the connection when passed', async () => {
|
|
264
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
265
|
+
const conn = await db.connect();
|
|
266
|
+
await db.end(conn);
|
|
267
|
+
|
|
268
|
+
expect(conn.end).toHaveBeenCalledTimes(1);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it('should end the persisted connection when none is passed', async () => {
|
|
272
|
+
const db = new AuroraDbRDSProxyService(auroraConfig);
|
|
273
|
+
await db.pConnect();
|
|
274
|
+
await db.end();
|
|
275
|
+
|
|
276
|
+
expect(db.conn.end).toHaveBeenCalledTimes(1);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -23,6 +23,16 @@ describe('test AuroraDbService instantiate', () => {
|
|
|
23
23
|
expect(dataApiClient).toHaveBeenCalledWith(auroraConfig);
|
|
24
24
|
expect(db.client.mocked).toMatchObject(auroraConfig);
|
|
25
25
|
});
|
|
26
|
+
|
|
27
|
+
it('should not throw exception with custom region', () => {
|
|
28
|
+
const db = new AuroraDbService({
|
|
29
|
+
...auroraConfig,
|
|
30
|
+
region: 'ap-southeast-1',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(dataApiClient).toHaveBeenCalledWith(auroraConfig);
|
|
34
|
+
expect(db.client.mocked).toMatchObject(auroraConfig);
|
|
35
|
+
});
|
|
26
36
|
});
|
|
27
37
|
|
|
28
38
|
describe('test AuroraDbService connect', () => {
|
|
@@ -12,8 +12,9 @@ export default class LengthAwarePaginator extends Paginator {
|
|
|
12
12
|
* @param sql
|
|
13
13
|
* @param sqlParams
|
|
14
14
|
* @param options
|
|
15
|
+
* @param connection
|
|
15
16
|
*/
|
|
16
|
-
constructor(db, sql, sqlParams, options) {
|
|
17
|
+
constructor(db, sql, sqlParams, options, connection = {}) {
|
|
17
18
|
const validFields = [{ key: 'total', type: 'number', required: true }];
|
|
18
19
|
|
|
19
20
|
let validated = {};
|
|
@@ -33,7 +34,7 @@ export default class LengthAwarePaginator extends Paginator {
|
|
|
33
34
|
|
|
34
35
|
const { total } = validated;
|
|
35
36
|
|
|
36
|
-
super(db, sql, sqlParams, options);
|
|
37
|
+
super(db, sql, sqlParams, options, connection);
|
|
37
38
|
this.totalProp = total;
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -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
|
});
|