account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.21

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 (53) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/.ncurc.yaml +1 -2
  3. package/audit-ci.jsonc +3 -1
  4. package/jest.config.js +2 -0
  5. package/package.json +15 -17
  6. package/src/constants.js +2 -1
  7. package/src/domain/oracle/oracle.js +63 -4
  8. package/src/domain/participants/participants.js +259 -133
  9. package/src/domain/parties/getPartiesByTypeAndID.js +36 -15
  10. package/src/domain/parties/parties.js +44 -14
  11. package/src/domain/parties/utils.js +13 -6
  12. package/src/domain/timeout/dto.js +4 -10
  13. package/src/domain/timeout/index.js +12 -1
  14. package/src/handlers/index.js +4 -4
  15. package/src/handlers/monitoring/index.js +1 -1
  16. package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
  17. package/src/interface/api-swagger.yaml +7 -6
  18. package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2043 -1583
  19. package/src/lib/config.js +1 -1
  20. package/src/lib/index.js +1 -2
  21. package/src/models/currency/currency.js +10 -1
  22. package/src/models/endpointType/endpointType.js +10 -1
  23. package/src/models/oracle/facade.js +24 -3
  24. package/src/models/oracle/oracleEndpoint.js +64 -10
  25. package/src/models/oracle/oracleEndpointCached.js +22 -3
  26. package/src/models/participantEndpoint/facade.js +61 -23
  27. package/src/models/partyIdType/partyIdType.js +10 -1
  28. package/src/plugins.js +20 -9
  29. package/src/server.js +11 -19
  30. package/test/fixtures/index.js +30 -6
  31. package/test/fixtures/iso.js +1 -1
  32. package/test/unit/api/health.test.js +3 -0
  33. package/test/unit/api/participants/participants.test.js +5 -7
  34. package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
  35. package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
  36. package/test/unit/api/participants.test.js +36 -3
  37. package/test/unit/domain/oracle/oracle.test.js +8 -0
  38. package/test/unit/domain/participants/participants.test.js +83 -48
  39. package/test/unit/domain/parties/parties.test.js +11 -3
  40. package/test/unit/domain/parties/utils.test.js +60 -0
  41. package/test/unit/domain/timeout/dto.test.js +1 -2
  42. package/test/unit/domain/timeout/index.test.js +8 -0
  43. package/test/unit/lib/TransformFacades.test.js +2 -1
  44. package/test/unit/lib/config.test.js +7 -0
  45. package/test/unit/models/participantEndpoint/facade.test.js +25 -8
  46. package/test/unit/plugins.test.js +4 -2
  47. package/test/util/apiClients/BasicApiClient.js +2 -2
  48. package/src/handlers/monitoring/plugins/metrics.js +0 -48
  49. package/src/lib/requestLogger.js +0 -54
  50. package/src/metrics/handler.js +0 -33
  51. package/src/metrics/plugin.js +0 -52
  52. package/src/metrics/routes.js +0 -43
  53. package/test/unit/lib/requestLogger.test.js +0 -115
