kequapp
Version:
A minimal, zero-magic Node web framework built on native APIs
103 lines (102 loc) • 2.79 kB
JavaScript
import Ex from "../built-in/tools/ex.js";
export default function normalizeBody(body, options) {
if (options.skipNormalize === true)
return body;
const result = { ...body };
const { required = [], arrays = [], numbers = [], booleans = [], validate, } = options;
// arrays
for (const key of arrays) {
if (!Array.isArray(result[key])) {
result[key] = result[key] === undefined ? [] : [result[key]];
}
}
// not arrays!
for (const key of Object.keys(result)) {
if (arrays.includes(key))
continue;
if (Array.isArray(result[key])) {
result[key] = result[key][0];
}
}
// required
for (const key of required) {
if (arrays.includes(key)) {
const values = result[key].filter((value) => !isEmpty(value));
result[key] = values;
if (values.length > 0)
continue;
}
else {
if (!isEmpty(result[key]))
continue;
}
throw Ex.UnprocessableEntity(`Value ${key} is required`, {
body,
required,
});
}
// numbers
for (const key of numbers) {
if (!(key in result))
continue;
if (arrays.includes(key)) {
const values = result[key].map(toNumber);
result[key] = values;
if (!values.some((value) => Number.isNaN(value)))
continue;
}
else {
const value = toNumber(result[key]);
result[key] = value;
if (!Number.isNaN(value))
continue;
}
throw Ex.UnprocessableEntity(`Value ${key} must be a number`, {
body,
numbers,
});
}
// booleans
for (const key of booleans) {
if (!(key in result))
continue;
if (arrays.includes(key)) {
const values = result[key].map(toBoolean);
result[key] = values;
}
else {
result[key] = toBoolean(result[key]);
}
}
// validate
if (typeof validate === 'function') {
const problem = validate(result);
if (problem) {
throw Ex.UnprocessableEntity(problem, {
body,
});
}
}
return result;
}
function isEmpty(value) {
if (value === null)
return true;
if (value === undefined)
return true;
return false;
}
function toNumber(value) {
return parseFloat(value);
}
function toBoolean(value) {
if (typeof value === 'string' && value.toLowerCase() === 'false') {
return false;
}
else if (value === '0') {
return false;
}
else {
return Boolean(value);
}
}