ml-testing-toolkit 18.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/.dockerignore +10 -0
  2. package/.grype.yaml +16 -0
  3. package/.ncurc.yaml +9 -0
  4. package/.nvmrc +1 -0
  5. package/.versionrc.js +16 -0
  6. package/CHANGELOG.md +504 -0
  7. package/CODEOWNERS +30 -0
  8. package/Dockerfile +42 -0
  9. package/Dockerfile-newman +13 -0
  10. package/LICENSE.md +9 -0
  11. package/README.md +119 -0
  12. package/assets/diagrams/architectural/architectural-diagram.svg +3 -0
  13. package/assets/diagrams/flow/flow-diagram.svg +3 -0
  14. package/assets/images/Sample-Response-Failure.png +0 -0
  15. package/assets/images/Screenshot 2020-04-16 at 22.58.04.png +0 -0
  16. package/assets/images/TLS-Enabled-on-Environment.png +0 -0
  17. package/assets/images/adapter-mutual-tls-enabled.png +0 -0
  18. package/assets/images/add-additional-input-values.png +0 -0
  19. package/assets/images/add-condition-button.png +0 -0
  20. package/assets/images/add-new-assertion.png +0 -0
  21. package/assets/images/add-new-input-value.png +0 -0
  22. package/assets/images/add-new-input-variable.png +0 -0
  23. package/assets/images/additional-transfers.png +0 -0
  24. package/assets/images/api-provisioning-add-new-api-confirmation.png +0 -0
  25. package/assets/images/api-provisioning-file-input-window.png +0 -0
  26. package/assets/images/api-provisioning-list-apis-view.png +0 -0
  27. package/assets/images/api-provisioning-menu-item.png +0 -0
  28. package/assets/images/apply_and_restart.jpg +0 -0
  29. package/assets/images/assess-request-or-response.png +0 -0
  30. package/assets/images/assess-response-equation-save.png +0 -0
  31. package/assets/images/assess-response-equation.png +0 -0
  32. package/assets/images/assess-response-status.png +0 -0
  33. package/assets/images/building-new-rules-file.png +0 -0
  34. package/assets/images/callback-rules-screen.png +0 -0
  35. package/assets/images/configurable-parameter-assertion.png +0 -0
  36. package/assets/images/configurable-parameter-currency.png +0 -0
  37. package/assets/images/configurable-parameter.png +0 -0
  38. package/assets/images/connection-manager-ui-opening.png +0 -0
  39. package/assets/images/create-inbound-user-simulator.png +0 -0
  40. package/assets/images/creating-new-rule-file.png +0 -0
  41. package/assets/images/dfsp-client-cacert.png +0 -0
  42. package/assets/images/dfsp-client-submit.png +0 -0
  43. package/assets/images/dfsp-client.png +0 -0
  44. package/assets/images/dfsp-p2p-happy-path.png +0 -0
  45. package/assets/images/dfsp-server-cacert.png +0 -0
  46. package/assets/images/dfsp-server-cert.png +0 -0
  47. package/assets/images/download-report.png +0 -0
  48. package/assets/images/drive_have_not_been_shared.jpg +0 -0
  49. package/assets/images/event-response-options.png +0 -0
  50. package/assets/images/expand-monitoring-messages.png +0 -0
  51. package/assets/images/fixed-response-sample.png +0 -0
  52. package/assets/images/header-selection.png +0 -0
  53. package/assets/images/heap_error_windows.jpg +0 -0
  54. package/assets/images/hosted-mode-docker-compose-intro.png +0 -0
  55. package/assets/images/hub-client-cert.png +0 -0
  56. package/assets/images/import-template.png +0 -0
  57. package/assets/images/inbound-requests-environment.png +0 -0
  58. package/assets/images/inbound-requests-scripts.png +0 -0
  59. package/assets/images/jws-certificate-submit.png +0 -0
  60. package/assets/images/jws-certificate.png +0 -0
  61. package/assets/images/jws-certs-keys.png +0 -0
  62. package/assets/images/jws-hub-certs-keys.png +0 -0
  63. package/assets/images/local-enable-jws-publickey.png +0 -0
  64. package/assets/images/local-mutual-tls-enabled.png +0 -0
  65. package/assets/images/local_drives_to_be_available.jpg +0 -0
  66. package/assets/images/mcm-environment-opening.png +0 -0
  67. package/assets/images/menu-items.png +0 -0
  68. package/assets/images/mock-response-sample.png +0 -0
  69. package/assets/images/monitoring-initial-state.png +0 -0
  70. package/assets/images/monitoring-messages.png +0 -0
  71. package/assets/images/new-empty-assertion.png +0 -0
  72. package/assets/images/opened-imported-template.png +0 -0
  73. package/assets/images/opening-default-settings.png +0 -0
  74. package/assets/images/opening-sync-response-rules.png +0 -0
  75. package/assets/images/opening-view.png +0 -0
  76. package/assets/images/outbound-display-opening-hub.png +0 -0
  77. package/assets/images/outbound-display-opening.png +0 -0
  78. package/assets/images/override-with-environment-variable.png +0 -0
  79. package/assets/images/populate-with-sample-body.png +0 -0
  80. package/assets/images/resource-selection.png +0 -0
  81. package/assets/images/rule-builder-select-api.png +0 -0
  82. package/assets/images/sample-condition-add-configurable-params.png +0 -0
  83. package/assets/images/sample-condition.png +0 -0
  84. package/assets/images/sample-editor.png +0 -0
  85. package/assets/images/sample-request.png +0 -0
  86. package/assets/images/sample-test-assertion.png +0 -0
  87. package/assets/images/send-transfer.png +0 -0
  88. package/assets/images/sending-single-test-case-1.png +0 -0
  89. package/assets/images/sending-single-test-case-2.png +0 -0
  90. package/assets/images/sending-test-cases.png +0 -0
  91. package/assets/images/server-certificates-submitted.png +0 -0
  92. package/assets/images/simulator-response.png +0 -0
  93. package/assets/images/simulator-scheme-adapter-endpoint.png +0 -0
  94. package/assets/images/summarized-view-of-rule.png +0 -0
  95. package/assets/images/template-window.png +0 -0
  96. package/assets/images/test-case-editor-console-log.png +0 -0
  97. package/assets/images/test-case-editor-environment-state.png +0 -0
  98. package/assets/images/test-case-editor-scripts.png +0 -0
  99. package/assets/images/test-case-editor.png +0 -0
  100. package/assets/images/testcase-definition-download.png +0 -0
  101. package/assets/images/testcase-definition-edit-meta-info.png +0 -0
  102. package/assets/images/testing-toolkit-mojaloop-testing-toolkit-endpoint.png +0 -0
  103. package/assets/images/tls-hub-certs-keys.png +0 -0
  104. package/assets/images/tls-jws-enabled-on-environment.png +0 -0
  105. package/assets/images/updated-sample-body-data.png +0 -0
  106. package/assets/images/using-configurable-parameter.png +0 -0
  107. package/assets/images/validation-rules-screen.png +0 -0
  108. package/assets/images/view-response.png +0 -0
  109. package/audit-ci.jsonc +7 -0
  110. package/connection-manager/docker-compose.yml +55 -0
  111. package/database/docker-compose.yml +16 -0
  112. package/docker/hosted-mode/docker-compose.yaml +107 -0
  113. package/docker/hosted-mode/keycloak/keycloak-realm.json +2298 -0
  114. package/docker/hosted-mode/mongo-init.sh +1 -0
  115. package/docker/hosted-mode-tls/docker-compose.yaml +171 -0
  116. package/docker/hosted-mode-tls/keycloak/keycloak-realm.json +2298 -0
  117. package/docker/hosted-mode-tls/mongo-init.sh +1 -0
  118. package/docker-compose.yml +62 -0
  119. package/documents/Mojaloop-Testing-Toolkit.md +296 -0
  120. package/documents/RULES_ENGINE.md +403 -0
  121. package/documents/User-Guide-API-Provisioning.md +121 -0
  122. package/documents/User-Guide-CLI.md +218 -0
  123. package/documents/User-Guide-Connection-Manager.md +282 -0
  124. package/documents/User-Guide-Frequently-Asked-Questions.md +39 -0
  125. package/documents/User-Guide-Hosted-Mode-Docker-Compose.md +110 -0
  126. package/documents/User-Guide-Installation.md +163 -0
  127. package/documents/User-Guide-Mojaloop-Testing-Toolkit.md +642 -0
  128. package/documents/User-Guide-OAuth-Server-Deployment.md +283 -0
  129. package/documents/User-Guide-Onboarding-DFSP.md +197 -0
  130. package/documents/User-Guide-Onboarding-HUB.md +191 -0
  131. package/documents/User-Guide.md +53 -0
  132. package/examples/collections/dfsp/p2p_failed_tests.json +7161 -0
  133. package/examples/collections/dfsp/p2p_fx_happy_path.json +502 -0
  134. package/examples/collections/dfsp/p2p_happy_path.json +350 -0
  135. package/examples/collections/dfsp/p2p_happy_path_extended.json +6106 -0
  136. package/examples/collections/dfsp/p2p_happy_path_jws.json +511 -0
  137. package/examples/collections/dfsp/p2p_payee_assertions_websocket.json +441 -0
  138. package/examples/collections/dfsp/sample.json +5029 -0
  139. package/examples/collections/dfsp/transaction_request_service.json +240 -0
  140. package/examples/collections/fxp/FXP.json +264 -0
  141. package/examples/collections/fxp/SDK_backend.json +98 -0
  142. package/examples/collections/fxp/SDK_outbound.json +163 -0
  143. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_receive_quote.json +400 -0
  144. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_send_quote.json +395 -0
  145. package/examples/collections/hub/hub_02_block_transfer/hub_block_transfer.json +393 -0
  146. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_in.json +224 -0
  147. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_out.json +780 -0
  148. package/examples/collections/hub/hub_04_settlements/hub_settlements.json +3138 -0
  149. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_abort.json +475 -0
  150. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_invalid_fulfillment.json +370 -0
  151. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_transfer_timeout.json +262 -0
  152. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_authorizations.json +117 -0
  153. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_error_framework.json +591 -0
  154. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_received_state.json +379 -0
  155. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_reject_state.json +361 -0
  156. package/examples/collections/hub/hub_07_quoting_service.json +525 -0
  157. package/examples/collections/hub/hub_08_participant_inactive_stop_transfers.json +706 -0
  158. package/examples/collections/hub/hub_09_duplicate_handling_transfers.json +1377 -0
  159. package/examples/collections/hub/hub_10_on_us_transfers.json +245 -0
  160. package/examples/collections/hub/hub_11_accented_and_spl_chars.json +629 -0
  161. package/examples/collections/hub/hub_12_fspiop_version_1.1.json +646 -0
  162. package/examples/collections/hub/hub_13_bulk_transfers.json +1857 -0
  163. package/examples/collections/iso20022/self_referencing_iso20022.json +926 -0
  164. package/examples/collections/provisioning/testingtoolkitdfsp.json +904 -0
  165. package/examples/environments/dfsp_local_environment.json +46 -0
  166. package/examples/environments/hub_local_environment.json +57 -0
  167. package/jest.config.js +17 -0
  168. package/package.json +199 -0
  169. package/sbom-v18.12.4.csv +1553 -0
  170. package/secrets/keygen.sh +5 -0
  171. package/secrets/privatekey.pem +27 -0
  172. package/secrets/publickey.cer +21 -0
  173. package/secrets/tls/01.pem +132 -0
  174. package/secrets/tls/createSecrets.sh +20 -0
  175. package/secrets/tls/hub_client.csr +32 -0
  176. package/secrets/tls/hub_client_cacert.pem +35 -0
  177. package/secrets/tls/hub_client_cakey.pem +52 -0
  178. package/secrets/tls/hub_client_key.key +52 -0
  179. package/secrets/tls/hub_server.csr +31 -0
  180. package/secrets/tls/hub_server_cacert.pem +35 -0
  181. package/secrets/tls/hub_server_cakey.pem +52 -0
  182. package/secrets/tls/hub_server_cert.pem +132 -0
  183. package/secrets/tls/hub_server_key.key +52 -0
  184. package/secrets/tls/index.txt +1 -0
  185. package/secrets/tls/index.txt.attr +1 -0
  186. package/secrets/tls/openssl-client.cnf +36 -0
  187. package/secrets/tls/openssl-clientca.cnf +71 -0
  188. package/secrets/tls/openssl-server.cnf +39 -0
  189. package/secrets/tls/openssl-serverca.cnf +71 -0
  190. package/secrets/tls/serial.txt +1 -0
  191. package/spec_files/api_definitions/als_admin_1.1/api_spec.yaml +804 -0
  192. package/spec_files/api_definitions/central_admin_1.0/api_spec.yaml +1850 -0
  193. package/spec_files/api_definitions/central_admin_1.0/response_map.json +96 -0
  194. package/spec_files/api_definitions/central_admin_old_9.3/api_spec.yaml +2467 -0
  195. package/spec_files/api_definitions/central_admin_old_9.3/response_map.json +96 -0
  196. package/spec_files/api_definitions/fspiop_1.0/api_spec.yaml +4187 -0
  197. package/spec_files/api_definitions/fspiop_1.0/callback_map.json +568 -0
  198. package/spec_files/api_definitions/fspiop_1.0/mockRef.json +79 -0
  199. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup.json +126 -0
  200. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup_quotes_only.json +97 -0
  201. package/spec_files/api_definitions/fspiop_1.1/api_spec.yaml +3778 -0
  202. package/spec_files/api_definitions/fspiop_1.1/callback_map.json +568 -0
  203. package/spec_files/api_definitions/fspiop_1.1/mockRef.json +79 -0
  204. package/spec_files/api_definitions/fspiop_1.1/trigger_templates/transaction_request_followup.json +125 -0
  205. package/spec_files/api_definitions/fspiop_2.0/api_spec.yaml +4839 -0
  206. package/spec_files/api_definitions/fspiop_2.0/callback_map.json +716 -0
  207. package/spec_files/api_definitions/fspiop_2.0/mockRef.json +79 -0
  208. package/spec_files/api_definitions/fspiop_2.0/trigger_templates/transaction_request_followup.json +125 -0
  209. package/spec_files/api_definitions/fspiop_2.0_iso20022/api_spec.yaml +8331 -0
  210. package/spec_files/api_definitions/fspiop_2.0_iso20022/callback_map.json +508 -0
  211. package/spec_files/api_definitions/fspiop_2.0_iso20022/mockRef.json +66 -0
  212. package/spec_files/api_definitions/fx-api_2.0/api_spec.yaml +1768 -0
  213. package/spec_files/api_definitions/fx-api_2.0/callback_map.json +188 -0
  214. package/spec_files/api_definitions/fx-api_2.0/mockRef.json +83 -0
  215. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/api_spec.yaml +2612 -0
  216. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/mockRef.json +22 -0
  217. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/response_map.json +35 -0
  218. package/spec_files/api_definitions/mojaloop_simulator_0.1/api_spec.yaml +225 -0
  219. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/api_spec.yaml +1087 -0
  220. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/mockRef.json +75 -0
  221. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/response_map.json +55 -0
  222. package/spec_files/api_definitions/payment_manager_1.4/api_spec.yaml +1389 -0
  223. package/spec_files/api_definitions/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +2834 -0
  224. package/spec_files/api_definitions/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +3449 -0
  225. package/spec_files/api_definitions/settlements_1.0/api_spec.yaml +983 -0
  226. package/spec_files/api_definitions/settlements_1.0/mockRef.json +38 -0
  227. package/spec_files/api_definitions/settlements_1.0/response_map.json +34 -0
  228. package/spec_files/api_definitions/settlements_2.0/api_spec.yaml +1001 -0
  229. package/spec_files/api_definitions/settlements_2.0/mockRef.json +38 -0
  230. package/spec_files/api_definitions/settlements_2.0/response_map.json +34 -0
  231. package/spec_files/api_definitions/thirdparty_sdk_outbound_0.1/api_spec.yaml +2139 -0
  232. package/spec_files/reports/templates/newman/html_template.html +1202 -0
  233. package/spec_files/reports/templates/newman/pdf_template.html +790 -0
  234. package/spec_files/reports/templates/testcase_definition/table_view.html +1602 -0
  235. package/spec_files/rules_callback/config.json +3 -0
  236. package/spec_files/rules_callback/default.json +2698 -0
  237. package/spec_files/rules_callback/p2p-limit.json +129 -0
  238. package/spec_files/rules_forward/config.json +3 -0
  239. package/spec_files/rules_forward/default.json +482 -0
  240. package/spec_files/rules_response/config.json +3 -0
  241. package/spec_files/rules_response/default.json +295 -0
  242. package/spec_files/rules_validation/config.json +3 -0
  243. package/spec_files/rules_validation/default.json +1 -0
  244. package/spec_files/rules_validation/p2p-limit.json +55 -0
  245. package/spec_files/system_config.json +175 -0
  246. package/spec_files/user_config.json +109 -0
  247. package/src/index.js +67 -0
  248. package/src/lib/MyEventEmitter.js +54 -0
  249. package/src/lib/api-management.js +143 -0
  250. package/src/lib/api-routes/config.js +83 -0
  251. package/src/lib/api-routes/history.js +139 -0
  252. package/src/lib/api-routes/keycloak.js +54 -0
  253. package/src/lib/api-routes/longpolling.js +70 -0
  254. package/src/lib/api-routes/oauth2.js +149 -0
  255. package/src/lib/api-routes/objectstore.js +53 -0
  256. package/src/lib/api-routes/openapi.js +224 -0
  257. package/src/lib/api-routes/outbound.js +134 -0
  258. package/src/lib/api-routes/reports.js +72 -0
  259. package/src/lib/api-routes/rules.js +356 -0
  260. package/src/lib/api-routes/samples.js +92 -0
  261. package/src/lib/api-routes/server-logs.js +44 -0
  262. package/src/lib/api-routes/settings.js +71 -0
  263. package/src/lib/api-server.js +135 -0
  264. package/src/lib/arrayStore.js +101 -0
  265. package/src/lib/callbackHandler.js +201 -0
  266. package/src/lib/config.js +177 -0
  267. package/src/lib/configuration-providers/mb-connection-manager.js +625 -0
  268. package/src/lib/db/adapters/dbAdapter.js +184 -0
  269. package/src/lib/db/dfspMockUsers.js +64 -0
  270. package/src/lib/db/models/mongoDBWrapper.js +78 -0
  271. package/src/lib/eventListenerClient/inboundEventListener.js +176 -0
  272. package/src/lib/fileAdapter.js +57 -0
  273. package/src/lib/httpAgentStore.js +135 -0
  274. package/src/lib/importExport.js +186 -0
  275. package/src/lib/jws/JwsSigning.js +141 -0
  276. package/src/lib/loadSamples.js +128 -0
  277. package/src/lib/logger.js +20 -0
  278. package/src/lib/longpollingEmitter.js +56 -0
  279. package/src/lib/metrics.js +51 -0
  280. package/src/lib/mocking/custom-functions/generic.js +57 -0
  281. package/src/lib/mocking/middleware-functions/ilpModel.js +238 -0
  282. package/src/lib/mocking/middleware-functions/quotesAssociation.js +75 -0
  283. package/src/lib/mocking/middleware-functions/transactionRequestsService.js +78 -0
  284. package/src/lib/mocking/openApiDefinitionsModel.js +64 -0
  285. package/src/lib/mocking/openApiMockHandler.js +466 -0
  286. package/src/lib/mocking/openApiRulesEngine.js +492 -0
  287. package/src/lib/mocking/openApiVersionTools.js +136 -0
  288. package/src/lib/mocking/transformers/fspiopToISO20022.js +230 -0
  289. package/src/lib/mocking/transformers/index.js +41 -0
  290. package/src/lib/notificationEmitter.js +64 -0
  291. package/src/lib/oauth/KeycloakHelper.js +220 -0
  292. package/src/lib/oauth/LoginService.js +133 -0
  293. package/src/lib/oauth/OAuthHelper.js +181 -0
  294. package/src/lib/oauth/OAuthValidator.js +118 -0
  295. package/src/lib/oauth/Wso2Client.js +64 -0
  296. package/src/lib/objectStore/inMemoryImpl.js +50 -0
  297. package/src/lib/objectStore/objectStoreInterface.js +51 -0
  298. package/src/lib/objectStore.js +122 -0
  299. package/src/lib/report-generator/generator.js +126 -0
  300. package/src/lib/report-generator/helpers.js +154 -0
  301. package/src/lib/requestLogger.js +190 -0
  302. package/src/lib/resources/wso2carbon-publickey.cert +20 -0
  303. package/src/lib/rulesEngine.js +95 -0
  304. package/src/lib/rulesEngineModel.js +463 -0
  305. package/src/lib/scripting-engines/postman-sandbox.js +142 -0
  306. package/src/lib/scripting-engines/vm-javascript-sandbox.js +294 -0
  307. package/src/lib/server-logs/adapters/elastic-search.js +102 -0
  308. package/src/lib/server-logs/adapters/grafana.js +0 -0
  309. package/src/lib/server-logs/index.js +75 -0
  310. package/src/lib/socket-server.js +55 -0
  311. package/src/lib/storageAdapter.js +109 -0
  312. package/src/lib/test-outbound/TestCaseRunner.js +173 -0
  313. package/src/lib/test-outbound/getTracing.js +19 -0
  314. package/src/lib/test-outbound/outbound-initiator.js +1107 -0
  315. package/src/lib/uniqueIdGenerator.js +35 -0
  316. package/src/lib/utils.js +89 -0
  317. package/src/lib/utilsInternal.js +56 -0
  318. package/src/lib/webSocketClient/WebSocketClientManager.js +197 -0
  319. package/src/server.js +218 -0