package/src/lib/config.js CHANGED
@@ -167,7 +167,7 @@ const config = {
167
167
  INSTRUMENTATION_METRICS_LABELS: RC.INSTRUMENTATION.METRICS.labels,
168
168
  INSTRUMENTATION_METRICS_CONFIG: RC.INSTRUMENTATION.METRICS.config,
169
169
  JWS_SIGN: RC.ENDPOINT_SECURITY.JWS.JWS_SIGN,
170
- FSPIOP_SOURCE_TO_SIGN: RC.HUB_NAME,
170
+ FSPIOP_SOURCE_TO_SIGN: RC.HUB_PARTICIPANT.NAME,
171
171
  JWS_SIGNING_KEY_PATH: RC.ENDPOINT_SECURITY.JWS.JWS_SIGNING_KEY_PATH,
172
172
  API_DOC_ENDPOINTS_ENABLED: RC.API_DOC_ENDPOINTS_ENABLED || false,
173
173
  FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE: RC.FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE || false,
package/src/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const { loggerFactory, asyncStorage } = require('@mojaloop/central-services-logger/src/contextLogger')
1
+ const { loggerFactory } = require('@mojaloop/central-services-logger/src/contextLogger')
2
2
  const { TransformFacades } = require('@mojaloop/ml-schema-transformer-lib')
3
3
 
4
4
  const logger = loggerFactory('ALS') // global logger without context
@@ -6,6 +6,5 @@ const logger = loggerFactory('ALS') // global logger without context
6
6
  module.exports = {
7
7
  logger,
8
8
  loggerFactory,
9
- asyncStorage,
10
9
  TransformFacades
11
10
  }
@@ -39,7 +39,16 @@ const getCurrencyById = async (currencyId) => {
39
39
  try {
40
40
  return Db.from('currency').findOne({ currencyId, isActive: true })
41
41
  } catch (err) {
42
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
42
+ const extensions = [{
43
+ key: 'system',
44
+ value: '["db"]'
45
+ }]
46
+ throw ErrorHandler.Factory.reformatFSPIOPError(
47
+ err,
48
+ undefined,
49
+ undefined,
50
+ extensions
51
+ )
43
52
  }
44
53
  }
45
54
 
@@ -39,7 +39,16 @@ const getEndpointTypeByType = async (type) => {
39
39
  try {
40
40
  return Db.from('endpointType').findOne({ type, isActive: true })
41
41
  } catch (err) {
42
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
42
+ const extensions = [{
43
+ key: 'system',
44
+ value: '["db"]'
45
+ }]
46
+ throw ErrorHandler.Factory.reformatFSPIOPError(
47
+ err,
48
+ undefined,
49
+ undefined,
50
+ extensions
51
+ )
43
52
  }
44
53
  }
45
54
 
@@ -123,6 +123,10 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
123
123
  throw err
124
124
  }
125
125
  } catch (err) {
126
+ const extensions = [{
127
+ key: 'system',
128
+ value: '["@hapi/catbox-memory","http"]'
129
+ }]
126
130
  Logger.isErrorEnabled && Logger.error(`error in oracleRequest: ${err?.stack}`)
127
131
  // If the error was a 400 from the Oracle, we'll modify the error to generate a response to the
128
132
  // initiator of the request.
@@ -131,15 +135,32 @@ exports.oracleRequest = async (headers, method, params = {}, query = {}, payload
131
135
  err.apiErrorCode.code === ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_COMMUNICATION_ERROR.code
132
136
  ) {
133
137
  if (err.extensions.some(ext => (ext.key === 'status' && ext.value === Enums.Http.ReturnCodes.BADREQUEST.CODE))) {
134
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
138
+ throw ErrorHandler.Factory.createFSPIOPError(
139
+ ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND,
140
+ undefined,
141
+ undefined,
142
+ undefined,
143
+ extensions
144
+ )
135
145
  // Added error 404 to cover a special case of the Mowali implementation
136
146
  // which uses mojaloop/als-oracle-pathfinder and currently returns 404
137
147
  // and in which case the Mowali implementation expects back `DESTINATION_FSP_ERROR`.
138
148
  } else if (err.extensions.some(ext => (ext.key === 'status' && ext.value === Enums.Http.ReturnCodes.NOTFOUND.CODE))) {
139
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR)
149
+ throw ErrorHandler.Factory.createFSPIOPError(
150
+ ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR,
151
+ undefined,
152
+ undefined,
153
+ undefined,
154
+ extensions
155
+ )
140
156
  }
141
157
  }
142
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
158
+ throw ErrorHandler.Factory.reformatFSPIOPError(
159
+ err,
160
+ undefined,
161
+ undefined,
162
+ extensions
163
+ )
143
164
  }
144
165
  }
145
166
 
@@ -27,6 +27,10 @@
27
27
 
28
28
  const Db = require('../../lib/db')
