Files
payload/src/fields/validations.js
2020-06-10 16:40:02 -04:00

183 lines
5.0 KiB
JavaScript

const { iterateFields } = require('./validateCreate');
const optionsToValidatorMap = {
number: (value, options = {}) => {
const parsedValue = parseInt(value, 10);
if (typeof parsedValue !== 'number' || Number.isNaN(parsedValue)) {
return 'Please enter a valid number.';
}
if (options.max && parsedValue > options.max) {
return `"${value}" is greater than the max allowed value of ${options.max}.`;
}
if (options.min && parsedValue < options.min) {
return `"${value}" is less than the min allowed value of ${options.min}.`;
}
return true;
},
text: (value, options = {}) => {
if (options.maxLength && (value && value.length > options.maxLength)) {
return `This value must be shorter than the max length of ${options.max} characters.`;
}
if (options.minLength && (value && value.length < options.minLength)) {
return `This value must be longer than the minimum length of ${options.max} characters.`;
}
if (typeof value !== 'string' || (typeof value === 'string' && value.length === 0)) {
return 'This field is required.';
}
return true;
},
password: (value, options = {}) => {
if (options.maxLength && value.length > options.maxLength) {
return `This value must be shorter than the max length of ${options.max} characters.`;
}
if (options.minLength && value.length < options.minLength) {
return `This value must be longer than the minimum length of ${options.max} characters.`;
}
return Boolean(value);
},
email: (value) => {
if (/\S+@\S+\.\S+/.test(value)) {
return true;
}
return 'Please enter a valid email address.';
},
textarea: (value, options = {}) => {
if (options.maxLength && value.length > options.maxLength) {
return `This value must be shorter than the max length of ${options.max} characters.`;
}
if (options.minLength && value.length < options.minLength) {
return `This value must be longer than the minimum length of ${options.max} characters.`;
}
return Boolean(value);
},
richText: (value) => {
//! Need better way to share an empty text node
//! it is used here and in field-types/RichText
const emptyRichTextNode = [{
children: [{ text: '' }],
}];
const blankSlateJSNode = JSON.stringify(emptyRichTextNode);
if (value && JSON.stringify(value) !== blankSlateJSNode) return true;
return 'This field is required.';
},
code: (value) => {
if (value) return true;
return 'This field is required.';
},
checkbox: (value) => {
if (typeof value === 'boolean') {
return true;
}
return 'This field can only be equal to true or false.';
},
date: (value) => {
if (value instanceof Date) {
return true;
}
return `"${value}" is not a valid date.`;
},
upload: (value) => {
if (value) return true;
return 'This field is required.';
},
relationship: (value) => {
if (value) return true;
return 'This field is required.';
},
group: async (value, options) => {
return iterateFields(value, options.fields, `${options.name}.`);
},
repeater: async (value, options = {}) => {
const path = options.path || options.name;
if (!value || value.length === 0) {
return 'This field requires at least one row.';
}
if (options.minRows && value.length < options.minRows) {
return `This field requires at least ${options.minRows} row(s).`;
}
if (options.maxRows && value.length > options.maxRows) {
return `This field requires no more than ${options.maxRows} row(s).`;
}
const errors = [];
const rowPromises = [];
value.forEach((row, i) => {
rowPromises.push(iterateFields(row, options.fields, `${path}.${i}.`));
});
const rowResults = await Promise.all(rowPromises);
rowResults.forEach((row) => {
row.forEach((fieldError) => {
errors.push(fieldError);
});
});
if (errors.length > 0) {
return errors;
}
return true;
},
select: (value) => {
if (value && value.length > 0) return true;
return 'This field is required.';
},
flexible: async (value, options) => {
if (value.length === 0) {
return `This field requires at least one ${options.singularLabel}.`;
}
const errors = [];
const rowPromises = [];
value.forEach((row, i) => {
const { blockType } = row;
const block = options.blocks.find(availableBlock => availableBlock.slug === blockType);
if (!block) {
return errors.push({
message: `Block ${i + 1} is missing a block type.`,
field: options.name,
});
}
return rowPromises.push(iterateFields(row, block.fields, `${options.name}.${i}.`));
});
const rowResults = await Promise.all(rowPromises);
rowResults.forEach((row) => {
row.forEach((fieldError) => {
errors.push(fieldError);
});
});
if (errors.length > 0) {
return errors;
}
return true;
},
};
module.exports = optionsToValidatorMap;