@@ -0,0 +1,184 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Georgi Logodazhki <georgi.logodazhki@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ 'use strict'
31
+
32
+ const mongoDBWrapper = require('../models/mongoDBWrapper')
33
+ const MongoUriBuilder = require('mongo-uri-builder')
34
+
35
+ let conn
36
+ const getConnection = async () => {
37
+ if (!conn) {
38
+ const Config = require('../../config')
39
+ const systemConfig = Config.getSystemConfig()
40
+ const connectionString = systemConfig.DB.CONNECTION_STRING || MongoUriBuilder({
41
+ username: encodeURIComponent(systemConfig.DB.USER),
42
+ password: encodeURIComponent(systemConfig.DB.PASSWORD),
43
+ host: systemConfig.DB.HOST,
44
+ port: systemConfig.DB.PORT,
45
+ database: systemConfig.DB.DATABASE
46
+ })
47
+ conn = await mongoDBWrapper.connect(connectionString, {
48
+ useNewUrlParser: true,
49
+ useUnifiedTopology: true
50
+ })
51
+ }
52
+ return conn
53
+ }
54
+
55
+ const read = async (id, user, additionalData) => {
56
+ const conn = await getConnection()
57
+ let documents
58
+ if (id === 'logs') {
59
+ const MyModel = conn.model(`${user.dfspId}_${id}`, mongoDBWrapper.models.logs)
60
+ // by default is taking the logs from the last hour
61
+ const query = {
62
+ logTime: {
63
+ $gte: additionalData && additionalData.query && additionalData.query.gte ? new Date(additionalData.query.gte) : new Date(Date.now() - (60 * 60 * 1000)),
64
+ $lt: additionalData && additionalData.query && additionalData.query.lt ? new Date(additionalData.query.lt) : new Date()
65
+ }
66
+ }
67
+ documents = await MyModel.find(query).select('-_id -__v').sort('logTime')
68
+ } else if (id === 'reports') {
69
+ const MyModel = conn.model(`${user.dfspId}_${id}`, mongoDBWrapper.models.reports)
70
+ // by default is taking the reports from the last 30 days
71
+ const query = {
72
+ 'runtimeInformation.completedTimeISO': {
73
+ $gte: additionalData && additionalData.query && additionalData.query.gte ? new Date(additionalData.query.gte) : new Date(Date.now() - (30 * 24 * 60 * 60 * 1000)),
74
+ $lt: additionalData && additionalData.query && additionalData.query.lt ? new Date(additionalData.query.lt) : new Date()
75
+ }
76
+ }
77
+ documents = await MyModel.find(query).select('-_id -__v').sort('-runtimeInformation.completedTimeISO')
78
+ } else {
79
+ const MyModel = conn.model(user.dfspId, mongoDBWrapper.models.common)
80
+ documents = await MyModel.findById(id)
81
+ if (!documents) {
82
+ documents = await MyModel.create({
83
+ _id: id,
84
+ data: {}
85
+ })
86
+ }
87
+ }
88
+ return documents
89
+ }
90
+
91
+ const find = async (id, user) => {
92
+ const conn = await getConnection()
93
+ const MyModel = conn.model(user.dfspId, mongoDBWrapper.models.commonModel)
94
+ const documents = await MyModel.find({ _id: { $regex: `${id}`, $options: 'i' } }).select('_id')
95
+ documents.forEach((item, i) => { documents[i] = item._id })
96
+ return documents
97
+ }
98
+
99
+ const upsert = async (id, data, user) => {
100
+ const conn = await getConnection()
101
+ if (id === 'logs') {
102
+ const collectionId = `${user.dfspId}_${id}`
103
+ const MyModel = conn.model(collectionId, mongoDBWrapper.models.logs)
104
+ data._id = new mongoDBWrapper.Types.ObjectId()
105
+ await MyModel.create(data)
106
+ } else if (id === 'reports') {
107
+ const collectionId = `${user.dfspId}_${id}`
108
+ const MyModel = conn.model(collectionId, mongoDBWrapper.models.reports)
109
+ data._id = `${data.name}_${data.runtimeInformation.completedTimeISO}`
110
+ await MyModel.create(data)
111
+ } else {
112
+ const MyModel = conn.model(user.dfspId, mongoDBWrapper.models.common)
113
+ const document = await MyModel.findOneAndUpdate({ _id: id }, { $set: { data } }, { new: true, upsert: true })
114
+ return document
115
+ }
116
+ }
117
+
118
+ const remove = async (id, user) => {
119
+ const conn = await getConnection()
120
+ const MyModel = conn.model(user.dfspId, mongoDBWrapper.models.common)
121
+ await MyModel.findOneAndRemove({ _id: id })
122
+ }
123
+
124
+ // The following are the functions added for saving test reports in non HOSTED mode
125
+ const upsertReport = async (reportData) => {
126
+ const conn = await getConnection()
127
+ const MyModel = conn.model('reports', mongoDBWrapper.models.reports)
128
+ reportData._id = `${reportData.runtimeInformation.testReportId}`
129
+ await MyModel.create(reportData)
130
+ }
131
+
132
+ const listReports = async (queryParams) => {
133
+ const conn = await getConnection()
134
+ const MyModel = conn.model('reports', mongoDBWrapper.models.reports)
135
+ const query = {}
136
+ if (queryParams?.filterDateRangeStart || queryParams?.filterDateRangeEnd) {
137
+ query['runtimeInformation.completedTime'] = {}
138
+ if (queryParams?.filterDateRangeStart) {
139
+ query['runtimeInformation.completedTime'].$gte = new Date(queryParams?.filterDateRangeStart)
140
+ }
141
+ if (queryParams?.filterDateRangeEnd) {
142
+ query['runtimeInformation.completedTime'].$lte = new Date(queryParams?.filterDateRangeEnd)
143
+ }
144
+ }
145
+
146
+ if (queryParams?.filterStatus === 'passed') {
147
+ query['runtimeInformation.isPassed'] = true
148
+ } else if (queryParams?.filterStatus === 'failed') {
149
+ query['runtimeInformation.isPassed'] = false
150
+ }
151
+
152
+ // General Query Options like skip and limit
153
+ const generalQueryOptions = {}
154
+ if (queryParams?.skip) {
155
+ generalQueryOptions.skip = queryParams.skip
156
+ }
157
+ if (queryParams?.limit) {
158
+ generalQueryOptions.limit = queryParams.limit
159
+ }
160
+
161
+ const documents = await MyModel.find(query, {}, generalQueryOptions).sort('-runtimeInformation.completedTime').select('_id name runtimeInformation')
162
+ const count = await MyModel.countDocuments(query)
163
+
164
+ return {
165
+ count,
166
+ documents
167
+ }
168
+ }
169
+
170
+ const getReport = async (reportId) => {
171
+ const conn = await getConnection()
172
+ const MyModel = conn.model('reports', mongoDBWrapper.models.reports)
173
+ return await MyModel.findById(reportId)
174
+ }
175
+
176
+ module.exports = {
177
+ read,
178
+ find,
179
+ upsert,
180
+ remove,
181
+ upsertReport,
182
+ listReports,
183
+ getReport
184
+ }
@@ -0,0 +1,64 @@
1
+ const Config = require('../config')
2
+ const { keycloakAuth, getKeyCloakUsers } = require('../oauth/KeycloakHelper')
3
+
4
+ const tempDfspList = [
5
+ {
6
+ id: 'userdfsp',
7
+ name: 'User DFSP'
8
+ },
9
+ {
10
+ id: 'userdfsp1',
11
+ name: 'User DFSP 1'
12
+ },
13
+ {
14
+ id: 'userdfsp2',
15
+ name: 'User DFSP 2'
16
+ }
17
+ ]
18
+
19
+ const getDFSPList = async (defaultTestingToolkitFspId) => {
20
+ const userConfig = await Config.getUserConfig({
21
+ dfspId: defaultTestingToolkitFspId
22
+ })
23
+ const systemConfig = Config.getSystemConfig()
24
+ let users = []
25
+ if (systemConfig.HOSTING_ENABLED) {
26
+ if (systemConfig.KEYCLOAK.ENABLED) {
27
+ const keycloakToken = await keycloakAuth()
28
+ users = await getKeyCloakUsers(keycloakToken)
29
+ } else {
30
+ users = tempDfspList
31
+ }
32
+ } else if (userConfig.HUB_ONLY_MODE) {
33
+ const dfsps = Object.keys(userConfig.ENDPOINTS_DFSP_WISE.dfsps || {})
34
+ if (dfsps.length > 0) {
35
+ dfsps.forEach(dfspId => {
36
+ users.push({
37
+ id: dfspId,
38
+ name: dfspId
39
+ })
40
+ })
41
+ }
42
+ }
43
+ if (users.length === 0) {
44
+ users.push({
45
+ id: userConfig.DEFAULT_USER_FSPID,
46
+ name: 'User DFSP'
47
+ })
48
+ }
49
+ return users
50
+ }
51
+
52
+ const checkDFSP = async (dfspId) => {
53
+ const dfspFound = (await getDFSPList()).find(item => item.id === dfspId)
54
+ if (dfspFound) {
55
+ return true
56
+ } else {
57
+ return false
58
+ }
59
+ }
60
+
61
+ module.exports = {
62
+ getDFSPList,
63
+ checkDFSP
64
+ }
@@ -0,0 +1,78 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Georgi Logodazhki <georgi.logodazhki@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ 'use strict'
31
+
32
+ const mongoose = require('mongoose')
33
+
34
+ const Schema = mongoose.Schema
35
+
36
+ const models = {
37
+ common: new Schema({
38
+ _id: String,
39
+ data: { type: Schema.Types.Mixed }
40
+ }),
41
+ logs: new Schema({
42
+ _id: mongoose.Types.ObjectId,
43
+ uniqueId: {
44
+ type: String,
45
+ required: false
46
+ },
47
+ traceID: {
48
+ type: String,
49
+ required: false
50
+ },
51
+ resource: Object,
52
+ messageType: String,
53
+ notificationType: String,
54
+ verbosity: String,
55
+ message: String,
56
+ additionalData: Schema.Types.Mixed,
57
+ logTime: Date
58
+ }, { _id: false }),
59
+ reports: new Schema({
60
+ _id: String,
61
+ name: String,
62
+ inputValues: Object,
63
+ test_cases: [],
64
+ runtimeInformation: Object
65
+ }).index({ 'runtimeInformation.completedTime': -1, 'runtimeInformation.isPassed': 1 })
66
+ }
67
+
68
+ /* istanbul ignore next */
69
+ process.on('SIGINT', async () => {
70
+ await mongoose.connection.close()
71
+ process.exit(0)
72
+ })
73
+
74
+ module.exports = {
75
+ models,
76
+ connect: mongoose.connect,
77
+ Types: mongoose.Types
78
+ }
@@ -0,0 +1,176 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const MyEventEmitter = require('../MyEventEmitter')
31
+ const EventEmitter = require('events')
32
+ class MyEmitter extends EventEmitter {}
33
+
34
+ const Config = require('../config')
35
+ class InboundEventListener {
36
+ constructor (consoleFn) {
37
+ this.eventListeners = {}
38
+ this.transformer = {}
39
+ this.userConfig = {}
40
+ if (consoleFn) {
41
+ this.consoleFn = consoleFn
42
+ } else {
43
+ this.consoleFn = console
44
+ }
45
+ this.emitter = MyEventEmitter.getEmitter('inboundRequest')
46
+ }
47
+
48
+ async init () {
49
+ this.userConfig = await Config.getStoredUserConfig()
50
+ this.emitter.on('newInbound', (data) => {
51
+ for (const [, eventListener] of Object.entries(this.eventListeners)) {
52
+ // Match method, path and condition for each inbound request
53
+ if (eventListener.method === data.method && eventListener.path === data.path) {
54
+ // Check for condition function
55
+ if (eventListener.conditionFn) {
56
+ if (eventListener.conditionFn(data.headers, data.body)) {
57
+ eventListener.eventEmitter.emit('newMessage', data)
58
+ }
59
+ } else {
60
+ eventListener.eventEmitter.emit('newMessage', data)
61
+ }
62
+ }
63
+ }
64
+ })
65
+ }
66
+
67
+ customLog (logMessage) {
68
+ this.consoleFn.log(logMessage)
69
+ }
70
+
71
+ setTransformer (transformerObj) {
72
+ this.transformer = transformerObj?.transformer || {}
73
+ }
74
+
75
+ addListener (clientName, method, path, conditionFn, timeout = 15000) {
76
+ if (this.eventListeners[clientName]) {
77
+ this.customLog('Event listener already exists with that name')
78
+ } else {
79
+ this.eventListeners[clientName] = {
80
+ method,
81
+ path,
82
+ conditionFn,
83
+ message: null
84
+ }
85
+
86
+ this.customLog('Event listener started')
87
+ this.eventListeners[clientName].eventEmitter = new MyEmitter()
88
+ setTimeout(() => {
89
+ // Auto destroy the event listener after timeout
90
+ this.destroy(clientName)
91
+ }, timeout)
92
+
93
+ this.eventListeners[clientName].eventEmitter.once('newMessage', (message) => {
94
+ this.eventListeners[clientName].message = message
95
+ })
96
+ }
97
+ }
98
+
99
+ getMessage (clientName, timeout = 5000) {
100
+ return new Promise((resolve, reject) => {
101
+ if (!this.eventListeners[clientName]) {
102
+ resolve(null)
103
+ } else {
104
+ // Check for the message received already
105
+ if (this.eventListeners[clientName].message !== null) {
106
+ // Store the message somewhere
107
+ const retMessage = this.parseMessage(this.eventListeners[clientName].message)
108
+ // Destroy the event listener
109
+ this.destroy(clientName)
110
+ // Return the stored message
111
+ // this.customLog('Returning stored message...')
112
+ if (this.transformer.reverseTransform) {
113
+ this.transformer.reverseTransform(retMessage).then((result) => {
114
+ resolve(result)
115
+ }).catch((err) => {
116
+ this.customLog('Error transforming message: ' + err)
117
+ resolve(retMessage)
118
+ })
119
+ } else {
120
+ resolve(retMessage)
121
+ }
122
+ } else {
123
+ // Listen for the new message for some time
124
+ let timer = null
125
+ // Set the timer
126
+ timer = setTimeout(() => {
127
+ try {
128
+ this.customLog('Error: Timeout')
129
+ // Destroy the event listener
130
+ this.destroy(clientName)
131
+ resolve(null)
132
+ } catch (err) {
133
+ reject(err)
134
+ }
135
+ }, timeout)
136
+ // Listen for message
137
+ this.eventListeners[clientName].eventEmitter.once('newMessage', (message) => {
138
+ clearTimeout(timer)
139
+ this.destroy(clientName)
140
+ const retMessage = this.parseMessage(message)
141
+ if (this.transformer.reverseTransform) {
142
+ this.transformer.reverseTransform(retMessage).then((result) => {
143
+ resolve(result)
144
+ }).catch((err) => {
145
+ this.customLog('Error transforming message: ' + err)
146
+ resolve(retMessage)
147
+ })
148
+ } else {
149
+ resolve(retMessage)
150
+ }
151
+ })
152
+ }
153
+ }
154
+ })
155
+ }
156
+
157
+ parseMessage (message) {
158
+ let parsedMessage = message
159
+ try {
160
+ parsedMessage = JSON.parse(message)
161
+ } catch (err) {}
162
+ return parsedMessage
163
+ }
164
+
165
+ destroy (clientName) {
166
+ if (this.eventListeners[clientName]) {
167
+ this.eventListeners[clientName].eventEmitter.removeAllListeners('newMessage')
168
+ delete this.eventListeners[clientName]
169
+ }
170
+ return true
171
+ }
172
+ }
173
+
174
+ module.exports = {
175
+ InboundEventListener
176
+ }
@@ -0,0 +1,57 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Georgi Logodazhki <georgi.logodazhki@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ 'use strict'
31
+
32
+ const utils = require('./utils')
33
+
34
+ const read = async (filename) => {
35
+ const data = await utils.readFileAsync(filename)
36
+ return JSON.parse(data)
37
+ }
38
+
39
+ const readDir = async (filename) => {
40
+ const data = await utils.readDirAsync(filename)
41
+ return data
42
+ }
43
+
44
+ const upsert = async (filename, data) => {
45
+ await utils.writeFileAsync(filename, JSON.stringify(data, null, 2))
46
+ }
47
+
48
+ const remove = async (filename) => {
49
+ await utils.deleteFileAsync(filename)
50
+ }
51
+
52
+ module.exports = {
53
+ read,
54
+ readDir,
55
+ upsert,
56
+ remove
57
+ }
@@ -0,0 +1,135 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 Mojaloop Foundation
5
+ The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ Contributors
12
+ --------------
13
+ This is the official list of the Mojaloop project contributors for this file.
14
+ Names of the original copyright holders (individuals or organizations)
15
+ should be listed with a '*' in the first column. People who have
16
+ contributed from an organization can be listed under the organization
17
+ that actually holds the copyright for their contributions (see the
18
+ Mojaloop Foundation for an example). Those individuals should have
19
+ their names indented and be marked with a '-'. Email address can be added
20
+ optionally within square brackets <email>.
21
+
22
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const http = require('http')
31
+ const https = require('https')
32
+ const _ = require('lodash')
33
+ const customLogger = require('./requestLogger')
34
+ const Config = require('./config')
35
+
36
+ const httpAgentStore = {}
37
+ const httpsAgentStore = {}
38
+
39
+ const _createAgent = (agentModule, options) => {
40
+ customLogger.logMessage('info', 'Creating new http/https agent', { notification: false })
41
+ const httpAgent = new agentModule.Agent({
42
+ ...options,
43
+ keepAlive: (Config.getSystemConfig().HTTP_CLIENT && Config.getSystemConfig().HTTP_CLIENT.KEEP_ALIVE) || true,
44
+ maxSockets: (Config.getSystemConfig().HTTP_CLIENT && Config.getSystemConfig().HTTP_CLIENT.MAX_SOCKETS) || 50
45
+ })
46
+ httpAgent.toJSON = () => ({})
47
+ return httpAgent
48
+ }
49
+
50
+ const _addAgentStoreItem = (agentStore, key, passedOptions, agent) => {
51
+ // Create a new entry in the store
52
+ agentStore[key] = {
53
+ createdDate: Date.now(),
54
+ lastAccessDate: Date.now(),
55
+ lastModifiedDate: Date.now(),
56
+ passedOptions,
57
+ agent
58
+ }
59
+ }
60
+
61
+ const _replaceAgentStoreItem = (agentStore, key, passedOptions, agent) => {
62
+ agentStore[key].agent = agent
63
+ agentStore[key].passedOptions = passedOptions
64
+ agentStore[key].lastModifiedDate = Date.now()
65
+ }
66
+
67
+ const _compareAgentStoreItemOptions = (agentStore, key, options) => {
68
+ return _.isEqual(options, agentStore[key].passedOptions)
69
+ }
70
+
71
+ const _pickAgentStoreItem = (agentStore, key) => {
72
+ customLogger.logMessage('info', 'Using existing http/https agent for ' + key, { notification: false })
73
+ agentStore[key].lastAccessDate = Date.now()
74
+ }
75
+
76
+ const getHttpAgent = (key, options) => {
77
+ if (!httpAgentStore[key]) {
78
+ const httpAgent = _createAgent(http, options)
79
+ _addAgentStoreItem(httpAgentStore, key, options, httpAgent)
80
+ } else {
81
+ if (!_compareAgentStoreItemOptions(httpAgentStore, key, options)) {
82
+ const httpAgent = _createAgent(http, options)
83
+ _replaceAgentStoreItem(httpAgentStore, key, options, httpAgent)
84
+ }
85
+ _pickAgentStoreItem(httpAgentStore, key)
86
+ }
87
+ return httpAgentStore[key].agent
88
+ }
89
+
90
+ const getHttpsAgent = (key, options) => {
91
+ if (!httpsAgentStore[key]) {
92
+ const httpsAgent = _createAgent(https, options)
93
+ _addAgentStoreItem(httpsAgentStore, key, options, httpsAgent)
94
+ } else {
95
+ if (!_compareAgentStoreItemOptions(httpsAgentStore, key, options)) {
96
+ const httpsAgent = _createAgent(http, options)
97
+ _replaceAgentStoreItem(httpsAgentStore, key, options, httpsAgent)
98
+ }
99
+ _pickAgentStoreItem(httpsAgentStore, key)
100
+ }
101
+ return httpsAgentStore[key].agent
102
+ }
103
+
104
+ const _clear = (agentStoreObj, interval) => {
105
+ for (const item in agentStoreObj) {
106
+ const timeDiff = Date.now() - agentStoreObj[item].lastAccessDate
107
+ if (timeDiff >= interval) {
108
+ // TODO: Check the current socket connections that this agent is using. Destroy only if the agent is free
109
+ try {
110
+ customLogger.logMessage('info', 'Destroying http/https agent for ' + item + ': Timeout reached ' + timeDiff + 'ms', { notification: false })
111
+ agentStoreObj[item].agent.destroy()
112
+ } catch (err) {
113
+ console.log('INFO: Error destroying http/https agent', err.stack)
114
+ }
115
+ delete agentStoreObj[item]
116
+ }
117
+ }
118
+ }
119
+
120
+ const _clearAgents = (unUsedAgentsExpiryMs) => {
121
+ _clear(httpsAgentStore, unUsedAgentsExpiryMs)
122
+ _clear(httpAgentStore, unUsedAgentsExpiryMs)
123
+ }
124
+
125
+ const init = () => {
126
+ const timerInterval = (Config.getSystemConfig().HTTP_CLIENT && Config.getSystemConfig().HTTP_CLIENT.UNUSED_AGENTS_CHECK_TIMER_MS !== undefined) ? Config.getSystemConfig().HTTP_CLIENT.UNUSED_AGENTS_CHECK_TIMER_MS : (5 * 60 * 1000) // Check for the cleanup every 5min
127
+ const unUsedAgentsExpiryMs = (Config.getSystemConfig().HTTP_CLIENT && Config.getSystemConfig().HTTP_CLIENT.UNUSED_AGENTS_EXPIRY_MS !== undefined) ? Config.getSystemConfig().HTTP_CLIENT.UNUSED_AGENTS_EXPIRY_MS : (30 * 60 * 1000) // Clear http agents not being used for more this time
128
+ setInterval(_clearAgents, timerInterval, unUsedAgentsExpiryMs)
129
+ }
130
+
131
+ module.exports = {
132
+ getHttpAgent,
133
+ getHttpsAgent,
134
+ init
135
+ }