29
29
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
30
+ const extensions = [{
31
+ key: 'system',
32
+ value: '["db"]'
33
+ }]
30
34
 
31
35
  const getOracleEndpointByType = async (type) => {
32
36
  try {
@@ -43,7 +47,12 @@ const getOracleEndpointByType = async (type) => {
43
47
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
44
48
  })
45
49
  } catch (err) {
46
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
50
+ throw ErrorHandler.Factory.reformatFSPIOPError(
51
+ err,
52
+ undefined,
53
+ undefined,
54
+ extensions
55
+ )
47
56
  }
48
57
  }
49
58
 
@@ -64,7 +73,12 @@ const getOracleEndpointByTypeAndCurrency = async (type, currencyId) => {
64
73
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
65
74
  })
66
75
  } catch (err) {
67
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
76
+ throw ErrorHandler.Factory.reformatFSPIOPError(
77
+ err,
78
+ undefined,
79
+ undefined,
80
+ extensions
81
+ )
68
82
  }
69
83
  }
70
84
 
@@ -84,7 +98,12 @@ const getOracleEndpointByCurrency = async (currencyId) => {
84
98
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
85
99
  })
86
100
  } catch (err) {
87
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
101
+ throw ErrorHandler.Factory.reformatFSPIOPError(
102
+ err,
103
+ undefined,
104
+ undefined,
105
+ extensions
106
+ )
88
107
  }
89
108
  }
90
109
 
@@ -104,7 +123,12 @@ const getOracleEndpointById = async (oracleEndpointId) => {
104
123
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
105
124
  })
106
125
  } catch (err) {
107
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
126
+ throw ErrorHandler.Factory.reformatFSPIOPError(
127
+ err,
128
+ undefined,
129
+ undefined,
130
+ extensions
131
+ )
108
132
  }
109
133
  }
110
134
 
@@ -122,7 +146,12 @@ const getAllOracleEndpoint = async () => {
122
146
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
123
147
  })
124
148
  } catch (err) {
125
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
149
+ throw ErrorHandler.Factory.reformatFSPIOPError(
150
+ err,
151
+ undefined,
152
+ undefined,
153
+ extensions
154
+ )
126
155
  }
127
156
  }
128
157
 
@@ -142,7 +171,12 @@ const getAllOracleEndpointsByMatchCondition = async (oracleEndpointModel, partyI
142
171
  'oracleEndpoint.isActive', 'oracleEndpoint.partyIdTypeId', 'oracleEndpoint.endpointTypeId', 'oracleEndpoint.currencyId')
143
172
  })
144
173
  } catch (err) {
145
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
174
+ throw ErrorHandler.Factory.reformatFSPIOPError(
175
+ err,
176
+ undefined,
177
+ undefined,
178
+ extensions
179
+ )
146
180
  }
147
181
  }
148
182
 
@@ -150,7 +184,12 @@ const createOracleEndpoint = async (oracleEndpointModel) => {
150
184
  try {
151
185
  return await Db.from('oracleEndpoint').insert(oracleEndpointModel)
152
186
  } catch (err) {
153
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
187
+ throw ErrorHandler.Factory.reformatFSPIOPError(
188
+ err,
189
+ undefined,
190
+ undefined,
191
+ extensions
192
+ )
154
193
  }
155
194
  }
156
195
 
@@ -158,7 +197,12 @@ const updateOracleEndpointById = async (id, oracleEndpointModel) => {
158
197
  try {
159
198
  return await Db.from('oracleEndpoint').update({ oracleEndpointId: id }, oracleEndpointModel)
160
199
  } catch (err) {
161
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
200
+ throw ErrorHandler.Factory.reformatFSPIOPError(
201
+ err,
202
+ undefined,
203
+ undefined,
204
+ extensions
205
+ )
162
206
  }
163
207
  }
164
208
 
