vtlab-generic-functions 1.0.4

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,30 @@
1
+ ### Example usage from Lambda JS:
2
+
3
+ ```javascript
4
+ let result = await pelRequest.get('https://api.sampleapis.com/coffee/hot', {
5
+ "auth": {
6
+ "test": "test"
7
+ },
8
+ "logId": "apiGateway/microservices",
9
+ "payload": []
10
+ });
11
+
12
+ console.log(result.data);
13
+
14
+ ```
15
+
16
+ #### Example SOAP usage from Lambda JS:
17
+ ```javascript
18
+ let result = await pelRequest.sendSoapRequest('http://www.gcomputer.net//webservices/dilbert.asmx', {
19
+ "auth": {
20
+ "test": "test"
21
+ },
22
+ "logId": "apiGateway/microservices",
23
+ "payload": xml,
24
+ "headers": {
25
+ "SOAPAction": "http://gcomputer.net/webservices/DailyDilbert"
26
+ }
27
+ });
28
+
29
+ console.log(result);
30
+ ```
package/axios/index.js ADDED
@@ -0,0 +1,287 @@
1
+ const axios = require('axios');
2
+ const Joi = require('joi');
3
+ const axiosLogs = require('./logs');
4
+
5
+ // set axios defaults
6
+ axios.defaults.timeout = 120000;
7
+ axios.defaults.headers.post['Content-Type'] = 'application/json';
8
+ axios.defaults.headers.get['Content-Type'] = 'application/json';
9
+ axios.defaults.headers.put['Content-Type'] = 'application/json';
10
+ axios.defaults.headers.patch['Content-Type'] = 'application/json';
11
+ axios.defaults.headers.post['Accept'] = 'application/json';
12
+ axios.defaults.headers.get['Accept'] = 'application/json';
13
+ axios.defaults.headers.put['Accept'] = 'application/json';
14
+ axios.defaults.headers.patch['Accept'] = 'application/json';
15
+
16
+ /**
17
+ * Joi schema validation for request param
18
+ * @type {Joi.ObjectSchema<any>}
19
+ */
20
+ const paramSchema = Joi.object({
21
+ 'logId': Joi.string().max(200).required().trim(), //this for us to store the request in the cloduwatch
22
+ 'payload': Joi.alternatives().try(Joi.array(), Joi.object(), Joi.string()).optional(), // this for the marketplace or 3rd party
23
+ 'config': Joi.object().optional(), // this to config the axios
24
+ 'headers': Joi.object().optional() // this to set/configure the headers like auth or anything
25
+ });
26
+
27
+ /**
28
+ * validate params against paramSchema
29
+ * @param params Object request param
30
+ * @returns {any} Object of valid param or Joi's error validation message
31
+ */
32
+ const validateParams = (params) => {
33
+ let result = paramSchema.validate(params, { abortEarly: false, stripUnknown: true });
34
+ if (result.error) {
35
+ throw new Error(result.error.message);
36
+ }
37
+ return result.value;
38
+ };
39
+
40
+ /**
41
+ * list of things before makes axios request
42
+ * @param url
43
+ * @param params
44
+ * @returns {Promise<void>}
45
+ * @private
46
+ */
47
+ const _beforeRequestHook = async (url, params) => {
48
+ await axiosLogs.processLogAndUploadToCW(params, params.logId)
49
+ };
50
+
51
+ /**
52
+ * list of this after axios SUCCESS response
53
+ * @param url
54
+ * @param params
55
+ * @param response
56
+ * @returns {Promise<void>}
57
+ * @private
58
+ */
59
+ const _afterRequestSuccessHook = async (url, params, response) => {
60
+ // Do something after request is sent
61
+ let logValue = JSON.stringify({
62
+ status: response.status,
63
+ statusText: response.statusText,
64
+ headers: response.headers,
65
+ config: response.config,
66
+ data: response.data
67
+ });
68
+
69
+ await axiosLogs.processLogAndUploadToCW(logValue, params.logId);
70
+ };
71
+
72
+ /**
73
+ * list of this after axios ERROR response
74
+ * @param url
75
+ * @param params
76
+ * @param response
77
+ * @returns {Promise<void>}
78
+ * @private
79
+ */
80
+ const _afterRequestErrorHook = async (url, params, response) => {
81
+ // Do something after request is sent
82
+ let logValue = JSON.stringify({
83
+ status: response.status,
84
+ statusText: response.statusText,
85
+ headers: response.headers,
86
+ config: response.config,
87
+ data: response.data,
88
+ isAxiosError: response.isAxiosError,
89
+ message: response.message,
90
+ stack: response.stack
91
+ });
92
+
93
+ await axiosLogs.processLogAndUploadToCW(logValue, params.logId);
94
+ };
95
+
96
+ /**
97
+ * filter payload from params
98
+ * @param params
99
+ * @returns {*[]}
100
+ * @private
101
+ */
102
+ const _preparePayload = (params) => {
103
+ return params.payload || '';
104
+ };
105
+
106
+ /**
107
+ * Make axios request
108
+ * @param url
109
+ * @param params
110
+ * @param method
111
+ * @returns {Promise<unknown>}
112
+ */
113
+ const request = (url, params, method) => {
114
+ return new Promise(async (resolve, reject) => {
115
+ //validate
116
+ let validParam = validateParams(params);
117
+
118
+ let configurationParams = {};
119
+
120
+ //steps before making request
121
+ await _beforeRequestHook(url, validParam);
122
+
123
+ //prepare payload
124
+ let payload = _preparePayload(validParam);
125
+ // console.log(`${method} ${url}`, payload);
126
+
127
+ // if any custom headers are required, add them to the request
128
+ if (validParam.headers) {
129
+ configurationParams['headers'] = validParam.headers;
130
+ }
131
+
132
+ // add config params
133
+ if (validParam.config) {
134
+ configurationParams = {
135
+ ...configurationParams,
136
+ ...validParam.config
137
+ }
138
+ }
139
+
140
+ //lets make axios request
141
+ axios[method](url, payload, configurationParams).then(async function (response) {
142
+
143
+ //success request
144
+ await _afterRequestSuccessHook(url, validParam, response);
145
+ resolve(response);
146
+ })
147
+ .catch(async function (error) {
148
+
149
+ //error response
150
+ await _afterRequestErrorHook(url, validParam, error);
151
+ reject(error);
152
+ });
153
+ });
154
+ };
155
+
156
+ /**
157
+ * Make axios request
158
+ * @param url
159
+ * @param params
160
+ * @param method
161
+ * @returns {Promise<unknown>}
162
+ */
163
+ const getRequest = (url, params, method) => {
164
+ return new Promise(async (resolve, reject) => {
165
+ //validate
166
+ let validParam = validateParams(params);
167
+
168
+ let configurationParams = {};
169
+
170
+ //steps before making request
171
+ await _beforeRequestHook(url, validParam);
172
+
173
+ //prepare payload
174
+ let payload = _preparePayload(validParam);
175
+ // console.log(`${method} ${url}`, payload);
176
+
177
+ // if any custom headers are required, add them to the request
178
+ if (validParam.headers) {
179
+ configurationParams['headers'] = validParam.headers;
180
+ }
181
+
182
+ // add config params
183
+ if (validParam.config) {
184
+ configurationParams = {
185
+ ...configurationParams,
186
+ ...validParam.config
187
+ }
188
+ }
189
+
190
+ //lets make axios request
191
+ axios[method](url, configurationParams).then(async function (response) {
192
+
193
+ //success request
194
+ await _afterRequestSuccessHook(url, validParam, response);
195
+ resolve(response);
196
+ })
197
+ .catch(async function (error) {
198
+
199
+ //error response
200
+ await _afterRequestErrorHook(url, validParam, error);
201
+ reject(error);
202
+ });
203
+ });
204
+ };
205
+
206
+ /**
207
+ * GET request handler
208
+ * @param url
209
+ * @param params
210
+ * @returns {Promise<*>}
211
+ */
212
+ const get = async (url, params) => {
213
+ return await getRequest(url, params, 'get');
214
+ };
215
+
216
+ /**
217
+ * POST method handler
218
+ * @param url
219
+ * @param params
220
+ * @returns {Promise<*>}
221
+ */
222
+ const post = async (url, params) => {
223
+ return await request(url, params, 'post');
224
+ };
225
+
226
+ /**
227
+ * PUT request handler
228
+ * @param url
229
+ * @param params
230
+ * @returns {Promise<*>}
231
+ */
232
+ const put = async (url, params) => {
233
+ return await request(url, params, 'put');
234
+ };
235
+
236
+ /**
237
+ * PATCH request handler
238
+ * @param url
239
+ * @param params
240
+ * @returns {Promise<*>}
241
+ */
242
+ const patch = async (url, params) => {
243
+ return await request(url, params, 'patch');
244
+ };
245
+
246
+
247
+ /**
248
+ * DELETE request handler
249
+ * @param url
250
+ * @param params
251
+ * @returns {Promise<*>}
252
+ */
253
+ const deletion = async (url, params) => {
254
+ return await getRequest(url, params, 'delete');
255
+ };
256
+
257
+ const sendSoapRequest = async (url, params) => {
258
+ //default headers
259
+ const headers = {
260
+ 'Content-Type': 'text/xml; charset=utf-8',
261
+ };
262
+ params.headers = Object.assign(params.headers, headers);
263
+ /*If you need to add aditional header. Add it in the params
264
+ eg header params
265
+ {
266
+ "auth": {
267
+ ...
268
+ },
269
+ "logId": "...",
270
+ "payload": xml,
271
+ "headers": {
272
+ "SOAPAction": "http://gcomputer.net/webservices/DailyDilbert"
273
+ }
274
+ }*/
275
+
276
+ return await post(url, params);
277
+ }
278
+
279
+ // export the request handler
280
+ module.exports = {
281
+ get,
282
+ post,
283
+ put,
284
+ patch,
285
+ deletion,
286
+ sendSoapRequest
287
+ };
package/axios/logs.js ADDED
@@ -0,0 +1,110 @@
1
+ const cloudwatch = require('../cloudwatch');
2
+ const s3bucket = require('../s3bucket');
3
+ const secretsManager = require('../config');
4
+
5
+ /**
6
+ * Processes a payload, checks its size, and if it's larger than the max size, uploads it to an S3 bucket.
7
+ *
8
+ * @async
9
+ * @param {string | Buffer | object} payload - The payload to process. Can be a string, a Buffer, or an object.
10
+ * @returns {Promise<string>} If the payload is larger than the max size, returns a presigned URL to the payload in the S3 bucket. Otherwise, returns the original payload.
11
+ * @throws {Error} If the payload is an unsupported data type.
12
+ */
13
+ const processPayload = async (payload) => {
14
+ // Maximum payload size in kilobytes
15
+ const maxPayloadSize = 15;
16
+
17
+ // Initialize dataSize with a default value
18
+ let dataSize = 0;
19
+
20
+ if (payload) {
21
+ // If the payload is a string, calculate the byte length of the string
22
+ if (typeof payload === 'string') {
23
+ dataSize = Buffer.byteLength(payload);
24
+ }
25
+ // If the payload is an object, stringify it and then calculate the byte length of the string
26
+ else if (typeof payload === 'object') {
27
+ dataSize = Buffer.byteLength(JSON.stringify(payload));
28
+ }
29
+ // If the payload is a Buffer, use its length property
30
+ else if (Buffer.isBuffer(payload)) {
31
+ dataSize = payload.length;
32
+ }
33
+ // If the payload is of another type, try to convert it to a string and then calculate the byte length
34
+ else {
35
+ try {
36
+ let dataToString = String(payload);
37
+ dataSize = Buffer.byteLength(dataToString);
38
+ } catch (e) {
39
+ throw new Error('Unsupported data type');
40
+ }
41
+ }
42
+ }
43
+
44
+ // Calculate the size of the data in kilobytes
45
+ const dataSizeKB = dataSize / 1024;
46
+
47
+ // Determine the environment
48
+ const environment = process.env.NODE_ENV === "production" ? "production" : "develop";
49
+
50
+ // Initialize response with the original payload
51
+ let response = payload;
52
+
53
+ // Create the path for the S3 bucket
54
+ const path = `${environment}/axios/${Date.now()}.txt`;
55
+
56
+ // If the payload size is larger than the maximum size, upload it to the S3 bucket and generate a presigned URL
57
+ if(dataSizeKB > maxPayloadSize) {
58
+ let bucketOptions = {
59
+ ACL: "private",
60
+ ContentType: 'text/plain'
61
+ }
62
+ let bucketConfirmedPath = await s3bucket.uploadToS3(path, payload, bucketOptions, "s3LogsBucket");
63
+ console.log("bucketConfirmedPath", bucketConfirmedPath);
64
+ // get bucket name from secrets manager
65
+ let bucket = await secretsManager.get('s3LogsBucket');
66
+ console.log("bucket", bucket);
67
+ let signedURL = s3bucket.generatePresignedUrl(bucket, path);
68
+ console.log("signedURL", signedURL)
69
+
70
+ // Update the response to be the presigned URL
71
+ response = `Payload size too big. Read the full log here: ${signedURL}`;
72
+ }
73
+
74
+ // Return the response
75
+ return response;
76
+ }
77
+
78
+
79
+
80
+ /**
81
+ * Processes a log and uploads it to CloudWatch.
82
+ *
83
+ * @async
84
+ * @param {string | Buffer | object} log - The log to process and upload.
85
+ * @param {string} logId - The ID of the log.
86
+ */
87
+ const processLogAndUploadToCW = async (log, logId) => {
88
+ try {
89
+ // If the global variable SKIPAXIOSLOGS is set to true, don't process or upload the log
90
+ if (global.SKIPAXIOSLOGS) {
91
+ return;
92
+ }
93
+
94
+ // Process the log payload
95
+ let logValue = await processPayload(log);
96
+
97
+ // Upload the processed log to CloudWatch
98
+ await cloudwatch.putLogEvents(logValue, logId);
99
+
100
+ } catch (e) {
101
+ // If an error occurs, log it
102
+ console.log("Layer error processLogAndUploadToCW: ", e);
103
+ }
104
+ }
105
+
106
+
107
+
108
+ module.exports = {
109
+ processLogAndUploadToCW
110
+ };
package/axios/utils.js ADDED
@@ -0,0 +1,37 @@
1
+ const xml2js = require('xml2js');
2
+
3
+ /**
4
+ * convert xml to JSON
5
+ * @param dataXml
6
+ * @param options
7
+ * @returns {Promise<*>}
8
+ */
9
+
10
+ const XMLToJSON = async (dataXml, options) =>{
11
+ try{
12
+ return xml2js.parseStringPromise(dataXml,options);
13
+ }catch(err){
14
+ throw err;
15
+ }
16
+ }
17
+
18
+ /**
19
+ * convert JSON to XML
20
+ * @param dataJson
21
+ * @param options
22
+ * @returns {Promise<*>}
23
+ */
24
+ const JSONToXML = async (dataJson, options) =>{
25
+ try{
26
+ let builder = new xml2js.Builder();
27
+ return builder.buildObject(dataJson);
28
+ }catch(err){
29
+ throw err
30
+ }
31
+ }
32
+
33
+
34
+ module.exports = {
35
+ XMLToJSON,
36
+ JSONToXML
37
+ }
@@ -0,0 +1,109 @@
1
+ const { SQSClient, SendMessageCommand } = require('@aws-sdk/client-sqs');
2
+ const { randomUUID } = require('crypto');
3
+ const config = require('../config');
4
+
5
+ if (!global.LOG_STREAM_NAME) {
6
+ global.LOG_STREAM_NAME = `${process.env.AWS_LAMBDA_FUNCTION_NAME}-${process.env.AWS_LAMBDA_LOG_STREAM_NAME}-${randomUUID()}`;
7
+ }
8
+
9
+ const putLogEvents = async (logEvents = [], logGroupName, logLevel = 2, logStreamName = null) => {
10
+ if (logLevel === 0) {
11
+ return;
12
+ }
13
+
14
+ if (!logGroupName) {
15
+ throw new Error('logEvents and logGroupName are required');
16
+ }
17
+
18
+ let awsCredentials = await config.get('awsCredentials');
19
+ const sqsClient = new SQSClient({
20
+ region: awsCredentials.region,
21
+ credentials: {
22
+ accessKeyId: awsCredentials.accessKeyId,
23
+ secretAccessKey: awsCredentials.secretAccessKey
24
+ }
25
+ });
26
+
27
+ Array.isArray(logEvents) || (logEvents = [String(logEvents)]);
28
+
29
+ if (logEvents.length === 0) {
30
+ throw new Error('Empty log event');
31
+ }
32
+
33
+ switch (logLevel) {
34
+ case 1:
35
+ logLevel = 'DEBUG';
36
+ break;
37
+ case 2:
38
+ logLevel = 'INFO';
39
+ break;
40
+ case 3:
41
+ logLevel = 'WARN';
42
+ break;
43
+ case 4:
44
+ logLevel = 'ERROR';
45
+ break;
46
+ case 5:
47
+ logLevel = 'CRITICAL';
48
+ break;
49
+ default:
50
+ logLevel = 'INFO';
51
+ }
52
+
53
+ let cloudWatchLogEvents = [];
54
+ let maxBytes = 200000;
55
+ for (let logEvent of logEvents) {
56
+ if (logEvent.length > maxBytes) {
57
+ for (let j = 0; j < logEvent.length; j += maxBytes) {
58
+ let logEventChunk = logEvent.substring(j, j + maxBytes);
59
+ cloudWatchLogEvents.push({
60
+ message: `${logLevel} ${logEventChunk}`,
61
+ timestamp: new Date().getTime()
62
+ });
63
+ }
64
+ } else {
65
+ cloudWatchLogEvents.push({
66
+ message: `${logLevel} ${logEvent}`,
67
+ timestamp: new Date().getTime()
68
+ });
69
+ }
70
+ }
71
+
72
+ let QueueUrl = 'https://sqs.eu-west-1.amazonaws.com/826419745875/tookane_SQS_save_log_on_cloudwatch_DEVELOP';
73
+ if (process.env.NODE_ENV === 'production') {
74
+ QueueUrl = 'https://sqs.eu-west-1.amazonaws.com/826419745875/tookane_SQS_save_log_on_cloudwatch';
75
+ }
76
+
77
+ let errors = [];
78
+ let sqsMessage = [];
79
+
80
+ for (const event of cloudWatchLogEvents) {
81
+ const sqsParams = {
82
+ MessageBody: JSON.stringify({
83
+ logEvents: [event],
84
+ logGroupName: logGroupName,
85
+ logStreamName: logStreamName || global.LOG_STREAM_NAME,
86
+ logLevel: logLevel
87
+ }),
88
+ QueueUrl
89
+ };
90
+
91
+ try {
92
+ const command = new SendMessageCommand(sqsParams);
93
+ const response = await sqsClient.send(command);
94
+ sqsMessage.push(response);
95
+ } catch (error) {
96
+ errors.push(error);
97
+ }
98
+ }
99
+
100
+ if (errors.length > 0) {
101
+ throw errors;
102
+ }
103
+
104
+ return sqsMessage;
105
+ };
106
+
107
+ module.exports = {
108
+ putLogEvents
109
+ };
@@ -0,0 +1,74 @@
1
+ // Importamos solo el cliente S3 y las operaciones necesarias
2
+ const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
3
+
4
+ // Creamos una instancia del cliente S3
5
+ const s3 = new S3Client({});
6
+
7
+ const getObjectByString = (obj, key) => {
8
+ const keys = key.split('.');
9
+ let temp = obj;
10
+ for (let key of keys) {
11
+ temp = temp[key];
12
+ }
13
+ return temp;
14
+ };
15
+
16
+ // Cache object
17
+ let cache = {};
18
+
19
+ const getConfigValuesFromS3Bucket = async (configKey = null, ifValuesFromRoot = null) => {
20
+ const { NODE_ENV, TOOK_SECRETS_BUCKET, TOOK_SECRETS_DEVELOP, TOOK_SECRETS_PRODUCTION } = process.env;
21
+ let defaultEnvironment = NODE_ENV;
22
+ const availableEnvironments = ['production', 'develop', 'staging', 'uat', 'demo', 'test', 'testing'];
23
+ if (!defaultEnvironment || !availableEnvironments.includes(defaultEnvironment)) {
24
+ defaultEnvironment = 'develop';
25
+ }
26
+ const effectiveEnvironment = ifValuesFromRoot || defaultEnvironment;
27
+ let secretName = TOOK_SECRETS_DEVELOP;
28
+ if (effectiveEnvironment === 'production') {
29
+ secretName = TOOK_SECRETS_PRODUCTION;
30
+ }
31
+ const secretsBucketName = TOOK_SECRETS_BUCKET;
32
+
33
+ // Check cache first
34
+ if (cache[effectiveEnvironment] && (!configKey || cache[effectiveEnvironment][configKey])) {
35
+ return cache[effectiveEnvironment][configKey] ? cache[effectiveEnvironment][configKey] : cache[effectiveEnvironment];
36
+ }
37
+
38
+ try {
39
+ // If not in cache, then get from S3
40
+ const data = await s3.send(new GetObjectCommand({
41
+ Bucket: secretsBucketName,
42
+ Key: `${secretName}/index.json`,
43
+ }));
44
+
45
+ let config = JSON.parse(await streamToString(data.Body));
46
+
47
+ config = config[effectiveEnvironment];
48
+
49
+ // Cache the config
50
+ cache[effectiveEnvironment] = config;
51
+
52
+ if (configKey) {
53
+ return getObjectByString(config, configKey);
54
+ } else {
55
+ return config;
56
+ }
57
+ } catch (err) {
58
+ throw err;
59
+ }
60
+ };
61
+
62
+ // Helper function to convert stream to string
63
+ const streamToString = (stream) => {
64
+ return new Promise((resolve, reject) => {
65
+ const chunks = [];
66
+ stream.on('data', (chunk) => chunks.push(chunk));
67
+ stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
68
+ stream.on('error', reject);
69
+ });
70
+ };
71
+
72
+ module.exports = {
73
+ get: getConfigValuesFromS3Bucket
74
+ };
@@ -0,0 +1,59 @@
1
+ const axiosRequest = require("../../../axios");
2
+ const cloudwatch = require("../../../cloudwatch");
3
+ const utils = require("../../../utils");
4
+
5
+ const getAuthToken = async ({
6
+ client_id = "",
7
+ client_secret = "",
8
+ baseUrl = "",
9
+ logId = "",
10
+ logGroupName = "",
11
+ }) => {
12
+ const payload = {
13
+ client_id: client_id,
14
+ client_secret: client_secret,
15
+ grant_type: "client_credentials",
16
+ };
17
+
18
+ const headers = {
19
+ "Content-Type": "application/json",
20
+ Accept: "application/json",
21
+ };
22
+
23
+ let paramsRequest = {
24
+ logId: logId,
25
+ headers: headers,
26
+ payload: payload,
27
+ };
28
+
29
+ baseUrl = baseUrl + "/oauth/token";
30
+ let response = null;
31
+ try {
32
+ await cloudwatch.putLogEvents(
33
+ logId +
34
+ "Data to be sent to BRINGG for login >>>>>>> : " +
35
+ utils.dataToString(paramsRequest, "data").res,
36
+ logGroupName
37
+ );
38
+
39
+ response = await axiosRequest.post(baseUrl, paramsRequest);
40
+ await cloudwatch.putLogEvents(
41
+ logId +
42
+ "Response fomr BRINGG login >>>>>>> : " +
43
+ utils.dataToString(response, "data").res,
44
+ logGroupName
45
+ );
46
+ return response && response.data ? response.data.access_token : "";
47
+ } catch (err) {
48
+ let {res} = utils.dataToString(err);
49
+ await cloudwatch.putLogEvents(
50
+ logId + "Finsish BRINGG LOGIN Process with errors: " + res,
51
+ logGroupName
52
+ );
53
+ throw err;
54
+ }
55
+ };
56
+
57
+ module.exports = {
58
+ getAuthToken,
59
+ };