@ind-rcg/backend 246.1008.0

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.
Files changed (39) hide show
  1. package/LICENSE.md +37 -0
  2. package/README.md +7 -0
  3. package/bin/libsqliteExtension.dll +0 -0
  4. package/bin/libsqliteExtension.dylib +0 -0
  5. package/binding.gyp +21 -0
  6. package/configuration.template.json +24 -0
  7. package/log4js.json +11 -0
  8. package/nativeSrc/PriceEngineWrap.cc +157 -0
  9. package/nativeSrc/PriceEngineWrap.h +24 -0
  10. package/nativeSrc/common/DBAccess/SimpleDBConnection.cpp +800 -0
  11. package/nativeSrc/common/DBAccess/SimpleDBConnection.h +54 -0
  12. package/nativeSrc/common/Libs/cJSON/CHANGELOG.md +428 -0
  13. package/nativeSrc/common/Libs/cJSON/LICENSE +20 -0
  14. package/nativeSrc/common/Libs/cJSON/README.md +571 -0
  15. package/nativeSrc/common/Libs/cJSON/cJSON.c +3110 -0
  16. package/nativeSrc/common/Libs/cJSON/cJSON.h +293 -0
  17. package/nativeSrc/common/Libs/sqlcipher/sqlite3.c +241624 -0
  18. package/nativeSrc/common/Libs/sqlcipher/sqlite3.h +12836 -0
  19. package/nativeSrc/common/Libs/sqlcipher/sqlite3ext.h +701 -0
  20. package/nativeSrc/common/LogAdapter/LogAdapter.cpp +25 -0
  21. package/nativeSrc/common/LogAdapter/LogAdapter.h +20 -0
  22. package/nativeSrc/common/PriceEngine/PriceEngine.cpp +251 -0
  23. package/nativeSrc/common/PriceEngine/PriceEngine.h +67 -0
  24. package/nativeSrc/common/Utils/StringFormat.cpp +905 -0
  25. package/nativeSrc/common/Utils/StringFormat.h +116 -0
  26. package/nativeSrc/common/Utils/miniz/timer.cpp +165 -0
  27. package/nativeSrc/common/Utils/miniz/timer.h +40 -0
  28. package/nativeSrc/common/stdngm.h +92 -0
  29. package/nativeSrc/nativeWrapper.cc +15 -0
  30. package/package.json +70 -0
  31. package/src/argsParser.js +73 -0
  32. package/src/bootstrap.js +156 -0
  33. package/src/fsHelper.js +36 -0
  34. package/src/globalConfig.js +23 -0
  35. package/src/local.js +546 -0
  36. package/src/server.js +64 -0
  37. package/src/sfAttachmentsHandler.js +283 -0
  38. package/src/utils.js +91 -0
  39. package/src/zipHandler.js +153 -0
