piper-utils 1.1.30 → 1.1.31

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.
@@ -1,287 +1,276 @@
1
- import _ from 'lodash';
2
- import { errorList } from './errorCodes.js';
3
-
4
- /**
5
- * @param {Object} body
6
- * @param {{dbClose?:function}} [options]
7
- */
8
- export function success(body, options) {
9
- const dbClose = _.get(options, 'dbClose', _.noop);
10
- dbClose();
11
-
12
- return buildResponse(200, body);
13
- }
14
-
15
- /**
16
- * @param {string} html
17
- * @param {{dbClose:function|undefined}} options
18
- */
19
- export function successHtml(html, options) {
20
- const dbClose = _.get(options, 'dbClose', _.noop);
21
-
22
- dbClose();
23
- return {
24
- statusCode: 200,
25
- headers: {
26
- 'Content-Type': 'text/html',
27
- 'Access-Control-Allow-Origin': '*',
28
- 'Access-Control-Allow-Credentials': true
29
- },
30
- body: html
31
- };
32
- }
33
-
34
- /**
35
- * @param {string} event
36
- * @returns string
37
- */
38
- export function getCurrentUserNameFromCognitoEvent(event) {
39
- const attributes = _.get(event, 'request.userAttributes');
40
-
41
- return attributes['cognito:email_alias'] || attributes['email'] || 'UNKNOWN USER';
42
- }
43
-
44
- /**
45
- * Get the user information from the event object
46
- *
47
- * @param event {Object} an event object
48
- * @returns {{username: string, id: number}}
49
- */
50
- export function getCurrentUser(event) {
51
- let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:UID') ||
52
- _.get(event, 'requestContext.authorizer.custom:UID') ||
53
- '0';
54
-
55
- const id = JSON.parse(jsonToParse);
56
-
57
- const username = _.get(event, 'requestContext.authorizer.claims.email') || _.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';
58
-
59
- return {
60
- username,
61
- id
62
- };
63
- }
64
-
65
- /**
66
- * Create a failure response
67
- *
68
- * @param body {Object} an event object
69
- * @param options {Object} an options object
70
- * @returns {{statusCode:number, headers:object, body:string}} a response object
71
- */
72
- export function failure(body = {}, options) {
73
- const dbClose = _.get(options, 'dbClose', _.noop);
74
- dbClose();
75
- let cleanedErrorBody;
76
-
77
- if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {
78
- if (_.isObject(body)) {
79
- console.error('------->ALL UTIL ERROR:', JSON.stringify(body, null, 2));
80
- }
81
- }
82
-
83
- const NORMAL_ERROR = { statusCode: 500, errorCode: '5XX', message: 'INTERNAL UTIL ERROR' };
84
- cleanedErrorBody = body;
85
- if (!_.isUndefined(body.details)) {
86
- cleanedErrorBody = detectJoyError(body);
87
- } else if (_.isUndefined(body.errorCode) || _.isUndefined(body.statusCode)) {
88
- cleanedErrorBody = detectSequelizeError(body);
89
- }
90
- if (_.get(body, 'response.data.message')) {
91
- const err = _.get(body, 'response.data.message');
92
- if (_.isObject(body)) {
93
- console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));
94
- }
95
- }
96
- const newBody = _.merge(NORMAL_ERROR, cleanedErrorBody);
97
-
98
- return buildResponse(newBody.statusCode, newBody);
99
- }
100
-
101
- /**
102
- * Create a failure response object
103
- *
104
- * @param statusCode {Number} a status code
105
- * @param body {Object} an event object
106
- * @returns {{statusCode:number, headers:object, body:string}} a response object
107
- */
108
- function buildResponse(statusCode, body) {
109
- return {
110
- statusCode: statusCode,
111
- headers: {
112
- 'Access-Control-Allow-Origin': '*',
113
- 'Access-Control-Allow-Credentials': true
114
- },
115
- body: JSON.stringify(body)
116
- };
117
- }
118
-
119
- /**
120
- * parse the body of the event object
121
- *
122
- * @param requestEvent {{body:string}} an event object
123
- * @returns event {*} the json object of the body
124
- */
125
- export function parseBody(requestEvent) {
126
-
127
- let eventBody = {};
128
- if (_.isString(requestEvent.body)) {
129
- try {
130
- eventBody = JSON.parse(requestEvent.body);
131
- } catch (e) {
132
- // Invalid JSON
133
- eventBody = null;
134
-
135
- throw errorList.invalidJson;
136
- }
137
- } else if (_.isObject(requestEvent.body)) {
138
- eventBody = requestEvent.body;
139
- }
140
-
141
- return eventBody;
142
- }
143
-
144
- /**
145
- * parse the body of the event object
146
- *
147
- * @param requestEvent {string|object} an event object
148
- * @param [callback] {function} undefined a call back function
149
- * @returns event {*} the json object of the body
150
- */
151
- export function parseEvent(requestEvent, callback) {
152
- let event = {};
153
- if (_.isString(requestEvent)) {
154
- try {
155
- event = JSON.parse(requestEvent);
156
- } catch (e) {
157
- // Invalid JSON
158
- event = null;
159
-
160
- if (callback) {
161
- callback(Error(e));
162
- }
163
- }
164
- } else if (_.isObject(requestEvent)) {
165
- event = requestEvent;
166
- }
167
-
168
- return event;
169
- }
170
-
171
- /**
172
- * parse the body of the event object
173
- * look for sequelize errors and return a message
174
- * ERRORS should not be caught here this is a fallback for unknown database errors
175
- *
176
- * @param body {object} part of a body response
177
- * @returns error message object {message:string}
178
- */
179
- export function detectSequelizeError(body) {
180
- const errorBody = {};
181
- const errorName = _.get(body, 'name', '');
182
-
183
- if (errorName === 'SequelizeForeignKeyConstraintError') {
184
- errorBody.message = 'You cannot delete this item as it is in use';
185
- errorBody.statusCode = 409;
186
- errorBody.errorCode = '4090';
187
- return errorBody;
188
- }
189
-
190
- if (errorName === 'SequelizeUniqueConstraintError') {
191
- const fields = _.get(body, 'errors', []).map(err => _.get(err, 'path')).filter(Boolean);
192
- errorBody.message = fields.length
193
- ? 'A record with this ' + fields.join(', ') + ' already exists'
194
- : 'A record with this value already exists';
195
- errorBody.statusCode = 409;
196
- errorBody.errorCode = '4091';
197
- return errorBody;
198
- }
199
-
200
- if (errorName === 'SequelizeValidationError') {
201
- const messages = _.get(body, 'errors', []).map(err => _.get(err, 'message')).filter(Boolean);
202
- errorBody.message = messages.length ? messages.join(', ') : 'Validation error';
203
- errorBody.statusCode = 400;
204
- errorBody.errorCode = '4001';
205
- return errorBody;
206
- }
207
-
208
- let sequelizeError = _.get(body, 'errors', []).reduce((acc, err) => {
209
- acc = acc + ' ' + _.get(err, 'message');
210
- return acc;
211
- }, '');
212
- const parentError = _.get(body, 'parent', '');
213
-
214
- sequelizeError = sequelizeError + _.get(body, 'original.detail', '') + _.get(body, 'TypeError', '') + parentError;
215
- errorBody.message = sequelizeError.trim();
216
- return errorBody;
217
- }
218
-
219
- export function detectJoyError(body) {
220
- const errorBody = {};
221
- const details = _.get(body, 'details') || [];
222
-
223
- console.error('USER VALIDATION ERROR:', body);
224
- const messages = extractJoyMessages(details);
225
- const msg = messages.join(', ');
226
-
227
- if (msg) {
228
- errorBody.message = msg;
229
- }
230
-
231
- errorBody.statusCode = 400;
232
- errorBody.errorCode = '4000';
233
- return errorBody;
234
- }
235
-
236
- function extractJoyMessages(details) {
237
- const messages = [];
238
- for (const detail of details) {
239
- const contextDetails = _.get(detail, 'context.details') || [];
240
- const directDetails = detail.details || [];
241
- const nestedDetails = contextDetails.length > 0 ? contextDetails : directDetails;
242
-
243
- if (nestedDetails.length > 0) {
244
- messages.push(...extractJoyMessages(nestedDetails));
245
- } else if (detail.message) {
246
- messages.push(detail.message);
247
- }
248
- }
249
- return messages;
250
- }
251
-
252
- /**
253
- * Parse the body of a Dynamoose error response.
254
- * Attempts to extract a human-readable error message from Dynamoose errors.
255
- * This is a fallback for unknown database errors.
256
- *
257
- * @param {object} body - Part of a body response containing error details.
258
- * @returns {object} - Error message object { message: string }
259
- */
260
- export function detectDynamooseError(body) {
261
- const errorBody = {};
262
-
263
- // Start with an empty message string.
264
- let dynamooseError = '';
265
-
266
- // If the error body contains an array of errors, concatenate their messages.
267
- if (Array.isArray(body.errors)) {
268
- dynamooseError += body.errors.reduce((acc, err) => {
269
- return acc + ' ' + (err.message || '');
270
- }, '');
271
- }
272
-
273
- // If there's a top-level message, add it.
274
- if (body.message) {
275
- dynamooseError += ' ' + body.message;
276
- }
277
-
278
- // If there is any additional detail provided, append it.
279
- if (body.detail) {
280
- dynamooseError += ' ' + body.detail;
281
- }
282
-
283
- // Trim the message to remove extra spaces.
284
- errorBody.message = dynamooseError.trim();
285
-
286
- return errorBody;
1
+ import _ from 'lodash';
2
+ import { errorList } from './errorCodes.js';
3
+
4
+ /**
5
+ * @param {Object} body
6
+ * @param {{dbClose?:function}} [options]
7
+ */
8
+ export function success(body, options) {
9
+ const dbClose = _.get(options, 'dbClose', _.noop);
10
+ dbClose();
11
+
12
+ return buildResponse(200, body);
13
+ }
14
+
15
+ /**
16
+ * @param {string} html
17
+ * @param {{dbClose:function|undefined}} options
18
+ */
19
+ export function successHtml(html, options) {
20
+ const dbClose = _.get(options, 'dbClose', _.noop);
21
+
22
+ dbClose();
23
+ return {
24
+ statusCode: 200,
25
+ headers: {
26
+ 'Content-Type': 'text/html',
27
+ 'Access-Control-Allow-Origin': '*',
28
+ 'Access-Control-Allow-Credentials': true
29
+ },
30
+ body: html
31
+ };
32
+ }
33
+
34
+ /**
35
+ * @param {string} event
36
+ * @returns string
37
+ */
38
+ export function getCurrentUserNameFromCognitoEvent(event) {
39
+ const attributes = _.get(event, 'request.userAttributes');
40
+
41
+ return attributes['cognito:email_alias'] || attributes['email'] || 'UNKNOWN USER';
42
+ }
43
+
44
+ /**
45
+ * Get the user information from the event object
46
+ *
47
+ * @param event {Object} an event object
48
+ * @returns {{username: string, id: number}}
49
+ */
50
+ export function getCurrentUser(event) {
51
+ let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:UID') ||
52
+ _.get(event, 'requestContext.authorizer.custom:UID') ||
53
+ '0';
54
+
55
+ const id = JSON.parse(jsonToParse);
56
+
57
+ const username = _.get(event, 'requestContext.authorizer.claims.email') || _.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';
58
+
59
+ return {
60
+ username,
61
+ id
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Create a failure response
67
+ *
68
+ * @param body {Object} an event object
69
+ * @param options {Object} an options object
70
+ * @returns {{statusCode:number, headers:object, body:string}} a response object
71
+ */
72
+ export function failure(body = {}, options) {
73
+ const dbClose = _.get(options, 'dbClose', _.noop);
74
+ dbClose();
75
+ let cleanedErrorBody;
76
+
77
+ if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {
78
+ if (_.isObject(body)) {
79
+ console.error('------->ALL UTIL ERROR:', JSON.stringify(body, null, 2));
80
+ }
81
+ }
82
+
83
+ const NORMAL_ERROR = { statusCode: 500, errorCode: '5XX', message: 'INTERNAL UTIL ERROR' };
84
+ cleanedErrorBody = body;
85
+ if (!_.isUndefined(body.details)) {
86
+ cleanedErrorBody = detectJoyError(body);
87
+ } else if (_.isUndefined(body.errorCode) || _.isUndefined(body.statusCode)) {
88
+ cleanedErrorBody = detectSequelizeError(body);
89
+ }
90
+ if (_.get(body, 'response.data.message')) {
91
+ const err = _.get(body, 'response.data.message');
92
+ if (_.isObject(body)) {
93
+ console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));
94
+ }
95
+ }
96
+ const newBody = _.merge(NORMAL_ERROR, cleanedErrorBody);
97
+
98
+ return buildResponse(newBody.statusCode, newBody);
99
+ }
100
+
101
+ /**
102
+ * Create a failure response object
103
+ *
104
+ * @param statusCode {Number} a status code
105
+ * @param body {Object} an event object
106
+ * @returns {{statusCode:number, headers:object, body:string}} a response object
107
+ */
108
+ function buildResponse(statusCode, body) {
109
+ return {
110
+ statusCode: statusCode,
111
+ headers: {
112
+ 'Access-Control-Allow-Origin': '*',
113
+ 'Access-Control-Allow-Credentials': true
114
+ },
115
+ body: JSON.stringify(body)
116
+ };
117
+ }
118
+
119
+ /**
120
+ * parse the body of the event object
121
+ *
122
+ * @param requestEvent {{body:string}} an event object
123
+ * @returns event {*} the json object of the body
124
+ */
125
+ export function parseBody(requestEvent) {
126
+
127
+ let eventBody = {};
128
+ if (_.isString(requestEvent.body)) {
129
+ try {
130
+ eventBody = JSON.parse(requestEvent.body);
131
+ } catch (e) {
132
+ // Invalid JSON
133
+ eventBody = null;
134
+
135
+ throw errorList.invalidJson;
136
+ }
137
+ } else if (_.isObject(requestEvent.body)) {
138
+ eventBody = requestEvent.body;
139
+ }
140
+
141
+ return eventBody;
142
+ }
143
+
144
+ /**
145
+ * parse the body of the event object
146
+ *
147
+ * @param requestEvent {string|object} an event object
148
+ * @param [callback] {function} undefined a call back function
149
+ * @returns event {*} the json object of the body
150
+ */
151
+ export function parseEvent(requestEvent, callback) {
152
+ let event = {};
153
+ if (_.isString(requestEvent)) {
154
+ try {
155
+ event = JSON.parse(requestEvent);
156
+ } catch (e) {
157
+ // Invalid JSON
158
+ event = null;
159
+
160
+ if (callback) {
161
+ callback(Error(e));
162
+ }
163
+ }
164
+ } else if (_.isObject(requestEvent)) {
165
+ event = requestEvent;
166
+ }
167
+
168
+ return event;
169
+ }
170
+
171
+ /**
172
+ * parse the body of the event object
173
+ * look for sequelize errors and return a message
174
+ * ERRORS should not be caught here this is a fallback for unknown database errors
175
+ *
176
+ * @param body {object} part of a body response
177
+ * @returns error message object {message:string}
178
+ */
179
+ export function detectSequelizeError(body) {
180
+ const errorBody = {};
181
+ const errorName = _.get(body, 'name', '');
182
+
183
+ if (errorName === 'SequelizeForeignKeyConstraintError') {
184
+ errorBody.message = 'You cannot delete this item as it is in use';
185
+ errorBody.statusCode = 409;
186
+ errorBody.errorCode = '4090';
187
+ return errorBody;
188
+ }
189
+
190
+ if (errorName === 'SequelizeUniqueConstraintError') {
191
+ const fields = _.get(body, 'errors', []).map(err => _.get(err, 'path')).filter(Boolean);
192
+ errorBody.message = fields.length
193
+ ? 'A record with this ' + fields.join(', ') + ' already exists'
194
+ : 'A record with this value already exists';
195
+ errorBody.statusCode = 409;
196
+ errorBody.errorCode = '4091';
197
+ return errorBody;
198
+ }
199
+
200
+ if (errorName === 'SequelizeValidationError') {
201
+ const messages = _.get(body, 'errors', []).map(err => _.get(err, 'message')).filter(Boolean);
202
+ errorBody.message = messages.length ? messages.join(', ') : 'Validation error';
203
+ errorBody.statusCode = 400;
204
+ errorBody.errorCode = '4001';
205
+ return errorBody;
206
+ }
207
+
208
+ let sequelizeError = _.get(body, 'errors', []).reduce((acc, err) => {
209
+ acc = acc + ' ' + _.get(err, 'message');
210
+ return acc;
211
+ }, '');
212
+ const parentError = _.get(body, 'parent', '');
213
+
214
+ sequelizeError = sequelizeError + _.get(body, 'original.detail', '') + _.get(body, 'TypeError', '') + parentError;
215
+ errorBody.message = sequelizeError.trim();
216
+ return errorBody;
217
+ }
218
+
219
+ export function detectJoyError(body) {
220
+ const errorBody = {};
221
+ const joyError = _.get(body, 'details[0]', {});
222
+ const additionalMessages = _.get(body, 'details[0].context.details') || [];
223
+
224
+ const v = additionalMessages.reduce((acc, contextItem) => {
225
+ acc = acc + ' ' + contextItem?.message || '';
226
+ return acc;
227
+ }, '');
228
+
229
+ console.error('USER VALIDATION ERROR:', JSON.stringify(body, null, 2));
230
+ const msg = (joyError?.message || '') + v;
231
+
232
+ if (msg) {
233
+ errorBody.message = _.trim(msg);
234
+ }
235
+
236
+ errorBody.statusCode = 400;
237
+ errorBody.errorCode = '4000';
238
+ return errorBody;
239
+ }
240
+
241
+ /**
242
+ * Parse the body of a Dynamoose error response.
243
+ * Attempts to extract a human-readable error message from Dynamoose errors.
244
+ * This is a fallback for unknown database errors.
245
+ *
246
+ * @param {object} body - Part of a body response containing error details.
247
+ * @returns {object} - Error message object { message: string }
248
+ */
249
+ export function detectDynamooseError(body) {
250
+ const errorBody = {};
251
+
252
+ // Start with an empty message string.
253
+ let dynamooseError = '';
254
+
255
+ // If the error body contains an array of errors, concatenate their messages.
256
+ if (Array.isArray(body.errors)) {
257
+ dynamooseError += body.errors.reduce((acc, err) => {
258
+ return acc + ' ' + (err.message || '');
259
+ }, '');
260
+ }
261
+
262
+ // If there's a top-level message, add it.
263
+ if (body.message) {
264
+ dynamooseError += ' ' + body.message;
265
+ }
266
+
267
+ // If there is any additional detail provided, append it.
268
+ if (body.detail) {
269
+ dynamooseError += ' ' + body.detail;
270
+ }
271
+
272
+ // Trim the message to remove extra spaces.
273
+ errorBody.message = dynamooseError.trim();
274
+
275
+ return errorBody;
287
276
  }