lesgo 0.7.1 → 0.7.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lesgo",
3
- "version": "0.7.1",
3
+ "version": "0.7.5",
4
4
  "description": "Core framework for lesgo node.js serverless framework.",
5
5
  "main": "./src/index.js",
6
6
  "author": "Sufiyan Rahmat",
@@ -51,7 +51,7 @@
51
51
  "prettier": "^1.18.2"
52
52
  },
53
53
  "dependencies": {
54
- "@elastic/elasticsearch": "^7.4.0",
54
+ "@elastic/elasticsearch": "^7.16.0",
55
55
  "@firebase/app": "^0.6.12",
56
56
  "data-api-client": "^1.1.0",
57
57
  "firebase-admin": "^9.3.0",
@@ -21,7 +21,7 @@ describe('MiddlewareGroup: test errorHandler middleware', () => {
21
21
  expect(dataBody).toHaveProperty('status', 'error');
22
22
  expect(dataBody).toHaveProperty('data', null);
23
23
  expect(dataBody).toHaveProperty('error');
24
- expect(dataBody).toHaveProperty('error.code', 'UNKNOWN_ERROR');
24
+ expect(dataBody).toHaveProperty('error.code', 'UNHANDLED_ERROR');
25
25
  expect(dataBody).toHaveProperty(
26
26
  'error.message',
27
27
  'Error: Test validation error'
@@ -78,7 +78,7 @@ describe('MiddlewareGroup: test errorHandler middleware', () => {
78
78
 
79
79
  expect(data.statusCode).toBe(500);
80
80
 
81
- expect(dataBody).toHaveProperty('error.code', 'UNKNOWN_ERROR');
81
+ expect(dataBody).toHaveProperty('error.code', 'UNHANDLED_ERROR');
82
82
  expect(dataBody).toHaveProperty('error.message', 'Test error message');
83
83
  expect(dataBody).toHaveProperty('error.details', '');
84
84
  });
@@ -126,7 +126,7 @@ describe('MiddlewareGroup: test errorHandler middleware', () => {
126
126
  expect(dataBody).toHaveProperty('status', 'error');
127
127
  expect(dataBody).toHaveProperty('data', null);
128
128
  expect(dataBody).toHaveProperty('error');
129
- expect(dataBody).toHaveProperty('error.code', 'UNKNOWN_ERROR');
129
+ expect(dataBody).toHaveProperty('error.code', 'UNHANDLED_ERROR');
130
130
  expect(dataBody).toHaveProperty('error.message', '');
131
131
  expect(dataBody).toHaveProperty('error.details', '');
132
132
  });
@@ -102,7 +102,6 @@ describe('MiddlewareGroup: test normalizeHttpRequestBeforeHandler', () => {
102
102
  };
103
103
 
104
104
  normalizeHttpRequestBeforeHandler(handler, () => {});
105
- expect(handler.event.requestContext.requestId).toBe('requestId');
106
105
  });
107
106
 
108
107
  it('should return auth.sub if Authorization exists', () => {
@@ -119,6 +118,44 @@ describe('MiddlewareGroup: test normalizeHttpRequestBeforeHandler', () => {
119
118
  expect(handler.event.auth.sub).toBe('f2b5349d-f5e3-44f5-9c08-ae6b01e95434');
120
119
  });
121
120
 
121
+ it.each`
122
+ version | tags
123
+ ${'1.0'} | ${{ path: '/v1/path', httpMethod: 'GET' }}
124
+ ${'2.0'} | ${{ path: '/v2/path', httpMethod: 'POST' }}
125
+ ${'3.0'} | ${{ path: '/v2/path', httpMethod: 'POST' }}
126
+ `(
127
+ 'should identify path and httpMethod based on version',
128
+ ({ version, tags }) => {
129
+ const handler = {
130
+ event: {
131
+ version,
132
+ headers: {},
133
+ ...tags,
134
+ requestContext: {
135
+ http: {
136
+ ...tags,
137
+ method: tags.httpMethod,
138
+ },
139
+ },
140
+ },
141
+ };
142
+ normalizeHttpRequestBeforeHandler(handler, () => {});
143
+ expect(logger.meta.tags).toStrictEqual(tags);
144
+ }
145
+ );
146
+
147
+ it('should not set tags when using API Gateway v2 and requestContext is empty', () => {
148
+ const handler = {
149
+ event: {
150
+ version: '2.0',
151
+ headers: {},
152
+ },
153
+ };
154
+
155
+ normalizeHttpRequestBeforeHandler(handler, () => {});
156
+ expect(logger.meta.tags).toStrictEqual({});
157
+ });
158
+
122
159
  it('should not set meta on debug', () => {
123
160
  app.debug = true;
124
161
  const handler = {
@@ -133,6 +170,7 @@ describe('MiddlewareGroup: test normalizeHttpRequestBeforeHandler', () => {
133
170
  },
134
171
  },
135
172
  };
173
+
136
174
  normalizeHttpRequestBeforeHandler(handler, () => {});
137
175
  expect(logger.meta.auth).toBe(handler.event.auth);
138
176
  expect(logger.meta.queryStringParameters).toStrictEqual(
@@ -1,6 +1,8 @@
1
1
  import logger from '../utils/logger';
2
2
  import isEmpty from '../utils/isEmpty';
3
3
 
4
+ const FILE = 'Lesgo/middlewares/errorHttpResponseMiddleware';
5
+
4
6
  export const errorHttpResponseHandler = async opts => {
5
7
  const defaults = {
6
8
  response: '',
@@ -29,7 +31,7 @@ export const errorHttpResponseHandler = async opts => {
29
31
  status: 'error',
30
32
  data: null,
31
33
  error: {
32
- code: options.error.code || 'UNKNOWN_ERROR',
34
+ code: options.error.code || 'UNHANDLED_ERROR',
33
35
  message: options.error.name
34
36
  ? `${options.error.name}: ${options.error.message}`
35
37
  : options.error.message || options.error,
@@ -40,18 +42,18 @@ export const errorHttpResponseHandler = async opts => {
40
42
 
41
43
  const statusCode = options.error.statusCode || options.statusCode;
42
44
 
43
- /* istanbul ignore next */
44
- if (statusCode === 500) {
45
- // this is likely an unhandled exception, log it
46
- logger.error(options.error);
45
+ if (!isEmpty(options.error)) {
46
+ logger.log(statusCode === 500 ? 'error' : 'warn', options.error);
47
47
  } else {
48
- logger.warn(options.error);
48
+ logger.log(statusCode === 500 ? 'error' : 'warn', jsonBody.error.message, {
49
+ error: jsonBody.error,
50
+ });
49
51
  }
50
52
 
51
53
  try {
52
54
  if (!isEmpty(opts.db)) await opts.db.end();
53
55
  } catch (err) {
54
- // do nothing
56
+ logger.error(`${FILE}::Failed to end db connection`, err);
55
57
  }
56
58
 
57
59
  return {
@@ -53,14 +53,26 @@ export const normalizeHttpRequestBeforeHandler = (handler, next) => {
53
53
  // eslint-disable-next-line no-param-reassign
54
54
  handler.event.auth = auth;
55
55
 
56
+ const tags = {};
57
+ switch (handler.event.version) {
58
+ case '2.0': {
59
+ if (handler.event.requestContext && handler.event.requestContext.http) {
60
+ tags.path = handler.event.requestContext.http.path;
61
+ tags.httpMethod = handler.event.requestContext.http.method;
62
+ }
63
+ break;
64
+ }
65
+ default:
66
+ tags.path = handler.event.path;
67
+ tags.httpMethod = handler.event.httpMethod;
68
+ break;
69
+ }
70
+
56
71
  logger.addMeta({
57
72
  requestId: handler.event.requestContext
58
73
  ? handler.event.requestContext.requestId
59
74
  : null,
60
- tags: {
61
- path: handler.event.path,
62
- httpMethod: handler.event.httpMethod,
63
- },
75
+ tags,
64
76
  });
65
77
 
66
78
  if (app.debug) {
@@ -38,24 +38,18 @@ class ElasticsearchService {
38
38
  return this.client;
39
39
  }
40
40
 
41
- search(body) {
42
- return new Promise((resolve, reject) => {
43
- const param = {
44
- index: this.index,
45
- type: this.type,
46
- body,
47
- };
48
- this.client.search(param, (err, response) => {
49
- /* istanbul ignore next */
50
- if (err) {
51
- reject(err);
52
- }
53
-
54
- this.result = response;
55
-
56
- resolve(response);
57
- });
58
- });
41
+ async search(body) {
42
+ const param = {
43
+ index: this.index,
44
+ type: this.type,
45
+ body,
46
+ };
47
+
48
+ const response = await this.client.search(param);
49
+
50
+ this.result = response;
51
+
52
+ return response;
59
53
  }
60
54
 
61
55
  /**
@@ -75,12 +69,7 @@ class ElasticsearchService {
75
69
  body: settings,
76
70
  };
77
71
 
78
- return new Promise((resolve, reject) => {
79
- this.client.indices.create(params, (err, response) => {
80
- // eslint-disable-next-line no-unused-expressions
81
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
82
- });
83
- });
72
+ return this.client.indices.create(params);
84
73
  }
85
74
 
86
75
  deleteIndices(index, options = {}) {
@@ -89,32 +78,20 @@ class ElasticsearchService {
89
78
  ...options,
90
79
  };
91
80
 
92
- return new Promise((resolve, reject) => {
93
- this.client.indices.delete(params, (err, response) => {
94
- // eslint-disable-next-line no-unused-expressions
95
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
96
- });
97
- });
81
+ return this.client.indices.delete(params);
98
82
  }
99
83
 
100
- existIndices(index, options = {}) {
84
+ async existIndices(index, options = {}) {
101
85
  const params = { index, ...options };
102
- return new Promise((resolve, reject) => {
103
- this.client.indices.exists(params, (err, response) => {
104
- // eslint-disable-next-line no-unused-expressions
105
- err ? /* istanbul ignore next */ reject(err) : resolve(response.body);
106
- });
107
- });
86
+
87
+ const response = await this.client.indices.exists(params);
88
+ return response.body;
108
89
  }
109
90
 
110
91
  putMapping(index, type, body) {
111
92
  const params = { index, type, body: { properties: body } };
112
- return new Promise((resolve, reject) => {
113
- this.client.indices.putMapping(params, (err, response) => {
114
- // eslint-disable-next-line no-unused-expressions
115
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
116
- });
117
- });
93
+
94
+ return this.client.indices.putMapping(params);
118
95
  }
119
96
 
120
97
  get(id) {
@@ -124,12 +101,7 @@ class ElasticsearchService {
124
101
  id,
125
102
  };
126
103
 
127
- return new Promise((resolve, reject) => {
128
- this.client.get(params, (err, response) => {
129
- // eslint-disable-next-line no-unused-expressions
130
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
131
- });
132
- });
104
+ return this.client.get(params);
133
105
  }
134
106
 
135
107
  indexOrCreateById(body, refresh = false) {
@@ -141,24 +113,11 @@ class ElasticsearchService {
141
113
  refresh,
142
114
  };
143
115
 
144
- return new Promise((resolve, reject) => {
145
- this.client.index(params, (err, response) => {
146
- // eslint-disable-next-line no-unused-expressions
147
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
148
- });
149
- });
116
+ return this.client.index(params);
150
117
  }
151
118
 
152
119
  bulkIndex(bodies) {
153
- return new Promise((resolve, reject) => {
154
- this.client.bulk(
155
- { body: this.constructBulkIndex(bodies) },
156
- (err, response) => {
157
- // eslint-disable-next-line no-unused-expressions
158
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
159
- }
160
- );
161
- });
120
+ return this.client.bulk({ body: this.constructBulkIndex(bodies) });
162
121
  }
163
122
 
164
123
  create(id, body) {
@@ -169,12 +128,7 @@ class ElasticsearchService {
169
128
  body,
170
129
  };
171
130
 
172
- return new Promise((resolve, reject) => {
173
- this.client.index(params, (err, response) => {
174
- // eslint-disable-next-line no-unused-expressions
175
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
176
- });
177
- });
131
+ return this.client.index(params);
178
132
  }
179
133
 
180
134
  updateById(id) {
@@ -184,12 +138,7 @@ class ElasticsearchService {
184
138
  id,
185
139
  };
186
140
 
187
- return new Promise((resolve, reject) => {
188
- this.client.get(params, (err, response) => {
189
- // eslint-disable-next-line no-unused-expressions
190
- err ? /* istanbul ignore next */ reject(err) : resolve(response);
191
- });
192
- });
141
+ return this.client.get(params);
193
142
  }
194
143
 
195
144
  /**
@@ -32,6 +32,8 @@ describe('test LengthAwarePaginator instantiate', () => {
32
32
  expect(await paginator.lastItem()).toMatchObject(mockDataLastItem);
33
33
  expect(paginator.perPage()).toEqual(5);
34
34
  expect(await paginator.total()).toEqual(30);
35
+
36
+ expect(db.select).toHaveBeenCalled();
35
37
  });
36
38
  it('should not throw exception when instantiating with current page', async () => {
37
39
  const paginator = new LengthAwarePaginator(
@@ -51,6 +53,8 @@ describe('test LengthAwarePaginator instantiate', () => {
51
53
  expect(await paginator.lastItem()).toMatchObject(mockDataLastItem);
52
54
  expect(paginator.perPage()).toEqual(5);
53
55
  expect(await paginator.total()).toEqual(30);
56
+
57
+ expect(db.select).toHaveBeenCalled();
54
58
  });
55
59
  it('should default perPage to 10 when instantiating without perPage', async () => {
56
60
  const paginator = new LengthAwarePaginator(
@@ -66,6 +70,8 @@ describe('test LengthAwarePaginator instantiate', () => {
66
70
  expect(paginator.currentPage()).toEqual(1);
67
71
  expect(paginator.perPage()).toEqual(10);
68
72
  expect(await paginator.total()).toEqual(30);
73
+
74
+ expect(db.select).toHaveBeenCalled();
69
75
  });
70
76
  it('should throw exception if total is not a number', async () => {
71
77
  try {
@@ -116,6 +122,43 @@ describe('test LengthAwarePaginator instantiate', () => {
116
122
  { ...mockDataLastItem },
117
123
  ],
118
124
  });
125
+
126
+ expect(db.select).toHaveBeenCalled();
127
+ });
128
+
129
+ it('should simply return an empty paginator object if total is explicitly zero', async () => {
130
+ const paginator = new LengthAwarePaginator(
131
+ db,
132
+ 'SELECT * FROM tests',
133
+ {},
134
+ {
135
+ perPage: 5,
136
+ currentPage: 1,
137
+ total: 0,
138
+ }
139
+ );
140
+
141
+ expect(await paginator.count()).toEqual(0);
142
+ expect(await paginator.previousPage()).toEqual(false);
143
+ expect(paginator.currentPage()).toEqual(1);
144
+ expect(await paginator.nextPage()).toEqual(false);
145
+ expect(await paginator.firstItem()).toBe(undefined);
146
+ expect(await paginator.lastItem()).toBe(undefined);
147
+ expect(paginator.perPage()).toEqual(5);
148
+ expect(await paginator.total()).toEqual(0);
149
+
150
+ expect(await paginator.toObject()).toMatchObject({
151
+ count: 0,
152
+ previous_page: false,
153
+ current_page: 1,
154
+ next_page: false,
155
+ per_page: 5,
156
+ last_page: 0,
157
+ total: 0,
158
+ items: [],
159
+ });
160
+
161
+ expect(db.select).not.toHaveBeenCalled();
119
162
  });
120
163
  });
121
164
 
@@ -138,7 +181,7 @@ describe('test total() usage', () => {
138
181
  });
139
182
 
140
183
  describe('test lastPage() usage', () => {
141
- it('should get the last page using supplied paramater as total data', async () => {
184
+ it('should get the last page using supplied parameter as total data', async () => {
142
185
  const paginator1 = new LengthAwarePaginator(
143
186
  db,
144
187
  'SELECT * FROM total_tests',
@@ -217,11 +217,17 @@ export default class Paginator {
217
217
  }
218
218
 
219
219
  async executeQuery() {
220
- this.response = await this.dbProp.select(
221
- this.generatePaginationSqlSnippet(),
222
- this.sqlParamsProp,
223
- this.connection
224
- );
220
+ const total = this.totalProp;
221
+ if (
222
+ (typeof total === 'number' && total > 0) ||
223
+ (typeof total !== 'number' && !total)
224
+ ) {
225
+ this.response = await this.dbProp.select(
226
+ this.generatePaginationSqlSnippet(),
227
+ this.sqlParamsProp,
228
+ this.connection
229
+ );
230
+ }
225
231
 
226
232
  this.hasNext = this.response.length > this.perPage();
227
233
  if (this.hasNext) {