From ab92637203c6cb3ef8a7b64864fa5ed2645fd336 Mon Sep 17 00:00:00 2001 From: "Pradeep.Kumar" Date: Tue, 26 Oct 2021 20:35:01 +0530 Subject: [PATCH 1/6] Added Upload feature / Added more SQL Insert and update method to make easy requests --- lib/index.js | 6 +-- lib/sql.js | 81 ++++++++++++++++++++++++++++++++++++++++ lib/util.js | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 4 deletions(-) diff --git a/lib/index.js b/lib/index.js index a0a4750..472cb15 100644 --- a/lib/index.js +++ b/lib/index.js @@ -96,7 +96,7 @@ class Framework { } } - async query({ controller, params, method = "POST" }) { + async query({ controller, params, body, method = "POST" }) { const { serverUrl, client } = this; const url = `${serverUrl}/Controllers/${controller}.ashx`; let result; @@ -104,9 +104,9 @@ class Framework { if (typeof params?.toFormData === 'function') { params = params.toFormData(); } - result = await client.post(url, { form: params }); + result = await client.post(url, { form: params, body }); } else { - result = await client({ url, form: params, method }); + result = await client({ url, form: params, method, body }); } if (result.statusCode === 200) { return result.headers["content-type"].match(/^application\/json/i) ? JSON.parse(result.body) : result.body; diff --git a/lib/sql.js b/lib/sql.js index 6b03934..102e51c 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -78,6 +78,87 @@ class Sql { } } } + async insertUpdate({ tableName, json, keyField, update = false }) { + try { + const request = await this.createRequest(); + const propNames = Object.keys(json); + propNames.forEach(prop => { // add parameters to the statement + request.input(prop, json[prop]); + }); + let statement; + if (update) { + statement = `UPDATE ${tableName} SET ${propNames.filter(propName => propName !== keyField).map(prop => `${prop} = @${prop}`).join(', ')} WHERE ${keyField} = @${keyField}`; + } else { + statement = `INSERT INTO ${tableName} (${propNames.join(', ')}) VALUES (${propNames.map(prop => '@' + prop).join(', ')});SELECT SCOPE_IDENTITY() AS Id;`; + } + const result = await request.query(statement); + return { success: true, data: result.recordset }; + } catch (err) { + return { success: false, queryException: err, data: {} }; + } + } + + /** + * @desc insert the record + * @param {Object} - json - Json Object + * @param {String} - tableName + */ + async insert(json, tableName) { + return await this.insertUpdate({ tableName, json, update: false }); + } + /** + * @desc update the record + * @param {Object} - json - Json Object + * @param {String} - tableName + */ + async update(json, tableName, keyField) { + return await this.insertUpdate({ tableName, json, keyField, update: true }); + } + addParameters({ query, request, parameters, forWhere = false }) { + if (!parameters) { + return query; + } + const fieldNames = Object.keys(parameters); + for (let index = 0, len = fieldNames.length; index < len; index++) { + const fieldName = fieldNames[index]; + const props = parameters[fieldName]; + const operator = props.operator || "="; + const value = props.operator ? props.value : props; + if (forWhere) { + query += `${index === 0 ? "" : " AND "} ${fieldName} ${operator} @${fieldName}`; + } + request.input(fieldName, value); + } + return query; + } + + /** + * @desc update the record + * @param {Object} - sql query - Json Object + * @param {Object} - parameters + * @param {Object} - isStoredProcedure + */ + async execute({ query, parameters, where, orderBy, isStoredProcedure, storedProc }) { + query = await this.getQuery(query); + isStoredProcedure = isStoredProcedure === true || storedProc === true || (storedProc !== false && !query.match(/^SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i)); + try { + const request = await this.createRequest(); + query = this.addParameters({ query, request, parameters, forWhere: false }); + if (where) { + query += " WHERE "; + } + query = this.addParameters({ query, request, parameters: where, forWhere: true }); + + if (orderBy) { + query += " ORDER BY " + orderBy; + } + + const result = isStoredProcedure ? await request.execute(query) : await request.query(query); + return { success: true, data: result.recordset }; + } catch (err) { + return { success: false, queryException: err, data: {} }; + } + } } export default Sql; diff --git a/lib/util.js b/lib/util.js index e9050d5..876f8d5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -2,13 +2,23 @@ import { promisify } from 'util'; import got from 'got' import stream from 'stream'; import fs from 'fs'; +import FormData from 'form-data'; +import { Buffer } from 'buffer'; + const macRegex = /([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/ const pipeline = promisify(stream.pipeline); +const dataModes = { + json: 1, + formAsJson: "input", + formIndividualValues: 3, + formLegenidValues: 4, + asFile: "file" +}; export default { macRegex, - + dataModes, dateFormat: 'M-D-Y', dateTimeFormat: 'M-D-Y HH:mm:ss', @@ -157,5 +167,95 @@ export default { }) .resume(); }); + }, + request: async function ({ uploadUrl, formMode, filename = "file", data, contentType = 'application/json', tokenUrl = null, token = null, tokenParameters = null }) { + for (let trial = 0; trial < 2; trial++) { + if (token === null && tokenUrl) { + token = await this.getToken(tokenUrl, tokenParameters); + } + const headers = {}; + if (token) { + headers.Authorization = token ? `Bearer ${this.token}` : "Basic " + Buffer.from(`pradeep.kumar@in.coolrgroup.com:admin`).toString("base64"); + //headers.ContentType = 'application/json'; + headers.Accept = '*/*'; + } + let body; + switch (formMode) { + case dataModes.formIndividualValues: + body = new FormData(); + { + const keys = data.Legenid; + const values = data.Values[0]; + for (const [index, key] of keys.entries()) { + body.append(key, values[index]); + } + } + break; + case dataModes.formAsJson: + body = new FormData(); + body.append(dataModes.formAsJson, JSON.stringify(data)); + break; + case dataModes.asFile: + body = new FormData(); + { + const blob = data ? Buffer.from(JSON.stringify(data)) : fs.createReadStream(filename); + body.append(dataModes.asFile, blob, { filename: filename, contentType: contentType }); + if (data) { + for (var key of Object.keys(data)) { + body.append(key, data[key]); + } + } + } + } + try { + const result = await got.post(uploadUrl, { + body, + json: body ? undefined : data, + headers + }); + + console.error({ status: result.statusCode, body: result.body }); + return result; + } catch (error) { + if (error.response) { + if (error.response.statusCode === 403) { + console.error('Token expired.. will retry'); + } else { + console.error({ status: error.response.statusCode, body: error.response.body }); + break; + } + } else { + console.error(error); + break; + } + } + } + }, + getToken: async function (tokenUrl, tokenParameters) { + try { + const result = await got.post(tokenUrl, { + form: tokenParameters + }).json(); + return result.access_token; + } catch (error) { + console.error(error.response.body); + return null; + } + }, + buildFormData: function (formData, data, parentKey) { + if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof Buffer)) { + Object.keys(data).forEach(key => { + this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); + }); + } else { + const value = data == null ? '' : data; + formData.append(parentKey, value); + } + }, + + jsonToFormData: function (data) { + const formData = new FormData(); + this.buildFormData(formData, data); + return formData; } }; \ No newline at end of file From 01e6f3315cea8c45f3b97065ee8de58b81c66665 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 9 Dec 2021 19:18:15 +0530 Subject: [PATCH 2/6] Removed the changes those are already merged in master and having latest changes --- lib/sql.js | 94 +++++------------------------------------------------ lib/util.js | 4 ++- 2 files changed, 11 insertions(+), 87 deletions(-) diff --git a/lib/sql.js b/lib/sql.js index 6490f4d..2cafcf9 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -163,12 +163,15 @@ class Sql { * @param {Object} - parameters * @param {Object} - isStoredProcedure */ - async execute({ query, parameters, where, orderBy, isStoredProcedure }) { + async execute({ query, parameters, where, orderBy, isStoredProcedure, storedProc }) { query = await this.getQuery(query); - isStoredProcedure = isStoredProcedure === true || !query.match(/SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i); + isStoredProcedure = isStoredProcedure === true || storedProc === true || (storedProc !== false && !query.match(/^SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i)); try { - const request = this.createRequest(); + const request = await this.createRequest(); query = this.addParameters({ query, request, parameters, forWhere: false }); + if (where) { + query += " WHERE "; + } query = this.addParameters({ query, request, parameters: where, forWhere: true }); if (orderBy) { @@ -178,7 +181,7 @@ class Sql { const result = isStoredProcedure ? await request.execute(query) : await request.query(query); return { success: true, data: result.recordset, ...result }; } catch (err) { - return { success: false, err, data: {} }; + return { success: false, queryException: err, data: {} }; } } @@ -202,7 +205,7 @@ class Sql { const result = await request.query(statement); return { success: true, data: result.recordset }; } catch (err) { - return { success: false, err, data: {} }; + return { success: false, queryException: err, data: {} }; } } @@ -268,87 +271,6 @@ class Sql { } } } - async insertUpdate({ tableName, json, keyField, update = false }) { - try { - const request = await this.createRequest(); - const propNames = Object.keys(json); - propNames.forEach(prop => { // add parameters to the statement - request.input(prop, json[prop]); - }); - let statement; - if (update) { - statement = `UPDATE ${tableName} SET ${propNames.filter(propName => propName !== keyField).map(prop => `${prop} = @${prop}`).join(', ')} WHERE ${keyField} = @${keyField}`; - } else { - statement = `INSERT INTO ${tableName} (${propNames.join(', ')}) VALUES (${propNames.map(prop => '@' + prop).join(', ')});SELECT SCOPE_IDENTITY() AS Id;`; - } - const result = await request.query(statement); - return { success: true, data: result.recordset }; - } catch (err) { - return { success: false, queryException: err, data: {} }; - } - } - - /** - * @desc insert the record - * @param {Object} - json - Json Object - * @param {String} - tableName - */ - async insert(json, tableName) { - return await this.insertUpdate({ tableName, json, update: false }); - } - /** - * @desc update the record - * @param {Object} - json - Json Object - * @param {String} - tableName - */ - async update(json, tableName, keyField) { - return await this.insertUpdate({ tableName, json, keyField, update: true }); - } - addParameters({ query, request, parameters, forWhere = false }) { - if (!parameters) { - return query; - } - const fieldNames = Object.keys(parameters); - for (let index = 0, len = fieldNames.length; index < len; index++) { - const fieldName = fieldNames[index]; - const props = parameters[fieldName]; - const operator = props.operator || "="; - const value = props.operator ? props.value : props; - if (forWhere) { - query += `${index === 0 ? "" : " AND "} ${fieldName} ${operator} @${fieldName}`; - } - request.input(fieldName, value); - } - return query; - } - - /** - * @desc update the record - * @param {Object} - sql query - Json Object - * @param {Object} - parameters - * @param {Object} - isStoredProcedure - */ - async execute({ query, parameters, where, orderBy, isStoredProcedure, storedProc }) { - query = await this.getQuery(query); - isStoredProcedure = isStoredProcedure === true || storedProc === true || (storedProc !== false && !query.match(/^SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i)); - try { - const request = await this.createRequest(); - query = this.addParameters({ query, request, parameters, forWhere: false }); - if (where) { - query += " WHERE "; - } - query = this.addParameters({ query, request, parameters: where, forWhere: true }); - - if (orderBy) { - query += " ORDER BY " + orderBy; - } - - const result = isStoredProcedure ? await request.execute(query) : await request.query(query); - return { success: true, data: result.recordset }; - } catch (err) { - return { success: false, queryException: err, data: {} }; - } - } } export default Sql; diff --git a/lib/util.js b/lib/util.js index 6f04516..11bc335 100644 --- a/lib/util.js +++ b/lib/util.js @@ -10,6 +10,8 @@ import { Buffer } from 'buffer'; const macRegex = /([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/ const pipeline = promisify(stream.pipeline); + +const env = process.env; const dataModes = { json: 1, formAsJson: "input", @@ -227,7 +229,7 @@ export default { } const headers = {}; if (token) { - headers.Authorization = token ? `Bearer ${this.token}` : "Basic " + Buffer.from(`pradeep.kumar@in.coolrgroup.com:admin`).toString("base64"); + headers.Authorization = token ? `Bearer ${this.token}` : "Basic " + Buffer.from(`${env.USER_NAME}:${env.PASSWORD}`).toString("base64"); //headers.ContentType = 'application/json'; headers.Accept = '*/*'; } From a9a2df2ed9970cf273d025342d48165987071619 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 9 Dec 2021 19:25:12 +0530 Subject: [PATCH 3/6] buildFormData with signature: --- lib/util.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/util.js b/lib/util.js index 11bc335..85bbb45 100644 --- a/lib/util.js +++ b/lib/util.js @@ -296,10 +296,10 @@ export default { return null; } }, - buildFormData: function (formData, data, parentKey) { + buildFormData: function (data, formData = new FormData(), parentKey) { if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof Buffer)) { Object.keys(data).forEach(key => { - this.buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key); + this.buildFormData(data[key], formData, parentKey ? `${parentKey}[${key}]` : key); }); } else { const value = data == null ? '' : data; @@ -308,8 +308,7 @@ export default { }, jsonToFormData: function (data) { - const formData = new FormData(); - this.buildFormData(formData, data); + this.buildFormData(data); return formData; } }; \ No newline at end of file From 315a54cd56546756595714f634805a494d27b146 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 9 Dec 2021 19:33:48 +0530 Subject: [PATCH 4/6] Reverted query execute method changes as these are not required --- lib/sql.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/sql.js b/lib/sql.js index 2cafcf9..5efa3e9 100644 --- a/lib/sql.js +++ b/lib/sql.js @@ -163,15 +163,12 @@ class Sql { * @param {Object} - parameters * @param {Object} - isStoredProcedure */ - async execute({ query, parameters, where, orderBy, isStoredProcedure, storedProc }) { + async execute({ query, parameters, where, orderBy, isStoredProcedure }) { query = await this.getQuery(query); - isStoredProcedure = isStoredProcedure === true || storedProc === true || (storedProc !== false && !query.match(/^SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i)); + isStoredProcedure = isStoredProcedure === true || !query.match(/SELECT |INSERT |UPDATE |DELETE |SET |DECLARE /i); try { - const request = await this.createRequest(); + const request = this.createRequest(); query = this.addParameters({ query, request, parameters, forWhere: false }); - if (where) { - query += " WHERE "; - } query = this.addParameters({ query, request, parameters: where, forWhere: true }); if (orderBy) { From c1add488473f517603ee64f39e0cb989b0aba593 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 9 Dec 2021 19:50:11 +0530 Subject: [PATCH 5/6] Corrected formData undefined issue --- lib/util.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 85bbb45..c262f99 100644 --- a/lib/util.js +++ b/lib/util.js @@ -307,8 +307,8 @@ export default { } }, - jsonToFormData: function (data) { - this.buildFormData(data); + jsonToFormData: function (data, formData = new FormData()) { + this.buildFormData(data, formData); return formData; } }; \ No newline at end of file From 173de14e941a8d4f9dba2c0c4b2b283c56492620 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 9 Dec 2021 19:58:39 +0530 Subject: [PATCH 6/6] Removed extra function and using only buildFormData --- lib/util.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/util.js b/lib/util.js index c262f99..dd5ddc9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -305,10 +305,6 @@ export default { const value = data == null ? '' : data; formData.append(parentKey, value); } - }, - - jsonToFormData: function (data, formData = new FormData()) { - this.buildFormData(data, formData); return formData; } }; \ No newline at end of file