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,466 @@
|
|
|
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>
|
|
27
|
+
* Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
|
|
28
|
+
--------------
|
|
29
|
+
******/
|
|
30
|
+
|
|
31
|
+
'use strict'
|
|
32
|
+
|
|
33
|
+
const addFormats = require('ajv-formats')
|
|
34
|
+
const OpenApiBackend = require('openapi-backend').default
|
|
35
|
+
const OpenApiDefinitionsModel = require('./openApiDefinitionsModel')
|
|
36
|
+
const OpenApiVersionTools = require('./openApiVersionTools')
|
|
37
|
+
const customLogger = require('../requestLogger')
|
|
38
|
+
const OpenApiRulesEngine = require('./openApiRulesEngine')
|
|
39
|
+
const CallbackHandler = require('../callbackHandler')
|
|
40
|
+
const _ = require('lodash')
|
|
41
|
+
const MyEventEmitter = require('../MyEventEmitter')
|
|
42
|
+
const utils = require('../utils')
|
|
43
|
+
const Config = require('../config')
|
|
44
|
+
const objectStore = require('../objectStore')
|
|
45
|
+
const arrayStore = require('../arrayStore')
|
|
46
|
+
const JwsSigning = require('../jws/JwsSigning')
|
|
47
|
+
|
|
48
|
+
const path = require('path')
|
|
49
|
+
|
|
50
|
+
const IlpModel = require('./middleware-functions/ilpModel')
|
|
51
|
+
const { generateULID } = require('./custom-functions/generic')
|
|
52
|
+
|
|
53
|
+
let apis = []
|
|
54
|
+
|
|
55
|
+
// TODO: Implement a logger and log the messages with different verbosity
|
|
56
|
+
// TODO: Write unit tests
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Operations on /
|
|
60
|
+
*/
|
|
61
|
+
module.exports.initilizeMockHandler = async () => {
|
|
62
|
+
// Initialize ILP
|
|
63
|
+
IlpModel.init((await Config.getUserConfig()).ILP_SECRET)
|
|
64
|
+
// Get API Definitions from configuration
|
|
65
|
+
const apiDefinitions = await OpenApiDefinitionsModel.getApiDefinitions()
|
|
66
|
+
// Create create openApiBackend objects for all the api definitions
|
|
67
|
+
apis = apiDefinitions.map(item => {
|
|
68
|
+
const tempObj = new OpenApiBackend({
|
|
69
|
+
definition: path.join(item.specFile),
|
|
70
|
+
customizeAjv: ajv => addFormats(ajv),
|
|
71
|
+
strict: true,
|
|
72
|
+
quick: true,
|
|
73
|
+
handlers: {
|
|
74
|
+
notImplemented: async (context, req, h) => {
|
|
75
|
+
const resp = await openApiBackendNotImplementedHandler(context, req, h, item)
|
|
76
|
+
return resp
|
|
77
|
+
},
|
|
78
|
+
validationFail: async (context, req, h) => {
|
|
79
|
+
const extensionList = [{
|
|
80
|
+
key: 'keyword',
|
|
81
|
+
value: context.validation.errors[0].keyword
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
key: 'instancePath',
|
|
85
|
+
value: context.validation.errors[0].instancePath
|
|
86
|
+
}]
|
|
87
|
+
for (const [key, value] of Object.entries(context.validation.errors[0].params)) {
|
|
88
|
+
extensionList.push({ key, value })
|
|
89
|
+
}
|
|
90
|
+
return h.response(errorResponseBuilder('3100', context.validation.errors[0].message, { extensionList })).code(400)
|
|
91
|
+
},
|
|
92
|
+
notFound: async (context, req, h) => {
|
|
93
|
+
customLogger.logMessage('error', 'Resource not found', { request: req })
|
|
94
|
+
return h.response({ error: 'Not Found' }).code(404)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
...item,
|
|
101
|
+
openApiBackendObject: tempObj
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
for (const api of apis) {
|
|
106
|
+
customLogger.logMessage('info', 'Initializing the api spec file: ' + api.specFile, { notification: false })
|
|
107
|
+
await api.openApiBackendObject.init()
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports.handleRequest = async (req, h) => {
|
|
112
|
+
// JWS Validation
|
|
113
|
+
try {
|
|
114
|
+
const jwsValidated = await JwsSigning.validate(req)
|
|
115
|
+
if (jwsValidated) {
|
|
116
|
+
customLogger.logMessage('debug', 'JWS Signature Validated', { request: req })
|
|
117
|
+
}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// TODO: The errorCode should be checked with the api specification
|
|
120
|
+
customLogger.logMessage('error', 'JWS validation failed', { additionalData: err.message, request: req })
|
|
121
|
+
return h.response(errorResponseBuilder('3105', 'Invalid signature')).code(400)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let selectedApi
|
|
125
|
+
// Pick a right api definition by searching for the requested resource in the definitions sequentially
|
|
126
|
+
// TODO: This should be optimized by defining a hash table (object) of all the resources in all definition files on startup.
|
|
127
|
+
|
|
128
|
+
const pickedApis = pickApiByMethodPathHostnameAndPrefix(req)
|
|
129
|
+
|
|
130
|
+
// Let's pick the first one for now and swap it with the right version later
|
|
131
|
+
selectedApi = pickedApis.length > 0 ? pickedApis[0] : null
|
|
132
|
+
|
|
133
|
+
if (!selectedApi) {
|
|
134
|
+
customLogger.logMessage('error', 'Resource not found', { request: req })
|
|
135
|
+
return h.response({ error: 'Not Found' }).code(404)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Modify request
|
|
139
|
+
if (selectedApi && selectedApi.prefix) {
|
|
140
|
+
req.path = req.path.slice(selectedApi.prefix.length)
|
|
141
|
+
customLogger.logMessage('info', 'Trimmed prefix from request path: ' + selectedApi.prefix, { request: req })
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if ((selectedApi.type === 'fspiop' || selectedApi.type === 'iso20022') && (await Config.getUserConfig(req.customInfo.user)).VERSIONING_SUPPORT_ENABLE) {
|
|
145
|
+
// Validate accept header for POST & GET.
|
|
146
|
+
if (req.method === 'post' || req.method === 'get') {
|
|
147
|
+
// Validate the accept header here
|
|
148
|
+
const acceptHeaderValidationResult = OpenApiVersionTools.validateAcceptHeader(req.headers.accept)
|
|
149
|
+
if (acceptHeaderValidationResult.validationFailed) {
|
|
150
|
+
return h.response(errorResponseBuilder('3001', acceptHeaderValidationResult.message)).code(400)
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
// Validate content-type header for all the remaining requests
|
|
154
|
+
const contentTypeHeaderValidationResult = OpenApiVersionTools.validateContentTypeHeader(req.headers['content-type'])
|
|
155
|
+
if (contentTypeHeaderValidationResult.validationFailed) {
|
|
156
|
+
return h.response(errorResponseBuilder('3001', contentTypeHeaderValidationResult.message)).code(400)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Pick the right API object based on the major and minor versions (Version negotiation as per the API Definition file)
|
|
160
|
+
const versionNegotiationResult = OpenApiVersionTools.negotiateVersion(req, pickedApis)
|
|
161
|
+
if (versionNegotiationResult.negotiationFailed) {
|
|
162
|
+
// Create extensionList property as per the API specification document with supported versions
|
|
163
|
+
const extensionList = pickedApis.map(item => {
|
|
164
|
+
return {
|
|
165
|
+
key: item.majorVersion + '',
|
|
166
|
+
value: item.minorVersion + ''
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
return h.response(errorResponseBuilder('3001', 'The Client requested an unsupported version, see extension list for supported version(s).', { extensionList })).code(406)
|
|
170
|
+
}
|
|
171
|
+
req.customInfo.negotiatedContentType = versionNegotiationResult.responseContentTypeHeader
|
|
172
|
+
selectedApi = pickedApis[versionNegotiationResult.negotiatedIndex]
|
|
173
|
+
req.customInfo.selectedApi = selectedApi
|
|
174
|
+
}
|
|
175
|
+
customLogger.logMessage('info', 'API matched: ' + selectedApi.type, { request: req })
|
|
176
|
+
try {
|
|
177
|
+
return await selectedApi.openApiBackendObject.handleRequest(
|
|
178
|
+
{
|
|
179
|
+
method: req.method,
|
|
180
|
+
path: req.path,
|
|
181
|
+
body: req.payload,
|
|
182
|
+
query: req.query,
|
|
183
|
+
headers: req.headers
|
|
184
|
+
},
|
|
185
|
+
req,
|
|
186
|
+
h
|
|
187
|
+
)
|
|
188
|
+
} catch (err) {
|
|
189
|
+
customLogger.logMessage('error', err.message, { request: req })
|
|
190
|
+
return h.response({ error: 'Not Found' }).code(404)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const pickApiByMethodPathHostnameAndPrefix = (req) => {
|
|
195
|
+
let potentialApis = apis
|
|
196
|
+
|
|
197
|
+
// Match path
|
|
198
|
+
const matchedPrefixApis = apis.filter(item => {
|
|
199
|
+
return item.prefix ? req.path.startsWith(item.prefix) : false
|
|
200
|
+
})
|
|
201
|
+
if (matchedPrefixApis.length > 0) {
|
|
202
|
+
return matchedPrefixApis.filter(item => {
|
|
203
|
+
return item.openApiBackendObject.matchOperation({ ...req, path: req.path.slice(item.prefix.length) })
|
|
204
|
+
})
|
|
205
|
+
} else {
|
|
206
|
+
// apis without prefix
|
|
207
|
+
potentialApis = potentialApis.filter(item => {
|
|
208
|
+
return !item.prefix
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Match hostnames
|
|
213
|
+
const matchedHostnameApis = potentialApis.filter(item => {
|
|
214
|
+
return item.hostnames && req.info && req.info.hostname ? item.hostnames.includes(req.info.hostname) : false
|
|
215
|
+
})
|
|
216
|
+
potentialApis = matchedHostnameApis.length > 0 ? matchedHostnameApis : potentialApis.filter(item => !item.hostnames || item.hostnames.length === 0)
|
|
217
|
+
|
|
218
|
+
// FSPIOP and ISO20022 version negotiation
|
|
219
|
+
let headerToCompare = req.headers['content-type']
|
|
220
|
+
if (req.method === 'get') {
|
|
221
|
+
headerToCompare = req.headers.accept
|
|
222
|
+
}
|
|
223
|
+
const headerComparisonResult = OpenApiVersionTools.parseAcceptHeader(headerToCompare)
|
|
224
|
+
if (headerComparisonResult && (headerComparisonResult.apiType === 'fspiop' || headerComparisonResult.apiType === 'iso20022')) {
|
|
225
|
+
potentialApis = potentialApis.filter(item => {
|
|
226
|
+
return item.type === headerComparisonResult.apiType
|
|
227
|
+
})
|
|
228
|
+
} else {
|
|
229
|
+
// Filter out the apis fspiop or iso20022
|
|
230
|
+
potentialApis = potentialApis.filter(item => {
|
|
231
|
+
return item.type !== 'fspiop' && item.type !== 'iso20022'
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const pickedApis = potentialApis.filter(item => {
|
|
236
|
+
return item.openApiBackendObject.matchOperation(req)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
return pickedApis
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const errorResponseBuilder = (errorCode, errorDescription, additionalProperties = null) => {
|
|
243
|
+
return {
|
|
244
|
+
errorInformation: {
|
|
245
|
+
errorCode,
|
|
246
|
+
errorDescription,
|
|
247
|
+
...additionalProperties
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
module.exports.getOpenApiObjects = () => {
|
|
253
|
+
return apis
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const openApiBackendNotImplementedHandler = async (context, req, h, item) => {
|
|
257
|
+
customLogger.logMessage('debug', 'Schema Validation Passed', { request: req })
|
|
258
|
+
MyEventEmitter.getEmitter('inboundRequest', req.customInfo.user).emit('newInbound', { method: req.method, path: req.path, headers: req.headers, body: req.payload })
|
|
259
|
+
if (req.method === 'put') {
|
|
260
|
+
MyEventEmitter.getEmitter('testOutbound', req.customInfo.user).emit(req.method + ' ' + req.path, req.headers, req.payload, req.method, req.path)
|
|
261
|
+
let assertionPath = req.path
|
|
262
|
+
const assertionData = { headers: req.headers, body: req.payload }
|
|
263
|
+
if (assertionPath.endsWith('/error')) {
|
|
264
|
+
assertionPath = assertionPath.replace('/error', '')
|
|
265
|
+
assertionData.error = true
|
|
266
|
+
}
|
|
267
|
+
objectStore.push('requests', assertionPath, assertionData)
|
|
268
|
+
MyEventEmitter.getEmitter('assertionRequest', req.customInfo.user).emit(assertionPath, assertionData)
|
|
269
|
+
}
|
|
270
|
+
// Store all the inbound requests
|
|
271
|
+
arrayStore.push('requestsHistory', { timestamp: Date.now(), method: req.method, path: req.path, headers: req.headers, body: req.payload })
|
|
272
|
+
|
|
273
|
+
req.customInfo.specFile = item.specFile
|
|
274
|
+
req.customInfo.jsfRefFile = item.jsfRefFile
|
|
275
|
+
let responseBody, responseStatus
|
|
276
|
+
// Check for response map file
|
|
277
|
+
try {
|
|
278
|
+
const respMapRawdata = await utils.readFileAsync(item.responseMapFile)
|
|
279
|
+
const responseMap = JSON.parse(respMapRawdata)
|
|
280
|
+
if (responseMap && responseMap[context.operation.path] && responseMap[context.operation.path][context.request.method]) {
|
|
281
|
+
const responseInfo = responseMap[context.operation.path][context.request.method]
|
|
282
|
+
req.customInfo.responseInfo = responseInfo
|
|
283
|
+
} else {
|
|
284
|
+
customLogger.logMessage('error', 'Response info not found for method in response map file for ' + context.request.method + ' ' + context.operation.path, { request: req })
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
} catch (err) { }
|
|
288
|
+
// Check for the synchronous response rules
|
|
289
|
+
const generatedResponse = await OpenApiRulesEngine.responseRules(context, req)
|
|
290
|
+
responseStatus = +generatedResponse.status
|
|
291
|
+
responseBody = generatedResponse.body
|
|
292
|
+
customLogger.logMessage('info', 'Generated response', { additionalData: generatedResponse, request: req })
|
|
293
|
+
if (generatedResponse.delay) {
|
|
294
|
+
await new Promise(resolve => setTimeout(resolve, generatedResponse.delay))
|
|
295
|
+
}
|
|
296
|
+
if (!responseBody) {
|
|
297
|
+
// Generate mock response from openAPI spec file
|
|
298
|
+
const { status, mock } = context.api.mockResponseForOperation(context.operation.operationId)
|
|
299
|
+
responseBody = mock
|
|
300
|
+
responseStatus = +status
|
|
301
|
+
}
|
|
302
|
+
// Verify that it is a success code, then generate callback
|
|
303
|
+
if (item.asynchronous && (req.method === 'post' || req.method === 'get' || req.method === 'put') && responseStatus >= 200 && responseStatus <= 299) {
|
|
304
|
+
// Generate callback asynchronously
|
|
305
|
+
setImmediate(generateAsyncCallback, item, context, req)
|
|
306
|
+
}
|
|
307
|
+
if (_.isEmpty(responseBody)) {
|
|
308
|
+
return h.response().code(responseStatus)
|
|
309
|
+
} else {
|
|
310
|
+
return h.response(responseBody).code(responseStatus)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const generateAsyncCallback = async (item, context, req) => {
|
|
315
|
+
const userConfig = await Config.getUserConfig(req.customInfo.user)
|
|
316
|
+
if (req.method === 'put') {
|
|
317
|
+
if (!userConfig.HUB_ONLY_MODE) {
|
|
318
|
+
return
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
// Getting callback info from callback map file
|
|
322
|
+
try {
|
|
323
|
+
const cbMapRawdata = await utils.readFileAsync(item.callbackMapFile)
|
|
324
|
+
const callbackMap = JSON.parse(cbMapRawdata)
|
|
325
|
+
if (!callbackMap[context.operation.path]) {
|
|
326
|
+
customLogger.logMessage('error', 'Callback not found for path in callback map file for ' + context.operation.path, req.customInfo.user, { request: req })
|
|
327
|
+
return
|
|
328
|
+
}
|
|
329
|
+
const callbackInfo = callbackMap[context.operation.path][context.request.method]
|
|
330
|
+
if (!callbackInfo) {
|
|
331
|
+
customLogger.logMessage('error', 'Callback info not found for method in callback map file for ' + context.operation.path + context.request.method, { request: req })
|
|
332
|
+
return
|
|
333
|
+
}
|
|
334
|
+
req.customInfo.callbackInfo = callbackInfo
|
|
335
|
+
} catch (err) {
|
|
336
|
+
customLogger.logMessage('error', 'Callback file not found.', { request: req })
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
// Additional validation based on the Json Rules Engine, send error callback on failure
|
|
340
|
+
const generatedErrorCallback = await OpenApiRulesEngine.validateRules(context, req)
|
|
341
|
+
if (generatedErrorCallback.skipCallback) {
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
if (generatedErrorCallback.body) {
|
|
345
|
+
// TODO: Handle method and path verifications against the generated ones
|
|
346
|
+
customLogger.logMessage('error', 'Sending error callback', { request: req })
|
|
347
|
+
CallbackHandler.handleCallback(generatedErrorCallback, context, req)
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Callback Rules engine - match the rules and generate the specified callback
|
|
353
|
+
const generatedCallback = await OpenApiRulesEngine.callbackRules(context, req)
|
|
354
|
+
if (generatedCallback.skipCallback) {
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// forward request after validation
|
|
359
|
+
if (userConfig.HUB_ONLY_MODE) {
|
|
360
|
+
const forwardRequest = await OpenApiRulesEngine.forwardRules(context, req)
|
|
361
|
+
if (forwardRequest) {
|
|
362
|
+
CallbackHandler.handleCallback(forwardRequest, context, req)
|
|
363
|
+
}
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
// TODO: Need to handle iso20022 error payloads.
|
|
367
|
+
// Handle quotes and transfer association - should do this first to get the associated quote
|
|
368
|
+
if (userConfig.TRANSFERS_VALIDATION_WITH_PREVIOUS_QUOTES) {
|
|
369
|
+
const matchFound = require('./middleware-functions/quotesAssociation').handleTransfers(context, req)
|
|
370
|
+
if (!matchFound) {
|
|
371
|
+
customLogger.logMessage('error', 'Matching Quote Not Found', { request: req })
|
|
372
|
+
const generatedErrorCallback = await OpenApiRulesEngine.generateMockErrorCallback(context, req)
|
|
373
|
+
if (req.customInfo.selectedApi?.type === 'iso20022') {
|
|
374
|
+
_handleISO20022ErrorCallback(generatedErrorCallback, '3208')
|
|
375
|
+
} else {
|
|
376
|
+
generatedErrorCallback.body = {
|
|
377
|
+
errorInformation: {
|
|
378
|
+
errorCode: '3208',
|
|
379
|
+
errorDescription: 'Provided Transfer ID was not found on the server.'
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
CallbackHandler.handleCallback(generatedErrorCallback, context, req)
|
|
384
|
+
return
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Handle transfer validation against decoded ILP Packet
|
|
389
|
+
if (userConfig.TRANSFERS_VALIDATION_ILP_PACKET) {
|
|
390
|
+
const validated = IlpModel.validateTransferIlpPacket(context, req)
|
|
391
|
+
if (!validated) {
|
|
392
|
+
customLogger.logMessage('error', 'ILP Packet is not matching with the content', { request: req })
|
|
393
|
+
const generatedErrorCallback = await OpenApiRulesEngine.generateMockErrorCallback(context, req)
|
|
394
|
+
if (req.customInfo.selectedApi?.type === 'iso20022') {
|
|
395
|
+
_handleISO20022ErrorCallback(generatedErrorCallback, '3106')
|
|
396
|
+
} else {
|
|
397
|
+
generatedErrorCallback.body = {
|
|
398
|
+
errorInformation: {
|
|
399
|
+
errorCode: '3106',
|
|
400
|
+
errorDescription: 'ILP Packet is not matching with the content.'
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
CallbackHandler.handleCallback(generatedErrorCallback, context, req)
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Handle condition validation in transfer request
|
|
410
|
+
if (userConfig.TRANSFERS_VALIDATION_CONDITION) {
|
|
411
|
+
const validated = IlpModel.validateTransferCondition(context, req)
|
|
412
|
+
if (!validated) {
|
|
413
|
+
customLogger.logMessage('error', 'Condition can not be validated', { request: req })
|
|
414
|
+
const generatedErrorCallback = await OpenApiRulesEngine.generateMockErrorCallback(context, req)
|
|
415
|
+
if (req.customInfo.selectedApi?.type === 'iso20022') {
|
|
416
|
+
_handleISO20022ErrorCallback(generatedErrorCallback, '3106')
|
|
417
|
+
} else {
|
|
418
|
+
generatedErrorCallback.body = {
|
|
419
|
+
errorInformation: {
|
|
420
|
+
errorCode: '3106',
|
|
421
|
+
errorDescription: 'Condition can not be validated.'
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
CallbackHandler.handleCallback(generatedErrorCallback, context, req)
|
|
426
|
+
return
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (generatedCallback.body) {
|
|
431
|
+
// Append ILP properties to callback
|
|
432
|
+
const fulfilment = IlpModel.handleQuoteIlp(context, generatedCallback)
|
|
433
|
+
IlpModel.handleTransferIlp(context, generatedCallback)
|
|
434
|
+
if (userConfig.TRANSFERS_VALIDATION_WITH_PREVIOUS_QUOTES) {
|
|
435
|
+
require('./middleware-functions/quotesAssociation').handleQuotes(context, req, fulfilment)
|
|
436
|
+
}
|
|
437
|
+
// TODO: Handle method and path verifications against the generated ones
|
|
438
|
+
CallbackHandler.handleCallback(generatedCallback, context, req)
|
|
439
|
+
// Handle triggers for a transaction request
|
|
440
|
+
require('./middleware-functions/transactionRequestsService').handleRequest(context, req, generatedCallback, item.triggerTemplatesFolder)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const _handleISO20022ErrorCallback = (generatedErrorCallback, errorCode) => {
|
|
445
|
+
generatedErrorCallback.headers = {
|
|
446
|
+
...generatedErrorCallback.headers,
|
|
447
|
+
'content-type': 'application/vnd.interoperability.iso20022.transfers+json;version=2.0'
|
|
448
|
+
}
|
|
449
|
+
generatedErrorCallback.body = {
|
|
450
|
+
GrpHdr: {
|
|
451
|
+
MsgId: generateULID(),
|
|
452
|
+
CreDtTm: new Date().toISOString()
|
|
453
|
+
},
|
|
454
|
+
TxInfAndSts: {
|
|
455
|
+
StsRsnInf: {
|
|
456
|
+
Rsn: {
|
|
457
|
+
Cd: errorCode
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return generatedErrorCallback
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
module.exports.openApiBackendNotImplementedHandler = openApiBackendNotImplementedHandler
|
|
466
|
+
module.exports.generateAsyncCallback = generateAsyncCallback
|