@naturalcycles/nodejs-lib
Version:
Standard library for Node.js
127 lines • 4.52 kB
JavaScript
;
/*
* Does 2 things:
* 1. Validates the value according to Schema passed.
* 2. Converts the value (also according to Schema).
*
* "Converts" mean e.g trims all strings from leading/trailing spaces.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const js_lib_1 = require("@naturalcycles/js-lib");
const joi_validation_error_1 = require("./joi.validation.error");
// Strip colors in production (for e.g Sentry reporting)
// const stripColors = process.env.NODE_ENV === 'production' || !!process.env.GAE_INSTANCE
// Currently colors do more bad than good, so let's strip them always for now
const stripColors = true;
const defaultOptions = {
abortEarly: false,
convert: true,
allowUnknown: true,
stripUnknown: {
objects: true,
// true: it will SILENTLY strip invalid values from arrays. Very dangerous! Can lead to data loss!
// false: it will THROW validation error if any of array items is invalid
// Q: is it invalid if it has unknown properties?
// A: no, unknown properties are just stripped (in both 'false' and 'true' states), array is still valid
// Q: will it strip or keep unknown properties in array items?..
// A: strip
arrays: false,
},
presence: 'required',
};
/**
* Validates with Joi.
* Throws AppValidationError if invalid.
* Returns *converted* value.
*
* If `schema` is undefined - returns value as is.
*/
function validate(value, schema, objectName, options = {}) {
const { value: returnValue, error } = getValidationResult(value, schema, objectName, options);
if (error) {
throw error;
}
return returnValue;
}
exports.validate = validate;
/**
* Validates with Joi.
* Returns ValidationResult with converted value and error (if any).
* Does not throw.
*
* If `schema` is undefined - returns value as is.
*/
function getValidationResult(value, schema, objectName, options = {}) {
if (!schema)
return { value };
const { value: returnValue, error } = schema.validate(value, {
...defaultOptions,
...options,
});
const vr = {
value: returnValue,
};
if (error) {
vr.error = createError(value, error, objectName);
}
return vr;
}
exports.getValidationResult = getValidationResult;
/**
* Convenience function that returns true if !error.
*/
function isValid(value, schema) {
if (!schema)
return { value };
const { error } = schema.validate(value, defaultOptions);
return !error;
}
exports.isValid = isValid;
function undefinedIfInvalid(value, schema) {
if (!schema)
return { value };
const { value: returnValue, error } = schema.validate(value, defaultOptions);
return error ? undefined : returnValue;
}
exports.undefinedIfInvalid = undefinedIfInvalid;
/**
* Will do joi-convertation, regardless of error/validity of value.
* @returns converted value
*/
function convert(value, schema) {
if (!schema)
return value;
const { value: returnValue } = schema.validate(value, defaultOptions);
return returnValue;
}
exports.convert = convert;
function createError(value, err, objectName) {
var _a;
if (!err)
return undefined;
const tokens = [];
const objectId = js_lib_1._isObject(value) ? value['id'] : undefined;
if (objectId || objectName) {
objectName = objectName || ((_a = value === null || value === void 0 ? void 0 : value.constructor) === null || _a === void 0 ? void 0 : _a.name);
tokens.push([objectName, objectId].filter(Boolean).join('.'));
}
const annotation = err.annotate(stripColors);
if (annotation.length > 1000) {
// Annotation message is too big and will be replaced by stringified `error.details` instead
tokens.push(annotation.substr(0, 1000), `... ${Math.ceil(annotation.length / 1024)} KB message truncated`);
// Up to 5 `details`
tokens.push(...err.details.slice(0, 5).map(i => `${i.message} @ .${i.path.join('.')}`));
if (err.details.length > 5)
tokens.push(`... ${err.details.length} errors`);
}
else {
tokens.push(annotation);
}
const msg = tokens.join('\n');
return new joi_validation_error_1.JoiValidationError(msg, {
joiValidationErrorItems: err.details,
...(objectName && { joiValidationObjectName: objectName }),
...(objectId && { joiValidationObjectId: objectId }),
});
}
//# sourceMappingURL=joi.validation.util.js.map