@blazedpath/commons 0.0.8 → 0.0.9

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/blz-base/index.js CHANGED
@@ -105,14 +105,14 @@ const beginNested = function (stack) {
105
105
  }
106
106
  }
107
107
 
108
- const beginNotSupported = function(stack) {
108
+ const beginNotSupported = function (stack) {
109
109
  stack.push({
110
110
  propagationType: "not-supported",
111
111
  connection: null
112
112
  });
113
113
  }
114
114
 
115
- const beginSupports = function(stack) {
115
+ const beginSupports = function (stack) {
116
116
  if (_.isEmpty(stack)) {
117
117
  stack.push({
118
118
  propagationType: "supports",
@@ -134,7 +134,7 @@ const beginSupports = function(stack) {
134
134
  });
135
135
  }
136
136
 
137
- const beginMandatory = function(stack) {
137
+ const beginMandatory = function (stack) {
138
138
  if (_.isEmpty(stack)) {
139
139
  throw new MandatoryTransactionViolation();
140
140
  }
@@ -465,20 +465,20 @@ const normalizeConfig = function (config = {}) {
465
465
  }
466
466
  }
467
467
  const deepClone = (obj) => {
468
- if (typeof obj !== 'object' || obj === null) {
469
- return obj;
470
- }
471
- let clone = Array.isArray(obj) ? [] : {};
472
- for (let key in obj) {
473
- if (obj.hasOwnProperty(key)) {
474
- clone[key] = deepClone(obj[key]);
475
- }
476
- }
477
- return clone;
468
+ if (typeof obj !== 'object' || obj === null) {
469
+ return obj;
470
+ }
471
+ let clone = Array.isArray(obj) ? [] : {};
472
+ for (let key in obj) {
473
+ if (obj.hasOwnProperty(key)) {
474
+ clone[key] = deepClone(obj[key]);
475
+ }
476
+ }
477
+ return clone;
478
478
  }
479
479
  let cache = new LRUCache({ max: 500, maxSize: 5000, ttl: 1000 * 60 * 60 * 3, sizeCalculation: (value, key) => { return 1 } })
480
480
 
481
- const safeRequire = function(path) {
481
+ const safeRequire = function (path) {
482
482
  try {
483
483
  require.resolve(path);
484
484
  return require(path);
@@ -495,972 +495,974 @@ const safeRequire = function(path) {
495
495
  }
496
496
 
497
497
  module.exports = {
498
- deepClone,
499
- beginTransaction,
500
- commitTransaction,
501
- rollbackTransaction,
502
- closeTransaction,
503
- compare,
504
- stringifyObject,
505
- checkDuplicateKeysInEnv,
506
- normalizeConfig,
507
- setMetadata: function (metadata) {
508
- _metadata = metadata;
509
- },
510
- getMetadataItem: function (metadataItemName) {
511
- if (_metadata[metadataItemName] === undefined)
512
- return null;
513
- return _metadata[metadataItemName];
514
- },
515
- getConnection: function (connectionName) {
516
- if (!_connections[connectionName]) {
517
- console.log(`The connectionName: "${connectionName}" does not seem to be defined. Please review the .env or yaml build configuration.`);
518
- } return _connections[connectionName];
519
- },
520
- setConnections: function (connections) {
521
- _connections = connections;
522
- },
523
- getConfigParameterValue: function (configParameterName) {
524
- if (_configParameters[configParameterName] === undefined) {
525
- console.log(`The configParameter: "${configParameterName}" does not seem to be defined. Please review the .env or yaml build configuration.`);
526
- return null;
527
- }
528
- return _configParameters[configParameterName];
529
- },
530
- setConfigParameters: function (configParameters) {
531
- _configParameters = configParameters;
532
- },
533
- setTransformations: function (transformations) {
534
- _transformations = transformations;
535
- },
536
- transform: async function (callContext, transformationName, source, writer) {
537
- let transformation = _metadata[transformationName];
538
- let transformationExecutor = require('../sources/' + transformation.sourceFileName);
539
- if (source) {
540
- if (source._blz_reader) { // reader
541
- let reader = source;
542
- if (writer) {
543
- return await reader.read(callContext, transformation.sourceCodePaths, async function (sourceItem) { return await writer.write(callContext, await transformationExecutor(callContext, sourceItem)); });
544
- }
545
- else {
546
- return await reader.read(callContext, transformation.sourceCodePaths, async function (sourceItem) { return await transformationExecutor(callContext, sourceItem); });
547
- }
498
+ Dual: {
499
+ deepClone,
500
+ beginTransaction,
501
+ commitTransaction,
502
+ rollbackTransaction,
503
+ closeTransaction,
504
+ compare,
505
+ stringifyObject,
506
+ checkDuplicateKeysInEnv,
507
+ normalizeConfig,
508
+ setMetadata: function (metadata) {
509
+ _metadata = metadata;
510
+ },
511
+ getMetadataItem: function (metadataItemName) {
512
+ if (_metadata[metadataItemName] === undefined)
513
+ return null;
514
+ return _metadata[metadataItemName];
515
+ },
516
+ getConnection: function (connectionName) {
517
+ if (!_connections[connectionName]) {
518
+ console.log(`The connectionName: "${connectionName}" does not seem to be defined. Please review the .env or yaml build configuration.`);
519
+ } return _connections[connectionName];
520
+ },
521
+ setConnections: function (connections) {
522
+ _connections = connections;
523
+ },
524
+ getConfigParameterValue: function (configParameterName) {
525
+ if (_configParameters[configParameterName] === undefined) {
526
+ console.log(`The configParameter: "${configParameterName}" does not seem to be defined. Please review the .env or yaml build configuration.`);
527
+ return null;
548
528
  }
549
- else if (Array.isArray(source)) { // list
550
- if (writer) {
551
- let target = [];
552
- for (let i = 0; i < source.length; i++) {
553
- let sourceItem = source[i];
554
- target.push(await writer.write(callContext, await transformationExecutor(callContext, sourceItem)));
529
+ return _configParameters[configParameterName];
530
+ },
531
+ setConfigParameters: function (configParameters) {
532
+ _configParameters = configParameters;
533
+ },
534
+ setTransformations: function (transformations) {
535
+ _transformations = transformations;
536
+ },
537
+ transform: async function (callContext, transformationName, source, writer) {
538
+ let transformation = _metadata[transformationName];
539
+ let transformationExecutor = require('../sources/' + transformation.sourceFileName);
540
+ if (source) {
541
+ if (source._blz_reader) { // reader
542
+ let reader = source;
543
+ if (writer) {
544
+ return await reader.read(callContext, transformation.sourceCodePaths, async function (sourceItem) { return await writer.write(callContext, await transformationExecutor(callContext, sourceItem)); });
545
+ }
546
+ else {
547
+ return await reader.read(callContext, transformation.sourceCodePaths, async function (sourceItem) { return await transformationExecutor(callContext, sourceItem); });
555
548
  }
556
- return target;
557
549
  }
558
- else {
559
- let target = [];
560
- for (let i = 0; i < source.length; i++) {
561
- let sourceItem = source[i];
562
- target.push(await transformationExecutor(callContext, sourceItem));
550
+ else if (Array.isArray(source)) { // list
551
+ if (writer) {
552
+ let target = [];
553
+ for (let i = 0; i < source.length; i++) {
554
+ let sourceItem = source[i];
555
+ target.push(await writer.write(callContext, await transformationExecutor(callContext, sourceItem)));
556
+ }
557
+ return target;
558
+ }
559
+ else {
560
+ let target = [];
561
+ for (let i = 0; i < source.length; i++) {
562
+ let sourceItem = source[i];
563
+ target.push(await transformationExecutor(callContext, sourceItem));
564
+ }
565
+ return target;
563
566
  }
564
- return target;
565
567
  }
568
+ else { // obj
569
+ if (writer) {
570
+ return await writer.write(callContext, transformationExecutor(callContext, source));
571
+ }
572
+ else {
573
+ return await transformationExecutor(callContext, source);
574
+ }
575
+ }
576
+ }
577
+ return null;
578
+ },
579
+ writer: function (callContext, functionName, extraArgs) {
580
+ let fn
581
+ try {
582
+ fn = require('../sources/' + module.exports.ensureDashedFormat(functionName) + '.js')
566
583
  }
567
- else { // obj
568
- if (writer) {
569
- return await writer.write(callContext, transformationExecutor(callContext, source));
584
+ catch (err) {
585
+ throw this.error('InvalidFunction', { functionName: functionName });
586
+ }
587
+ return {
588
+ isWriter: true,
589
+ fn: fn,
590
+ extraArgs: extraArgs,
591
+ write: async function (callContext, obj) {
592
+ if (this.extraArgs) {
593
+ return await this.fn(callContext, obj, ...this.extraArgs);
594
+ }
595
+ else {
596
+ return await this.fn(callContext, obj);
597
+ }
570
598
  }
571
- else {
572
- return await transformationExecutor(callContext, source);
599
+ };
600
+ },
601
+ getValue: function (root, bind) {
602
+ if (root === null)
603
+ return null;
604
+ if (bind || bind === 0) {
605
+ let rootType = toString.call(root);
606
+ if (rootType === '[object Object]' || rootType === '[object Error]') {
607
+ let bindParts = bind.split('.');
608
+ let current = root;
609
+ for (let i = 0; i < bindParts.length; i++) {
610
+ let bindPart = bindParts[i];
611
+ if (current[bindPart] === null || current[bindPart] === undefined)
612
+ return null;
613
+ current = current[bindPart];
614
+ }
615
+ return current;
573
616
  }
574
- }
575
- }
576
- return null;
577
- },
578
- writer: function (callContext, functionName, extraArgs) {
579
- let fn
580
- try {
581
- fn = require('../sources/' + module.exports.ensureDashedFormat(functionName) + '.js')
582
- }
583
- catch (err) {
584
- throw this.error('InvalidFunction', { functionName: functionName });
585
- }
586
- return {
587
- isWriter: true,
588
- fn: fn,
589
- extraArgs: extraArgs,
590
- write: async function (callContext, obj) {
591
- if (this.extraArgs) {
592
- return await this.fn(callContext, obj, ...this.extraArgs);
617
+ else if (rootType === '[object Array]') {
618
+ return root[bind];
593
619
  }
594
620
  else {
595
- return await this.fn(callContext, obj);
621
+ return null;
596
622
  }
597
623
  }
598
- };
599
- },
600
- getValue: function (root, bind) {
601
- if (root === null)
602
- return null;
603
- if (bind || bind === 0) {
604
- let rootType = toString.call(root);
605
- if (rootType === '[object Object]' || rootType === '[object Error]') {
606
- let bindParts = bind.split('.');
607
- let current = root;
608
- for (let i = 0; i < bindParts.length; i++) {
609
- let bindPart = bindParts[i];
610
- if (current[bindPart] === null || current[bindPart] === undefined)
611
- return null;
612
- current = current[bindPart];
613
- }
614
- return current;
624
+ else {
625
+ return root;
615
626
  }
616
- else if (rootType === '[object Array]') {
617
- return root[bind];
627
+ },
628
+ setValue: function (root, bind, value) {
629
+ let bindParts = bind.split('.');
630
+ let current = root;
631
+ for (let i = 0; i < (bindParts.length - 1); i++) {
632
+ let bindPart = bindParts[i];
633
+ if (current[bindPart] === null || current[bindPart] === undefined)
634
+ current[bindPart] = {};
635
+ current = current[bindPart];
636
+ }
637
+ current[bindParts[bindParts.length - 1]] = value;
638
+ },
639
+ divide: function (dividend, divisor) {
640
+ if (divisor === null || divisor === 0) {
641
+ let err = new Error();
642
+ err.code = 'DivisionByZero';
643
+ err.data = { dividend: dividend, divisor: divisor };
644
+ throw err;
618
645
  }
619
646
  else {
620
- return null;
647
+ return dividend / divisor;
621
648
  }
622
- }
623
- else {
624
- return root;
625
- }
626
- },
627
- setValue: function (root, bind, value) {
628
- let bindParts = bind.split('.');
629
- let current = root;
630
- for (let i = 0; i < (bindParts.length - 1); i++) {
631
- let bindPart = bindParts[i];
632
- if (current[bindPart] === null || current[bindPart] === undefined)
633
- current[bindPart] = {};
634
- current = current[bindPart];
635
- }
636
- current[bindParts[bindParts.length - 1]] = value;
637
- },
638
- divide: function (dividend, divisor) {
639
- if (divisor === null || divisor === 0) {
640
- let err = new Error();
641
- err.code = 'DivisionByZero';
642
- err.data = { dividend: dividend, divisor: divisor };
643
- throw err;
644
- }
645
- else {
646
- return dividend / divisor;
647
- }
648
- },
649
- remainder: function (dividend, divisor) {
650
- if (divisor === null || divisor === 0) {
651
- let err = new Error();
652
- err.code = 'RemainderByZero';
653
- err.data = { dividend: dividend, divisor: divisor };
654
- throw err;
655
- }
656
- else {
657
- return dividend % divisor;
658
- }
659
- },
660
- httpErrors: {
661
- 400: 'BadRequest',
662
- 401: 'Unauthorized',
663
- 402: 'PaymentRequired',
664
- 403: 'Forbidden',
665
- 404: 'NotFound',
666
- 405: 'MethodNotAllowed',
667
- 406: 'NotAcceptable',
668
- 407: 'ProxyAuthenticationRequired',
669
- 408: 'RequestTimeout',
670
- 409: 'Conflict',
671
- 410: 'Gone',
672
- 411: 'LengthRequired',
673
- 412: 'PreconditionFailed',
674
- 500: 'InternalServerError',
675
- 501: 'NotImplemented',
676
- 502: 'BadGateway',
677
- 503: 'ServiceUnavailable',
678
- 504: 'GatewayTimeout',
679
- 524: 'Timeout'
680
- },
681
- httpStatuses: {
682
- 'BadRequest': 400,
683
- 'Unauthorized': 401,
684
- 'PaymentRequired': 402,
685
- 'Forbidden': 403,
686
- 'NotFound': 404,
687
- 'MethodNotAllowed': 405,
688
- 'NotAcceptable': 406,
689
- 'ProxyAuthenticationRequired': 407,
690
- 'RequestTimeout': 408,
691
- 'Conflict': 409,
692
- 'Gone': 410,
693
- 'LengthRequired': 411,
694
- 'PreconditionFailed': 412,
695
- 'InternalServerError': 500,
696
- 'NotImplemented': 501,
697
- 'BadGateway': 502,
698
- 'ServiceUnavailable': 503,
699
- 'GatewayTimeout': 504,
700
- 'Timeout': 524
701
- },
702
- getHttpStatus: function (err) {
703
- return this.httpStatuses[err.code];
704
- },
705
- httpCall: async function (httpRequest) {
706
- let requestUrl = httpRequest.url;
707
- let requestOptions = {
708
- method: httpRequest.method,
709
- headers: {},
710
- throwHttpErrors: false
711
- };
712
- if (httpRequest.method !== 'GET')
713
- requestOptions.body = httpRequest.body;
714
- if (httpRequest.headers)
715
- for (let i = 0; i < httpRequest.headers.length; i++) {
716
- let httpHeader = httpRequest.headers[i];
717
- requestOptions.headers[httpHeader.name] = httpHeader.value;
649
+ },
650
+ remainder: function (dividend, divisor) {
651
+ if (divisor === null || divisor === 0) {
652
+ let err = new Error();
653
+ err.code = 'RemainderByZero';
654
+ err.data = { dividend: dividend, divisor: divisor };
655
+ throw err;
718
656
  }
719
- if (requestUrl.match(/https.*/)) {
720
- requestOptions = {
721
- ...requestOptions,
722
- https: {
723
- requestCert: true, // Request a certificate from clients that connect and attempt to verify that certificate.
724
- rejectUnauthorized: false, // The server will reject any connection which is not authorized with the list of supplied CAs.
725
- agent: false // Is responsible for managing connection persistence and reuse for https clients.
726
- }
657
+ else {
658
+ return dividend % divisor;
659
+ }
660
+ },
661
+ httpErrors: {
662
+ 400: 'BadRequest',
663
+ 401: 'Unauthorized',
664
+ 402: 'PaymentRequired',
665
+ 403: 'Forbidden',
666
+ 404: 'NotFound',
667
+ 405: 'MethodNotAllowed',
668
+ 406: 'NotAcceptable',
669
+ 407: 'ProxyAuthenticationRequired',
670
+ 408: 'RequestTimeout',
671
+ 409: 'Conflict',
672
+ 410: 'Gone',
673
+ 411: 'LengthRequired',
674
+ 412: 'PreconditionFailed',
675
+ 500: 'InternalServerError',
676
+ 501: 'NotImplemented',
677
+ 502: 'BadGateway',
678
+ 503: 'ServiceUnavailable',
679
+ 504: 'GatewayTimeout',
680
+ 524: 'Timeout'
681
+ },
682
+ httpStatuses: {
683
+ 'BadRequest': 400,
684
+ 'Unauthorized': 401,
685
+ 'PaymentRequired': 402,
686
+ 'Forbidden': 403,
687
+ 'NotFound': 404,
688
+ 'MethodNotAllowed': 405,
689
+ 'NotAcceptable': 406,
690
+ 'ProxyAuthenticationRequired': 407,
691
+ 'RequestTimeout': 408,
692
+ 'Conflict': 409,
693
+ 'Gone': 410,
694
+ 'LengthRequired': 411,
695
+ 'PreconditionFailed': 412,
696
+ 'InternalServerError': 500,
697
+ 'NotImplemented': 501,
698
+ 'BadGateway': 502,
699
+ 'ServiceUnavailable': 503,
700
+ 'GatewayTimeout': 504,
701
+ 'Timeout': 524
702
+ },
703
+ getHttpStatus: function (err) {
704
+ return this.httpStatuses[err.code];
705
+ },
706
+ httpCall: async function (httpRequest) {
707
+ let requestUrl = httpRequest.url;
708
+ let requestOptions = {
709
+ method: httpRequest.method,
710
+ headers: {},
711
+ throwHttpErrors: false
727
712
  };
728
- }
729
- let response = await Got(requestUrl, requestOptions);
730
- let httpErrorCode = this.httpErrors[response.statusCode];
731
- if (httpErrorCode) {
713
+ if (httpRequest.method !== 'GET')
714
+ requestOptions.body = httpRequest.body;
715
+ if (httpRequest.headers)
716
+ for (let i = 0; i < httpRequest.headers.length; i++) {
717
+ let httpHeader = httpRequest.headers[i];
718
+ requestOptions.headers[httpHeader.name] = httpHeader.value;
719
+ }
720
+ if (requestUrl.match(/https.*/)) {
721
+ requestOptions = {
722
+ ...requestOptions,
723
+ https: {
724
+ requestCert: true, // Request a certificate from clients that connect and attempt to verify that certificate.
725
+ rejectUnauthorized: false, // The server will reject any connection which is not authorized with the list of supplied CAs.
726
+ agent: false // Is responsible for managing connection persistence and reuse for https clients.
727
+ }
728
+ };
729
+ }
730
+ let response = await Got(requestUrl, requestOptions);
731
+ let httpErrorCode = this.httpErrors[response.statusCode];
732
+ if (httpErrorCode) {
733
+ let err = new Error();
734
+ err.code = httpErrorCode;
735
+ try { err.data = JSON.parse(response.body); } catch (err2) { }
736
+ throw err;
737
+ }
738
+ else {
739
+ return { status: response.statusCode, body: response.body };
740
+ }
741
+ },
742
+ internalCall: async function (callContext, functionName, args) {
743
+ let fn = null;
744
+ try {
745
+ fn = require('../sources/' + module.exports.ensureDashedFormat(functionName) + '.js')
746
+ }
747
+ catch (err) {
748
+ throw this.error('InvalidFunction', { functionName: functionName });
749
+ }
750
+ if (args)
751
+ return await fn(callContext, ...args);
752
+ else
753
+ return await fn(callContext);
754
+ },
755
+ externalCall: async function (callContext, connection, functionName, values) {
756
+ if (connection.type === 'Microservice' || connection.type === 'RestApi' || connection.type === 'ProcessEngine') {
757
+ let restMappings = _metadata['_rest_mappings'];
758
+ return await module.exports.callRest(connection, restMappings[connection.name], functionName, values, null, _configParameters, callContext);
759
+ }
760
+ else if (connection.type === 'SoapApi') {
761
+ let soapMappings = _metadata['_soap_mappings'];
762
+ return await module.exports.callSoap(connection, soapMappings[connection.name], functionName, values, null, _configParameters, callContext);
763
+ }
764
+ },
765
+ error: function (code, data, innerError) {
732
766
  let err = new Error();
733
- err.code = httpErrorCode;
734
- try { err.data = JSON.parse(response.body); } catch (err2) { }
735
- throw err;
736
- }
737
- else {
738
- return { status: response.statusCode, body: response.body };
739
- }
740
- },
741
- internalCall: async function (callContext, functionName, args) {
742
- let fn = null;
743
- try {
744
- fn = require('../sources/' + module.exports.ensureDashedFormat(functionName) + '.js')
745
- }
746
- catch (err) {
747
- throw this.error('InvalidFunction', { functionName: functionName });
748
- }
749
- if (args)
750
- return await fn(callContext, ...args);
751
- else
752
- return await fn(callContext);
753
- },
754
- externalCall: async function (callContext, connection, functionName, values) {
755
- if (connection.type === 'Microservice' || connection.type === 'RestApi' || connection.type === 'ProcessEngine') {
756
- let restMappings = _metadata['_rest_mappings'];
757
- return await module.exports.callRest(connection, restMappings[connection.name], functionName, values, null, _configParameters, callContext);
758
- }
759
- else if (connection.type === 'SoapApi') {
760
- let soapMappings = _metadata['_soap_mappings'];
761
- return await module.exports.callSoap(connection, soapMappings[connection.name], functionName, values, null, _configParameters, callContext);
762
- }
763
- },
764
- error: function (code, data, innerError) {
765
- let err = new Error();
766
- err.code = code;
767
- if (data)
768
- err.data = data;
769
- if (innerError)
770
- err.innerError = innerError;
771
- return err;
772
- },
773
- convertToString: function (value) {
774
- if (value === null || value === undefined)
775
- return null;
776
- let valueType = toString.call(value);
777
- if (valueType === '[object String]')
778
- return value;
779
- if (valueType === '[object Number]')
780
- return value.toString();
781
- if (valueType === '[object Boolean]')
782
- return value ? 'true' : 'false';
783
- if (valueType === '[object Date]')
784
- return value.toJSON();
785
- if (valueType === '[object Object]' && value.type === 'Buffer' && value.data)
786
- return Buffer.from(value.data).toString();
787
- if (Buffer.isBuffer(value))
788
- return value.toString();
789
- throw this.error('InvalidConversion', { value: value, targetType: 'string' });
790
- },
791
- convertToInteger: function (value) {
792
- if (value === null)
793
- return null;
794
- let valueType = toString.call(value);
795
- if (valueType === '[object String]' && !isNaN(value))
796
- return Math.round(Number(value));
797
- if (valueType === '[object Number]')
798
- return Math.round(value);
799
- if (valueType === '[object Boolean]')
800
- return value ? 1 : 0;
801
- throw this.error('InvalidConversion', { value: value, targetType: 'integer' });
802
- },
803
- convertToDecimal: function (value) {
804
- if (value === null)
805
- return null;
806
- let valueType = toString.call(value);
807
- if (valueType === '[object String]' && !isNaN(value))
808
- return Number(value);
809
- if (valueType === '[object Number]')
810
- return value;
811
- if (valueType === '[object Boolean]')
812
- return value ? 1 : 0;
813
- throw this.error('InvalidConversion', { value: value, targetType: 'decimal' });
814
- },
815
- convertToBoolean: function (value) {
816
- if (value === null)
817
- return null;
818
- let valueType = toString.call(value);
819
- if (valueType === '[object String]') {
820
- if (value === '1' || value.toUpperCase() === 'T' || value.toUpperCase() === 'TRUE' || value.toUpperCase() === 'Y' || value.toUpperCase() === 'YES')
821
- return true;
822
- if (value === '0' || value.toUpperCase() === 'F' || value.toUpperCase() === 'FALSE' || value.toUpperCase() === 'N' || value.toUpperCase() === 'NO')
823
- return false;
824
- }
825
- if (valueType === '[object Number]') {
826
- if (value === 1)
827
- return true;
828
- if (value === 0)
829
- return false;
830
- }
831
- if (valueType === '[object Boolean]')
832
- return value;
833
- throw this.error('InvalidConversion', { value: value, targetType: 'boolean' });
834
- },
835
- convertToDatetime: function (value) {
836
- if (value === null)
837
- return null;
838
- let valueType = toString.call(value);
839
- if (valueType === '[object String]') {
840
- let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
841
- if (matchDatetime)
842
- return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
843
- }
844
- if (valueType === '[object Date]') {
845
- return value;
846
- }
847
- throw this.error('InvalidConversion', { value: value, targetType: 'datetime' });
848
- },
849
- convertToDate: function (value) {
850
- if (value === null)
851
- return null;
852
- let valueType = toString.call(value);
853
- if (valueType === '[object String]') {
854
- let matchDate = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(value);
855
- if (matchDate)
856
- return new Date(Date.UTC(Number(matchDate[1]), Number(matchDate[2]) - 1, Number(matchDate[3]), 0, 0, 0, 0));
857
- let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
858
- if (matchDatetime)
859
- return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), 0, 0, 0, 0));
860
- }
861
- if (valueType === '[object Date]') {
862
- return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), 0, 0, 0, 0));
863
- }
864
- throw this.error('InvalidConversion', { value: value, targetType: 'date' });
865
- },
866
- convertToTime: function (value) {
867
- if (value === null)
868
- return null;
869
- let valueType = toString.call(value);
870
- if (valueType === '[object String]') {
871
- let matchTime = /^(\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?$/.exec(value);
872
- if (matchTime)
873
- return new Date(Date.UTC(1970, 0, 1, Number(matchTime[1]), Number(matchTime[2]), Number(matchTime[3]), convertMilliseconds(matchTime[4])));
874
- let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
875
- if (matchDatetime)
876
- return new Date(Date.UTC(1970, 0, 1, Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
877
- }
878
- if (valueType === '[object Date]') {
879
- return new Date(Date.UTC(1970, 0, 1, value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds()));
880
- }
881
- throw this.error('InvalidConversion', { value: value, targetType: 'time' });
882
- },
883
- ensureDashedFormat: function (str) {
884
- if (str === null)
885
- return null;
886
- let result = '';
887
- let lastChar = '';
888
- for (let i = 0; i < str.length; i++) {
889
- let char = str[i];
890
- if (char.match(/[0-9]/)) {
891
- result += char;
767
+ err.code = code;
768
+ if (data)
769
+ err.data = data;
770
+ if (innerError)
771
+ err.innerError = innerError;
772
+ return err;
773
+ },
774
+ convertToString: function (value) {
775
+ if (value === null || value === undefined)
776
+ return null;
777
+ let valueType = toString.call(value);
778
+ if (valueType === '[object String]')
779
+ return value;
780
+ if (valueType === '[object Number]')
781
+ return value.toString();
782
+ if (valueType === '[object Boolean]')
783
+ return value ? 'true' : 'false';
784
+ if (valueType === '[object Date]')
785
+ return value.toJSON();
786
+ if (valueType === '[object Object]' && value.type === 'Buffer' && value.data)
787
+ return Buffer.from(value.data).toString();
788
+ if (Buffer.isBuffer(value))
789
+ return value.toString();
790
+ throw this.error('InvalidConversion', { value: value, targetType: 'string' });
791
+ },
792
+ convertToInteger: function (value) {
793
+ if (value === null)
794
+ return null;
795
+ let valueType = toString.call(value);
796
+ if (valueType === '[object String]' && !isNaN(value))
797
+ return Math.round(Number(value));
798
+ if (valueType === '[object Number]')
799
+ return Math.round(value);
800
+ if (valueType === '[object Boolean]')
801
+ return value ? 1 : 0;
802
+ throw this.error('InvalidConversion', { value: value, targetType: 'integer' });
803
+ },
804
+ convertToDecimal: function (value) {
805
+ if (value === null)
806
+ return null;
807
+ let valueType = toString.call(value);
808
+ if (valueType === '[object String]' && !isNaN(value))
809
+ return Number(value);
810
+ if (valueType === '[object Number]')
811
+ return value;
812
+ if (valueType === '[object Boolean]')
813
+ return value ? 1 : 0;
814
+ throw this.error('InvalidConversion', { value: value, targetType: 'decimal' });
815
+ },
816
+ convertToBoolean: function (value) {
817
+ if (value === null)
818
+ return null;
819
+ let valueType = toString.call(value);
820
+ if (valueType === '[object String]') {
821
+ if (value === '1' || value.toUpperCase() === 'T' || value.toUpperCase() === 'TRUE' || value.toUpperCase() === 'Y' || value.toUpperCase() === 'YES')
822
+ return true;
823
+ if (value === '0' || value.toUpperCase() === 'F' || value.toUpperCase() === 'FALSE' || value.toUpperCase() === 'N' || value.toUpperCase() === 'NO')
824
+ return false;
892
825
  }
893
- else if (lastChar.match(/[A-Z]/) && char.match(/[A-Z]/)) {
894
- result += char.toLowerCase();
826
+ if (valueType === '[object Number]') {
827
+ if (value === 1)
828
+ return true;
829
+ if (value === 0)
830
+ return false;
895
831
  }
896
- else if (lastChar.match(/[A-Z]/) && char.match(/[a-z]/)) {
897
- result += char;
832
+ if (valueType === '[object Boolean]')
833
+ return value;
834
+ throw this.error('InvalidConversion', { value: value, targetType: 'boolean' });
835
+ },
836
+ convertToDatetime: function (value) {
837
+ if (value === null)
838
+ return null;
839
+ let valueType = toString.call(value);
840
+ if (valueType === '[object String]') {
841
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
842
+ if (matchDatetime)
843
+ return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
898
844
  }
899
- else if (lastChar.match(/[a-z]/) && char.match(/[A-Z]/)) {
900
- result += '-' + char.toLowerCase();
845
+ if (valueType === '[object Date]') {
846
+ return value;
901
847
  }
902
- else if (lastChar.match(/[a-z]/) && char.match(/[a-z]/)) {
903
- result += char;
848
+ throw this.error('InvalidConversion', { value: value, targetType: 'datetime' });
849
+ },
850
+ convertToDate: function (value) {
851
+ if (value === null)
852
+ return null;
853
+ let valueType = toString.call(value);
854
+ if (valueType === '[object String]') {
855
+ let matchDate = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(value);
856
+ if (matchDate)
857
+ return new Date(Date.UTC(Number(matchDate[1]), Number(matchDate[2]) - 1, Number(matchDate[3]), 0, 0, 0, 0));
858
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
859
+ if (matchDatetime)
860
+ return new Date(Date.UTC(Number(matchDatetime[1]), Number(matchDatetime[2]) - 1, Number(matchDatetime[3]), 0, 0, 0, 0));
904
861
  }
905
- else if (char.match(/[A-Z]/)) {
906
- result += char.toLowerCase();
862
+ if (valueType === '[object Date]') {
863
+ return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), 0, 0, 0, 0));
907
864
  }
908
- else if (char.match(/[a-z]/)) {
909
- result += char;
865
+ throw this.error('InvalidConversion', { value: value, targetType: 'date' });
866
+ },
867
+ convertToTime: function (value) {
868
+ if (value === null)
869
+ return null;
870
+ let valueType = toString.call(value);
871
+ if (valueType === '[object String]') {
872
+ let matchTime = /^(\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?$/.exec(value);
873
+ if (matchTime)
874
+ return new Date(Date.UTC(1970, 0, 1, Number(matchTime[1]), Number(matchTime[2]), Number(matchTime[3]), convertMilliseconds(matchTime[4])));
875
+ let matchDatetime = /^(\d{4})-(\d{1,2})-(\d{1,2})[T,\s](\d{1,2})\:(\d{1,2})\:(\d{1,2})\.?(\d+)?Z?$/.exec(value);
876
+ if (matchDatetime)
877
+ return new Date(Date.UTC(1970, 0, 1, Number(matchDatetime[4]), Number(matchDatetime[5]), Number(matchDatetime[6] || 0), convertMilliseconds(matchDatetime[7])));
910
878
  }
911
- lastChar = char;
912
- }
913
- return result;
914
- },
915
- mapRoutingParameters: function (request, routingParameters) {
916
- let result = {};
917
- if (routingParameters) {
918
- const lowerCaseHeadersKeysEntries = Object.keys(request.headers || {}).map(headerKey => [headerKey.toLowerCase(), headerKey])
919
- const lowerCaseHeadersKeysMap = Object.fromEntries(lowerCaseHeadersKeysEntries)
920
- for (let i = 0; i < routingParameters.length; i++) {
921
- let routingParameter = routingParameters[i];
922
- if (routingParameter.name && routingParameter.type) {
923
- if (routingParameter.in === 'Path' || routingParameter.in === 'Query' || routingParameter.in === 'Header') {
924
- let value = null;
925
- if (routingParameter.in === 'Path') {
926
- if (request.params && request.params[routingParameter.name])
927
- value = request.params[routingParameter.name];
928
- }
929
- else if (routingParameter.in === 'Query') {
930
- if (request.query && request.query[routingParameter.name])
931
- value = request.query[routingParameter.name];
932
- }
933
- else if (routingParameter.in === 'Header') {
934
- const headerKey = lowerCaseHeadersKeysMap[routingParameter.name.toLowerCase()]
935
- const headerValue = headerKey && request.headers && request.headers[headerKey]
936
- if (headerValue) {
937
- value = headerValue
879
+ if (valueType === '[object Date]') {
880
+ return new Date(Date.UTC(1970, 0, 1, value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds()));
881
+ }
882
+ throw this.error('InvalidConversion', { value: value, targetType: 'time' });
883
+ },
884
+ ensureDashedFormat: function (str) {
885
+ if (str === null)
886
+ return null;
887
+ let result = '';
888
+ let lastChar = '';
889
+ for (let i = 0; i < str.length; i++) {
890
+ let char = str[i];
891
+ if (char.match(/[0-9]/)) {
892
+ result += char;
893
+ }
894
+ else if (lastChar.match(/[A-Z]/) && char.match(/[A-Z]/)) {
895
+ result += char.toLowerCase();
896
+ }
897
+ else if (lastChar.match(/[A-Z]/) && char.match(/[a-z]/)) {
898
+ result += char;
899
+ }
900
+ else if (lastChar.match(/[a-z]/) && char.match(/[A-Z]/)) {
901
+ result += '-' + char.toLowerCase();
902
+ }
903
+ else if (lastChar.match(/[a-z]/) && char.match(/[a-z]/)) {
904
+ result += char;
905
+ }
906
+ else if (char.match(/[A-Z]/)) {
907
+ result += char.toLowerCase();
908
+ }
909
+ else if (char.match(/[a-z]/)) {
910
+ result += char;
911
+ }
912
+ lastChar = char;
913
+ }
914
+ return result;
915
+ },
916
+ mapRoutingParameters: function (request, routingParameters) {
917
+ let result = {};
918
+ if (routingParameters) {
919
+ const lowerCaseHeadersKeysEntries = Object.keys(request.headers || {}).map(headerKey => [headerKey.toLowerCase(), headerKey])
920
+ const lowerCaseHeadersKeysMap = Object.fromEntries(lowerCaseHeadersKeysEntries)
921
+ for (let i = 0; i < routingParameters.length; i++) {
922
+ let routingParameter = routingParameters[i];
923
+ if (routingParameter.name && routingParameter.type) {
924
+ if (routingParameter.in === 'Path' || routingParameter.in === 'Query' || routingParameter.in === 'Header') {
925
+ let value = null;
926
+ if (routingParameter.in === 'Path') {
927
+ if (request.params && request.params[routingParameter.name])
928
+ value = request.params[routingParameter.name];
929
+ }
930
+ else if (routingParameter.in === 'Query') {
931
+ if (request.query && request.query[routingParameter.name])
932
+ value = request.query[routingParameter.name];
933
+ }
934
+ else if (routingParameter.in === 'Header') {
935
+ const headerKey = lowerCaseHeadersKeysMap[routingParameter.name.toLowerCase()]
936
+ const headerValue = headerKey && request.headers && request.headers[headerKey]
937
+ if (headerValue) {
938
+ value = headerValue
939
+ }
940
+ }
941
+ if (value) {
942
+ if (routingParameter.type === 'string')
943
+ this.setValue(result, routingParameter.bind, this.convertToString(value));
944
+ else if (routingParameter.type === 'integer')
945
+ this.setValue(result, routingParameter.bind, this.convertToInteger(value));
946
+ else if (routingParameter.type === 'decimal')
947
+ this.setValue(result, routingParameter.bind, this.convertToDecimal(value));
948
+ else if (routingParameter.type === 'boolean')
949
+ this.setValue(result, routingParameter.bind, this.convertToBoolean(value));
950
+ else if (routingParameter.type === 'datetime')
951
+ this.setValue(result, routingParameter.bind, this.convertToDatetime(value));
952
+ else if (routingParameter.type === 'date')
953
+ this.setValue(result, routingParameter.bind, this.convertToDate(value));
954
+ else if (routingParameter.type === 'time')
955
+ this.setValue(result, routingParameter.bind, this.convertToTime(value));
956
+ else if (routingParameter.type === 'list(string)')
957
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToString));
958
+ else if (routingParameter.type === 'list(integer)')
959
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToInteger));
960
+ else if (routingParameter.type === 'list(decimal)')
961
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDecimal));
962
+ else if (routingParameter.type === 'list(boolean)')
963
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToBoolean));
964
+ else if (routingParameter.type === 'list(datetime)')
965
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDatetime));
966
+ else if (routingParameter.type === 'list(date)')
967
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDate));
968
+ else if (routingParameter.type === 'list(time)')
969
+ this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToTime));
938
970
  }
939
971
  }
940
- if (value) {
941
- if (routingParameter.type === 'string')
942
- this.setValue(result, routingParameter.bind, this.convertToString(value));
943
- else if (routingParameter.type === 'integer')
944
- this.setValue(result, routingParameter.bind, this.convertToInteger(value));
945
- else if (routingParameter.type === 'decimal')
946
- this.setValue(result, routingParameter.bind, this.convertToDecimal(value));
947
- else if (routingParameter.type === 'boolean')
948
- this.setValue(result, routingParameter.bind, this.convertToBoolean(value));
949
- else if (routingParameter.type === 'datetime')
950
- this.setValue(result, routingParameter.bind, this.convertToDatetime(value));
951
- else if (routingParameter.type === 'date')
952
- this.setValue(result, routingParameter.bind, this.convertToDate(value));
953
- else if (routingParameter.type === 'time')
954
- this.setValue(result, routingParameter.bind, this.convertToTime(value));
955
- else if (routingParameter.type === 'list(string)')
956
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToString));
957
- else if (routingParameter.type === 'list(integer)')
958
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToInteger));
959
- else if (routingParameter.type === 'list(decimal)')
960
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDecimal));
961
- else if (routingParameter.type === 'list(boolean)')
962
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToBoolean));
963
- else if (routingParameter.type === 'list(datetime)')
964
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDatetime));
965
- else if (routingParameter.type === 'list(date)')
966
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToDate));
967
- else if (routingParameter.type === 'list(time)')
968
- this.setValue(result, routingParameter.bind, convertToListOf(value, this.convertToTime));
972
+ else if (routingParameter.in === 'Body') {
973
+ this.setValue(result, routingParameter.bind, request.payload);
969
974
  }
970
975
  }
971
- else if (routingParameter.in === 'Body') {
972
- this.setValue(result, routingParameter.bind, request.payload);
973
- }
974
976
  }
975
977
  }
976
- }
977
- return result;
978
- },
979
- decodeApiKey: function (request, apiKeyIn, apiKeyName) {
980
- switch (apiKeyIn) {
981
- case 'Header': {
982
- if (request.headers) {
983
- let headerValue = request.headers[apiKeyName];
984
- if (headerValue) {
985
- return { key: headerValue };
978
+ return result;
979
+ },
980
+ decodeApiKey: function (request, apiKeyIn, apiKeyName) {
981
+ switch (apiKeyIn) {
982
+ case 'Header': {
983
+ if (request.headers) {
984
+ let headerValue = request.headers[apiKeyName];
985
+ if (headerValue) {
986
+ return { key: headerValue };
987
+ }
986
988
  }
989
+ break;
990
+ }
991
+ case 'Query': {
992
+ if (request.query) {
993
+ let queryValue = request.query[apiKeyName];
994
+ if (queryValue) {
995
+ return { key: queryValue };
996
+ }
997
+ }
998
+ break;
987
999
  }
988
- break;
989
1000
  }
990
- case 'Query': {
991
- if (request.query) {
992
- let queryValue = request.query[apiKeyName];
993
- if (queryValue) {
994
- return { key: queryValue };
1001
+ return null;
1002
+ },
1003
+ decodeBasicAuth: function (request) {
1004
+ if (request.headers) {
1005
+ let headerValue = request.headers['authorization'];
1006
+ if (headerValue && headerValue.startsWith('Basic')) {
1007
+ try {
1008
+ let buffer = Buffer.from(headerValue.split(' ')[1], 'base64');
1009
+ let plain = buffer.toString();
1010
+ let credentials = plain.split(':');
1011
+ return { user: credentials[0], password: credentials[1] };
995
1012
  }
1013
+ catch (err2) { }
996
1014
  }
997
- break;
998
1015
  }
999
- }
1000
- return null;
1001
- },
1002
- decodeBasicAuth: function (request) {
1003
- if (request.headers) {
1004
- let headerValue = request.headers['authorization'];
1005
- if (headerValue && headerValue.startsWith('Basic')) {
1006
- try {
1007
- let buffer = Buffer.from(headerValue.split(' ')[1], 'base64');
1008
- let plain = buffer.toString();
1009
- let credentials = plain.split(':');
1010
- return { user: credentials[0], password: credentials[1] };
1016
+ return null;
1017
+ },
1018
+ decodeBearerToken: function (request) {
1019
+ if (request.headers) {
1020
+ let headerValue = request.headers['authorization'];
1021
+ if (headerValue && headerValue.startsWith('Bearer')) {
1022
+ return { token: headerValue.split(' ')[1] };
1011
1023
  }
1012
- catch (err2) { }
1013
1024
  }
1014
- }
1015
- return null;
1016
- },
1017
- decodeBearerToken: function (request) {
1018
- if (request.headers) {
1019
- let headerValue = request.headers['authorization'];
1020
- if (headerValue && headerValue.startsWith('Bearer')) {
1021
- return { token: headerValue.split(' ')[1] };
1025
+ return null;
1026
+ },
1027
+ loadResource: async function (path) {
1028
+ try {
1029
+ let resourceContent = await Fs.readFile(Path.join(_metadata.appPath, '../resources', path), 'utf8');
1030
+ if (path.endsWith('.json')) return JSON.parse(resourceContent)
1031
+ else if (path.endsWith('.yaml') || path.endsWith('.yml')) return jsyaml.load(resourceContent)
1032
+ else return resourceContent;
1022
1033
  }
1023
- }
1024
- return null;
1025
- },
1026
- loadResource: async function (path) {
1027
- try {
1028
- let resourceContent = await Fs.readFile(Path.join(_metadata.appPath, '../resources', path), 'utf8');
1029
- if (path.endsWith('.json') ) return JSON.parse(resourceContent)
1030
- else if (path.endsWith('.yaml') || path.endsWith('.yml'))return jsyaml.load(resourceContent)
1031
- else return resourceContent;
1032
- }
1033
- catch (fserr) {
1034
- if (fserr.code !== 'ENOENT')
1035
- throw fserr
1036
- }
1037
- let err = new Error();
1038
- err.code = 'ResourceNotFound';
1039
- err.data = { path: path };
1040
- throw err;
1041
- },
1042
- callRest: async function (connection, restMapping, functionName, values, request, configParameters, callContext) {
1043
- let restMappingFunction = restMapping[functionName];
1044
- let requestUrl = connection.url.trim();
1045
- let requestUrlIndex = requestUrl.length - 1;
1046
- while (requestUrlIndex >= 0 && requestUrl[requestUrlIndex] === '/') {
1047
- requestUrlIndex--;
1048
- }
1049
- requestUrl = requestUrl.substring(0, requestUrlIndex + 1) + restMappingFunction.path;
1050
- let requestOptions = {
1051
- method: restMappingFunction.method,
1052
- headers: { 'Content-Type': 'application/json' },
1053
- throwHttpErrors: false
1054
- };
1055
- if (restMappingFunction.timeout && restMappingFunction.timeout > 0) {
1056
- requestOptions.timeout = restMappingFunction.timeout;
1057
- }
1058
- var isFirstQueryParameter = true;
1059
- if (restMappingFunction.parameters) {
1060
- for (let i = 0; i < restMappingFunction.parameters.length; i++) {
1061
- let routingParameter = restMappingFunction.parameters[i];
1062
- let bindParts = routingParameter.bind.split('.');
1063
- let value = values;
1064
- for (let j = 0; j < bindParts.length; j++) {
1065
- let bindPart = bindParts[j];
1066
- if (value)
1067
- value = value[bindPart];
1068
- }
1069
- if (value === null && routingParameter.in === 'Path')
1070
- throw new Error('Error trying to call [' + connection.url + restMappingFunction.path + ']. The parameter [' + routingParameter.name + '] is mandatory.');
1071
- if (value !== null && value !== undefined) {
1072
- if (routingParameter.in === 'Path') {
1073
- requestUrl = requestUrl.split('{' + routingParameter.name + '}').join(encodeURIComponent(this.convertToString(value)));
1034
+ catch (fserr) {
1035
+ if (fserr.code !== 'ENOENT')
1036
+ throw fserr
1037
+ }
1038
+ let err = new Error();
1039
+ err.code = 'ResourceNotFound';
1040
+ err.data = { path: path };
1041
+ throw err;
1042
+ },
1043
+ callRest: async function (connection, restMapping, functionName, values, request, configParameters, callContext) {
1044
+ let restMappingFunction = restMapping[functionName];
1045
+ let requestUrl = connection.url.trim();
1046
+ let requestUrlIndex = requestUrl.length - 1;
1047
+ while (requestUrlIndex >= 0 && requestUrl[requestUrlIndex] === '/') {
1048
+ requestUrlIndex--;
1049
+ }
1050
+ requestUrl = requestUrl.substring(0, requestUrlIndex + 1) + restMappingFunction.path;
1051
+ let requestOptions = {
1052
+ method: restMappingFunction.method,
1053
+ headers: { 'Content-Type': 'application/json' },
1054
+ throwHttpErrors: false
1055
+ };
1056
+ if (restMappingFunction.timeout && restMappingFunction.timeout > 0) {
1057
+ requestOptions.timeout = restMappingFunction.timeout;
1058
+ }
1059
+ var isFirstQueryParameter = true;
1060
+ if (restMappingFunction.parameters) {
1061
+ for (let i = 0; i < restMappingFunction.parameters.length; i++) {
1062
+ let routingParameter = restMappingFunction.parameters[i];
1063
+ let bindParts = routingParameter.bind.split('.');
1064
+ let value = values;
1065
+ for (let j = 0; j < bindParts.length; j++) {
1066
+ let bindPart = bindParts[j];
1067
+ if (value)
1068
+ value = value[bindPart];
1074
1069
  }
1075
- else if (routingParameter.in === 'Query') {
1076
- if (Array.isArray(value)) {
1077
- for (let k = 0; k < value.length; k++) {
1078
- requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(routingParameter.name) + '=' + encodeURIComponent(this.convertToString(value[k]));
1070
+ if (value === null && routingParameter.in === 'Path')
1071
+ throw new Error('Error trying to call [' + connection.url + restMappingFunction.path + ']. The parameter [' + routingParameter.name + '] is mandatory.');
1072
+ if (value !== null && value !== undefined) {
1073
+ if (routingParameter.in === 'Path') {
1074
+ requestUrl = requestUrl.split('{' + routingParameter.name + '}').join(encodeURIComponent(this.convertToString(value)));
1075
+ }
1076
+ else if (routingParameter.in === 'Query') {
1077
+ if (Array.isArray(value)) {
1078
+ for (let k = 0; k < value.length; k++) {
1079
+ requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(routingParameter.name) + '=' + encodeURIComponent(this.convertToString(value[k]));
1080
+ isFirstQueryParameter = false;
1081
+ }
1082
+ }
1083
+ else {
1084
+ requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(routingParameter.name) + '=' + encodeURIComponent(this.convertToString(value));
1079
1085
  isFirstQueryParameter = false;
1080
1086
  }
1081
1087
  }
1082
- else {
1083
- requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(routingParameter.name) + '=' + encodeURIComponent(this.convertToString(value));
1084
- isFirstQueryParameter = false;
1088
+ else if (routingParameter.in === 'Header') {
1089
+ requestOptions.headers[routingParameter.name] = this.convertToString(value);
1090
+ }
1091
+ else if (routingParameter.in === 'Body') {
1092
+ requestOptions.body = JSON.stringify(value);
1085
1093
  }
1086
- }
1087
- else if (routingParameter.in === 'Header') {
1088
- requestOptions.headers[routingParameter.name] = this.convertToString(value);
1089
- }
1090
- else if (routingParameter.in === 'Body') {
1091
- requestOptions.body = JSON.stringify(value);
1092
1094
  }
1093
1095
  }
1094
1096
  }
1095
- }
1096
- if (restMappingFunction.security) {
1097
- let securityApplied = false;
1098
- for (let i = 0; i < restMappingFunction.security.length; i++) {
1099
- if (!securityApplied) {
1100
- let securityItem = restMappingFunction.security[i];
1101
- let securityItemOk = true;
1102
- let securityItemValues = [];
1103
- for (let j = 0; j < securityItem.length; j++) {
1104
- let securityConditionItem = securityItem[j];
1105
- let value = null;
1106
- switch (securityConditionItem.source) {
1107
- case 'ConfigParameter': {
1108
- value = configParameters[securityConditionItem.configParameterName];
1109
- break;
1110
- }
1111
- case 'AccessToken': {
1112
- const SESSION_STATE = securityService.getCookieName('session_state')
1113
- let sessionState = request.state[SESSION_STATE];
1114
- // For backward compatibility with previous versions, the session_state is searched if the name of the configured cookie was not found.
1115
- if (!sessionState) {
1116
- sessionState = request.state['session_state'];
1117
- }
1118
- // If sessionState still does not exists, then token is on the header as it should
1119
- // Removed since sessionState is now also required in Azure
1120
- // if(!sessionState) {
1121
- // value = await securityService.extractTokenhNoDecode(request);
1122
- // break;
1123
- // }
1124
- // added request on getUseToken in case we use hapi modules full stack
1125
- const token = await securityService.getUseToken(sessionState, request);
1126
- if (token) {
1127
- value = token;
1128
- } else {
1129
- const ACCESS_TOKEN = securityService.getCookieName('access_token')
1130
- value = request.state[ACCESS_TOKEN];
1131
- }
1132
- break;
1133
- }
1134
- case 'Cookie': {
1135
- value = request.state[securityConditionItem.cookieName];
1136
- break;
1137
- }
1138
- case 'CallVariable': {
1139
- value = callContext.callVariables[securityConditionItem.callVariableName];
1140
- break;
1141
- }
1142
- }
1143
- if (value)
1144
- securityItemValues.push(value);
1145
- else
1146
- securityItemOk = false;
1147
- }
1148
- if (securityItemOk) {
1097
+ if (restMappingFunction.security) {
1098
+ let securityApplied = false;
1099
+ for (let i = 0; i < restMappingFunction.security.length; i++) {
1100
+ if (!securityApplied) {
1101
+ let securityItem = restMappingFunction.security[i];
1102
+ let securityItemOk = true;
1103
+ let securityItemValues = [];
1149
1104
  for (let j = 0; j < securityItem.length; j++) {
1150
1105
  let securityConditionItem = securityItem[j];
1151
- let value = securityItemValues[j];
1152
- switch (securityConditionItem.securityType) {
1153
- case 'ApiKey': {
1154
- switch (securityConditionItem.apiKeyIn) {
1155
- case 'Query': {
1156
- requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(securityConditionItem.apiKeyName) + '=' + encodeURIComponent(value);
1157
- isFirstQueryParameter = false;
1158
- break;
1159
- }
1160
- case 'Header': {
1161
- requestOptions.headers[securityConditionItem.apiKeyName] = value;
1162
- break;
1163
- }
1106
+ let value = null;
1107
+ switch (securityConditionItem.source) {
1108
+ case 'ConfigParameter': {
1109
+ value = configParameters[securityConditionItem.configParameterName];
1110
+ break;
1111
+ }
1112
+ case 'AccessToken': {
1113
+ const SESSION_STATE = securityService.getCookieName('session_state')
1114
+ let sessionState = request.state[SESSION_STATE];
1115
+ // For backward compatibility with previous versions, the session_state is searched if the name of the configured cookie was not found.
1116
+ if (!sessionState) {
1117
+ sessionState = request.state['session_state'];
1118
+ }
1119
+ // If sessionState still does not exists, then token is on the header as it should
1120
+ // Removed since sessionState is now also required in Azure
1121
+ // if(!sessionState) {
1122
+ // value = await securityService.extractTokenhNoDecode(request);
1123
+ // break;
1124
+ // }
1125
+ // added request on getUseToken in case we use hapi modules full stack
1126
+ const token = await securityService.getUseToken(sessionState, request);
1127
+ if (token) {
1128
+ value = token;
1129
+ } else {
1130
+ const ACCESS_TOKEN = securityService.getCookieName('access_token')
1131
+ value = request.state[ACCESS_TOKEN];
1164
1132
  }
1165
1133
  break;
1166
1134
  }
1167
- case 'BasicAuth': {
1168
- requestOptions.headers['Authorization'] = 'Basic ' + Buffer.from(value.user + ':' + value.password, 'ascii').toString('base64');
1135
+ case 'Cookie': {
1136
+ value = request.state[securityConditionItem.cookieName];
1169
1137
  break;
1170
1138
  }
1171
- case 'BearerToken': {
1172
- requestOptions.headers['Authorization'] = 'Bearer ' + value;
1139
+ case 'CallVariable': {
1140
+ value = callContext.callVariables[securityConditionItem.callVariableName];
1173
1141
  break;
1174
1142
  }
1175
1143
  }
1144
+ if (value)
1145
+ securityItemValues.push(value);
1146
+ else
1147
+ securityItemOk = false;
1148
+ }
1149
+ if (securityItemOk) {
1150
+ for (let j = 0; j < securityItem.length; j++) {
1151
+ let securityConditionItem = securityItem[j];
1152
+ let value = securityItemValues[j];
1153
+ switch (securityConditionItem.securityType) {
1154
+ case 'ApiKey': {
1155
+ switch (securityConditionItem.apiKeyIn) {
1156
+ case 'Query': {
1157
+ requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(securityConditionItem.apiKeyName) + '=' + encodeURIComponent(value);
1158
+ isFirstQueryParameter = false;
1159
+ break;
1160
+ }
1161
+ case 'Header': {
1162
+ requestOptions.headers[securityConditionItem.apiKeyName] = value;
1163
+ break;
1164
+ }
1165
+ }
1166
+ break;
1167
+ }
1168
+ case 'BasicAuth': {
1169
+ requestOptions.headers['Authorization'] = 'Basic ' + Buffer.from(value.user + ':' + value.password, 'ascii').toString('base64');
1170
+ break;
1171
+ }
1172
+ case 'BearerToken': {
1173
+ requestOptions.headers['Authorization'] = 'Bearer ' + value;
1174
+ break;
1175
+ }
1176
+ }
1177
+ }
1178
+ securityApplied = true;
1176
1179
  }
1177
- securityApplied = true;
1178
1180
  }
1179
1181
  }
1180
1182
  }
1181
- }
1182
- securityService.validateSecureRequest(request)
1183
- // The following IF code block should not exists. Only for propagating without properly configuring it the suite.
1184
- let propagateAuthToken = process.env.blz_propagateAuthToken;
1185
- if(propagateAuthToken) {
1186
- // check if the system is to be ignored for the redirection of the Security token
1187
- let propagateAuthTokenIgnoreSystems = process.env.blz_propagateAuthTokenIgnoreSystems;
1188
- const ignoredSystems = propagateAuthTokenIgnoreSystems ? propagateAuthTokenIgnoreSystems.split(",") : [];
1189
- const ignorePropagation = ignoredSystems.includes(connection.name);
1190
- // If system is included in the list, ignore propagation. If not, propagate
1191
- if(!ignorePropagation) {
1192
- let value = null;
1193
- const SESSION_STATE = securityService.getCookieName('session_state')
1194
- // request object comes null when called in a microservice. if it exists it is inside the frontend.
1195
- if (request){
1196
- let sessionState = request.state[SESSION_STATE];
1197
- // For backward compatibility with previous versions, the session_state is searched if the name of the configured cookie was not found.
1198
- if (!sessionState) {
1199
- sessionState = request.state['session_state'];
1200
- }
1201
- // If sessionState still does not exists, then it is on the header
1202
- if(!sessionState) {
1203
- value = await securityService.extractTokenhNoDecode(request);
1204
- } else {
1205
- // added request on getUseToken in case we use hapi modules full stack
1206
- const token = await securityService.getUseToken(sessionState, request);
1207
- if (token) {
1208
- value = token;
1183
+ securityService.validateSecureRequest(request)
1184
+ // The following IF code block should not exists. Only for propagating without properly configuring it the suite.
1185
+ let propagateAuthToken = process.env.blz_propagateAuthToken;
1186
+ if (propagateAuthToken) {
1187
+ // check if the system is to be ignored for the redirection of the Security token
1188
+ let propagateAuthTokenIgnoreSystems = process.env.blz_propagateAuthTokenIgnoreSystems;
1189
+ const ignoredSystems = propagateAuthTokenIgnoreSystems ? propagateAuthTokenIgnoreSystems.split(",") : [];
1190
+ const ignorePropagation = ignoredSystems.includes(connection.name);
1191
+ // If system is included in the list, ignore propagation. If not, propagate
1192
+ if (!ignorePropagation) {
1193
+ let value = null;
1194
+ const SESSION_STATE = securityService.getCookieName('session_state')
1195
+ // request object comes null when called in a microservice. if it exists it is inside the frontend.
1196
+ if (request) {
1197
+ let sessionState = request.state[SESSION_STATE];
1198
+ // For backward compatibility with previous versions, the session_state is searched if the name of the configured cookie was not found.
1199
+ if (!sessionState) {
1200
+ sessionState = request.state['session_state'];
1201
+ }
1202
+ // If sessionState still does not exists, then it is on the header
1203
+ if (!sessionState) {
1204
+ value = await securityService.extractTokenhNoDecode(request);
1209
1205
  } else {
1210
- const ACCESS_TOKEN = securityService.getCookieName('access_token')
1211
- value = request.state[ACCESS_TOKEN];
1206
+ // added request on getUseToken in case we use hapi modules full stack
1207
+ const token = await securityService.getUseToken(sessionState, request);
1208
+ if (token) {
1209
+ value = token;
1210
+ } else {
1211
+ const ACCESS_TOKEN = securityService.getCookieName('access_token')
1212
+ value = request.state[ACCESS_TOKEN];
1213
+ }
1212
1214
  }
1215
+ } else if (callContext && callContext.callVariables && callContext.callVariables['CallVariable-BearerToken']) {
1216
+ // if i am working from inside a microservice. where should i get the token from?
1217
+ // artificial call variable used to store token
1218
+ value = callContext.callVariables['CallVariable-BearerToken'];
1219
+ } else {
1220
+ value = null;
1213
1221
  }
1214
- } else if (callContext && callContext.callVariables && callContext.callVariables['CallVariable-BearerToken']) {
1215
- // if i am working from inside a microservice. where should i get the token from?
1216
- // artificial call variable used to store token
1217
- value = callContext.callVariables['CallVariable-BearerToken'];
1218
- } else {
1219
- value = null;
1220
- }
1221
- switch (propagateAuthToken){
1222
- case 'BearerToken': {
1223
- if (/^Bearer /.test(value)) {
1224
- requestOptions.headers['Authorization'] = value;
1225
- } else {
1226
- requestOptions.headers['Authorization'] = 'Bearer ' + value;
1222
+ switch (propagateAuthToken) {
1223
+ case 'BearerToken': {
1224
+ if (/^Bearer /.test(value)) {
1225
+ requestOptions.headers['Authorization'] = value;
1226
+ } else {
1227
+ requestOptions.headers['Authorization'] = 'Bearer ' + value;
1228
+ }
1229
+ break;
1227
1230
  }
1228
- break;
1231
+ default:
1232
+ break;
1229
1233
  }
1230
- default:
1231
- break;
1232
1234
  }
1233
1235
  }
1234
- }
1235
- if (requestUrl.match(/https.*/)) {
1236
- requestOptions = {
1237
- ...requestOptions,
1238
- https: {
1239
- requestCert: true, // Request a certificate from clients that connect and attempt to verify that certificate.
1240
- rejectUnauthorized: false, // The server will reject any connection which is not authorized with the list of supplied CAs.
1241
- agent: false // Is responsible for managing connection persistence and reuse for https clients.
1242
- }
1243
- };
1244
- }
1245
- let traceStartTime = Date.now();
1246
- const dateISOString = new Date().toISOString();
1247
- if (typeof _externalRestCallId === 'undefined')
1248
- _externalRestCallId = 1;
1249
- else
1250
- _externalRestCallId++;
1251
- const traceId = _externalRestCallId;
1252
- if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalRestCalls === 'true') {
1253
- console.log((callContext.devTime ? '' : dateISOString + ' | ') + 'EXTERNAL REST CALL (' + traceId + ') | ' + connection.name + ' | ' + requestOptions.method + ' ' + requestUrl + ' | HEADERS: ' + JSON.stringify(requestOptions.headers) + (requestOptions.body ? ' | BODY: ' + requestOptions.body : ''));
1254
- }
1255
- try {
1256
-
1257
- const response = await Got(requestUrl, requestOptions);
1258
- const responseTime = Date.now() - traceStartTime;
1259
- if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalRestCalls === 'true') {
1260
- console.log((callContext.devTime ? '' : dateISOString + ' | ') + 'EXTERNAL REST CALL (' + traceId + ') | ' + connection.name + ' | STATUS: ' + response.statusCode + ' | BODY: ' + response.body + ' | TIME: ' + responseTime + ' milliseconds');
1236
+ if (requestUrl.match(/https.*/)) {
1237
+ requestOptions = {
1238
+ ...requestOptions,
1239
+ https: {
1240
+ requestCert: true, // Request a certificate from clients that connect and attempt to verify that certificate.
1241
+ rejectUnauthorized: false, // The server will reject any connection which is not authorized with the list of supplied CAs.
1242
+ agent: false // Is responsible for managing connection persistence and reuse for https clients.
1243
+ }
1244
+ };
1261
1245
  }
1262
- // These 2 are added for the PostProcessRequest event
1263
- if (request) {
1264
- request.httpRequestLog = {url: request.path, method: requestOptions.method, headers: Object.entries(requestOptions.headers), body: requestOptions.body, clientInfo: request.clientInfo }
1265
- request.httpResponseLog = { status: response.statusCode, headers: Object.entries(response.headers), body: response.body}
1246
+ let traceStartTime = Date.now();
1247
+ const dateISOString = new Date().toISOString();
1248
+ if (typeof _externalRestCallId === 'undefined')
1249
+ _externalRestCallId = 1;
1250
+ else
1251
+ _externalRestCallId++;
1252
+ const traceId = _externalRestCallId;
1253
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalRestCalls === 'true') {
1254
+ console.log((callContext.devTime ? '' : dateISOString + ' | ') + 'EXTERNAL REST CALL (' + traceId + ') | ' + connection.name + ' | ' + requestOptions.method + ' ' + requestUrl + ' | HEADERS: ' + JSON.stringify(requestOptions.headers) + (requestOptions.body ? ' | BODY: ' + requestOptions.body : ''));
1266
1255
  }
1267
- let httpErrorCode = this.httpErrors[response.statusCode];
1268
- // If the request has the header x-navigation-info, it means that the request is a navigation request and the response should be saved in the security service.
1269
- if (request && request.headers['x-navigation-info']) {
1270
- try{
1271
- const clientNavigation = request.headers['x-navigation-info'];
1272
- const userInfo = await securityService.getUserInfo(request)
1273
- const config = configService.getConfig()
1274
- securityService.pushNavigation({
1275
- app: config.buildSystem.name,
1276
- username: userInfo.user_name,
1277
- date: dateISOString,
1278
- client: {
1279
- nav: JSON.parse(Buffer.from(clientNavigation, 'base64').toString('utf-8')),
1280
- ip: request.headers['x-forwarded-for'] || request.info.remoteAddress,
1281
- userAgent: request.headers['user-agent'],
1282
- lang: request.headers['accept-language'],
1283
- host: request.info.host,
1284
- protocol: request.headers['x-forwarded-proto'] || request.server.info.protocol,
1285
- id: request.info.id
1286
- },
1287
- request: {
1288
- traceId: traceId,
1289
- traceStartTime: traceStartTime,
1290
- connection: connection.name,
1291
- method: request.method,
1292
- path: request.path,
1293
- url: requestUrl,
1294
- body: requestOptions.body
1295
- },
1296
- response: {
1297
- status: response.statusCode,
1298
- body: response.body,
1299
- time: responseTime
1300
- }
1301
- });
1302
- } catch(error) {
1303
- console.error('Error saving navigation in security service', error);
1256
+ try {
1257
+
1258
+ const response = await Got(requestUrl, requestOptions);
1259
+ const responseTime = Date.now() - traceStartTime;
1260
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalRestCalls === 'true') {
1261
+ console.log((callContext.devTime ? '' : dateISOString + ' | ') + 'EXTERNAL REST CALL (' + traceId + ') | ' + connection.name + ' | STATUS: ' + response.statusCode + ' | BODY: ' + response.body + ' | TIME: ' + responseTime + ' milliseconds');
1304
1262
  }
1305
- }
1306
-
1307
- if (httpErrorCode) {
1308
- let err = new Error();
1309
- err.code = httpErrorCode;
1310
- try {
1311
- if (process.env.NODE_ENV === 'production') {
1312
- const data = {
1313
- requestUrl: requestUrl,
1314
- responseStatus: response.statusCode,
1315
- responseBody: tryParse(response.body, response.body)
1316
- }
1317
- console.log(`Handle error ${err.code}: ${data}`)
1318
- } else {
1319
- err.data = {
1320
- requestUrl: requestUrl,
1321
- responseStatus: response.statusCode,
1322
- responseBody: tryParse(response.body, response.body)
1323
- };
1324
- }
1325
- } catch (ex) {
1326
- console.log(`Handle error ${err.code}: ${ex}`)
1263
+ // These 2 are added for the PostProcessRequest event
1264
+ if (request) {
1265
+ request.httpRequestLog = { url: request.path, method: requestOptions.method, headers: Object.entries(requestOptions.headers), body: requestOptions.body, clientInfo: request.clientInfo }
1266
+ request.httpResponseLog = { status: response.statusCode, headers: Object.entries(response.headers), body: response.body }
1327
1267
  }
1328
- throw err;
1329
- }
1330
- else {
1331
- return tryParse(response.body, response.body)
1332
- }
1333
- } catch (error) {
1334
- if (error.code == 'ETIMEDOUT') {
1335
- // Here we check for the timeout originated from the request options timeout added for the Got request.
1336
- // All other errors should be handled in finally.
1337
- // response is destroyed if it timed out
1338
- let err = new Error();
1339
- err.code = 'GatewayTimeout';
1340
- err.data = {
1341
- requestUrl: requestUrl,
1342
- responseStatus: this.httpStatuses.GatewayTimeout,
1343
- responseBody: ""
1344
- };
1345
- console.error(err);
1346
- throw err;
1347
- } else {
1348
- console.error(error);
1349
- throw error;
1350
- }
1351
- }
1352
- },
1353
- callSoap: async function (connection, soapMapping, functionName, values, request, configParameters, callContext) {
1354
- let soapClient = await Soap.createClientAsync(soapMapping.wsdlFileName, { endpoint: connection.url });
1355
- if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalSoapCalls === 'true') {
1356
- let traceId = null;
1357
- let traceStartTime = null;
1358
- soapClient.on('request', function (xml) {
1359
- if (typeof _externalSoapCallId === 'undefined')
1360
- _externalSoapCallId = 1;
1361
- else
1362
- _externalSoapCallId++;
1363
- traceId = _externalSoapCallId;
1364
- traceStartTime = Date.now();
1365
- console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'EXTERNAL SOAP CALL (' + traceId + ') | ' + connection.name + ' | POST ' + connection.url + ' | HEADERS: {} | BODY: ' + xml);
1366
- }.bind(this));
1367
- soapClient.on('response', function (body, response) {
1368
- console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'EXTERNAL SOAP CALL (' + traceId + ') | ' + connection.name + ' | STATUS: ' + response.statusCode + ' | BODY: ' + response.body + ' | TIME: ' + (Date.now() - traceStartTime) + ' milliseconds');
1369
- }.bind(this));
1370
- }
1371
- if (soapMapping.security) {
1372
- let value = null;
1373
- switch (soapMapping.security.source) {
1374
- case 'ConfigParameter': {
1375
- value = configParameters[soapMapping.security.configParameterName];
1376
- break;
1268
+ let httpErrorCode = this.httpErrors[response.statusCode];
1269
+ // If the request has the header x-navigation-info, it means that the request is a navigation request and the response should be saved in the security service.
1270
+ if (request && request.headers['x-navigation-info']) {
1271
+ try {
1272
+ const clientNavigation = request.headers['x-navigation-info'];
1273
+ const userInfo = await securityService.getUserInfo(request)
1274
+ const config = configService.getConfig()
1275
+ securityService.pushNavigation({
1276
+ app: config.buildSystem.name,
1277
+ username: userInfo.user_name,
1278
+ date: dateISOString,
1279
+ client: {
1280
+ nav: JSON.parse(Buffer.from(clientNavigation, 'base64').toString('utf-8')),
1281
+ ip: request.headers['x-forwarded-for'] || request.info.remoteAddress,
1282
+ userAgent: request.headers['user-agent'],
1283
+ lang: request.headers['accept-language'],
1284
+ host: request.info.host,
1285
+ protocol: request.headers['x-forwarded-proto'] || request.server.info.protocol,
1286
+ id: request.info.id
1287
+ },
1288
+ request: {
1289
+ traceId: traceId,
1290
+ traceStartTime: traceStartTime,
1291
+ connection: connection.name,
1292
+ method: request.method,
1293
+ path: request.path,
1294
+ url: requestUrl,
1295
+ body: requestOptions.body
1296
+ },
1297
+ response: {
1298
+ status: response.statusCode,
1299
+ body: response.body,
1300
+ time: responseTime
1301
+ }
1302
+ });
1303
+ } catch (error) {
1304
+ console.error('Error saving navigation in security service', error);
1305
+ }
1377
1306
  }
1378
- case 'AccessToken': {
1379
- value = request.state['access_token'];
1380
- break;
1307
+
1308
+ if (httpErrorCode) {
1309
+ let err = new Error();
1310
+ err.code = httpErrorCode;
1311
+ try {
1312
+ if (process.env.NODE_ENV === 'production') {
1313
+ const data = {
1314
+ requestUrl: requestUrl,
1315
+ responseStatus: response.statusCode,
1316
+ responseBody: tryParse(response.body, response.body)
1317
+ }
1318
+ console.log(`Handle error ${err.code}: ${data}`)
1319
+ } else {
1320
+ err.data = {
1321
+ requestUrl: requestUrl,
1322
+ responseStatus: response.statusCode,
1323
+ responseBody: tryParse(response.body, response.body)
1324
+ };
1325
+ }
1326
+ } catch (ex) {
1327
+ console.log(`Handle error ${err.code}: ${ex}`)
1328
+ }
1329
+ throw err;
1381
1330
  }
1382
- case 'Cookie': {
1383
- value = request.state[soapMapping.security.cookieName];
1384
- break;
1331
+ else {
1332
+ return tryParse(response.body, response.body)
1385
1333
  }
1386
- case 'CallVariable': {
1387
- value = callContext.callVariables[soapMapping.security.callVariableName];
1388
- break;
1334
+ } catch (error) {
1335
+ if (error.code == 'ETIMEDOUT') {
1336
+ // Here we check for the timeout originated from the request options timeout added for the Got request.
1337
+ // All other errors should be handled in finally.
1338
+ // response is destroyed if it timed out
1339
+ let err = new Error();
1340
+ err.code = 'GatewayTimeout';
1341
+ err.data = {
1342
+ requestUrl: requestUrl,
1343
+ responseStatus: this.httpStatuses.GatewayTimeout,
1344
+ responseBody: ""
1345
+ };
1346
+ console.error(err);
1347
+ throw err;
1348
+ } else {
1349
+ console.error(error);
1350
+ throw error;
1389
1351
  }
1390
1352
  }
1391
- switch (soapMapping.security.securityType) {
1392
- case 'BasicAuth': {
1393
- soapClient.setSecurity(new Soap.BasicAuthSecurity(value.user, value.password));
1394
- break;
1353
+ },
1354
+ callSoap: async function (connection, soapMapping, functionName, values, request, configParameters, callContext) {
1355
+ let soapClient = await Soap.createClientAsync(soapMapping.wsdlFileName, { endpoint: connection.url });
1356
+ if (process.env.blz_traceAll === 'true' || process.env.blz_traceExternalSoapCalls === 'true') {
1357
+ let traceId = null;
1358
+ let traceStartTime = null;
1359
+ soapClient.on('request', function (xml) {
1360
+ if (typeof _externalSoapCallId === 'undefined')
1361
+ _externalSoapCallId = 1;
1362
+ else
1363
+ _externalSoapCallId++;
1364
+ traceId = _externalSoapCallId;
1365
+ traceStartTime = Date.now();
1366
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'EXTERNAL SOAP CALL (' + traceId + ') | ' + connection.name + ' | POST ' + connection.url + ' | HEADERS: {} | BODY: ' + xml);
1367
+ }.bind(this));
1368
+ soapClient.on('response', function (body, response) {
1369
+ console.log((callContext.devTime ? '' : new Date().toISOString() + ' | ') + 'EXTERNAL SOAP CALL (' + traceId + ') | ' + connection.name + ' | STATUS: ' + response.statusCode + ' | BODY: ' + response.body + ' | TIME: ' + (Date.now() - traceStartTime) + ' milliseconds');
1370
+ }.bind(this));
1371
+ }
1372
+ if (soapMapping.security) {
1373
+ let value = null;
1374
+ switch (soapMapping.security.source) {
1375
+ case 'ConfigParameter': {
1376
+ value = configParameters[soapMapping.security.configParameterName];
1377
+ break;
1378
+ }
1379
+ case 'AccessToken': {
1380
+ value = request.state['access_token'];
1381
+ break;
1382
+ }
1383
+ case 'Cookie': {
1384
+ value = request.state[soapMapping.security.cookieName];
1385
+ break;
1386
+ }
1387
+ case 'CallVariable': {
1388
+ value = callContext.callVariables[soapMapping.security.callVariableName];
1389
+ break;
1390
+ }
1395
1391
  }
1396
- case 'BearerToken': {
1397
- soapClient.setSecurity(new Soap.BearerSecurity(value));
1398
- break;
1392
+ switch (soapMapping.security.securityType) {
1393
+ case 'BasicAuth': {
1394
+ soapClient.setSecurity(new Soap.BasicAuthSecurity(value.user, value.password));
1395
+ break;
1396
+ }
1397
+ case 'BearerToken': {
1398
+ soapClient.setSecurity(new Soap.BearerSecurity(value));
1399
+ break;
1400
+ }
1399
1401
  }
1400
1402
  }
1401
- }
1402
- let soapFunctionName = functionName + 'Async';
1403
- if (soapClient[soapFunctionName]) {
1404
- let result = (await soapClient[soapFunctionName](values.request))[0];
1405
- if (isSoapNull(result))
1406
- return null;
1407
- fixSoapValue(result);
1408
- return result;
1409
- }
1410
- let soapFunctionNameSimplified = simplifyName(soapFunctionName);
1411
- for (let key in soapClient) {
1412
- if (soapFunctionNameSimplified === simplifyName(key)) {
1413
- let result = (await soapClient[key](values.request))[0];
1403
+ let soapFunctionName = functionName + 'Async';
1404
+ if (soapClient[soapFunctionName]) {
1405
+ let result = (await soapClient[soapFunctionName](values.request))[0];
1414
1406
  if (isSoapNull(result))
1415
1407
  return null;
1416
1408
  fixSoapValue(result);
1417
1409
  return result;
1418
1410
  }
1419
- }
1420
- throw new Error('Soap Function "' + soapFunctionName + '" not recognized.');
1421
- },
1422
- getFullUrl(request) {
1423
- let { protocol, host, pathname } = request.url;
1424
- protocol = ((request.headers['x-forwarded-proto'] || protocol).match(/[a-z]+/gim) || ['https'])[0];
1425
- return `${protocol}://${request.headers['x-forwarded-host'] || host}${pathname}`;
1426
- },
1427
- setCache(key, value, maxAge) {
1428
- cache.set(key, value, maxAge);
1429
- },
1430
- getCache(key) {
1431
- return cache.get(key);
1432
- },
1433
- existsPath: async function (sourcePath) {
1434
- const fullPath = this.resolvePath(sourcePath)
1435
- return new Promise((resolve) => {
1436
- Fs.access(fullPath, (err) => {
1437
- if (err) {
1438
- resolve(false)
1439
- } else {
1440
- resolve(true)
1411
+ let soapFunctionNameSimplified = simplifyName(soapFunctionName);
1412
+ for (let key in soapClient) {
1413
+ if (soapFunctionNameSimplified === simplifyName(key)) {
1414
+ let result = (await soapClient[key](values.request))[0];
1415
+ if (isSoapNull(result))
1416
+ return null;
1417
+ fixSoapValue(result);
1418
+ return result;
1441
1419
  }
1420
+ }
1421
+ throw new Error('Soap Function "' + soapFunctionName + '" not recognized.');
1422
+ },
1423
+ getFullUrl(request) {
1424
+ let { protocol, host, pathname } = request.url;
1425
+ protocol = ((request.headers['x-forwarded-proto'] || protocol).match(/[a-z]+/gim) || ['https'])[0];
1426
+ return `${protocol}://${request.headers['x-forwarded-host'] || host}${pathname}`;
1427
+ },
1428
+ setCache(key, value, maxAge) {
1429
+ cache.set(key, value, maxAge);
1430
+ },
1431
+ getCache(key) {
1432
+ return cache.get(key);
1433
+ },
1434
+ existsPath: async function (sourcePath) {
1435
+ const fullPath = this.resolvePath(sourcePath)
1436
+ return new Promise((resolve) => {
1437
+ Fs.access(fullPath, (err) => {
1438
+ if (err) {
1439
+ resolve(false)
1440
+ } else {
1441
+ resolve(true)
1442
+ }
1443
+ })
1442
1444
  })
1443
- })
1444
- },
1445
- resolvePath: function (source) {
1446
- const _source = source.trim()
1447
- if (_source.startsWith('.')) {
1448
- return Path.join(process.cwd(), source)
1449
- }
1450
- if (_source.startsWith('~')) {
1451
- return _source.replace('~', process.env.HOME)
1452
- }
1453
- return source
1454
- },
1455
- readFile: async function(filePath) {
1456
- const fullPath = this.resolvePath(filePath)
1457
- if (!await this.existsPath(fullPath)) {
1458
- return null
1459
- }
1460
- return new Promise((resolve, reject) => {
1461
- Fs.readFile(fullPath, (err, data) => err ? reject(err) : resolve(data.toString('utf8')))
1462
- })
1463
- },
1464
- safeRequire,
1465
- getHealthStatus
1445
+ },
1446
+ resolvePath: function (source) {
1447
+ const _source = source.trim()
1448
+ if (_source.startsWith('.')) {
1449
+ return Path.join(process.cwd(), source)
1450
+ }
1451
+ if (_source.startsWith('~')) {
1452
+ return _source.replace('~', process.env.HOME)
1453
+ }
1454
+ return source
1455
+ },
1456
+ readFile: async function (filePath) {
1457
+ const fullPath = this.resolvePath(filePath)
1458
+ if (!await this.existsPath(fullPath)) {
1459
+ return null
1460
+ }
1461
+ return new Promise((resolve, reject) => {
1462
+ Fs.readFile(fullPath, (err, data) => err ? reject(err) : resolve(data.toString('utf8')))
1463
+ })
1464
+ },
1465
+ safeRequire,
1466
+ getHealthStatus
1467
+ }
1466
1468
  };