* allow serviceData to override cacheSeconds with a longer value * prevent [endpoint] json cacheSeconds property exceeding service default * allow ShieldsRuntimeError to specify a cacheSeconds property By default error responses use the cacheLength of the service class throwing the error. This allows error to tell the handling layer the maxAge that should be set on the error badge response. * add customExceptions param This 1. allows us to specify custom properties to pass to the exception constructor if we throw any of the standard got errors e.g: `ETIMEDOUT`, `ECONNRESET`, etc 2. uses a custom `cacheSeconds` property (if set on the exception) to set the response maxAge * customExceptions --> systemErrors * errorMessages --> httpErrors
107 lines
3.3 KiB
JavaScript
107 lines
3.3 KiB
JavaScript
/**
|
|
* Common functions and utilities for tasks related to endpoint badges.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import Joi from 'joi'
|
|
import validate from '../core/base-service/validate.js'
|
|
import { InvalidResponse } from './index.js'
|
|
|
|
const optionalStringWhenNamedLogoPresent = Joi.alternatives().conditional(
|
|
'namedLogo',
|
|
{
|
|
is: Joi.string().required(),
|
|
then: Joi.string(),
|
|
}
|
|
)
|
|
|
|
const optionalNumberWhenAnyLogoPresent = Joi.alternatives()
|
|
.conditional('namedLogo', { is: Joi.string().required(), then: Joi.number() })
|
|
.conditional('logoSvg', { is: Joi.string().required(), then: Joi.number() })
|
|
|
|
/**
|
|
* Joi schema for validating endpoint.
|
|
*
|
|
* @type {Joi}
|
|
*/
|
|
const endpointSchema = Joi.object({
|
|
schemaVersion: 1,
|
|
label: Joi.string().allow('').required(),
|
|
message: Joi.string().required(),
|
|
color: Joi.string(),
|
|
labelColor: Joi.string(),
|
|
isError: Joi.boolean().default(false),
|
|
namedLogo: Joi.string(),
|
|
logoSvg: Joi.string(),
|
|
logoColor: optionalStringWhenNamedLogoPresent,
|
|
logoWidth: optionalNumberWhenAnyLogoPresent,
|
|
logoPosition: optionalNumberWhenAnyLogoPresent,
|
|
style: Joi.string(),
|
|
cacheSeconds: Joi.number().integer().min(0),
|
|
})
|
|
// `namedLogo` or `logoSvg`; not both.
|
|
.oxor('namedLogo', 'logoSvg')
|
|
.required()
|
|
|
|
/**
|
|
* Strictly validate the data according to the endpoint schema.
|
|
* This rejects unknown/invalid keys.
|
|
* Optionally it prints those keys in the message to provide detailed feedback.
|
|
*
|
|
* @param {object} data Object containing the data for validation
|
|
* @param {object} attrs Refer to individual attributes
|
|
* @param {string} [attrs.prettyErrorMessage] If provided then error message is set to this value
|
|
* @param {boolean} [attrs.includeKeys] If true then includes error details in error message, defaults to false
|
|
* @throws {InvalidResponse|Error} Error if Joi validation fails due to invalid or no schema
|
|
* @returns {object} Value if Joi validation is success
|
|
*/
|
|
function validateEndpointData(
|
|
data,
|
|
{ prettyErrorMessage = 'invalid response data', includeKeys = false } = {}
|
|
) {
|
|
return validate(
|
|
{
|
|
ErrorClass: InvalidResponse,
|
|
prettyErrorMessage,
|
|
includeKeys,
|
|
traceErrorMessage: 'Response did not match schema',
|
|
traceSuccessMessage: 'Response after validation',
|
|
allowAndStripUnknownKeys: false,
|
|
},
|
|
data,
|
|
endpointSchema
|
|
)
|
|
}
|
|
|
|
const anySchema = Joi.any()
|
|
|
|
/**
|
|
* Fetches data from the endpoint and validates the data.
|
|
*
|
|
* @param {object} serviceInstance Instance of Endpoint class
|
|
* @param {object} attrs Refer to individual attributes
|
|
* @param {string} attrs.url Endpoint URL
|
|
* @param {object} attrs.httpErrors Object containing error messages for different error codes
|
|
* @param {string} attrs.validationPrettyErrorMessage If provided then the error message is set to this value
|
|
* @param {boolean} attrs.includeKeys If true then includes error details in error message
|
|
* @returns {object} Data fetched from endpoint
|
|
*/
|
|
async function fetchEndpointData(
|
|
serviceInstance,
|
|
{ url, httpErrors, validationPrettyErrorMessage, includeKeys }
|
|
) {
|
|
const json = await serviceInstance._requestJson({
|
|
schema: anySchema,
|
|
url,
|
|
httpErrors,
|
|
options: { decompress: true },
|
|
})
|
|
return validateEndpointData(json, {
|
|
prettyErrorMessage: validationPrettyErrorMessage,
|
|
includeKeys,
|
|
})
|
|
}
|
|
|
|
export { validateEndpointData, fetchEndpointData }
|