@@ -166,7 +210,12 @@ const setIsActiveOracleEndpoint = async (oracleType, isActive) => {
166
210
  try {
167
211
  return await Db.from('oracleEndpoint').update({ oracleType }, { isActive })
168
212
  } catch (err) {
169
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
213
+ throw ErrorHandler.Factory.reformatFSPIOPError(
214
+ err,
215
+ undefined,
216
+ undefined,
217
+ extensions
218
+ )
170
219
  }
171
220
  }
172
221
 
@@ -174,7 +223,12 @@ const destroyOracleEndpointById = async (oracleEndpointId) => {
174
223
  try {
175
224
  return await Db.from('oracleEndpoint').update({ oracleEndpointId }, { isActive: false })
176
225
  } catch (err) {
177
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
226
+ throw ErrorHandler.Factory.reformatFSPIOPError(
227
+ err,
228
+ undefined,
229
+ undefined,
230
+ extensions
231
+ )
178
232
  }
179
233
  }
180
234
 
@@ -31,6 +31,10 @@ const Metrics = require('@mojaloop/central-services-metrics')
31
31
  const OracleEndpointUncached = require('./oracleEndpoint')
32
32
 
33
33
  let cacheClient
34
+ const extensions = [{
35
+ key: 'system',
36
+ value: '["db","@hapi/catbox-memory"]'
37
+ }]
34
38
 
