unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
100 lines • 4.74 kB
JavaScript
import getProp from 'lodash.get';
import { UnleashError } from './unleash-error.js';
class BadDataError extends UnleashError {
constructor(message, errors) {
const topLevelMessage = `Request validation failed: your request body or params contain invalid data${errors
? '. Refer to the `details` list for more information.'
: `: ${message}`}`;
super(topLevelMessage);
this.statusCode = 400;
this.details = errors ?? [{ message: message }];
}
toJSON() {
return {
...super.toJSON(),
details: this.details,
};
}
}
export default BadDataError;
const constructPath = (pathToParent, propertyName) => [pathToParent, propertyName].filter(Boolean).join('/');
const missingRequiredPropertyMessage = (pathToParentObject, missingPropertyName) => {
const path = constructPath(pathToParentObject, missingPropertyName);
const message = `The \`${path}\` property is required. It was not present on the data you sent.`;
return {
path,
message,
};
};
const additionalPropertiesMessage = (pathToParentObject, additionalPropertyName) => {
const path = constructPath(pathToParentObject, additionalPropertyName);
const message = `The ${pathToParentObject ? `\`${pathToParentObject}\`` : 'root'} object of the request body does not allow additional properties. Your request included the \`${path}\` property.`;
return {
path,
message,
};
};
const genericErrorMessage = (propertyName, propertyValue, errorMessage = 'is invalid') => {
const youSent = JSON.stringify(propertyValue);
const message = `The \`${propertyName}\` property ${errorMessage}. You sent ${youSent}.`;
return {
message,
path: propertyName,
};
};
const oneOfMessage = (propertyName, errorMessage = 'is invalid') => {
const errorPosition = propertyName === '' ? 'root object' : `"${propertyName}" property`;
const message = `The ${errorPosition} ${errorMessage}. The data you provided matches more than one option in the schema. These options are mutually exclusive. Please refer back to the schema and remove any excess properties.`;
return {
message,
path: propertyName,
};
};
const enumMessage = (propertyName, message, allowedValues, suppliedValue) => {
const fullMessage = `The \`${propertyName}\` property ${message ?? 'must match one of the allowed values'}: ${allowedValues
.map((value) => `"${value}"`)
.join(', ')}. You provided "${suppliedValue}", which is not valid. Please use one of the allowed values instead..`;
return {
message: fullMessage,
path: propertyName,
};
};
export const fromOpenApiValidationError = (data) => (validationError) => {
const { instancePath, params, message } = validationError;
const propertyValue = getProp(data, instancePath.split('/').filter(Boolean));
switch (validationError.keyword) {
case 'required':
return missingRequiredPropertyMessage(instancePath, params.missingProperty);
case 'additionalProperties':
return additionalPropertiesMessage(instancePath, params.additionalProperty);
case 'enum':
return enumMessage(instancePath.substring(instancePath.lastIndexOf('/') + 1), message, params.allowedValues, propertyValue);
case 'oneOf':
return oneOfMessage(instancePath, validationError.message);
default:
return genericErrorMessage(instancePath, propertyValue, message);
}
};
export const fromOpenApiValidationErrors = (data, validationErrors) => {
const [firstDetail, ...remainingDetails] = validationErrors.map(fromOpenApiValidationError(data));
return new BadDataError("Request validation failed: your request doesn't conform to the schema. Check the `details` property for a list of errors that we found.", [firstDetail, ...remainingDetails]);
};
export const fromJoiError = (err) => {
const details = err.details.map((detail) => {
const messageEnd = detail.context?.value
? `. You provided ${JSON.stringify(detail.context.value)}.`
: '.';
const message = detail.message + messageEnd;
return {
message,
};
});
const [first, ...rest] = details;
if (first) {
return new BadDataError('A validation error occurred while processing your request data. Refer to the `details` property for more information.', [first, ...rest]);
}
else {
return new BadDataError('A validation error occurred while processing your request data. Please make sure it conforms to the request data schema.');
}
};
//# sourceMappingURL=bad-data-error.js.map