Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 26 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@
"devDependencies": {
"@hapi/boom": "10.0.1",
"audit-ci": "^7.1.0",
"npm-check-updates": "22.2.9",
"npm-check-updates": "23.0.0",
"nyc": "18.0.0",
"pre-commit": "2.0.0",
"proxyquire": "2.1.3",
"replace": "^1.2.2",
"sinon": "22.0.0",
"sinon": "22.1.0",
"standard": "17.1.2",
"standard-version": "^9.5.0",
"tap-spec": "^5.0.0",
Expand All @@ -71,8 +71,8 @@
"@babel/helpers": "7.26.10",
"cross-spawn": "7.0.6",
"trim": "0.0.3",
"brace-expansion": "2.0.3",
"js-yaml": "4.2.0",
"brace-expansion": "5.0.8",
"js-yaml": "4.3.0",
"uuid": "11.1.1",
"replace": {
"minimatch": "3.1.5"
Expand Down
10 changes: 10 additions & 0 deletions src/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,17 @@ const createFSPIOPErrorFromOpenapiError = (error, replyTo) => {
return Enums.FSPIOPErrorCodes.MISSING_ELEMENT
case 'additionalProperties':
return Enums.FSPIOPErrorCodes.TOO_MANY_ELEMENTS
// enum/const/format/pattern mirror createFSPIOPErrorFromJoiError's
// any.only (mojaloop/project#2013), date.format and string.* cases, so
// services migrating from hapi-openapi/joi keep returning 3101 for
// syntactically invalid values. minLength/maxLength are deliberately
// NOT mapped: they fall through to 3100, the behavior existing
// openapi-backend services already expose (and Golden Path asserts).
case 'type':
case 'enum':
case 'const':
case 'format':
case 'pattern':
return Enums.FSPIOPErrorCodes.MALFORMED_SYNTAX
case 'notFound':
return Enums.FSPIOPErrorCodes.UNKNOWN_URI
Expand Down
81 changes: 81 additions & 0 deletions test/factory.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,87 @@ Test('Factory should', factoryTest => {
test.end()
})

factoryTest.test('create an FSPIOPError from a Openapi-backend enum violation (joi any.only parity, mojaloop/project#2013)', function (test) {
const error = {
keyword: 'enum',
instancePath: '/query/state',
schemaPath: '#/properties/query/properties/state/enum',
params: { allowedValues: ['OPEN', 'CLOSED'] },
message: 'must be equal to one of the allowed values'
}
const fspiopError = Factory.createFSPIOPErrorFromOpenapiError(error, 'dfsp1')
test.ok(fspiopError)
test.deepEqual(fspiopError.toApiErrorObject(), {
errorInformation: {
errorCode: '3101',
errorDescription: 'Malformed syntax - /query/state must be equal to one of the allowed values'
}
})
test.end()
})

factoryTest.test('create an FSPIOPError from a Openapi-backend const violation', function (test) {
const error = {
keyword: 'const',
instancePath: '/body/currency',
params: { allowedValue: 'USD' },
message: 'must be equal to constant'
}
const fspiopError = Factory.createFSPIOPErrorFromOpenapiError(error, 'dfsp1')
test.ok(fspiopError)
test.equal(fspiopError.toApiErrorObject().errorInformation.errorCode, '3101')
test.end()
})

factoryTest.test('create an FSPIOPError from a Openapi-backend format violation (joi date.format/string.* parity)', function (test) {
const error = {
keyword: 'format',
instancePath: '/body/expiration',
params: { format: 'date-time' },
message: 'must match format "date-time"'
}
const fspiopError = Factory.createFSPIOPErrorFromOpenapiError(error, 'dfsp1')
test.ok(fspiopError)
test.deepEqual(fspiopError.toApiErrorObject(), {
errorInformation: {
errorCode: '3101',
errorDescription: 'Malformed syntax - /body/expiration must match format "date-time"'
}
})
test.end()
})

factoryTest.test('create an FSPIOPError from a Openapi-backend pattern violation (joi string.regex parity)', function (test) {
const error = {
keyword: 'pattern',
instancePath: '/body/amount/amount',
params: { pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' },
message: 'must match pattern'
}
const fspiopError = Factory.createFSPIOPErrorFromOpenapiError(error, 'dfsp1')
test.ok(fspiopError)
test.equal(fspiopError.toApiErrorObject().errorInformation.errorCode, '3101')
test.end()
})

factoryTest.test('Openapi-backend minLength violation stays 3100 (deliberately unmapped — existing fleet/GP behavior)', function (test) {
const error = {
keyword: 'minLength',
instancePath: '/requestBody/quoteId',
params: { limit: 1 },
message: 'must NOT have fewer than 1 characters'
}
const fspiopError = Factory.createFSPIOPErrorFromOpenapiError(error, 'dfsp1')
test.ok(fspiopError)
test.deepEqual(fspiopError.toApiErrorObject(), {
errorInformation: {
errorCode: '3100',
errorDescription: 'Generic validation error - /requestBody/quoteId must NOT have fewer than 1 characters'
}
})
test.end()
})

factoryTest.test('create an FSPIOPError from a Openapi-backend additional property error response with toApiErrorObject includeCauseExtension: false, truncateExtensions: true', function (test) {
const error = {
keyword: 'additionalProperties',
Expand Down