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.
- package/.dockerignore +10 -0
- package/.grype.yaml +16 -0
- package/.ncurc.yaml +9 -0
- package/.nvmrc +1 -0
- package/.versionrc.js +16 -0
- package/CHANGELOG.md +504 -0
- package/CODEOWNERS +30 -0
- package/Dockerfile +42 -0
- package/Dockerfile-newman +13 -0
- package/LICENSE.md +9 -0
- package/README.md +119 -0
- package/assets/diagrams/architectural/architectural-diagram.svg +3 -0
- package/assets/diagrams/flow/flow-diagram.svg +3 -0
- package/assets/images/Sample-Response-Failure.png +0 -0
- package/assets/images/Screenshot 2020-04-16 at 22.58.04.png +0 -0
- package/assets/images/TLS-Enabled-on-Environment.png +0 -0
- package/assets/images/adapter-mutual-tls-enabled.png +0 -0
- package/assets/images/add-additional-input-values.png +0 -0
- package/assets/images/add-condition-button.png +0 -0
- package/assets/images/add-new-assertion.png +0 -0
- package/assets/images/add-new-input-value.png +0 -0
- package/assets/images/add-new-input-variable.png +0 -0
- package/assets/images/additional-transfers.png +0 -0
- package/assets/images/api-provisioning-add-new-api-confirmation.png +0 -0
- package/assets/images/api-provisioning-file-input-window.png +0 -0
- package/assets/images/api-provisioning-list-apis-view.png +0 -0
- package/assets/images/api-provisioning-menu-item.png +0 -0
- package/assets/images/apply_and_restart.jpg +0 -0
- package/assets/images/assess-request-or-response.png +0 -0
- package/assets/images/assess-response-equation-save.png +0 -0
- package/assets/images/assess-response-equation.png +0 -0
- package/assets/images/assess-response-status.png +0 -0
- package/assets/images/building-new-rules-file.png +0 -0
- package/assets/images/callback-rules-screen.png +0 -0
- package/assets/images/configurable-parameter-assertion.png +0 -0
- package/assets/images/configurable-parameter-currency.png +0 -0
- package/assets/images/configurable-parameter.png +0 -0
- package/assets/images/connection-manager-ui-opening.png +0 -0
- package/assets/images/create-inbound-user-simulator.png +0 -0
- package/assets/images/creating-new-rule-file.png +0 -0
- package/assets/images/dfsp-client-cacert.png +0 -0
- package/assets/images/dfsp-client-submit.png +0 -0
- package/assets/images/dfsp-client.png +0 -0
- package/assets/images/dfsp-p2p-happy-path.png +0 -0
- package/assets/images/dfsp-server-cacert.png +0 -0
- package/assets/images/dfsp-server-cert.png +0 -0
- package/assets/images/download-report.png +0 -0
- package/assets/images/drive_have_not_been_shared.jpg +0 -0
- package/assets/images/event-response-options.png +0 -0
- package/assets/images/expand-monitoring-messages.png +0 -0
- package/assets/images/fixed-response-sample.png +0 -0
- package/assets/images/header-selection.png +0 -0
- package/assets/images/heap_error_windows.jpg +0 -0
- package/assets/images/hosted-mode-docker-compose-intro.png +0 -0
- package/assets/images/hub-client-cert.png +0 -0
- package/assets/images/import-template.png +0 -0
- package/assets/images/inbound-requests-environment.png +0 -0
- package/assets/images/inbound-requests-scripts.png +0 -0
- package/assets/images/jws-certificate-submit.png +0 -0
- package/assets/images/jws-certificate.png +0 -0
- package/assets/images/jws-certs-keys.png +0 -0
- package/assets/images/jws-hub-certs-keys.png +0 -0
- package/assets/images/local-enable-jws-publickey.png +0 -0
- package/assets/images/local-mutual-tls-enabled.png +0 -0
- package/assets/images/local_drives_to_be_available.jpg +0 -0
- package/assets/images/mcm-environment-opening.png +0 -0
- package/assets/images/menu-items.png +0 -0
- package/assets/images/mock-response-sample.png +0 -0
- package/assets/images/monitoring-initial-state.png +0 -0
- package/assets/images/monitoring-messages.png +0 -0
- package/assets/images/new-empty-assertion.png +0 -0
- package/assets/images/opened-imported-template.png +0 -0
- package/assets/images/opening-default-settings.png +0 -0
- package/assets/images/opening-sync-response-rules.png +0 -0
- package/assets/images/opening-view.png +0 -0
- package/assets/images/outbound-display-opening-hub.png +0 -0
- package/assets/images/outbound-display-opening.png +0 -0
- package/assets/images/override-with-environment-variable.png +0 -0
- package/assets/images/populate-with-sample-body.png +0 -0
- package/assets/images/resource-selection.png +0 -0
- package/assets/images/rule-builder-select-api.png +0 -0
- package/assets/images/sample-condition-add-configurable-params.png +0 -0
- package/assets/images/sample-condition.png +0 -0
- package/assets/images/sample-editor.png +0 -0
- package/assets/images/sample-request.png +0 -0
- package/assets/images/sample-test-assertion.png +0 -0
- package/assets/images/send-transfer.png +0 -0
- package/assets/images/sending-single-test-case-1.png +0 -0
- package/assets/images/sending-single-test-case-2.png +0 -0
- package/assets/images/sending-test-cases.png +0 -0
- package/assets/images/server-certificates-submitted.png +0 -0
- package/assets/images/simulator-response.png +0 -0
- package/assets/images/simulator-scheme-adapter-endpoint.png +0 -0
- package/assets/images/summarized-view-of-rule.png +0 -0
- package/assets/images/template-window.png +0 -0
- package/assets/images/test-case-editor-console-log.png +0 -0
- package/assets/images/test-case-editor-environment-state.png +0 -0
- package/assets/images/test-case-editor-scripts.png +0 -0
- package/assets/images/test-case-editor.png +0 -0
- package/assets/images/testcase-definition-download.png +0 -0
- package/assets/images/testcase-definition-edit-meta-info.png +0 -0
- package/assets/images/testing-toolkit-mojaloop-testing-toolkit-endpoint.png +0 -0
- package/assets/images/tls-hub-certs-keys.png +0 -0
- package/assets/images/tls-jws-enabled-on-environment.png +0 -0
- package/assets/images/updated-sample-body-data.png +0 -0
- package/assets/images/using-configurable-parameter.png +0 -0
- package/assets/images/validation-rules-screen.png +0 -0
- package/assets/images/view-response.png +0 -0
- package/audit-ci.jsonc +7 -0
- package/connection-manager/docker-compose.yml +55 -0
- package/database/docker-compose.yml +16 -0
- package/docker/hosted-mode/docker-compose.yaml +107 -0
- package/docker/hosted-mode/keycloak/keycloak-realm.json +2298 -0
- package/docker/hosted-mode/mongo-init.sh +1 -0
- package/docker/hosted-mode-tls/docker-compose.yaml +171 -0
- package/docker/hosted-mode-tls/keycloak/keycloak-realm.json +2298 -0
- package/docker/hosted-mode-tls/mongo-init.sh +1 -0
- package/docker-compose.yml +62 -0
- package/documents/Mojaloop-Testing-Toolkit.md +296 -0
- package/documents/RULES_ENGINE.md +403 -0
- package/documents/User-Guide-API-Provisioning.md +121 -0
- package/documents/User-Guide-CLI.md +218 -0
- package/documents/User-Guide-Connection-Manager.md +282 -0
- package/documents/User-Guide-Frequently-Asked-Questions.md +39 -0
- package/documents/User-Guide-Hosted-Mode-Docker-Compose.md +110 -0
- package/documents/User-Guide-Installation.md +163 -0
- package/documents/User-Guide-Mojaloop-Testing-Toolkit.md +642 -0
- package/documents/User-Guide-OAuth-Server-Deployment.md +283 -0
- package/documents/User-Guide-Onboarding-DFSP.md +197 -0
- package/documents/User-Guide-Onboarding-HUB.md +191 -0
- package/documents/User-Guide.md +53 -0
- package/examples/collections/dfsp/p2p_failed_tests.json +7161 -0
- package/examples/collections/dfsp/p2p_fx_happy_path.json +502 -0
- package/examples/collections/dfsp/p2p_happy_path.json +350 -0
- package/examples/collections/dfsp/p2p_happy_path_extended.json +6106 -0
- package/examples/collections/dfsp/p2p_happy_path_jws.json +511 -0
- package/examples/collections/dfsp/p2p_payee_assertions_websocket.json +441 -0
- package/examples/collections/dfsp/sample.json +5029 -0
- package/examples/collections/dfsp/transaction_request_service.json +240 -0
- package/examples/collections/fxp/FXP.json +264 -0
- package/examples/collections/fxp/SDK_backend.json +98 -0
- package/examples/collections/fxp/SDK_outbound.json +163 -0
- package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_receive_quote.json +400 -0
- package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_send_quote.json +395 -0
- package/examples/collections/hub/hub_02_block_transfer/hub_block_transfer.json +393 -0
- package/examples/collections/hub/hub_03_funds_in_out/hub_funds_in.json +224 -0
- package/examples/collections/hub/hub_03_funds_in_out/hub_funds_out.json +780 -0
- package/examples/collections/hub/hub_04_settlements/hub_settlements.json +3138 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_abort.json +475 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_invalid_fulfillment.json +370 -0
- package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_transfer_timeout.json +262 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_authorizations.json +117 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_error_framework.json +591 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_received_state.json +379 -0
- package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_reject_state.json +361 -0
- package/examples/collections/hub/hub_07_quoting_service.json +525 -0
- package/examples/collections/hub/hub_08_participant_inactive_stop_transfers.json +706 -0
- package/examples/collections/hub/hub_09_duplicate_handling_transfers.json +1377 -0
- package/examples/collections/hub/hub_10_on_us_transfers.json +245 -0
- package/examples/collections/hub/hub_11_accented_and_spl_chars.json +629 -0
- package/examples/collections/hub/hub_12_fspiop_version_1.1.json +646 -0
- package/examples/collections/hub/hub_13_bulk_transfers.json +1857 -0
- package/examples/collections/iso20022/self_referencing_iso20022.json +926 -0
- package/examples/collections/provisioning/testingtoolkitdfsp.json +904 -0
- package/examples/environments/dfsp_local_environment.json +46 -0
- package/examples/environments/hub_local_environment.json +57 -0
- package/jest.config.js +17 -0
- package/package.json +199 -0
- package/sbom-v18.12.4.csv +1553 -0
- package/secrets/keygen.sh +5 -0
- package/secrets/privatekey.pem +27 -0
- package/secrets/publickey.cer +21 -0
- package/secrets/tls/01.pem +132 -0
- package/secrets/tls/createSecrets.sh +20 -0
- package/secrets/tls/hub_client.csr +32 -0
- package/secrets/tls/hub_client_cacert.pem +35 -0
- package/secrets/tls/hub_client_cakey.pem +52 -0
- package/secrets/tls/hub_client_key.key +52 -0
- package/secrets/tls/hub_server.csr +31 -0
- package/secrets/tls/hub_server_cacert.pem +35 -0
- package/secrets/tls/hub_server_cakey.pem +52 -0
- package/secrets/tls/hub_server_cert.pem +132 -0
- package/secrets/tls/hub_server_key.key +52 -0
- package/secrets/tls/index.txt +1 -0
- package/secrets/tls/index.txt.attr +1 -0
- package/secrets/tls/openssl-client.cnf +36 -0
- package/secrets/tls/openssl-clientca.cnf +71 -0
- package/secrets/tls/openssl-server.cnf +39 -0
- package/secrets/tls/openssl-serverca.cnf +71 -0
- package/secrets/tls/serial.txt +1 -0
- package/spec_files/api_definitions/als_admin_1.1/api_spec.yaml +804 -0
- package/spec_files/api_definitions/central_admin_1.0/api_spec.yaml +1850 -0
- package/spec_files/api_definitions/central_admin_1.0/response_map.json +96 -0
- package/spec_files/api_definitions/central_admin_old_9.3/api_spec.yaml +2467 -0
- package/spec_files/api_definitions/central_admin_old_9.3/response_map.json +96 -0
- package/spec_files/api_definitions/fspiop_1.0/api_spec.yaml +4187 -0
- package/spec_files/api_definitions/fspiop_1.0/callback_map.json +568 -0
- package/spec_files/api_definitions/fspiop_1.0/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup.json +126 -0
- package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup_quotes_only.json +97 -0
- package/spec_files/api_definitions/fspiop_1.1/api_spec.yaml +3778 -0
- package/spec_files/api_definitions/fspiop_1.1/callback_map.json +568 -0
- package/spec_files/api_definitions/fspiop_1.1/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_1.1/trigger_templates/transaction_request_followup.json +125 -0
- package/spec_files/api_definitions/fspiop_2.0/api_spec.yaml +4839 -0
- package/spec_files/api_definitions/fspiop_2.0/callback_map.json +716 -0
- package/spec_files/api_definitions/fspiop_2.0/mockRef.json +79 -0
- package/spec_files/api_definitions/fspiop_2.0/trigger_templates/transaction_request_followup.json +125 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/api_spec.yaml +8331 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/callback_map.json +508 -0
- package/spec_files/api_definitions/fspiop_2.0_iso20022/mockRef.json +66 -0
- package/spec_files/api_definitions/fx-api_2.0/api_spec.yaml +1768 -0
- package/spec_files/api_definitions/fx-api_2.0/callback_map.json +188 -0
- package/spec_files/api_definitions/fx-api_2.0/mockRef.json +83 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/api_spec.yaml +2612 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/mockRef.json +22 -0
- package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/response_map.json +35 -0
- package/spec_files/api_definitions/mojaloop_simulator_0.1/api_spec.yaml +225 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/api_spec.yaml +1087 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/mockRef.json +75 -0
- package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/response_map.json +55 -0
- package/spec_files/api_definitions/payment_manager_1.4/api_spec.yaml +1389 -0
- package/spec_files/api_definitions/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +2834 -0
- package/spec_files/api_definitions/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +3449 -0
- package/spec_files/api_definitions/settlements_1.0/api_spec.yaml +983 -0
- package/spec_files/api_definitions/settlements_1.0/mockRef.json +38 -0
- package/spec_files/api_definitions/settlements_1.0/response_map.json +34 -0
- package/spec_files/api_definitions/settlements_2.0/api_spec.yaml +1001 -0
- package/spec_files/api_definitions/settlements_2.0/mockRef.json +38 -0
- package/spec_files/api_definitions/settlements_2.0/response_map.json +34 -0
- package/spec_files/api_definitions/thirdparty_sdk_outbound_0.1/api_spec.yaml +2139 -0
- package/spec_files/reports/templates/newman/html_template.html +1202 -0
- package/spec_files/reports/templates/newman/pdf_template.html +790 -0
- package/spec_files/reports/templates/testcase_definition/table_view.html +1602 -0
- package/spec_files/rules_callback/config.json +3 -0
- package/spec_files/rules_callback/default.json +2698 -0
- package/spec_files/rules_callback/p2p-limit.json +129 -0
- package/spec_files/rules_forward/config.json +3 -0
- package/spec_files/rules_forward/default.json +482 -0
- package/spec_files/rules_response/config.json +3 -0
- package/spec_files/rules_response/default.json +295 -0
- package/spec_files/rules_validation/config.json +3 -0
- package/spec_files/rules_validation/default.json +1 -0
- package/spec_files/rules_validation/p2p-limit.json +55 -0
- package/spec_files/system_config.json +175 -0
- package/spec_files/user_config.json +109 -0
- package/src/index.js +67 -0
- package/src/lib/MyEventEmitter.js +54 -0
- package/src/lib/api-management.js +143 -0
- package/src/lib/api-routes/config.js +83 -0
- package/src/lib/api-routes/history.js +139 -0
- package/src/lib/api-routes/keycloak.js +54 -0
- package/src/lib/api-routes/longpolling.js +70 -0
- package/src/lib/api-routes/oauth2.js +149 -0
- package/src/lib/api-routes/objectstore.js +53 -0
- package/src/lib/api-routes/openapi.js +224 -0
- package/src/lib/api-routes/outbound.js +134 -0
- package/src/lib/api-routes/reports.js +72 -0
- package/src/lib/api-routes/rules.js +356 -0
- package/src/lib/api-routes/samples.js +92 -0
- package/src/lib/api-routes/server-logs.js +44 -0
- package/src/lib/api-routes/settings.js +71 -0
- package/src/lib/api-server.js +135 -0
- package/src/lib/arrayStore.js +101 -0
- package/src/lib/callbackHandler.js +201 -0
- package/src/lib/config.js +177 -0
- package/src/lib/configuration-providers/mb-connection-manager.js +625 -0
- package/src/lib/db/adapters/dbAdapter.js +184 -0
- package/src/lib/db/dfspMockUsers.js +64 -0
- package/src/lib/db/models/mongoDBWrapper.js +78 -0
- package/src/lib/eventListenerClient/inboundEventListener.js +176 -0
- package/src/lib/fileAdapter.js +57 -0
- package/src/lib/httpAgentStore.js +135 -0
- package/src/lib/importExport.js +186 -0
- package/src/lib/jws/JwsSigning.js +141 -0
- package/src/lib/loadSamples.js +128 -0
- package/src/lib/logger.js +20 -0
- package/src/lib/longpollingEmitter.js +56 -0
- package/src/lib/metrics.js +51 -0
- package/src/lib/mocking/custom-functions/generic.js +57 -0
- package/src/lib/mocking/middleware-functions/ilpModel.js +238 -0
- package/src/lib/mocking/middleware-functions/quotesAssociation.js +75 -0
- package/src/lib/mocking/middleware-functions/transactionRequestsService.js +78 -0
- package/src/lib/mocking/openApiDefinitionsModel.js +64 -0
- package/src/lib/mocking/openApiMockHandler.js +466 -0
- package/src/lib/mocking/openApiRulesEngine.js +492 -0
- package/src/lib/mocking/openApiVersionTools.js +136 -0
- package/src/lib/mocking/transformers/fspiopToISO20022.js +230 -0
- package/src/lib/mocking/transformers/index.js +41 -0
- package/src/lib/notificationEmitter.js +64 -0
- package/src/lib/oauth/KeycloakHelper.js +220 -0
- package/src/lib/oauth/LoginService.js +133 -0
- package/src/lib/oauth/OAuthHelper.js +181 -0
- package/src/lib/oauth/OAuthValidator.js +118 -0
- package/src/lib/oauth/Wso2Client.js +64 -0
- package/src/lib/objectStore/inMemoryImpl.js +50 -0
- package/src/lib/objectStore/objectStoreInterface.js +51 -0
- package/src/lib/objectStore.js +122 -0
- package/src/lib/report-generator/generator.js +126 -0
- package/src/lib/report-generator/helpers.js +154 -0
- package/src/lib/requestLogger.js +190 -0
- package/src/lib/resources/wso2carbon-publickey.cert +20 -0
- package/src/lib/rulesEngine.js +95 -0
- package/src/lib/rulesEngineModel.js +463 -0
- package/src/lib/scripting-engines/postman-sandbox.js +142 -0
- package/src/lib/scripting-engines/vm-javascript-sandbox.js +294 -0
- package/src/lib/server-logs/adapters/elastic-search.js +102 -0
- package/src/lib/server-logs/adapters/grafana.js +0 -0
- package/src/lib/server-logs/index.js +75 -0
- package/src/lib/socket-server.js +55 -0
- package/src/lib/storageAdapter.js +109 -0
- package/src/lib/test-outbound/TestCaseRunner.js +173 -0
- package/src/lib/test-outbound/getTracing.js +19 -0
- package/src/lib/test-outbound/outbound-initiator.js +1107 -0
- package/src/lib/uniqueIdGenerator.js +35 -0
- package/src/lib/utils.js +89 -0
- package/src/lib/utilsInternal.js +56 -0
- package/src/lib/webSocketClient/WebSocketClientManager.js +197 -0
- 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
|
+
}
|