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.
@@ -0,0 +1,183 @@
1
+ import mysql from 'mysql2/promise';
2
+ import logger from '../utils/logger';
3
+ import isEmpty from '../utils/isEmpty';
4
+ import LesgoException from '../exceptions/LesgoException';
5
+ import LengthAwarePaginator from './pagination/LengthAwarePaginator';
6
+ import Paginator from './pagination/Paginator';
7
+
8
+ const FILE = 'Lesgo/services/AuroraDbRDSProxyService';
9
+
10
+ /**
11
+ * Service to connect to AWS Aurora Provisioned MySQL Database via RDS Proxy.
12
+ * Use Services/AuroraDbServerlessService for the Serverless type via Data API.
13
+ */
14
+ export default class AuroraDbRDSProxyService {
15
+ constructor(opts = {}) {
16
+ const { host, user, password, database, persists } = opts;
17
+
18
+ this.clientOpts = {
19
+ host,
20
+ user,
21
+ password,
22
+ database,
23
+ persists,
24
+ };
25
+
26
+ this.conn = {};
27
+ }
28
+
29
+ /**
30
+ * Persists the database connection for later use
31
+ *
32
+ * @param {*} connectionOpts
33
+ * @returns
34
+ */
35
+ async pConnect(connectionOpts = {}) {
36
+ await this.connect({ ...connectionOpts, persists: true });
37
+ }
38
+
39
+ async connect(connectionOpts = {}) {
40
+ const clientOpts = {
41
+ host: connectionOpts.host ? connectionOpts.host : this.clientOpts.host,
42
+ user: connectionOpts.user ? connectionOpts.user : this.clientOpts.user,
43
+ password: connectionOpts.password
44
+ ? connectionOpts.password
45
+ : this.clientOpts.password,
46
+ database: connectionOpts.database
47
+ ? connectionOpts.database
48
+ : this.clientOpts.database,
49
+ };
50
+
51
+ const persistentConn = connectionOpts.persists || this.clientOpts.persists;
52
+
53
+ logger.debug(`${FILE}::PREPARING DB CONNECTION`, {
54
+ clientOpts,
55
+ persistentConn,
56
+ });
57
+
58
+ const conn = await mysql.createConnection(clientOpts);
59
+ conn.config.namedPlaceholders = true;
60
+ logger.debug(`${FILE}::DB CONNECTED`);
61
+
62
+ if (persistentConn) {
63
+ this.conn = conn;
64
+ }
65
+
66
+ return conn;
67
+ }
68
+
69
+ /* eslint-disable-next-line class-methods-use-this */
70
+ async end(conn = {}) {
71
+ logger.debug(`${FILE}::ENDING DB CONNECTION`);
72
+ if (!isEmpty(conn)) {
73
+ await conn.end();
74
+ logger.debug(`${FILE}::DB DISCONNECTED`);
75
+ } else {
76
+ await this.conn.end();
77
+ logger.debug(`${FILE}::PERSISTED DB DISCONNECTED`);
78
+ }
79
+ }
80
+
81
+ async query(sql, sqlParams, connectionOpts = {}) {
82
+ let conn = {};
83
+ if (!isEmpty(connectionOpts)) {
84
+ conn = await this.connect(connectionOpts);
85
+ } else if (isEmpty(this.conn)) {
86
+ conn = await this.connect();
87
+ } else {
88
+ conn = this.conn;
89
+ }
90
+
91
+ try {
92
+ logger.debug(`${FILE}::QUERYING_DB`, { sql, sqlParams });
93
+ const [results, fields] = await conn.execute(sql, sqlParams);
94
+ logger.debug(`${FILE}::DB_RESPONSE`, { results, fields });
95
+
96
+ return { results, fields };
97
+ } catch (err) {
98
+ throw new LesgoException(
99
+ 'Exception caught executing SQL Statement',
100
+ `${FILE}::QUERY_EXECUTION_EXCEPTION`,
101
+ 500,
102
+ { err }
103
+ );
104
+ } finally {
105
+ if (isEmpty(this.conn) || !isEmpty(connectionOpts)) await this.end(conn);
106
+ }
107
+ }
108
+
109
+ async select(sql, sqlParams, connectionOpts = {}) {
110
+ const resp = await this.query(sql, sqlParams, connectionOpts);
111
+ return resp.results;
112
+ }
113
+
114
+ async selectFirst(sql, sqlParams, connectionOpts = {}) {
115
+ const resp = await this.query(sql, sqlParams, connectionOpts);
116
+ return resp.results[0];
117
+ }
118
+
119
+ async selectPaginate(
120
+ sql,
121
+ sqlParams,
122
+ perPage = 10,
123
+ currentPage = 1,
124
+ total = null,
125
+ connectionOpts = {}
126
+ ) {
127
+ let paginator;
128
+ if (typeof total === 'number') {
129
+ paginator = new LengthAwarePaginator(
130
+ this,
131
+ sql,
132
+ sqlParams,
133
+ {
134
+ perPage,
135
+ currentPage,
136
+ total,
137
+ },
138
+ connectionOpts
139
+ );
140
+ } else {
141
+ paginator = new Paginator(
142
+ this,
143
+ sql,
144
+ sqlParams,
145
+ {
146
+ perPage,
147
+ currentPage,
148
+ },
149
+ connectionOpts
150
+ );
151
+ }
152
+
153
+ return (await paginator).toObject();
154
+ }
155
+
156
+ async insert(sql, sqlParams, connectionOpts = {}) {
157
+ const resp = await this.query(sql, sqlParams, connectionOpts);
158
+
159
+ if (resp.results.affectedRows <= 0) {
160
+ throw new LesgoException(
161
+ 'No records inserted from INSERT query',
162
+ `${FILE}::NO_RECORDS_INSERTED`,
163
+ 400,
164
+ { resp, sql, sqlParams }
165
+ );
166
+ }
167
+
168
+ return resp.results.insertId;
169
+ }
170
+
171
+ async update(sql, sqlParams, connectionOpts = {}) {
172
+ const resp = await this.query(sql, sqlParams, connectionOpts);
173
+
174
+ if (resp.results.changedRows <= 0) {
175
+ logger.warn(`${FILE}::No records updated from UPDATE query`, {
176
+ sql,
177
+ sqlParams,
178
+ });
179
+ }
180
+
181
+ return Promise.resolve();
182
+ }
183
+ }
@@ -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
- this.client = dataApiClient({
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.info('QUERYING AURORA DB', { sql, sqlParams });
33
+ logger.debug(`${FILE}::QUERYING_DB`, { sql, sqlParams });
26
34
  const resp = await this.client.query(sql, sqlParams);
27
- logger.info('AURORA DB RESPONSE', { resp });
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.info('PREPARING TO QUERY DYNAMODB', { params });
40
+ logger.debug(`${FILE}::PREPARING_QUERY`, { params });
39
41
 
40
42
  try {
41
43
  const data = await this.client.query(params).promise();
42
- logger.info('RECEIVED RESPONSE FROM DYNAMODB', { data });
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.info('PREPARING TO QUERY COUNT DYNAMODB', { params });
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.info('RECEIVED RESPONSE FROM DYNAMODB', { data });
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.info('PREPARING TO PUT ITEM TO DYNAMODB', { params });
86
+ logger.debug(`${FILE}::PREPARING_PUT`, { params });
85
87
 
86
88
  try {
87
89
  const data = await this.client.put(params).promise();
88
- logger.info('RECEIVED RESPONSE FROM DYNAMODB', { data });
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.info('PREPARING TO UPDATE ITEM ON DYNAMODB', { params });
110
+ logger.debug(`${FILE}::PREPARING_UPDATE`, { params });
109
111
 
110
112
  try {
111
113
  const data = await this.client.update(params).promise();
112
- logger.info('RECEIVED RESPONSE FROM DYNAMODB', { data });
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.info('FETCHING FIREBASE USERS', {
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.info('FETCHED FIREBASE USERS', { users });
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.info('CREATING USER ON FIREBASE', { userData, data });
63
+ logger.debug(`${FILE}::CREATING_USER`, { userData, data });
62
64
  const user = await this.app.auth().createUser(userData);
63
- logger.info('USER CREATED ON FIREBASE', { user });
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.info('DELETING FIREBASE USER');
79
+ logger.debug(`${FILE}::DELETING_USER`);
78
80
  const deleted = await this.app.auth().deleteUser(uid);
79
- logger.info('DELETED FIREBASE USER', { deleted, uid });
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.info('DELETING FIREBASE APP');
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