@blazedpath/commons 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +3 -0
  2. package/blz-base/health/index.js +215 -0
  3. package/blz-base/index.js +1466 -0
  4. package/blz-cache/LruCache.js +44 -0
  5. package/blz-cache/index.js +29 -0
  6. package/blz-config/index.js +434 -0
  7. package/blz-core/index.js +364 -0
  8. package/blz-cryptography/index.js +54 -0
  9. package/blz-datetimes/index.js +356 -0
  10. package/blz-file/example.dat +2545 -0
  11. package/blz-file/fileService.js +205 -0
  12. package/blz-file/index.js +94 -0
  13. package/blz-file/index.test.js +31 -0
  14. package/blz-file/lab.js +33 -0
  15. package/blz-hazelcast/index.js +189 -0
  16. package/blz-hazelcast/lib/credentials.js +25 -0
  17. package/blz-hazelcast/lib/credentialsFactory.js +12 -0
  18. package/blz-hazelcast/lib/hazelcastCache.js +234 -0
  19. package/blz-iterable/index.js +446 -0
  20. package/blz-json-schema/index.js +11 -0
  21. package/blz-jwt/index.js +121 -0
  22. package/blz-kafka/index.js +522 -0
  23. package/blz-math/index.js +131 -0
  24. package/blz-mongodb/index.js +326 -0
  25. package/blz-rds/__test__/scape.test.js +58 -0
  26. package/blz-rds/blz-rds-executor.js +578 -0
  27. package/blz-rds/blz-rds-helper.js +310 -0
  28. package/blz-rds/commands/core/add.js +13 -0
  29. package/blz-rds/commands/core/and.js +18 -0
  30. package/blz-rds/commands/core/asc.js +10 -0
  31. package/blz-rds/commands/core/avg.js +10 -0
  32. package/blz-rds/commands/core/column-ref.js +8 -0
  33. package/blz-rds/commands/core/count-distinct.js +10 -0
  34. package/blz-rds/commands/core/count.js +10 -0
  35. package/blz-rds/commands/core/decimal.js +8 -0
  36. package/blz-rds/commands/core/desc.js +10 -0
  37. package/blz-rds/commands/core/distinct.js +10 -0
  38. package/blz-rds/commands/core/divide.js +11 -0
  39. package/blz-rds/commands/core/embedded-exists.js +17 -0
  40. package/blz-rds/commands/core/embedded-select.js +17 -0
  41. package/blz-rds/commands/core/equals.js +9 -0
  42. package/blz-rds/commands/core/false.js +8 -0
  43. package/blz-rds/commands/core/greater-or-equal.js +9 -0
  44. package/blz-rds/commands/core/greater.js +9 -0
  45. package/blz-rds/commands/core/in.js +9 -0
  46. package/blz-rds/commands/core/integer.js +8 -0
  47. package/blz-rds/commands/core/is-not-null.js +11 -0
  48. package/blz-rds/commands/core/is-null-or-value.js +10 -0
  49. package/blz-rds/commands/core/is-null.js +11 -0
  50. package/blz-rds/commands/core/less-or-equal.js +9 -0
  51. package/blz-rds/commands/core/less-unary.js +12 -0
  52. package/blz-rds/commands/core/less.js +9 -0
  53. package/blz-rds/commands/core/like.js +12 -0
  54. package/blz-rds/commands/core/max.js +10 -0
  55. package/blz-rds/commands/core/min.js +10 -0
  56. package/blz-rds/commands/core/multiply.js +13 -0
  57. package/blz-rds/commands/core/not-equals.js +9 -0
  58. package/blz-rds/commands/core/not-in.js +9 -0
  59. package/blz-rds/commands/core/not.js +13 -0
  60. package/blz-rds/commands/core/null.js +8 -0
  61. package/blz-rds/commands/core/nvl.js +11 -0
  62. package/blz-rds/commands/core/or.js +13 -0
  63. package/blz-rds/commands/core/parameter.js +34 -0
  64. package/blz-rds/commands/core/remainder.js +16 -0
  65. package/blz-rds/commands/core/string.js +8 -0
  66. package/blz-rds/commands/core/subtract.js +13 -0
  67. package/blz-rds/commands/core/sum.js +10 -0
  68. package/blz-rds/commands/core/true.js +8 -0
  69. package/blz-rds/commands/core/tuple.js +13 -0
  70. package/blz-rds/commands/datetimes/add-days.js +11 -0
  71. package/blz-rds/commands/datetimes/add-hours.js +11 -0
  72. package/blz-rds/commands/datetimes/add-milliseconds.js +11 -0
  73. package/blz-rds/commands/datetimes/add-minutes.js +11 -0
  74. package/blz-rds/commands/datetimes/add-months.js +11 -0
  75. package/blz-rds/commands/datetimes/add-seconds.js +11 -0
  76. package/blz-rds/commands/datetimes/add-years.js +11 -0
  77. package/blz-rds/commands/datetimes/date-diff.js +11 -0
  78. package/blz-rds/commands/datetimes/date.js +12 -0
  79. package/blz-rds/commands/datetimes/datetime-diff.js +11 -0
  80. package/blz-rds/commands/datetimes/datetime.js +15 -0
  81. package/blz-rds/commands/datetimes/day.js +10 -0
  82. package/blz-rds/commands/datetimes/hour.js +10 -0
  83. package/blz-rds/commands/datetimes/millisecond.js +10 -0
  84. package/blz-rds/commands/datetimes/minute.js +10 -0
  85. package/blz-rds/commands/datetimes/month-text.js +10 -0
  86. package/blz-rds/commands/datetimes/month.js +10 -0
  87. package/blz-rds/commands/datetimes/now.js +9 -0
  88. package/blz-rds/commands/datetimes/second.js +10 -0
  89. package/blz-rds/commands/datetimes/subtract-days.js +11 -0
  90. package/blz-rds/commands/datetimes/subtract-hours.js +11 -0
  91. package/blz-rds/commands/datetimes/subtract-milliseconds.js +11 -0
  92. package/blz-rds/commands/datetimes/subtract-minutes.js +11 -0
  93. package/blz-rds/commands/datetimes/subtract-seconds.js +11 -0
  94. package/blz-rds/commands/datetimes/time-diff.js +11 -0
  95. package/blz-rds/commands/datetimes/time.js +13 -0
  96. package/blz-rds/commands/datetimes/today.js +9 -0
  97. package/blz-rds/commands/datetimes/week-day-text.js +10 -0
  98. package/blz-rds/commands/datetimes/week-day.js +10 -0
  99. package/blz-rds/commands/datetimes/week.js +10 -0
  100. package/blz-rds/commands/datetimes/year.js +10 -0
  101. package/blz-rds/commands/math/abs.js +10 -0
  102. package/blz-rds/commands/math/acos.js +10 -0
  103. package/blz-rds/commands/math/asin.js +10 -0
  104. package/blz-rds/commands/math/atan.js +10 -0
  105. package/blz-rds/commands/math/atan2.js +11 -0
  106. package/blz-rds/commands/math/ceil.js +10 -0
  107. package/blz-rds/commands/math/cos.js +10 -0
  108. package/blz-rds/commands/math/cosh.js +10 -0
  109. package/blz-rds/commands/math/exp.js +10 -0
  110. package/blz-rds/commands/math/floor.js +10 -0
  111. package/blz-rds/commands/math/log.js +18 -0
  112. package/blz-rds/commands/math/log10.js +10 -0
  113. package/blz-rds/commands/math/pow.js +11 -0
  114. package/blz-rds/commands/math/random.js +9 -0
  115. package/blz-rds/commands/math/round.js +18 -0
  116. package/blz-rds/commands/math/sign.js +10 -0
  117. package/blz-rds/commands/math/sin.js +10 -0
  118. package/blz-rds/commands/math/sinh.js +10 -0
  119. package/blz-rds/commands/math/sqrt.js +10 -0
  120. package/blz-rds/commands/math/tan.js +10 -0
  121. package/blz-rds/commands/math/tanh.js +10 -0
  122. package/blz-rds/commands/math/trunc.js +18 -0
  123. package/blz-rds/commands/strings/concat.js +20 -0
  124. package/blz-rds/commands/strings/contains.js +12 -0
  125. package/blz-rds/commands/strings/ends-with.js +12 -0
  126. package/blz-rds/commands/strings/index-of.js +11 -0
  127. package/blz-rds/commands/strings/is-null-or-empty.js +11 -0
  128. package/blz-rds/commands/strings/is-null-or-white-space.js +11 -0
  129. package/blz-rds/commands/strings/join.js +22 -0
  130. package/blz-rds/commands/strings/last-index-of.js +11 -0
  131. package/blz-rds/commands/strings/length.js +10 -0
  132. package/blz-rds/commands/strings/pad-left.js +20 -0
  133. package/blz-rds/commands/strings/pad-right.js +20 -0
  134. package/blz-rds/commands/strings/replace.js +12 -0
  135. package/blz-rds/commands/strings/starts-with.js +12 -0
  136. package/blz-rds/commands/strings/substring.js +12 -0
  137. package/blz-rds/commands/strings/to-lower.js +10 -0
  138. package/blz-rds/commands/strings/to-upper.js +10 -0
  139. package/blz-rds/commands/strings/trim-end.js +10 -0
  140. package/blz-rds/commands/strings/trim-start.js +10 -0
  141. package/blz-rds/commands/strings/trim.js +10 -0
  142. package/blz-rds/index.js +744 -0
  143. package/blz-rds-mysql/base.js +857 -0
  144. package/blz-rds-mysql/connection-manager.js +129 -0
  145. package/blz-rds-mysql/execute-bulk-insert.js +35 -0
  146. package/blz-rds-mysql/execute-bulk-merge.js +45 -0
  147. package/blz-rds-mysql/execute-non-query.js +34 -0
  148. package/blz-rds-mysql/execute-query.js +50 -0
  149. package/blz-rds-mysql/index.js +41 -0
  150. package/blz-rds-mysql/stored-procedure.js +207 -0
  151. package/blz-rds-mysql/syntaxis.json +114 -0
  152. package/blz-rds-mysqlx/base.js +846 -0
  153. package/blz-rds-mysqlx/connection-manager.js +141 -0
  154. package/blz-rds-mysqlx/execute-bulk-insert.js +35 -0
  155. package/blz-rds-mysqlx/execute-bulk-merge.js +45 -0
  156. package/blz-rds-mysqlx/execute-non-query.js +29 -0
  157. package/blz-rds-mysqlx/execute-query.js +39 -0
  158. package/blz-rds-mysqlx/index.js +41 -0
  159. package/blz-rds-mysqlx/stored-procedure.js +179 -0
  160. package/blz-rds-mysqlx/syntaxis.json +105 -0
  161. package/blz-rds-oracle/index.js +540 -0
  162. package/blz-rds-oracle/syntaxis.json +112 -0
  163. package/blz-rds-postgres/base.js +861 -0
  164. package/blz-rds-postgres/connection-manager.js +225 -0
  165. package/blz-rds-postgres/execute-bulk-insert.js +81 -0
  166. package/blz-rds-postgres/execute-bulk-merge.js +93 -0
  167. package/blz-rds-postgres/execute-non-query.js +23 -0
  168. package/blz-rds-postgres/execute-query.js +37 -0
  169. package/blz-rds-postgres/index.js +41 -0
  170. package/blz-rds-postgres/result-set.js +51 -0
  171. package/blz-rds-postgres/stored-procedure.js +116 -0
  172. package/blz-rds-postgres/syntaxis.json +114 -0
  173. package/blz-redis/index.js +217 -0
  174. package/blz-redis/lib/redisCache.js +265 -0
  175. package/blz-regex/index.js +25 -0
  176. package/blz-security/.eslintrc.js +15 -0
  177. package/blz-security/__test__/AuthorizationKpn.yaml +1043 -0
  178. package/blz-security/__test__/FinancingSetting.yaml +177 -0
  179. package/blz-security/__test__/KpnConfigPortal.yaml +330 -0
  180. package/blz-security/__test__/OrderManagement.yaml +5190 -0
  181. package/blz-security/__test__/Security.yaml +128 -0
  182. package/blz-security/__test__/autorization.test.js +105 -0
  183. package/blz-security/__test__/orderManagement.test.js +26 -0
  184. package/blz-security/__test__/secureUrl.test.js +79 -0
  185. package/blz-security/__test__/solveMergeRule.test.js +109 -0
  186. package/blz-security/__test__/sqlInjectionGuard.test.js +203 -0
  187. package/blz-security/__test__/xssGuard.test.js +204 -0
  188. package/blz-security/authorizationService.js +536 -0
  189. package/blz-security/config/global.js +8 -0
  190. package/blz-security/config/welcome +8 -0
  191. package/blz-security/doc/README.md +75 -0
  192. package/blz-security/filescanner/index.js +46 -0
  193. package/blz-security/helpers/consts.js +229 -0
  194. package/blz-security/helpers/utils.js +267 -0
  195. package/blz-security/implementations/cache.js +90 -0
  196. package/blz-security/implementations/oidc.js +404 -0
  197. package/blz-security/implementations/pkceCacheStore.js +23 -0
  198. package/blz-security/implementations/saml.js +10 -0
  199. package/blz-security/implementations/uma.js +63 -0
  200. package/blz-security/implementations/webAuthn.js +9 -0
  201. package/blz-security/implementations/wstg.js +72 -0
  202. package/blz-security/index.js +77 -0
  203. package/blz-security/lab/index.js +27 -0
  204. package/blz-security/middleware/HapiServerAzureAd.js +641 -0
  205. package/blz-security/middleware/HapiServerKeycloak.js +840 -0
  206. package/blz-security/middleware/HapiServerSimToken.js +247 -0
  207. package/blz-security/middleware/hapi.js +515 -0
  208. package/blz-security/middleware/hapiServer.js +974 -0
  209. package/blz-security/navigationMemoryRepository.js +15 -0
  210. package/blz-security/navigationMongoDbRepository.js +73 -0
  211. package/blz-security/secureUrlService.js +47 -0
  212. package/blz-security/securityService.js +409 -0
  213. package/blz-security/sqlInjectionGuard.js +162 -0
  214. package/blz-security/templates/forbidden.html +0 -0
  215. package/blz-security/templates/session-iframe-azure-ad.html +7 -0
  216. package/blz-security/templates/session-iframe.html +73 -0
  217. package/blz-security/templates/unauthorized.html +1 -0
  218. package/blz-security/xssGuard.js +87 -0
  219. package/blz-strings/index.js +167 -0
  220. package/blz-uuid/index.js +7 -0
  221. package/blz-yaml/index.js +19 -0
  222. package/index.js +84 -0
  223. package/package.json +97 -0
  224. package/process-managers/index.js +422 -0
