@mojaloop/central-services-shared 15.0.1 → 15.3.0-snapshot.2

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/.ncurc.json CHANGED
@@ -1,5 +1,4 @@
1
1
  {
2
2
  "reject": [
3
- "@mojaloop/sdk-standard-components"
4
3
  ]
5
4
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [15.3.0](https://github.com/mojaloop/central-services-shared/compare/v15.2.0...v15.3.0) (2022-02-07)
6
+
7
+
8
+ ### Features
9
+
10
+ * **mojaloop/project#2556:** implement patch notification for failure scenarios (following v1.1 update) ([#321](https://github.com/mojaloop/central-services-shared/issues/321)) ([92015a7](https://github.com/mojaloop/central-services-shared/commit/92015a7d9eec7e01e85eff86af5cc6e6147e5f20)), closes [mojaloop/project#2556](https://github.com/mojaloop/project/issues/2556)
11
+
12
+ ## [15.2.0](https://github.com/mojaloop/central-services-shared/compare/v15.1.0...v15.2.0) (2021-12-13)
13
+
14
+
15
+ ### Features
16
+
17
+ * **mojaloop/#2608:** injected resource versions config for outbound requests ([#319](https://github.com/mojaloop/central-services-shared/issues/319)) ([13a3d9d](https://github.com/mojaloop/central-services-shared/commit/13a3d9dc8ab8d4815db2aea22563317e3670a19b)), closes [mojaloop/#2608](https://github.com/mojaloop/central-services-shared/issues/2608)
18
+
19
+ ## [15.1.0](https://github.com/mojaloop/central-services-shared/compare/v15.0.1...v15.1.0) (2021-11-17)
20
+
21
+
22
+ ### Features
23
+
24
+ * add a new action enum for `RESERVED_ABORTED` ([#317](https://github.com/mojaloop/central-services-shared/issues/317)) ([0e743b8](https://github.com/mojaloop/central-services-shared/commit/0e743b82a90dd0c97ce3c72454621c191d2a6675))
25
+
5
26
  ### [15.0.1](https://github.com/mojaloop/central-services-shared/compare/v15.0.0...v15.0.1) (2021-11-08)
6
27
 
7
28
 
@@ -24,6 +24,75 @@
24
24
  "decision": "ignore",
25
25
  "madeAt": 1636372055094,
26
26
  "expiresAt": 1638964045850
27
+ },
28
+ "1004809|widdershins>openapi-sampler>json-pointer": {
29
+ "decision": "ignore",
30
+ "madeAt": 1636956486789,
31
+ "expiresAt": 1639548471465
32
+ },
33
+ "1004812|widdershins>swagger2openapi>better-ajv-errors>jsonpointer": {
34
+ "decision": "ignore",
35
+ "madeAt": 1636956491233,
36
+ "expiresAt": 1639548471465
37
+ },
38
+ "1004812|widdershins>swagger2openapi>oas-validator>better-ajv-errors>jsonpointer": {
39
+ "decision": "ignore",
40
+ "madeAt": 1636956491233,
41
+ "expiresAt": 1639548471465
42
+ },
43
+ "1004854|widdershins>openapi-sampler>json-pointer": {
44
+ "decision": "ignore",
45
+ "madeAt": 1644227612906,
46
+ "expiresAt": 1646819457744
47
+ },
48
+ "1004869|widdershins>swagger2openapi>better-ajv-errors>jsonpointer": {
49
+ "decision": "ignore",
50
+ "madeAt": 1644227615371,
51
+ "expiresAt": 1646819457744
52
+ },
53
+ "1004869|widdershins>swagger2openapi>oas-validator>better-ajv-errors>jsonpointer": {
54
+ "decision": "ignore",
55
+ "madeAt": 1644227615371,
56
+ "expiresAt": 1646819457744
57
+ },
58
+ "1004946|widdershins>yargs>string-width>strip-ansi>ansi-regex": {
59
+ "decision": "ignore",
60
+ "madeAt": 1644227616947,
61
+ "expiresAt": 1646819457744
62
+ },
63
+ "1004946|widdershins>yargs>cliui>string-width>strip-ansi>ansi-regex": {
64
+ "decision": "ignore",
65
+ "madeAt": 1644227616947,
66
+ "expiresAt": 1646819457744
67
+ },
68
+ "1005383|shins>sanitize-html": {
69
+ "decision": "ignore",
70
+ "madeAt": 1644227618453,
71
+ "expiresAt": 1646819457744
72
+ },
73
+ "1005384|shins>sanitize-html": {
74
+ "decision": "ignore",
75
+ "madeAt": 1644227618454,
76
+ "expiresAt": 1646819457744
77
+ },
78
+ "1005534|widdershins>yargs>yargs-parser": {
79
+ "decision": "ignore",
80
+ "madeAt": 1644227619978,
81
+ "expiresAt": 1646819457744
82
+ },
83
+ "1006899|widdershins>node-fetch": {
84
+ "decision": "fix",
85
+ "madeAt": 1644227510867
86
+ },
87
+ "1006846|shins>sanitize-html>postcss": {
88
+ "decision": "ignore",
89
+ "madeAt": 1644227621510,
90
+ "expiresAt": 1646819457744
91
+ },
92
+ "1006886|shins>markdown-it": {
93
+ "decision": "ignore",
94
+ "madeAt": 1644227622831,
95
+ "expiresAt": 1646819457744
27
96
  }
28
97
  },
29
98
  "rules": {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mojaloop/central-services-shared",
3
- "version": "15.0.1",
3
+ "version": "15.3.0-snapshot.2",
4
4
  "description": "Shared code for mojaloop central services",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -48,16 +48,16 @@
48
48
  "dependencies": {
49
49
  "@hapi/catbox": "11.1.1",
50
50
  "@hapi/catbox-memory": "5.0.1",
51
- "axios": "0.24.0",
51
+ "axios": "0.25.0",
52
52
  "clone": "2.1.2",
53
- "dotenv": "10.0.0",
53
+ "dotenv": "16.0.0",
54
54
  "env-var": "7.1.1",
55
55
  "event-stream": "4.0.1",
56
56
  "immutable": "4.0.0",
57
57
  "lodash": "4.17.21",
58
58
  "mustache": "4.2.0",
59
- "openapi-backend": "5.0.0",
60
- "raw-body": "2.4.1",
59
+ "openapi-backend": "5.2.0",
60
+ "raw-body": "2.4.2",
61
61
  "rc": "1.2.8",
62
62
  "shins": "2.6.0",
63
63
  "uuid4": "2.0.2",
@@ -72,22 +72,22 @@
72
72
  "@mojaloop/central-services-metrics": "11.0.0",
73
73
  "@mojaloop/event-sdk": "10.7.1",
74
74
  "@mojaloop/sdk-standard-components": "10.3.2",
75
- "ajv": "8.6.3",
76
- "ajv-keywords": "5.0.0",
75
+ "ajv": "8.10.0",
76
+ "ajv-keywords": "5.1.0",
77
77
  "base64url": "3.0.1",
78
78
  "chance": "1.1.8",
79
79
  "npm-audit-resolver": "2.3.1",
80
- "npm-check-updates": "12.0.0",
80
+ "npm-check-updates": "12.2.1",
81
81
  "nyc": "15.1.0",
82
82
  "pre-commit": "1.2.2",
83
83
  "proxyquire": "2.1.3",
84
- "rewire": "5.0.0",
85
- "sinon": "12.0.1",
84
+ "rewire": "6.0.0",
85
+ "sinon": "13.0.1",
86
86
  "standard": "16.0.4",
87
87
  "standard-version": "9.3.2",
88
88
  "tap-spec": "^5.0.0",
89
89
  "tap-xunit": "2.4.1",
90
- "tape": "5.3.1",
90
+ "tape": "5.5.0",
91
91
  "tapes": "4.1.0"
92
92
  },
93
93
  "peerDependencies": {
@@ -95,8 +95,8 @@
95
95
  "@mojaloop/central-services-logger": "10.6.2",
96
96
  "@mojaloop/central-services-metrics": "11.0.0",
97
97
  "@mojaloop/event-sdk": "10.7.1",
98
- "ajv": "8.6.3",
99
- "ajv-keywords": "5.0.0"
98
+ "ajv": "8.10.0",
99
+ "ajv-keywords": "5.1.0"
100
100
  },
101
101
  "peerDependenciesMeta": {
102
102
  "@mojaloop/central-services-error-handling": {
@@ -93,6 +93,10 @@ const Event = {
93
93
  RECORD_FUNDS_OUT_PREPARE_RESERVE: 'recordFundsOutPrepareReserve',
94
94
  REJECT: 'reject',
95
95
  RESOLVE: 'resolve',
96
+
97
+ // The Transfer was marked as RESERVED by the payee DFSP
98
+ // and was then aborted by the switch
99
+ RESERVED_ABORTED: 'reserved-aborted',
96
100
  REQUEST: 'request',
97
101
  RESERVE: 'reserve',
98
102
  SETTLEMENT_WINDOW: 'settlement-window',
@@ -150,6 +150,10 @@ const TopicMap = {
150
150
  functionality: transferEventType.NOTIFICATION,
151
151
  action: transferEventAction.EVENT
152
152
  },
153
+ 'reserved-aborted': {
154
+ functionality: transferEventType.NOTIFICATION,
155
+ action: transferEventAction.EVENT
156
+ },
153
157
  'settlement-window': {
154
158
  functionality: transferEventType.NOTIFICATION,
155
159
  action: transferEventAction.EVENT
package/src/index.d.ts CHANGED
@@ -260,6 +260,7 @@ declare namespace CentralServicesShared {
260
260
  enum EventActionEnum {
261
261
  ABORT = 'abort',
262
262
  ABORT_DUPLICATE = 'abort-duplicate',
263
+ ABORT_VALIDATION = 'abort-validation',
263
264
  ACCEPT = 'accept',
264
265
  BULK_ABORT = 'bulk-abort',
265
266
  BULK_COMMIT = 'bulk-commit',
@@ -294,6 +295,7 @@ declare namespace CentralServicesShared {
294
295
  RESOLVE = 'resolve',
295
296
  REQUEST = 'request',
296
297
  RESERVE = 'reserve',
298
+ RESERVED_ABORTED = 'reserved-aborted',
297
299
  SETTLEMENT_WINDOW = 'settlement-window',
298
300
  TIMEOUT_RECEIVED = 'timeout-received',
299
301
  TIMEOUT_RESERVED = 'timeout-reserved',
@@ -317,6 +319,7 @@ declare namespace CentralServicesShared {
317
319
  Action: {
318
320
  ABORT: EventActionEnum.ABORT;
319
321
  ABORT_DUPLICATE: EventActionEnum.ABORT_DUPLICATE;
322
+ ABORT_VALIDATION: EventActionEnum.ABORT_VALIDATION;
320
323
  ACCEPT: EventActionEnum.ACCEPT;
321
324
  BULK_ABORT: EventActionEnum.BULK_ABORT;
322
325
  BULK_COMMIT: EventActionEnum.BULK_COMMIT;
@@ -351,6 +354,7 @@ declare namespace CentralServicesShared {
351
354
  RESOLVE: EventActionEnum.RESOLVE;
352
355
  REQUEST: EventActionEnum.REQUEST;
353
356
  RESERVE: EventActionEnum.RESERVE;
357
+ RESERVED_ABORTED: EventActionEnum.RESERVED_ABORTED;
354
358
  SETTLEMENT_WINDOW: EventActionEnum.SETTLEMENT_WINDOW;
355
359
  TIMEOUT_RECEIVED: EventActionEnum.TIMEOUT_RECEIVED;
356
360
  TIMEOUT_RESERVED: EventActionEnum.TIMEOUT_RESERVED;
@@ -399,8 +403,13 @@ declare namespace CentralServicesShared {
399
403
  getEndpointAndRender(switchUrl: string, fsp: string, endpointType: FspEndpointTypesEnum, path: string, options?: any): Promise<string>
400
404
  }
401
405
 
406
+ interface ProtocolVersionsType {
407
+ content: string,
408
+ accept: string
409
+ }
410
+
402
411
  interface Request {
403
- sendRequest(url: string, headers: HapiUtil.Dictionary<string>, source: string, destination: string, method?: RestMethodsEnum, payload?: any, responseType?: string, span?: any, jwsSigner?: any): Promise<any>
412
+ sendRequest(url: string, headers: HapiUtil.Dictionary<string>, source: string, destination: string, method?: RestMethodsEnum, payload?: any, responseType?: string, span?: any, jwsSigner?: any, protocolVersions?: ProtocolVersionsType): Promise<any>
404
413
  }
405
414
 
406
415
  interface Kafka {
@@ -30,12 +30,36 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
30
30
 
31
31
  const resourceVersions = require('../helpers').resourceVersions
32
32
 
33
- const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(\w*)+(\+json\s{0,1};\s{0,1}version=)(.*)/
34
-
35
33
  /**
36
34
  * @module src/headers/transformer
37
35
  */
38
36
 
37
+ const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(\w*)+(\+json\s{0,1};\s{0,1}version=)(.*)/
38
+
39
+ /**
40
+ * @function getResourceInfoFromHeader
41
+ *
42
+ * @description This will parse either a FSPIOP Content-Type or Accept header and return an object containing the resourceType and applicable version
43
+ *
44
+ * @typedef ResourceInfo
45
+ * @type {object}
46
+ * @property {string} resourceType - resource parsed from the headerValue.
47
+ * @property {string} version - version parsed from the headerValue.
48
+ *
49
+ * @param {string} headerValue - the http header from the request, thus must be either an FSPIOP Content-Type or Accept header.
50
+ *
51
+ * @returns {ResourceInfo} Returns resourceInfo object. If the headerValue was not parsed correctly, an empty object {} will be returned.
52
+ */
53
+ const getResourceInfoFromHeader = (headerValue) => {
54
+ const result = {}
55
+ const regex = regexForContentAndAcceptHeaders.exec(headerValue)
56
+ if (regex) {
57
+ if (regex[2]) result.resourceType = regex[2]
58
+ if (regex[4]) result.version = regex[4]
59
+ }
60
+ return result
61
+ }
62
+
39
63
  /**
40
64
  * @function transformHeaders
41
65
  *
@@ -45,7 +69,31 @@ const regexForContentAndAcceptHeaders = /(application\/vnd\.interoperability\.)(
45
69
  *
46
70
  * see https://nodejs.org/dist/latest-v10.x/docs/api/http.html#http_message_headers
47
71
  *
72
+ * @typedef TransformProtocolVersions
73
+ * @type {object}
74
+ * @property {string} content - protocol version to be used in the ContentType HTTP Header.
75
+ * @property {string} accept - protocol version to be used in the Accept HTTP Header.
76
+ *
77
+ * @typedef TransformHeadersConfig
78
+ * @type {object}
79
+ * @property {string} contentType - HTTP method such as "POST", "PUT", etc.
80
+ * @property {string} accept - Source FSP Identifier.
81
+ * @property {string} destinationFsp - Destination FSP Identifier.
82
+ * @property {TransformProtocolVersions} protocolVersions - Config for Protocol versions to be used.
83
+ *
84
+ * Config supports the following parameters:
85
+ * config: {
86
+ * httpMethod: string,
87
+ * sourceFsp: string,
88
+ * destinationFsp: string,
89
+ * protocolVersions: {
90
+ * content: string,
91
+ * accept: string
92
+ * }
93
+ * }
94
+ *
48
95
  * @param {object} headers - the http header from the request
96
+ * @param {TransformHeadersConfig} headers - the http header from the request
49
97
  *
50
98
  * @returns {object} Returns the normalized headers
51
99
  */
@@ -62,8 +110,15 @@ const transformHeaders = (headers, config) => {
62
110
  const normalizedHeaders = {}
63
111
 
64
112
  // resource type for content-type and accept headers
65
- const getResourceFromHeader = (headerValue) => regexForContentAndAcceptHeaders.exec(headerValue)[2]
66
113
  let resourceType
114
+ let acceptVersion
115
+ let contentVersion
116
+
117
+ // Determine the acceptVersion using the injected config
118
+ if (config && config.protocolVersions && config.protocolVersions.accept) acceptVersion = config.protocolVersions.accept
119
+
120
+ // Determine the contentVersion using the injected config
121
+ if (config && config.protocolVersions && config.protocolVersions.content) contentVersion = config.protocolVersions.content
67
122
 
68
123
  // check to see if FSPIOP-Destination header has been left out of the initial request. If so then add it.
69
124
  if (!normalizedKeys[ENUM.Headers.FSPIOP.DESTINATION]) {
@@ -127,16 +182,20 @@ const transformHeaders = (headers, config) => {
127
182
  normalizedHeaders[headerKey] = headerValue
128
183
  break
129
184
  }
130
- if (!resourceType) resourceType = getResourceFromHeader(headers[headerKey])
131
- normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${resourceVersions[resourceType].acceptVersion}`
185
+ if (!resourceType) resourceType = getResourceInfoFromHeader(headers[headerKey]).resourceType
186
+ // Fall back to using the legacy approach to determine the resourceVersion
187
+ if (resourceType && !acceptVersion) acceptVersion = resourceVersions[resourceType].acceptVersion
188
+ normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${acceptVersion}`
132
189
  break
133
190
  case (ENUM.Headers.GENERAL.CONTENT_TYPE.value):
134
191
  if (!ENUM.Headers.FSPIOP.SWITCH.regex.test(config.sourceFsp)) {
135
192
  normalizedHeaders[headerKey] = headerValue
136
193
  break
137
194
  }
138
- if (!resourceType) resourceType = getResourceFromHeader(headers[headerKey])
139
- normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${resourceVersions[resourceType].contentVersion}`
195
+ if (!resourceType) resourceType = getResourceInfoFromHeader(headers[headerKey]).resourceType
196
+ // Fall back to using the legacy approach to determine the resourceVersion
197
+ if (resourceType && !contentVersion) contentVersion = resourceVersions[resourceType].contentVersion
198
+ normalizedHeaders[headerKey] = `application/vnd.interoperability.${resourceType}+json;version=${contentVersion}`
140
199
  break
141
200
  default:
142
201
  normalizedHeaders[headerKey] = headerValue
@@ -157,5 +216,6 @@ const transformHeaders = (headers, config) => {
157
216
  }
158
217
 
159
218
  module.exports = {
219
+ getResourceInfoFromHeader,
160
220
  transformHeaders
161
221
  }
@@ -327,5 +327,8 @@ module.exports = {
327
327
  produceParticipantMessage,
328
328
  produceGeneralMessage,
329
329
  commitMessageSync,
330
- proceed
330
+ proceed,
331
+
332
+ // exported for testing purposes:
333
+ _getFunctionalityAction: getFunctionalityAction
331
334
  }
@@ -43,20 +43,26 @@ delete request.defaults.headers.common.Accept
43
43
  *
44
44
  * @description sends a request to url
45
45
  *
46
+ * @typedef SendRequestProtocolVersions
47
+ * @type {object}
48
+ * @property {string} content - protocol version to be used in the ContentType HTTP Header.
49
+ * @property {string} accept - protocol version to be used in the Accept HTTP Header.
50
+ *
46
51
  * @param {string} url the endpoint for the service you require
47
52
  * @param {object} headers the http headers
48
53
  * @param {string} method http method being requested i.e. GET, POST, PUT
49
54
  * @param {string} source id for which callback is being sent from
50
55
  * @param {string} destination id for which callback is being sent
51
- * @param {object} payload the body of the request being sent
56
+ * @param {object | undefined} payload the body of the request being sent
52
57
  * @param {string} responseType the type of the response object
53
- * @param {object} span a span for event logging if this request is within a span
54
- * @param {object} jwsSigner the jws signer for signing the requests
58
+ * @param {object | undefined} span a span for event logging if this request is within a span
59
+ * @param {object | undefined} jwsSigner the jws signer for signing the requests
60
+ * @param {SendRequestProtocolVersions | undefined} protocolVersions the config for Protocol versions to be used
55
61
  *
56
- *@return {object} The response for the request being sent or error object with response included
62
+ *@return {Promise<any>} The response for the request being sent or error object with response included
57
63
  */
58
64
 
59
- const sendRequest = async (url, headers, source, destination, method = enums.Http.RestMethods.GET, payload = undefined, responseType = enums.Http.ResponseTypes.JSON, span = undefined, jwsSigner = undefined) => {
65
+ const sendRequest = async (url, headers, source, destination, method = enums.Http.RestMethods.GET, payload = undefined, responseType = enums.Http.ResponseTypes.JSON, span = undefined, jwsSigner = undefined, protocolVersions = undefined) => {
60
66
  const histTimerEnd = !!Metrics.isInitiated() && Metrics.getHistogram(
61
67
  'sendRequest',
62
68
  `sending ${method} request to: ${url} from: ${source} to: ${destination}`,
@@ -75,7 +81,8 @@ const sendRequest = async (url, headers, source, destination, method = enums.Htt
75
81
  const transformedHeaders = Headers.transformHeaders(headers, {
76
82
  httpMethod: method,
77
83
  sourceFsp: source,
78
- destinationFsp: destination
84
+ destinationFsp: destination,
85
+ protocolVersions
79
86
  })
80
87
  requestOptions = {
81
88
  url,
@@ -31,6 +31,7 @@ const Sinon = require('sinon')
31
31
  const Transformer = require('../../../src/util').Headers
32
32
  const Enum = require('../../../src/enums')
33
33
  const Util = require('../../../src/util')
34
+ const Helper = require('../../util/helper')
34
35
 
35
36
  const headerConfigExample = {
36
37
  httpMethod: 'PUT',
@@ -67,6 +68,30 @@ Test('Transfer Transformer tests', TransformerTest => {
67
68
  t.end()
68
69
  })
69
70
 
71
+ TransformerTest.test('Transformer.getResourceInfoFromHeaderTest() should', getResourceInfoFromHeaderTest => {
72
+ getResourceInfoFromHeaderTest.test('parse FSPIOP Content-Type example correctly', async test => {
73
+ const result = Transformer.getResourceInfoFromHeader(headerDataInputExample['Content-Type'])
74
+ test.equal(headerDataInputExample['Content-Type'], Helper.generateProtocolHeader(result.resourceType, result.version))
75
+ test.end()
76
+ })
77
+
78
+ getResourceInfoFromHeaderTest.test('return an empty result with standard application/json', async test => {
79
+ const contentType = 'application/json'
80
+ const result = Transformer.getResourceInfoFromHeader(contentType)
81
+ test.same(result, {})
82
+ test.end()
83
+ })
84
+
85
+ getResourceInfoFromHeaderTest.test('return an empty result with incorrect FSPIOP Content-Type input', async test => {
86
+ const contentType = 'application/vnd.interoperability.transfers+json'
87
+ const result = Transformer.getResourceInfoFromHeader(contentType)
88
+ test.same(result, {})
89
+ test.end()
90
+ })
91
+
92
+ getResourceInfoFromHeaderTest.end()
93
+ })
94
+
70
95
  TransformerTest.test('Transformer.transformHeaders() should', transformHeadersTest => {
71
96
  transformHeadersTest.test('Remove all unnecessary fields from Header', async test => {
72
97
  const headerData = Util.clone(headerDataInputExample)
@@ -78,6 +103,58 @@ Test('Transfer Transformer tests', TransformerTest => {
78
103
  test.end()
79
104
  })
80
105
 
106
+ transformHeadersTest.test('Set ContentType && Accept versions via RESOURCE_VERSIONS env variable', async test => {
107
+ const RESOURCE_VERSIONS_BACKUP = process.env.RESOURCE_VERSIONS
108
+ process.env.RESOURCE_VERSIONS = 'transfers=1.1,quotes=1.0'
109
+
110
+ const headerConfig = {
111
+ httpMethod: 'PUT',
112
+ sourceFsp: 'switch',
113
+ destinationFsp: 'FSPDest'
114
+ }
115
+
116
+ const headerData = Util.clone(headerDataInputExample)
117
+ headerData.Accept = Helper.generateProtocolHeader('transfers', '1')
118
+
119
+ const transformedHeaderData = Transformer.transformHeaders(headerData, headerConfig)
120
+
121
+ test.deepEqual(headerData['Content-Type'], transformedHeaderData['Content-Type'])
122
+ test.deepEqual(headerData.Accept, transformedHeaderData.Accept)
123
+ test.end()
124
+ process.env.RESOURCE_VERSIONS = RESOURCE_VERSIONS_BACKUP
125
+ })
126
+
127
+ transformHeadersTest.test('Set ContentType && Accept versions via config', async test => {
128
+ const RESOURCE_VERSIONS_BACKUP = process.env.RESOURCE_VERSIONS
129
+ // we keep this here to make sure it does not override the injected protocolVersions config
130
+ process.env.RESOURCE_VERSIONS = 'transfers=1.0,quotes=1.0'
131
+
132
+ const headerConfig = {
133
+ httpMethod: 'PUT',
134
+ sourceFsp: 'switch',
135
+ destinationFsp: 'FSPDest',
136
+ protocolVersions: {
137
+ content: '1.1',
138
+ accept: '1'
139
+ }
140
+ }
141
+
142
+ const headerData = Util.clone(headerDataInputExample)
143
+ headerData.Accept = Helper.generateProtocolHeader('transfers', '1.1')
144
+
145
+ const resourceInfoFromHeader = Transformer.getResourceInfoFromHeader(headerData['Content-Type'])
146
+
147
+ const transformedHeaderData = Transformer.transformHeaders(headerData, headerConfig)
148
+ const resourceInfoFromTransformedHeader = Transformer.getResourceInfoFromHeader(transformedHeaderData['Content-Type'])
149
+
150
+ test.equal(resourceInfoFromHeader.resourceType, resourceInfoFromTransformedHeader.resourceType)
151
+ test.equal(resourceInfoFromHeader.version, '1.0')
152
+ test.equal(resourceInfoFromTransformedHeader.version, '1.1')
153
+ test.equal(transformedHeaderData.Accept, Helper.generateProtocolHeader('transfers', headerConfig.protocolVersions.accept))
154
+ test.end()
155
+ process.env.RESOURCE_VERSIONS = RESOURCE_VERSIONS_BACKUP
156
+ })
157
+
81
158
  transformHeadersTest.test('Translate Date field into correct format for String value', async test => {
82
159
  const key = 'Date'
83
160
  const val = '2018-09-13T13:52:15.221Z'
@@ -46,6 +46,7 @@ const Utility = require('../../../../src/util').Kafka
46
46
  const Enum = require('../../../../src').Enum
47
47
  const Config = require('../../../util/config')
48
48
  const clone = require('../../../../src/util').clone
49
+ const { _getFunctionalityAction } = require('../../../../src/util/kafka')
49
50
 
50
51
  let participantName
51
52
  const TRANSFER = Enum.Events.Event.Type.TRANSFER
@@ -124,6 +125,43 @@ Test('Utility Test', utilityTest => {
124
125
  test.end()
125
126
  })
126
127
 
128
+ utilityTest.test('getFunctionalityAction', gfaTest => {
129
+ gfaTest.test('should return config for transfer-prepare', test => {
130
+ // Arrange
131
+ const expected = { functionalityMapped: 'transfer', actionMapped: 'prepare' }
132
+ // Act
133
+ const result = _getFunctionalityAction('transfer', 'prepare')
134
+
135
+ // Assert
136
+ test.deepEqual(result, expected)
137
+ test.end()
138
+ })
139
+
140
+ gfaTest.test('should return config for NOTIFICATION ABORT_VALIDATION', test => {
141
+ // Arrange
142
+ const expected = { functionalityMapped: 'notification', actionMapped: 'event' }
143
+ // Act
144
+ const result = _getFunctionalityAction('notification', 'abort-validation')
145
+
146
+ // Assert
147
+ test.deepEqual(result, expected)
148
+ test.end()
149
+ })
150
+
151
+ gfaTest.test('should return config for transfer-reserved-aborted', test => {
152
+ // Arrange
153
+ const expected = { functionalityMapped: 'notification', actionMapped: 'event' }
154
+ // Act
155
+ const result = _getFunctionalityAction('notification', 'reserved-aborted')
156
+
157
+ // Assert
158
+ test.deepEqual(result, expected)
159
+ test.end()
160
+ })
161
+
162
+ gfaTest.end()
163
+ })
164
+
127
165
  utilityTest.test('createParticipantTopicConf should', createParticipantTopicConfTest => {
128
166
  createParticipantTopicConfTest.test('return a participant topic conf object', test => {
129
167
  const response = Utility.createParticipantTopicConf(Config.KAFKA_CONFIG.TOPIC_TEMPLATES.PARTICIPANT_TOPIC_TEMPLATE.TEMPLATE, participantName, TRANSFER, PREPARE, 0)
@@ -112,6 +112,59 @@ Test('ParticipantEndpoint Model Test', modelTest => {
112
112
  }
113
113
  })
114
114
 
115
+ getEndpointTest.test('handle protocolVersions for config injection', async (test) => {
116
+ const protocolVersions = {
117
+ content: '2.1',
118
+ accept: '2'
119
+ }
120
+ const fsp = 'fsp'
121
+ const requestOptions = {
122
+ url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }),
123
+ method: 'get'
124
+ }
125
+ const requestFunction = (request) => {
126
+ test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', protocolVersions.content))
127
+ test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', protocolVersions.accept))
128
+ return Helper.getEndPointsResponse
129
+ }
130
+ const span = EventSdk.Tracer.createSpan('test-span')
131
+ Model = proxyquire('../../../src/util/request', { axios: requestFunction })
132
+
133
+ try {
134
+ const result = await Model.sendRequest(requestOptions.url, Helper.defaultHeaders(Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.PARTICIPANTS, Enum.Http.HeaderResources.SWITCH), Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.SWITCH, Enum.Http.RestMethods.GET, undefined, Enum.Http.ResponseTypes.JSON, span, null, protocolVersions)
135
+ test.deepEqual(result, Helper.getEndPointsResponse, 'The results match')
136
+ test.end()
137
+ } catch (err) {
138
+ test.fail('Error thrown', err)
139
+ test.end()
140
+ }
141
+ })
142
+
143
+ getEndpointTest.test('handle protocolVersions without config injection', async (test) => {
144
+ const protocolVersions = null
145
+ const fsp = 'fsp'
146
+ const requestOptions = {
147
+ url: Mustache.render(Config.ENDPOINT_SOURCE_URL + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp }),
148
+ method: 'get'
149
+ }
150
+ const requestFunction = (request) => {
151
+ test.equal(request.headers['content-type'], Helper.generateProtocolHeader('participants', '1.0'))
152
+ test.equal(request.headers.accept, Helper.generateProtocolHeader('participants', '1'))
153
+ return Helper.getEndPointsResponse
154
+ }
155
+ const span = EventSdk.Tracer.createSpan('test-span')
156
+ Model = proxyquire('../../../src/util/request', { axios: requestFunction })
157
+
158
+ try {
159
+ const result = await Model.sendRequest(requestOptions.url, Helper.defaultHeaders(Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.PARTICIPANTS, Enum.Http.HeaderResources.SWITCH), Enum.Http.HeaderResources.SWITCH, Enum.Http.HeaderResources.SWITCH, Enum.Http.RestMethods.GET, undefined, Enum.Http.ResponseTypes.JSON, span, null, protocolVersions)
160
+ test.deepEqual(result, Helper.getEndPointsResponse, 'The results match')
161
+ test.end()
162
+ } catch (err) {
163
+ test.fail('Error thrown', err)
164
+ test.end()
165
+ }
166
+ })
167
+
115
168
  getEndpointTest.test('throw error', async (test) => {
116
169
  const fsp = 'fsp1'
117
170
 
@@ -26,13 +26,15 @@
26
26
 
27
27
  const Enums = require('../../src/enums')
28
28
 
29
- function defaultHeaders (destination, resource, source, version = '1.0') {
29
+ const generateProtocolHeader = (resource, version) => `application/vnd.interoperability.${resource}+json;version=${version}`
30
+
31
+ const defaultHeaders = (destination, resource, source, version = '1.0') => {
30
32
  // TODO: See API section 3.2.1; what should we do about X-Forwarded-For? Also, should we
31
33
  // add/append to this field in all 'queueResponse' calls?
32
34
  return {
33
- accept: `application/vnd.interoperability.${resource}+json;version=${version}`,
35
+ accept: generateProtocolHeader(resource, version),
34
36
  'fspiop-destination': destination || '',
35
- 'content-type': `application/vnd.interoperability.${resource}+json;version=${version}`,
37
+ 'content-type': generateProtocolHeader(resource, version),
36
38
  date: '2019-05-24 08:52:19',
37
39
  'fspiop-source': source
38
40
  }
@@ -74,6 +76,7 @@ const getEndpointAndRenderResponse = {
74
76
 
75
77
  module.exports = {
76
78
  defaultHeaders,
79
+ generateProtocolHeader,
77
80
  getEndPointsResponse,
78
81
  getEndpointAndRenderResponse
79
82
  }