35
39
  const getCacheKey = (params) => {
36
40
  return cacheClient.createKey(`${Object.values(params).join('__')}`)
@@ -87,7 +91,12 @@ exports.getOracleEndpointByTypeAndCurrency = async (partyIdType, currency) => {
87
91
  try {
88
92
  return await getOracleEndpointCached({ partyIdType, currency })
89
93
  } catch (err) {
90
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
94
+ throw ErrorHandler.Factory.reformatFSPIOPError(
95
+ err,
96
+ undefined,
97
+ undefined,
98
+ extensions
99
+ )
91
100
  }
92
101
  }
93
102
 
@@ -95,7 +104,12 @@ exports.getOracleEndpointByType = async (partyIdType) => {
95
104
  try {
96
105
  return await getOracleEndpointCached({ partyIdType })
97
106
  } catch (err) {
98
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
107
+ throw ErrorHandler.Factory.reformatFSPIOPError(
108
+ err,
109
+ undefined,
110
+ undefined,
111
+ extensions
112
+ )
99
113
  }
100
114
  }
101
115
 
@@ -103,6 +117,11 @@ exports.getOracleEndpointByCurrency = async (currency) => {
103
117
  try {
104
118
  return await getOracleEndpointCached({ currency })
105
119
  } catch (err) {
106
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
120
+ throw ErrorHandler.Factory.reformatFSPIOPError(
121
+ err,
122
+ undefined,
123
+ undefined,
124
+ extensions
125
+ )
107
126
  }
108
127
  }
@@ -33,7 +33,9 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
33
33
  const JwsSigner = require('@mojaloop/sdk-standard-components').Jws.signer
34
34
  const Metrics = require('@mojaloop/central-services-metrics')
35
35
  const Config = require('../../lib/config')
36
+ const { logger } = require('../../lib')
36
37
  const { hubNameRegex } = require('../../lib/util').hubNameConfig
38
+
37
39
  const uriRegex = /(?:^.*)(\/(participants|parties|quotes|transfers)(\/.*)*)$/
38
40
 
39
41
  /**
@@ -47,7 +49,7 @@ const defineJwsSigner = (config, headers, requestedEndpoint) => {
47
49
  // We need below 2 headers for JWS
48
50
  headers[Enums.Http.Headers.FSPIOP.HTTP_METHOD] = headers[Enums.Http.Headers.FSPIOP.HTTP_METHOD] || Enums.Http.RestMethods.PUT
49
51
  headers[Enums.Http.Headers.FSPIOP.URI] = headers[Enums.Http.Headers.FSPIOP.URI] || uriRegex.exec(requestedEndpoint)[1]
50
- Logger.isDebugEnabled && Logger.debug('JWS is enabled, getting JwsSigner')
52
+ logger.debug('JWS is enabled, getting JwsSigner')
51
53
  jwsSigner = new JwsSigner({
52
54
  logger: Logger,
53
55
  signingKey: config.JWS_SIGNING_KEY
@@ -83,10 +85,10 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
83
85
  try {
84
86
  requestedEndpoint = await Util.Endpoints.getEndpoint(Config.SWITCH_ENDPOINT, requestedParticipant, endpointType, options || undefined)
85
87
  histTimerEndGetParticipantEndpoint({ success: true, endpointType, participantName: requestedParticipant })
86
- Logger.isDebugEnabled && Logger.debug(`participant endpoint url: ${requestedEndpoint} for endpoint type ${endpointType}`)
88
+ logger.debug('participant requestedEndpoint and endpointType: ', { requestedEndpoint, endpointType })
87
89
  } catch (err) {
88
90
  histTimerEndGetParticipantEndpoint({ success: false, endpointType, participantName: requestedParticipant })
89
- Logger.isErrorEnabled && Logger.error(`error in getEndpoint: ${err?.stack}`)
91
+ logger.warn('error in getEndpoint: ', err)
90
92
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
91
93
  }
92
94
 
@@ -102,9 +104,7 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
102
104
  content: Config.PROTOCOL_VERSIONS.CONTENT.DEFAULT.toString(),
103
105
  accept: Config.PROTOCOL_VERSIONS.ACCEPT.DEFAULT.toString()
104
106
  }
105
- const jwsSigner = defineJwsSigner(Config, headers, requestedEndpoint)
106
-
107
- const resp = await Util.Request.sendRequest({
107
+ const params = {
108
108
  url: requestedEndpoint,
109
109
  headers,
110
110
  source: headers[Enums.Http.Headers.FSPIOP.SOURCE],
@@ -113,18 +113,29 @@ exports.sendRequest = async (headers, requestedParticipant, endpointType, method
113
113
  payload,
114
114
  responseType: Enums.Http.ResponseTypes.JSON,
115
115
  span,
116
- jwsSigner,
117
116
  protocolVersions,
118
117
  hubNameRegex,
119
118
  apiType: Config.API_TYPE
120
- })
119
+ }
120
+ logger.debug('participant - sendRequest params:', { params })
121
+ params.jwsSigner = defineJwsSigner(Config, headers, requestedEndpoint)
122
+
123
+ const resp = await Util.Request.sendRequest(params)
121
124
  histTimerEndSendRequestToParticipant({ success: true, endpointType, participantName: requestedParticipant })
122
125
  return resp
123
126
  } catch (err) {
124
127
  histTimerEndSendRequestToParticipant({ success: false, endpointType, participantName: requestedParticipant })
125
- Logger.isErrorEnabled && Logger.error(`error in sendRequest: ${err?.stack}`)
126
-
127
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
128
+ logger.warn('error in sendRequest: ', err)
129
+ const extensions = [{
130
+ key: 'system',
131
+ value: '["http"]'
132
+ }]
133
+ throw ErrorHandler.Factory.reformatFSPIOPError(
134
+ err,
135
+ undefined,
136
+ undefined,
137
+ extensions
138
+ )
128
139
  }
129
140
  }
130
141
 
@@ -148,8 +159,17 @@ exports.validateParticipant = async (fsp) => {
148
159
  return resp
149
160
  } catch (err) {
150
161
  histTimerEnd({ success: false })
151
- Logger.isErrorEnabled && Logger.error(`error in validateParticipant: ${err?.stack}`)
152
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
162
+ logger.warn('error in validateParticipant: ', err)
163
+ const extensions = [{
164
+ key: 'system',
165
+ value: '["http"]'
166
+ }]
167
+ throw ErrorHandler.Factory.reformatFSPIOPError(
168
+ err,
169
+ undefined,
170
+ undefined,
171
+ extensions
172
+ )
153
173
  }
154
174
  }
155
175
 
@@ -188,8 +208,17 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
188
208
  histTimerEndGetParticipantEndpoint({ success: true, endpointType, participantName })
189
209
  } catch (err) {
190
210
  histTimerEndGetParticipantEndpoint({ success: false, endpointType, participantName })
191
- Logger.isWarnEnabled && Logger.warn(`error in getEndpoint: ${err?.message}`)
192
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
211
+ logger.warn('error in getEndpoint: ', err)
212
+ const extensions = [{
213
+ key: 'system',
214
+ value: '["http"]'
215
+ }]
216
+ throw ErrorHandler.Factory.reformatFSPIOPError(
217
+ err,
218
+ undefined,
219
+ undefined,
220
+ extensions
221
+ )
193
222
  }
194
223
 
195
224
  // Send error to participant
@@ -212,10 +241,7 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
212
241
  clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
213
242
  }
214
243
 
215
- Logger.isDebugEnabled && Logger.debug(`participant endpoint url: ${requesterErrorEndpoint} for endpoint type ${endpointType}`)
216
- const jwsSigner = defineJwsSigner(Config, clonedHeaders, requesterErrorEndpoint)
217
-
218
- await Util.Request.sendRequest({
244
+ const params = {
219
245
  url: requesterErrorEndpoint,
220
246
  headers: clonedHeaders,
221
247
  source: clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE],
@@ -225,14 +251,26 @@ exports.sendErrorToParticipant = async (participantName, endpointType, errorInfo
225
251
  responseType: Enums.Http.ResponseTypes.JSON,
226
252
  hubNameRegex,
227
253
  span,
228
- jwsSigner,
229
254
  protocolVersions,
230
255
  apiType: Config.API_TYPE
231
- })
256
+ }
257
+ logger.debug('participant - sendErrorToParticipant params: ', { params })
258
+ params.jwsSigner = defineJwsSigner(Config, clonedHeaders, requesterErrorEndpoint)
259
+
260
+ await Util.Request.sendRequest(params)
232
261
  histTimerEndSendRequestToParticipant({ success: true, endpointType, participantName })
233
262
  } catch (err) {
234
263
  histTimerEndSendRequestToParticipant({ success: false, endpointType, participantName })
235
- Logger.isWarnEnabled && Logger.warn(`error in sendErrorToParticipant: ${err?.message}`)
236
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
264
+ logger.warn('error in sendErrorToParticipant: ', err)
265
+ const extensions = [{
266
+ key: 'system',
267
+ value: '["http"]'
268
+ }]
269
+ throw ErrorHandler.Factory.reformatFSPIOPError(
270
+ err,
271
+ undefined,
272
+ undefined,
273
+ extensions
274
+ )
237
275
  }
238
276
  }
@@ -32,7 +32,16 @@ const getPartyIdTypeByName = async (name) => {
32
32
  try {
33
33
  return Db.from('partyIdType').findOne({ name, isActive: true })
34
34
  } catch (err) {
35
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
35
+ const extensions = [{
36
+ key: 'system',
37
+ value: '["db"]'
38
+ }]
39
+ throw ErrorHandler.Factory.reformatFSPIOPError(
40
+ err,
41
+ undefined,
42
+ undefined,
43
+ extensions
44
+ )
36
45
  }
37
46
  }
38
47
 
package/src/plugins.js CHANGED
@@ -24,16 +24,22 @@
24
24
  ******/
25
25
  'use strict'
26
26
 
27
- const Config = require('./lib/config')
28
27
  const Inert = require('@hapi/inert')
29
28
  const Vision = require('@hapi/vision')
30
29
  const Blipp = require('blipp')
31
30
  const ErrorHandling = require('@mojaloop/central-services-error-handling')
32
- const CentralServices = require('@mojaloop/central-services-shared')
33
- const RawPayloadToDataUri = require('@mojaloop/central-services-shared').Util.Hapi.HapiRawPayload
34
- const OpenapiBackendValidator = require('@mojaloop/central-services-shared').Util.Hapi.OpenapiBackendValidator
35
- const APIDocumentation = require('@mojaloop/central-services-shared').Util.Hapi.APIDocumentation
36
- const MetricsPlugin = require('./metrics/plugin')
31
+ const MetricsPlugin = require('@mojaloop/central-services-metrics').plugin
32
+ const {
33
+ APIDocumentation,
34
+ FSPIOPHeaderValidation,
35
+ HapiEventPlugin,
36
+ HapiRawPayload,
37
+ OpenapiBackendValidator,
38
+ loggingPlugin
39
+ } = require('@mojaloop/central-services-shared').Util.Hapi
40
+
41
+ const { logger } = require('./lib')
42
+ const Config = require('./lib/config')
37
43
 
38
44
  const registerPlugins = async (server, openAPIBackend) => {
39
45
  await server.register(OpenapiBackendValidator)
@@ -121,10 +127,10 @@ const registerPlugins = async (server, openAPIBackend) => {
121
127
  Inert,
122
128
  Vision,
123
129
  ErrorHandling,
124
- RawPayloadToDataUri,
125
- CentralServices.Util.Hapi.HapiEventPlugin,
130
+ HapiRawPayload,
131
+ HapiEventPlugin,
126
132
  {
127
- plugin: CentralServices.Util.Hapi.FSPIOPHeaderValidation.plugin,
133
+ plugin: FSPIOPHeaderValidation.plugin,
128
134
  options: getOptionsForFSPIOPHeaderValidation()
129
135
  }
130
136
  ])
@@ -132,6 +138,11 @@ const registerPlugins = async (server, openAPIBackend) => {
132
138
  if (Config.DISPLAY_ROUTES === true) {
133
139
  await server.register([Blipp])
134
140
  }
141
+
142
+ await server.register({
143
+ plugin: loggingPlugin,
144
+ options: { log: logger }
145
+ })
135
146
  }
136
147
 
137
148
  module.exports = {
package/src/server.js CHANGED
@@ -23,7 +23,6 @@
23
23
  ******/
24
24
  'use strict'
25
25
 
26
- const { randomUUID } = require('node:crypto')
27
26
  const Hapi = require('@hapi/hapi')
28
27
  const Boom = require('@hapi/boom')
29
28
 
@@ -37,7 +36,6 @@ const { name, version } = require('../package.json')
37
36
  const Db = require('./lib/db')
38
37
  const Util = require('./lib/util')
39
38
  const Plugins = require('./plugins')
40
- const RequestLogger = require('./lib/requestLogger')
41
39
  const Migrator = require('./lib/migrator')
42
40
  const APIHandlers = require('./api')
43
41
  const Routes = require('./api/routes')
@@ -104,26 +102,17 @@ const createServer = async (port, api, routes, isAdmin, proxyCacheConfig, proxyM
104
102
  }
105
103
  }
106
104
 
107
- await server.ext([
108
- {
109
- type: 'onPreHandler',
110
- method: (request, h) => {
111
- request.headers.traceid = request.headers.traceid || randomUUID()
112
- RequestLogger.logRequest(request)
113
- return h.continue
114
- }
115
- },
116
- {
117
- type: 'onPreResponse',
118
- method: (request, h) => {
119
- RequestLogger.logResponse(request)
120
- return h.continue
121
- }
122
- }
123
- ])
124
105
  await Plugins.registerPlugins(server, api, isAdmin)
125
106
 
126
107
  server.route(routes)
108
+
109
+ // Initialize the error count metric
110
+ Metrics.getCounter(
111
+ 'errorCount',
112
+ 'Error count',
113
+ ['code', 'system', 'operation', 'step']
114
+ )
115
+
127
116
  // TODO: follow instructions https://github.com/anttiviljami/openapi-backend/blob/master/DOCS.md#postresponsehandler-handler
128
117
  await server.start()
129
118
 
@@ -148,6 +137,9 @@ const initializeApi = async (appConfig) => {
148
137
  } = appConfig
149
138
 
150
139
  if (!INSTRUMENTATION_METRICS_DISABLED) {
140
+ if (INSTRUMENTATION_METRICS_CONFIG.defaultLabels) {
141
+ INSTRUMENTATION_METRICS_CONFIG.defaultLabels.serviceVersion = version
142
+ }
151
143
  initializeInstrumentation(INSTRUMENTATION_METRICS_CONFIG)
152
144
  }
153
145
  await connectDatabase(DATABASE)
@@ -9,14 +9,15 @@ const headersDto = ({
9
9
  destination = 'toDfsp',
10
10
  proxy = '',
11
11
  date = '2024-05-24 08:52:19',
12
- accept
12
+ accept,
13
+ contentType
13
14
  } = {}) => Object.freeze({
14
15
  [Headers.FSPIOP.SOURCE]: source,
15
16
  ...(destination && { [Headers.FSPIOP.DESTINATION]: destination }),
16
17
  ...(proxy && { [Headers.FSPIOP.PROXY]: proxy }),
17
18
  date,
18
19
  accept,
19
- 'content-type': accept
20
+ 'content-type': contentType || accept
20
21
  })
21
22
 
22
23
  const protocolVersionsDto = () => ({
@@ -40,22 +41,29 @@ const partiesCallHeadersDto = ({
40
41
  destination,
41
42
  proxy,
42
43
  date,
43
- accept: 'application/vnd.interoperability.parties+json;version=1.1'
44
+ accept: interopHeader('parties', '1'),
45
+ contentType: interopHeader('parties', '1.1')
44
46
  })
45
47
 
46
48
  const participantsCallHeadersDto = ({
47
49
  source,
48
50
  destination,
49
51
  proxy,
50
- date
52
+ date,
53
+ acceptVersion = '1',
54
+ contentTypeVersion = '1.1'
51
55
  } = {}) => headersDto({
52
56
  source,
53
57
  destination,
54
58
  proxy,
55
59
  date,
56
- accept: 'application/vnd.interoperability.participants+json;version=1'
60
+ accept: interopHeader('participants', acceptVersion),
61
+ contentType: interopHeader('participants', contentTypeVersion)
57
62
  })
58
63
 
64
+ // todo: add ISO mode support
65
+ const interopHeader = (resource, version = '1') => `application/vnd.interoperability.${resource}+json;version=${version}`
66
+
59
67
  const oracleRequestResponseDto = ({
60
68
  partyList = [{ fspId: 'dfspFromOracle' }]
61
69
  } = {}) => ({
@@ -83,6 +91,20 @@ const putPartiesSuccessResponseDto = ({
83
91
  }
84
92
  })
85
93
 
94
+ const postParticipantsPayloadDto = ({
95
+ requestId = randomUUID(), // '01JE8SG3F4WNHY8B9876THQ344',
96
+ partyList = [{
97
+ partyIdType: 'MSISDN',
98
+ partyIdentifier: '123456',
99
+ fspId: 'fspId123'
100
+ }],
101
+ currency = 'XXX'
102
+ } = {}) => Object.freeze({
103
+ requestId,
104
+ partyList,
105
+ ...(currency && { currency })
106
+ })
107
+
86
108
  const errorCallbackResponseDto = ({
87
109
  errorCode = '1234',
88
110
  errorDescription = 'Error description',
@@ -124,8 +146,10 @@ module.exports = {
124
146
  participantsCallHeadersDto,
125
147
  oracleRequestResponseDto,
126
148
  putPartiesSuccessResponseDto,
149
+ postParticipantsPayloadDto,
127
150
  errorCallbackResponseDto,
128
151
  mockAlsRequestDto,
129
152
  protocolVersionsDto,
130
- mockHapiRequestDto
153
+ mockHapiRequestDto,
154
+ interopHeader
131
155
  }