@@ -0,0 +1,1466 @@
1
+ const _ = require("underscore");
2
+ const Got = require('got');
3
+ const Soap = require('soap');
4
+ const Fs = require('fs-extra');
5
+ const Path = require('path');
6
+ const Util = require('util');
7
+ const { LRUCache } = require('lru-cache');
8
+ const securityService = require('../blz-security/index');
9
+ const configService = require('../blz-config/index');
10
+ const jsyaml = require('js-yaml');
11
+ const { getHealthStatus } = require('./health/index')
12
+
13
+ let _metadata = null;
14
+ let _connections = null;
15
+ let _configParameters = null;
16
+ let _transformations = null;
17
+ let _externalRestCallId = null;
18
+ let _externalSoapCallId = null;
19
+
20
+ class MandatoryTransactionViolation extends Error {
21
+ constructor() {
22
+ super("Any transaction exists over transaction stack");
23
+ this.code = this.constructor.name;
24
+ }
25
+ }
26
+
27
+ class NeverTransactionViolation extends Error {
28
+ constructor() {
29
+ super("A transaction exists over transaction stack");
30
+ this.code = this.constructor.name;
31
+ }
32
+ }
33
+
34
+ class StackEmptyViolation extends Error {
35
+ constructor() {
36
+ super("Stack transaction is empty");
37
+ this.code = this.constructor.name;
38
+ }
39
+ }
40
+
41
+ class InvalidStackViolation extends Error {
42
+ constructor() {
43
+ super("Invalid stack. You dont have any (valid) connection");
44
+ this.code = this.constructor.name;
45
+ }
46
+ }
47
+ function transactionsContext(context) {
48
+ if (!context.rdsTransactionContext) {
49
+ context.rdsTransactionContext = [];
50
+ }
51
+ return context.rdsTransactionContext;
52
+ }
53
+ function checkValidTransaction(stack) {
54
+ let brick = _.last(stack);
55
+ if (brick.propagationType == "not-supported" || brick.propagationType == "never") {
56
+ throw new InvalidStackViolation();
57
+ }
58
+ if (!brick.connection) {
59
+ throw new InvalidStackViolation();
60
+ }
61
+ }
62
+ function beginRequiredNew(stack) {
63
+ if (_.isEmpty(stack)) {
64
+ stack.push({
65
+ propagationType: "requires-new",
66
+ connection: Object.create(null)
67
+ });
68
+ } else {
69
+ checkValidTransaction(stack);
70
+ stack.push({
71
+ propagationType: "requires-new",
72
+ connection: Object.create(null)
73
+ });
74
+ }
75
+ }
76
+ const beginRequired = function (stack) {
77
+ if (_.isEmpty(stack)) {
78
+ stack.push({
79
+ propagationType: "requires-new",
80
+ connection: Object.create(null)
81
+ });
82
+ } else {
83
+ checkValidTransaction(stack);
84
+ let brick = _.last(stack);
85
+ stack.push({
86
+ propagationType: "required",
87
+ connection: brick.connection
88
+ });
89
+ }
90
+ }
91
+
92
+ const beginNested = function (stack) {
93
+ if (_.isEmpty(stack)) {
94
+ stack.push({
95
+ propagationType: "requires-new",
96
+ connection: Object.create(null)
97
+ });
98
+ } else {
99
+ checkValidTransaction(stack);
100
+ let brick = _.last(stack);
101
+ stack.push({
102
+ propagationType: "nested",
103
+ connection: brick.connection
104
+ });
105
+ }
106
+ }
107
+
108
+ const beginNotSupported = function(stack) {
109
+ stack.push({
110
+ propagationType: "not-supported",
111
+ connection: null
112
+ });
113
+ }
114
+
115
+ const beginSupports = function(stack) {
116
+ if (_.isEmpty(stack)) {
117
+ stack.push({
118
+ propagationType: "supports",
119
+ connection: null
120
+ });
121
+ return;
122
+ }
123
+ let brick = _.last(stack);
124
+ if (!brick.connection) {
125
+ stack.push({
126
+ propagationType: "supports",
127
+ connection: null
128
+ });
129
+ return;
130
+ }
131
+ stack.push({
132
+ propagationType: "supports",
133
+ connection: brick.connection
134
+ });
135
+ }
136
+
137
+ const beginMandatory = function(stack) {
138
+ if (_.isEmpty(stack)) {
139
+ throw new MandatoryTransactionViolation();
140
+ }
141
+ let brick = _.last(stack);
142
+ if (!brick.connection) {
143
+ throw new MandatoryTransactionViolation();
144
+ }
145
+ stack.push({
146
+ propagationType: "mandatory",
147
+ connection: brick.connection
148
+ });
149
+ }
150
+
151
+ const beginNever = function (stack) {
152
+ if (!_.isEmpty(stack)) {
153
+ let brick = _.last(stack);
154
+ if (brick.connection) {
155
+ throw new NeverTransactionViolation();
156
+ }
157
+ }
158
+ stack.push({
159
+ propagationType: "never",
160
+ connection: null
161
+ });
162
+ }
163
+
164
+
165
+ const beginTransaction = function (context, type) {
166
+ let stack = transactionsContext(context);
167
+ switch (type) {
168
+ case "nested":
169
+ beginNested(stack);
170
+ break;
171
+ case "never":
172
+ beginNever(stack);
173
+ break;
174
+ case "not-supported":
175
+ beginNotSupported(stack);
176
+ break;
177
+ case "mandatory":
178
+ beginMandatory(stack);
179
+ break;
180
+ case "required":
181
+ beginRequired(stack);
182
+ break;
183
+ case "requires-new":
184
+ beginRequiredNew(stack);
185
+ break;
186
+ case "supports":
187
+ beginSupports(stack);
188
+ break;
189
+ default:
190
+ throw new Error(`${type} is not supported yet`);
191
+ }
192
+ }
193
+
194
+ const commitTransaction = async function (context, type) {
195
+ let transactionsStack = transactionsContext(context);
196
+ if (_.isEmpty(transactionsStack)) {
197
+ return;
198
+ }
199
+ let transactionBrick = transactionsStack[transactionsStack.length - 1];
200
+ switch (transactionBrick.propagationType) {
201
+ case "nested":
202
+ for (let connectionName in transactionBrick.connection) {
203
+ await transactionBrick.connection[connectionName].commitTransaction();
204
+ }
205
+ break;
206
+ case "never":
207
+ break;
208
+ case "not-supported":
209
+ break;
210
+ case "mandatory":
211
+ break;
212
+ case "required":
213
+ break;
214
+ case "requires-new":
215
+ for (let connectionName in transactionBrick.connection) {
216
+ await transactionBrick.connection[connectionName].commitTransaction();
217
+ }
218
+ break;
219
+ case "supports":
220
+ break;
221
+ default:
222
+ break;
223
+ }
224
+ }
225
+
226
+ const rollbackTransaction = async function (context, type) {
227
+ let transactionsStack = transactionsContext(context);
228
+ if (_.isEmpty(transactionsStack)) {
229
+ return;
230
+ }
231
+ let transactionBrick = transactionsStack[transactionsStack.length - 1];
232
+ switch (transactionBrick.propagationType) {
233
+ case "nested":
234
+ for (let connectionName in transactionBrick.connection) {
235
+ await transactionBrick.connection[connectionName].rollbackTransaction();
236
+ }
237
+ break;
238
+ case "never":
239
+ break;
240
+ case "not-supported":
241
+ break;
242
+ case "mandatory":
243
+ break;
244
+ case "required":
245
+ break;
246
+ case "requires-new":
247
+ for (let connectionName in transactionBrick.connection) {
248
+ await transactionBrick.connection[connectionName].rollbackTransaction();
249
+ }
250
+ break;
251
+ case "supports":
252
+ break;
253
+ default:
254
+ break;
255
+ }
256
+ }
257
+
258
+ const closeTransaction = async function (context, type) {
259
+ let transactionsStack = transactionsContext(context);
260
+ if (_.isEmpty(transactionsStack)) {
261
+ return;
262
+ }
263
+ let transactionBrick = transactionsStack.pop();
264
+ switch (transactionBrick.propagationType) {
265
+ case "nested":
266
+ break;
267
+ case "never":
268
+ break;
269
+ case "not-supported":
270
+ break;
271
+ case "mandatory":
272
+ break;
273
+ case "required":
274
+ break;
275
+ case "requires-new":
276
+ for (let connectionName in transactionBrick.connection) {
277
+ await transactionBrick.connection[connectionName].close()
278
+ }
279
+ break;
280
+ case "supports":
281
+ break;
282
+ default:
283
+ break;
284
+ }
285
+ }
286
+
287
+ const tryParse = function (value, _default = null) {
288
+ try {
289
+ return value && typeof value === 'string'
290
+ ? JSON.parse(value)
291
+ : _default
292
+ } catch (ex) {
293
+ return _default
294
+ }
295
+ }
296
+
297
+ const compare = function (value1, value2) {
298
+ if (value1 === null && value2 === null)
299
+ return 0;
300
+ if (value1 === null && value2 !== null)
301
+ return -1;
302
+ if (value1 !== null && value2 === null)
303
+ return 1;
304
+ let value1Type = toString.call(value1);
305
+ let value2Type = toString.call(value2);
306
+ let value1ToCompare = null;
307
+ let value2ToCompare = null;
308
+ if ((value1Type === '[object String]' && value2Type === '[object String]') ||
309
+ (value1Type === '[object Number]' && value2Type === '[object Number]')) {
310
+ value1ToCompare = value1;
311
+ value2ToCompare = value2;
312
+ }
313
+ else if (value1Type === '[object Boolean]' && value2Type === '[object Boolean]') {
314
+ value1ToCompare = value1 ? 1 : 0;
315
+ value2ToCompare = value2 ? 1 : 0;
316
+ }
317
+ else if (value1Type === '[object Date]' && value2Type === '[object Date]') {
318
+ value1ToCompare = value1.getTime();
319
+ value2ToCompare = value2.getTime();
320
+ }
321
+ else if (value1Type === '[object Object]' && value2Type === '[object Object]') {
322
+ value1ToCompare = JSON.stringify(value1);
323
+ value2ToCompare = JSON.stringify(value2);
324
+ }
325
+ else if (value1Type === '[object Array]' && value2Type === '[object Array]') {
326
+ let result = compare(value1.length, value2.length);
327
+ if (result !== 0)
328
+ return result;
329
+ for (let i = 0; i < value1.length; i++) {
330
+ let item1 = value1[i];
331
+ let item2 = value2[i];
332
+ result = compare(item1, item2);
333
+ if (result !== 0)
334
+ return result;
335
+ }
336
+ return 0;
337
+ }
338
+ else {
339
+ if (value1Type === '[object String]')
340
+ value1ToCompare = value1;
341
+ else if (value1Type === '[object Number]')
342
+ value1ToCompare = value1.toString();
343
+ else if (value1Type === '[object Boolean]')
344
+ value1ToCompare = value1 ? '1' : '0';
345
+ else if (value1Type === '[object Date]')
346
+ value1ToCompare = value1.toJSON();
347
+ else
348
+ value1ToCompare = value1.toString();
349
+ if (value2Type === '[object String]')
350
+ value2ToCompare = value2;
351
+ else if (value2Type === '[object Number]')
352
+ value2ToCompare = value2.toString();
353
+ else if (value2Type === '[object Boolean]')
354
+ value2ToCompare = value2 ? '1' : '0';
355
+ else if (value2Type === '[object Date]')
356
+ value2ToCompare = value2.toJSON();
357
+ else
358
+ value2ToCompare = value2.toString();
359
+ }
360
+ if (value1ToCompare === value2ToCompare)
361
+ return 0;
362
+ else if (value1ToCompare < value2ToCompare)
363
+ return -1;
364
+ else if (value1ToCompare > value2ToCompare)
365
+ return 1;
366
+ else
367
+ return null;
368
+ };
369
+
370
+ const convertToListOf = function (value, fnConvert) {
371
+ if (Array.isArray(value)) {
372
+ let list = [];
373
+ for (let i = 0; i < value.length; i++) {
374
+ list.push(fnConvert(value[i]));
375
+ }
376
+ return list;
377
+ }
378
+ else {
379
+ return [fnConvert(value)];
380
+ }
381
+ };
382
+
383
+ const convertMilliseconds = function (strMilliseconds) {
384
+ if (strMilliseconds) {
385
+ if (strMilliseconds.length < 3)
386
+ strMilliseconds = strMilliseconds.padEnd(3, '0');
387
+ if (strMilliseconds.length > 3)
388
+ strMilliseconds = strMilliseconds.substr(0, 3);
389
+ return Number(strMilliseconds);
390
+ }
391
+ else
392
+ return 0;
393
+ };
394
+
395
+ const simplifyName = function (value) {
396
+ return value.toUpperCase().replace('-', '').replace('_', '');
397
+ };
398
+
399
+ const fixSoapValue = function (value) {
400
+ if (value !== null && typeof value === 'object') {
401
+ for (let key in value) {
402
+ let childValue = value[key];
403
+ if (isSoapNull(childValue))
404
+ value[key] = null;
405
+ else
406
+ fixSoapValue(childValue);
407
+ }
408
+ }
409
+ };
410
+ const isSoapNull = function (value) {
411
+ return value && value.attributes && value.attributes['xsi:nil'] && value.attributes['xsi:nil'] === 'true';
412
+ };
413
+
414
+ // See more options in: https://nodejs.org/docs/latest-v16.x/api/util.html#utilinspectobject-options
415
+ const STRINGIFY_OBJECT_DEFAULT_OPTIONS = {
416
+ showHidden: true,
417
+ depth: 5,
418
+ }
419
+ const stringifyObject = function (obj, options = {}) {
420
+ const inspectOptions = {
421
+ ...STRINGIFY_OBJECT_DEFAULT_OPTIONS,
422
+ ...options
423
+ }
424
+ return Util.inspect(obj, inspectOptions)
425
+ }
426
+
427
+ const checkDuplicateKeysInEnv = function (environmentPath) {
428
+ const env = Fs.readFileSync(environmentPath, 'utf8')
429
+ const lines = env.split('\n')
430
+ const keys = []
431
+ const duplicateKeys = []
432
+ lines.forEach((line) => {
433
+ line = line.trim()
434
+ if (line === '' || line.startsWith('#')) return
435
+ const [key] = line.split('=')
436
+ if (keys.includes(key)) {
437
+ duplicateKeys.push(key)
438
+ }
439
+ keys.push(key)
440
+ })
441
+ if (duplicateKeys.length > 0) {
442
+ throw new Error(`Error. Duplicate keys in .env file: ${JSON.stringify([...new Set(duplicateKeys)])}`)
443
+ }
444
+ }
445
+
446
+ const normalizeConfig = function (config = {}) {
447
+ for (const p in config.connections) {
448
+ const connection = config.connections[p]
449
+
450
+ if (connection.type !== "Mongodb") continue
451
+ const hasOldFormat = Boolean(connection.database && connection.database.trim())
452
+ const hasNewFormat = Boolean(connection.databaseName && connection.databaseName.trim())
453
+ const hasToWarnAboutConfusion = hasOldFormat && hasNewFormat
454
+ const hasToUpdate = hasOldFormat && !hasNewFormat
455
+
456
+ if (hasToWarnAboutConfusion) {
457
+ console.warn(`Warning: Your are using the old format ("blz_${p}_database") and the new format ("blz_${p}_databaseName"). We will use the new one ("blz_${p}_databaseName"). Please, consider to remove the old format to avoid confusion.`)
458
+ delete connection.database
459
+ }
460
+ if (hasToUpdate) {
461
+ console.warn(`Warning: Your are using the "blz_${p}_database" variable, but you need to use "blz_${p}_databaseName" instead. Environment variables for MongoDb databases with "blz_xxx_database" format may will disappear in the future. Please, update it.`)
462
+ connection.databaseName = connection.database
463
+ delete connection.database
464
+ }
465
+ }
466
+ }
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;
478
+ }
479
+ let cache = new LRUCache({ max: 500, maxSize: 5000, ttl: 1000 * 60 * 60 * 3, sizeCalculation: (value, key) => { return 1 } })
480
+
481
+ const safeRequire = function(path) {
482
+ try {
483
+ require.resolve(path);
484
+ return require(path);
485
+ } catch (err) {
486
+ if (err.code === 'MODULE_NOT_FOUND') {
487
+ let newPath = path.replace(/^\.\.\//, '');
488
+ if (path !== newPath) {
489
+ return safeRequire(newPath);
490
+ }
491
+ return undefined;
492
+ }
493
+ throw err;
494
+ }
495
+ }
496
+
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
+ }
548
+ }
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)));
555
+ }
556
+ return target;
557
+ }
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));
563
+ }
564
+ return target;
565
+ }
566
+ }
567
+ else { // obj
568
+ if (writer) {
569
+ return await writer.write(callContext, transformationExecutor(callContext, source));
570
+ }
571
+ else {
572
+ return await transformationExecutor(callContext, source);
573
+ }
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);
593
+ }
594
+ else {
595
+ return await this.fn(callContext, obj);
596
+ }
597
+ }
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;
615
+ }
616
+ else if (rootType === '[object Array]') {
617
+ return root[bind];
618
+ }
619
+ else {
620
+ return null;
621
+ }
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;
718
+ }
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
+ }
727
+ };
728
+ }
729
+ let response = await Got(requestUrl, requestOptions);
730
+ let httpErrorCode = this.httpErrors[response.statusCode];
731
+ if (httpErrorCode) {
732
+ 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;
892
+ }
893
+ else if (lastChar.match(/[A-Z]/) && char.match(/[A-Z]/)) {
894
+ result += char.toLowerCase();
895
+ }
896
+ else if (lastChar.match(/[A-Z]/) && char.match(/[a-z]/)) {
897
+ result += char;
898
+ }
899
+ else if (lastChar.match(/[a-z]/) && char.match(/[A-Z]/)) {
900
+ result += '-' + char.toLowerCase();
901
+ }
902
+ else if (lastChar.match(/[a-z]/) && char.match(/[a-z]/)) {
903
+ result += char;
904
+ }
905
+ else if (char.match(/[A-Z]/)) {
906
+ result += char.toLowerCase();
907
+ }
908
+ else if (char.match(/[a-z]/)) {
909
+ result += char;
910
+ }
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
938
+ }
939
+ }
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));
969
+ }
970
+ }
971
+ else if (routingParameter.in === 'Body') {
972
+ this.setValue(result, routingParameter.bind, request.payload);
973
+ }
974
+ }
975
+ }
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 };
986
+ }
987
+ }
988
+ break;
989
+ }
990
+ case 'Query': {
991
+ if (request.query) {
992
+ let queryValue = request.query[apiKeyName];
993
+ if (queryValue) {
994
+ return { key: queryValue };
995
+ }
996
+ }
997
+ break;
998
+ }
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] };
1011
+ }
1012
+ catch (err2) { }
1013
+ }
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] };
1022
+ }
1023
+ }
1024
+ return null;
1025
+ },
1026
+ loadResource: async function (path) {
1027
+ try {
1028
+ let resourceContent = await Fs.readFile(Path.join(__dirname, '../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)));
1074
+ }
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]));
1079
+ isFirstQueryParameter = false;
1080
+ }
1081
+ }
1082
+ else {
1083
+ requestUrl += (isFirstQueryParameter ? '?' : '&') + encodeURIComponent(routingParameter.name) + '=' + encodeURIComponent(this.convertToString(value));
1084
+ isFirstQueryParameter = false;
1085
+ }
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
+ }
1093
+ }
1094
+ }
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) {
1149
+ for (let j = 0; j < securityItem.length; j++) {
1150
+ 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
+ }
1164
+ }
1165
+ break;
1166
+ }
1167
+ case 'BasicAuth': {
1168
+ requestOptions.headers['Authorization'] = 'Basic ' + Buffer.from(value.user + ':' + value.password, 'ascii').toString('base64');
1169
+ break;
1170
+ }
1171
+ case 'BearerToken': {
1172
+ requestOptions.headers['Authorization'] = 'Bearer ' + value;
1173
+ break;
1174
+ }
1175
+ }
1176
+ }
1177
+ securityApplied = true;
1178
+ }
1179
+ }
1180
+ }
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;
1209
+ } else {
1210
+ const ACCESS_TOKEN = securityService.getCookieName('access_token')
1211
+ value = request.state[ACCESS_TOKEN];
1212
+ }
1213
+ }
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;
1227
+ }
1228
+ break;
1229
+ }
1230
+ default:
1231
+ break;
1232
+ }
1233
+ }
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');
1261
+ }
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}
1266
+ }
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);
1304
+ }
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}`)
1327
+ }
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;
1377
+ }
1378
+ case 'AccessToken': {
1379
+ value = request.state['access_token'];
1380
+ break;
1381
+ }
1382
+ case 'Cookie': {
1383
+ value = request.state[soapMapping.security.cookieName];
1384
+ break;
1385
+ }
1386
+ case 'CallVariable': {
1387
+ value = callContext.callVariables[soapMapping.security.callVariableName];
1388
+ break;
1389
+ }
1390
+ }
1391
+ switch (soapMapping.security.securityType) {
1392
+ case 'BasicAuth': {
1393
+ soapClient.setSecurity(new Soap.BasicAuthSecurity(value.user, value.password));
1394
+ break;
1395
+ }
1396
+ case 'BearerToken': {
1397
+ soapClient.setSecurity(new Soap.BearerSecurity(value));
1398
+ break;
1399
+ }
1400
+ }
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];
1414
+ if (isSoapNull(result))
1415
+ return null;
1416
+ fixSoapValue(result);
1417
+ return result;
1418
+ }
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)
1441
+ }
1442
+ })
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
1466
+ };