package/src/local.js ADDED
@@ -0,0 +1,546 @@
1
+ /*
2
+ * FILE_HEADER
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const sqlite3 = require("sqlite3");
8
+ const TransactionDatabase = require("sqlite3-transactions").TransactionDatabase;
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+
12
+ const log = require('log4js').getLogger("local");
13
+ const _ = require('lodash');
14
+ let db;
15
+ const mobileNativeCode = require('bindings')('mobileNativeCode.node');
16
+ const GlobalConfig = require('./globalConfig');
17
+ const os = require('os');
18
+ const SFAttachmentsHandler = require("./sfAttachmentsHandler");
19
+ const ZipHandler = require('./zipHandler');
20
+ const Utils = require("./utils");
21
+
22
+ let priceEngine;
23
+
24
+ const loadExtensionAsync = (distanceDatabaseExtension) => {
25
+ return new Promise(function(resolve, reject) {
26
+ db.loadExtension(distanceDatabaseExtension, function (status) {
27
+ if (_.isNil(status)) {
28
+ resolve();
29
+ } else {
30
+ reject(status);
31
+ }
32
+ });
33
+ });
34
+ };
35
+
36
+ let initialize = (webServerConfig) => {
37
+ // get db file (path) from config
38
+ let file = webServerConfig.database;
39
+ priceEngine = new mobileNativeCode.PriceEngineWrap();
40
+
41
+ if (!fs.existsSync(file)) {
42
+ log.error("DB file", file, "does not exist!");
43
+ return Promise.reject(false);
44
+ }
45
+
46
+ const openDBResponse = priceEngine.openDbConnection(file);
47
+
48
+ //failed to open db connection
49
+ if(!openDBResponse.success) {
50
+ log.error(`We couldn’t complete the openDbConnection operation. Try again or contact Salesforce Support and provide the error details: ${JSON.stringify(openDBResponse?.results?.messages)}`);
51
+ return Promise.reject(false);
52
+ }
53
+
54
+ // console.log("before " + file);
55
+ db = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);
56
+ //console.log("after " + file);
57
+ log.info("The local database", file, "started successfully.");
58
+
59
+ //retrieves the path to the node module in each case (sfdx plugin / local development)
60
+ let sqlLiteExtensionModulePath = path.join(path.dirname(__filename), '..', 'bin');
61
+
62
+ let distanceDatabaseExtension = os.type() === "Darwin" ?
63
+ path.join(sqlLiteExtensionModulePath, "libsqliteExtension.dylib"):
64
+ path.join(sqlLiteExtensionModulePath, "libsqliteExtension.dll");
65
+
66
+ if (!fs.existsSync(distanceDatabaseExtension)) {
67
+ log.error("DB extension", distanceDatabaseExtension, "not found. SQL distance() function will not be available.");
68
+ return Promise.resolve(true);
69
+ }
70
+
71
+ return loadExtensionAsync(distanceDatabaseExtension)
72
+ .then(() => {
73
+ log.info("The database extension loaded successfully. The SQL operator DISTANCE() is ready for use in the server.");
74
+ return Promise.resolve(true);
75
+ })
76
+ .catch((err) => {
77
+ log.error("Couldn't load the database extension. The SQL operator DISTANCE() is unavailable for use in the server. "+
78
+ "Try again or contact Salesforce Support with the status code:", err);
79
+ return Promise.resolve(true);
80
+ });
81
+ };
82
+
83
+
84
+
85
+ let closeDBConnection = () => {
86
+ //closing the db connection
87
+ const closeDBResponse = priceEngine.closeDbConnection();
88
+
89
+ //failure occurred
90
+ if(!closeDBResponse.success) {
91
+ log.error(`We couldn’t complete the closeDbConnection operation. Try again or contact Salesforce Support and provide the error details: ${JSON.stringify(closeDBResponse?.results?.messages)}`);
92
+ }
93
+
94
+ return closeDBResponse.success;
95
+ };
96
+
97
+ let sendResponse = (startTime, resultSet, res) => {
98
+ log.debug("OVERALL EXECUTION TIME:", new Date() - startTime, "ms");
99
+ res.writeHead(200, { 'Content-Type': 'application/json' });
100
+ res.end(JSON.stringify(resultSet));
101
+ };
102
+
103
+ let execCall = (payload, res) => {
104
+ const queries = payload.workload instanceof Array ? payload.workload : [payload.workload];
105
+ log.debug(`/exec REQUEST WITH ${queries.length} `);
106
+ const startTime = new Date();
107
+ let exec = function (dbRef, queriesRef, execCb) {
108
+ let results = [],
109
+ querysLength = queries.length;
110
+ return queriesRef.forEach(function (queryEle, i) {
111
+ let query = Utils.sanitizeQuery(queryEle);
112
+ let qid;
113
+ let params;
114
+ if (_.isObject(query)) {
115
+ params = query.parameters;
116
+ qid = query.qid;
117
+ query = query.query;
118
+ }
119
+ log.debug("QUERY", i, ":", JSON.stringify(query));
120
+ if (!query) return;
121
+ query = query.trim();
122
+ let cb = function(err){
123
+ let result = {
124
+ "result": true
125
+ };
126
+ if(!_.isUndefined(qid))
127
+ result.qid = qid;
128
+ if(err){
129
+ result.result = false;
130
+ result.rowsAffected = 0;
131
+ }else{
132
+ result.rowsAffected = this.changes;
133
+ }
134
+ if(results.push(result) === querysLength)
135
+ execCb(results);
136
+ };
137
+ if (params) {
138
+ let stmt = dbRef.prepare(query);
139
+ stmt.run(params, cb);
140
+ } else {
141
+ dbRef.run(query, cb);
142
+ }
143
+ });
144
+ };
145
+ if (_.isEmpty(queries)) {
146
+ log.debug("The request is empty. Provide a valid request and try again.");
147
+ sendResponse(startTime, { success: true, results: [] }, res);
148
+ } else if (payload.transaction === "1") {
149
+ log.debug("OPENING A TRANSACTION...");
150
+ let tranDb = new TransactionDatabase(db);
151
+ tranDb.beginTransaction(function (err, T) {
152
+ if (err) log.error("Error opening transaction!", err);
153
+ else {
154
+ exec(T, queries, results => {
155
+ T.commit(function (error) {
156
+ if (error) {
157
+ log.error("Transaction commit failed!", error);
158
+ T.rollback();
159
+ sendResponse(startTime, { success: false, results: error.message }, res);
160
+ return;
161
+ } else {
162
+ log.debug("Transaction committed successfully!");
163
+ sendResponse(startTime, { success: true, results: results }, res);
164
+ }
165
+ });
166
+ });
167
+ }
168
+ });
169
+ } else {
170
+ exec(db, queries, results => {
171
+ sendResponse(startTime, { success: true, results: results }, res);
172
+ });
173
+ }
174
+ };
175
+
176
+ let queryCall = (payload, res) => {
177
+ const query = payload.workload;
178
+ if (!query) return;
179
+
180
+ const anchor_id = payload.anchor_id;
181
+
182
+ const result = {
183
+ "anchor_id": anchor_id,
184
+ "success": true
185
+ };
186
+
187
+ log.debug("/query", "REQUEST RECEIVED");
188
+ const startTime = new Date();
189
+
190
+ let getQueryFn = queryRef => {
191
+ if (queryRef.parameters) {
192
+ const params = queryRef.parameters;
193
+ queryRef = queryRef.query.trim();
194
+
195
+ return cb => {
196
+ let stmt = db.prepare(queryRef, (resInner)=>{
197
+ if(resInner !== null){
198
+ //prepare failed
199
+ cb(resInner, []);
200
+ } else {
201
+ stmt.all(params, cb);
202
+ }
203
+ } );
204
+ };
205
+ } else {
206
+ queryRef = queryRef.trim();
207
+ return cb => db.all(queryRef, cb);
208
+ }
209
+ };
210
+
211
+ let fn;
212
+ if (_.isArray(query)) {
213
+ result.results = [];
214
+ const iterator = queryRef => {
215
+ if(queryRef.length > 0){
216
+ let currentQuery = queryRef.shift();
217
+ fn = getQueryFn(currentQuery);
218
+ fn(function (err, rows) {
219
+ log.debug("QUERY:", JSON.stringify(currentQuery));
220
+ if (err) {
221
+ result.success = false;
222
+ log.error("ERROR:", err);
223
+ result.results.push({
224
+ "qid": currentQuery.qid,
225
+ "result": err.message});
226
+ } else {
227
+ log.debug("ROWS RETURNED:", rows.length);
228
+ result.results.push({
229
+ "qid": currentQuery.qid,
230
+ "result": rows});
231
+ }
232
+ iterator(queryRef);
233
+ });
234
+ }else{
235
+ log.debug(JSON.stringify(result));
236
+ sendResponse(startTime, result, res);
237
+ }
238
+ };
239
+ iterator(query);
240
+ } else {
241
+ fn = getQueryFn(query);
242
+ fn(function (err, rows) {
243
+ log.debug("QUERY:", JSON.stringify(query));
244
+ if (err) {
245
+ result.success = false;
246
+ log.error("ERROR:", err);
247
+ result.results = err.message;
248
+ sendResponse(startTime, result, res);
249
+ } else {
250
+ log.debug("ROWS RETURNED:", rows.length);
251
+ result.results = rows;
252
+ log.debug(JSON.stringify(rows));
253
+ sendResponse(startTime, result, res);
254
+ }
255
+ });
256
+ }
257
+ };
258
+
259
+ let __mimeTypeToExtension = (mimeType) => {
260
+ const knownTypes = {
261
+ "image/png": "png",
262
+ "image/jpeg": "jpg",
263
+ "image/svg+xml": "svg",
264
+ "application/pdf": "pdf",
265
+ "application/zip": "zip"
266
+
267
+ };
268
+ return knownTypes[mimeType];
269
+ };
270
+
271
+
272
+ let __composeResponse = (targetFolder, newfileName, content, payload, res) => {
273
+ if (!fs.existsSync(targetFolder)) {
274
+ fs.mkdirSync(targetFolder);
275
+ }
276
+ fs.writeFileSync(path.join(targetFolder, newfileName), content);
277
+ sendResponse(new Date().getTime(), {
278
+ success: true,
279
+ performance: 0,
280
+ anchor_id: payload.anchor_id,
281
+ results: path.join(GlobalConfig.hesaFolder, newfileName)
282
+ }, res);
283
+ };
284
+
285
+ module.exports.performCall = (req, res) => {
286
+
287
+ // Checkmarx False Positive
288
+ // This function is only used on a developer machine to improve implementation speed. The data which will be retrieved by that
289
+ // function can be accessed over the developers file system anyway. This part of the application is only for internal developer
290
+ // purpose and not live outside.
291
+ let payload = req.body;
292
+
293
+ if (req.headers['content-type'] === 'application/octet-stream') {
294
+ payload = JSON.parse(req.body);
295
+ }
296
+
297
+ log.debug(`Executing operation : ${payload.operation}`);
298
+ log.debug(`Payload : ${JSON.stringify(payload)}`);
299
+
300
+ if (payload.operation === 'executeBatch' || payload.operation === 'executeParameterized' || payload.operation === 'execute' ) {
301
+ execCall(payload, res);
302
+ } else if (payload.operation === 'select' || payload.operation === 'selectParameterized') {
303
+ queryCall(payload, res);
304
+ } else if (payload.operation === 'savePrintingData') {
305
+ log.debug('saving printing data for print:', payload.workload);
306
+ let printId = payload.workload[0];
307
+ let printData = payload.workload[1];
308
+ let printingDataFolder = 'Printing';
309
+ if (!fs.existsSync(printingDataFolder)) {
310
+ fs.mkdirSync(printingDataFolder);
311
+ }
312
+ let dataFile = path.join(printingDataFolder, (printId + '.json'));
313
+ fs.writeFileSync(dataFile, printData);
314
+ sendResponse(new Date().getTime(), {success: true, anchor_id: payload.anchor_id, results: []}, res);
315
+ } else if(payload.operation === 'saveDatasourceToggles') {
316
+ let toggleData = payload.workload[0];
317
+ let DataSourceGenerationFolder = 'DataSourceGeneration';
318
+ if (!fs.existsSync(DataSourceGenerationFolder)) {
319
+ fs.mkdirSync(DataSourceGenerationFolder);
320
+ }
321
+ let dataFile = path.join(DataSourceGenerationFolder, ('Toggles.json'));
322
+ let hasSucceeded = false;
323
+ try {
324
+ //Reparse to write the data in pretty print format
325
+ let toggleDataJSON = JSON.parse(toggleData);
326
+ fs.writeFileSync(dataFile, JSON.stringify(toggleDataJSON, null, 4));
327
+ hasSucceeded = true;
328
+ } catch (e) {
329
+ log.error("The saveDatasourceToggles operation failed. Review the exception details to fix the issue, or contact Salesforce Support for help.", e);
330
+ }
331
+ sendResponse(new Date().getTime(), {success: hasSucceeded, anchor_id: payload.anchor_id, results: []}, res);
332
+ } else if(payload.operation === 'saveDatasourceParameters') {
333
+ let boName = payload.workload[0];
334
+ let paramsData = payload.workload[1];
335
+ let DataSourceGenerationFolder = 'DataSourceGeneration';
336
+ if (!fs.existsSync(DataSourceGenerationFolder)) {
337
+ fs.mkdirSync(DataSourceGenerationFolder);
338
+ }
339
+ let dataFile = path.join(DataSourceGenerationFolder, (boName + '.json'));
340
+ let hasSucceeded = false;
341
+ try {
342
+ //Reparse to write the data in pretty print format
343
+ let paramsDataJSON = JSON.parse(paramsData);
344
+ fs.writeFileSync(dataFile, JSON.stringify(paramsDataJSON, null, 4));
345
+ hasSucceeded = true;
346
+ } catch (e) {
347
+ log.error("The saveDatasourceParameters operation failed. Review the exception details to fix the issue, or contact Salesforce Support for help.", e);
348
+ }
349
+ sendResponse(new Date().getTime(), {success: hasSucceeded, anchor_id: payload.anchor_id, results: []}, res);
350
+ } else if (payload.operation === 'saveAttachment') {
351
+ const dataUrl = payload.workload[0];
352
+ const blobPKey = payload.workload[2];
353
+
354
+ if (!Utils.isValidParamString(blobPKey) || !Utils.isValidParamString(payload.workload[1]) || !Utils.isValidString(dataUrl)) {
355
+ const invalidParamErrorMessage = "Invalid input parameters for saveAttachment. Check the input parameters and try again.";
356
+ log.error(invalidParamErrorMessage);
357
+ sendResponse(new Date().getTime(), { success: false, performance: 0, anchor_id: payload.anchor_id, results: false, error_message: invalidParamErrorMessage }, res);
358
+ }
359
+
360
+ const regex = /^data:(\w+\/[\w+]+);base64,(.+)$/;
361
+ const matches = dataUrl.match(regex);
362
+ const extension = __mimeTypeToExtension(matches[1]);
363
+
364
+ if (!Utils.isValidParamString(extension)) {
365
+ const errorMessage = "This isn’t a supported file extension. Specify a valid file extension and try again.";
366
+ log.error(errorMessage);
367
+ sendResponse(new Date().getTime(), { success: false, performance: 0, anchor_id: payload.anchor_id, results: false, error_message: errorMessage }, res);
368
+ }
369
+
370
+ const tableName = payload.workload[1] + GlobalConfig.BlobFolder;
371
+ const targetFolder = path.join(GlobalConfig.AttachmentsFolder, tableName);
372
+ const data = matches[2];
373
+ const buffer = Buffer.from(data, 'base64');
374
+
375
+ if (!fs.existsSync(targetFolder)) {
376
+ fs.mkdirSync(targetFolder);
377
+ }
378
+
379
+ const filename = Utils.getSFFileName(blobPKey, extension);
380
+ fs.writeFileSync(path.join(targetFolder, filename), buffer);
381
+ sendResponse(new Date().getTime(), { success: true, performance: 0, anchor_id: payload.anchor_id, results: true }, res);
382
+
383
+ } else if(payload.operation === 'validateThemeZip') {
384
+ log.debug('validateThemeZip:', payload.workload);
385
+ ZipHandler.extractZipFiles(payload.workload[0])
386
+ .then((zip) => {
387
+ const results = ZipHandler.validateThemeZip(payload.workload[0], zip);
388
+ if (!results.isOk){
389
+ sendResponse(new Date().getTime(), { success: true, anchor_id: payload.anchor_id, results }, res);
390
+ } else {
391
+ sendResponse(new Date().getTime(), { success: true, anchor_id: payload.anchor_id, results }, res);
392
+ }
393
+ }, (details) => {
394
+ sendResponse(new Date().getTime(), {success: true, anchor_id: payload.anchor_id, results: { isOk: false, details }}, res);
395
+ });
396
+ } else if(payload.operation === 'extractThemeZip') {
397
+ log.debug('extractThemeZip:', payload.workload);
398
+ ZipHandler.extractZipFiles(payload.workload[0])
399
+ .then((zip) => {
400
+ ZipHandler.writeZipFilesOnMemory(zip).then(() => {
401
+ sendResponse(new Date().getTime(), {success: true, anchor_id: payload.anchor_id, results: { success: true, fileCache: ZipHandler.serializeZipAsJSON(zip) }}, res);
402
+ });
403
+ }, (details) => {
404
+ sendResponse(new Date().getTime(), {success: true, anchor_id: payload.anchor_id, results: { success: false, details }}, res);
405
+ });
406
+ } else if(payload.operation === 'saveSFFile') {
407
+ if (req && req.body && req.body.workload && req.body.workload.length === 4) {
408
+ SFAttachmentsHandler.saveSFFile(req.body.workload[0], req.body.workload[1], req.body.workload[2], req.body.workload[3])
409
+ .then((result) => {
410
+ sendResponse(new Date().getTime(), {
411
+ success: true,
412
+ performance: 0,
413
+ anchor_id: payload.anchor_id,
414
+ results: result
415
+ }, res);
416
+ })
417
+ .catch((errorMessage) => {
418
+ log.error("error saving SFFile! " + errorMessage);
419
+ sendResponse(new Date().getTime(), {success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage}}, res);
420
+ });
421
+ } else {
422
+ const errorMessage = Utils.getParamsMissingErrorMessage(payload.operation);
423
+ log.error(errorMessage);
424
+ sendResponse(new Date().getTime(), {success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage }}, res);
425
+ }
426
+
427
+ } else if (payload.operation === 'readSFFile') {
428
+ if (req && req.body && req.body.workload && req.body.workload.length >= 2 && req.body.workload.length <= 3) {
429
+ const result = SFAttachmentsHandler.readSFFile(req.body.workload[0], req.body.workload[1], req.body.workload[2] ? req.body.workload[2] : false);
430
+ sendResponse(new Date().getTime(), {
431
+ success: result.success,
432
+ performance: 0,
433
+ anchor_id: payload.anchor_id,
434
+ results: result.results
435
+ }, res);
436
+ } else {
437
+ const errorMessage = Utils.getParamsMissingErrorMessage(payload.operation);
438
+ log.error(errorMessage);
439
+ sendResponse(new Date().getTime(), {success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage }}, res);
440
+ }
441
+
442
+ } else if (payload.operation === 'renameSFFile') {
443
+ if (req && req.body && req.body.workload && req.body.workload.length >= 3) {
444
+ let oldId = req.body.workload[0];
445
+ let fileType = req.body.workload[1];
446
+ let newId = req.body.workload[2];
447
+
448
+ const result = SFAttachmentsHandler.renameSFFile(oldId, fileType, newId);
449
+ sendResponse(new Date().getTime(), {
450
+ success: result.success,
451
+ performance: 0,
452
+ anchor_id: payload.anchor_id,
453
+ results: result.results
454
+ }, res);
455
+ } else {
456
+ const errorMessage = Utils.getParamsMissingErrorMessage(payload.operation);
457
+ log.error(errorMessage);
458
+ sendResponse(new Date().getTime(), {success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage }}, res);
459
+ }
460
+ } else if (payload.operation === 'deleteSFFile') {
461
+ if (req && req.body && req.body.workload && req.body.workload.length >= 2) {
462
+ let id = req.body.workload[0];
463
+ let fileType = req.body.workload[1];
464
+
465
+ const result = SFAttachmentsHandler.deleteSFFile(id, fileType);
466
+ sendResponse(new Date().getTime(), {
467
+ success: result.success,
468
+ performance: 0,
469
+ anchor_id: payload.anchor_id,
470
+ results: result.results
471
+ }, res);
472
+
473
+ } else {
474
+ const errorMessage = Utils.getParamsMissingErrorMessage(payload.operation);
475
+ log.error(errorMessage);
476
+ sendResponse(new Date().getTime(), { success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage } }, res);
477
+ }
478
+ } else if (payload.operation === 'conditionSearch') {
479
+ if (req && req.body && req.body.workload) {
480
+
481
+ const workload = req.body.workload;
482
+ if (!Array.isArray(workload)) {
483
+ log.error(`Invalid input parameters for conditionSearch. Check the input parameters and try again.`);
484
+ sendResponse(new Date().getTime(), { success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": Utils.internalServerError } }, res);
485
+ }
486
+
487
+ let conditionJSON = JSON.stringify(req.body.workload);
488
+
489
+ //search for conditions
490
+ const response = priceEngine.conditionSearch(conditionJSON);
491
+
492
+ if (!response.success) {
493
+ //failure case
494
+ const errorMessage = response.results.messages.toString();
495
+ log.error(`We couldn’t complete the conditionSearch operation. Try again or contact Salesforce Support and provide the error details: ${errorMessage}`);
496
+ sendResponse(new Date().getTime(), {
497
+ success: false,
498
+ performance: 0,
499
+ anchor_id: payload.anchor_id,
500
+ results: { "error_message": errorMessage }
501
+ }, res);
502
+ } else {
503
+ sendResponse(new Date().getTime(), {
504
+ success: response.success,
505
+ performance: 0,
506
+ anchor_id: payload.anchor_id,
507
+ results: JSON.parse(response.results.conditions)
508
+ }, res);
509
+ }
510
+ } else {
511
+ const errorMessage = Utils.getParamsMissingErrorMessage(payload.operation);
512
+ log.error(errorMessage);
513
+ sendResponse(new Date().getTime(), {success: false, performance: 0, anchor_id: payload.anchor_id, results: { "error_message": errorMessage }}, res);
514
+ }
515
+ } else if (payload.operation === 'saveFile') {
516
+ const data = payload.workload[0];
517
+ const type = payload.workload[1];
518
+ const compress = payload.workload[2];
519
+
520
+ if (!Utils.isValidString(data) || !Utils.isValidParamString(type) || !_.isBoolean(compress)) {
521
+ const errorMessage = "Invalid input parameters for saveFile. Check the input parameters and try again.";
522
+ sendResponse(new Date().getTime(), {
523
+ success: false,
524
+ performance: 0,
525
+ anchor_id: payload.anchor_id,
526
+ results: { "error_message": errorMessage }
527
+ }, res);
528
+ }
529
+ const targetFolder = path.join(GlobalConfig.AttachmentsFolder, GlobalConfig.hesaFolder);
530
+ const filename = Utils.getSFFileName(new Date().getTime().toString(), type);
531
+ if(compress) {
532
+ ZipHandler.createZipFile(filename, data).then(content => {
533
+ let newfileName = filename.substring(0, filename.indexOf(".")) + ".zip";
534
+ __composeResponse(targetFolder, newfileName, content, payload, res);
535
+ });
536
+ } else {
537
+ __composeResponse(targetFolder, filename, data, payload, res);
538
+ }
539
+ } else {
540
+ log.error("Probably UNKNOWN operation detected :: " + payload.operation + " --> " + payload.action);
541
+ sendResponse(new Date().getTime(), { success: true, anchor_id: payload.anchor_id, results: [] }, res);
542
+ }
543
+ };
544
+
545
+ module.exports.initialize = initialize;
546
+ module.exports.closeDBConnection = closeDBConnection;
package/src/server.js ADDED
@@ -0,0 +1,64 @@
1
+ /*
2
+ * FILE_HEADER
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const log4js = require('log4js');
8
+
9
+ const bootstrap = require('./bootstrap');
10
+ const argsParser = require('./argsParser');
11
+ const fsHelper = require('./fsHelper');
12
+
13
+ let result = argsParser.run(process.argv);
14
+ if (result && result.success) {
15
+
16
+ let settings = result.data;
17
+
18
+ // configure logging
19
+ log4js.configure(settings.loggingConfig);
20
+ const log = log4js.getLogger('server');
21
+
22
+ // load web server configuration file
23
+ let webServerConfig = fsHelper.readJsonFile(settings.webServerConfig);
24
+ if (webServerConfig) {
25
+
26
+ // configure, setup and start web server
27
+ bootstrap.setup(webServerConfig)
28
+ .then((app) => {
29
+ // take port from webServerConfig or take fallback/default port 3000
30
+ let webServerPort = webServerConfig.port || 3000;
31
+
32
+ const server = app.listen(webServerPort, "localhost", function () {
33
+ const port = server.address().port;
34
+ log.info('Backend server has started. Use the URL http://localhost:' +
35
+ port +
36
+ '/framework/index.html?desktop to perform any testing activities. ' +
37
+ 'It is recommended to execute the application in incognito window of your browser ' +
38
+ 'and take care only one incognito window is opened to avoid influences.');
39
+ log.info('Use CTRL+C to stop the backend server.');
40
+ });
41
+
42
+ server.on('close', function () {
43
+ bootstrap.closeConnection();
44
+ log.info('The server closed successfully.');
45
+ });
46
+
47
+ // listen for SIGINT signal
48
+ process.on('SIGINT', function () {
49
+ server.close();
50
+ });
51
+ })
52
+ .catch(() => {
53
+ log.error("Couldn't start the backend server and the web application setup failed. Verify that the TCP port is available and you have the required permissions to perform this task. If the issue persists, contact Salesforce Support for help.");
54
+ process.exit(1);
55
+ });
56
+ } else {
57
+ log.error("The backend server failed to start and the web server configuration file couldn't be loaded. Make sure the appropriate access permissions are configured and that the configuration file format is valid. If the issue persists, contact Salesforce Support for help.");
58
+ process.exit(1);
59
+ }
60
+
61
+ } else {
62
+ console.error('The backend server failed to start. Review the error details to fix the issue, and if the issue persists, contact Salesforce Support for help:', result.error ? result.error : '');
63
+ process.exit(1);
64
+ }