flattens create field recursion
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
const mkdirp = require('mkdirp');
|
||||
|
||||
const executePolicy = require('../../auth/executePolicy');
|
||||
const executeFieldHooks = require('../../fields/executeHooks');
|
||||
const validateCreate = require('../../validation/validateCreate');
|
||||
|
||||
const { MissingFile } = require('../../errors');
|
||||
const resizeAndSave = require('../../uploads/imageResizer');
|
||||
const getSafeFilename = require('../../uploads/getSafeFilename');
|
||||
|
||||
const recurseFields = require('../../fields/recurseBeforeOperation');
|
||||
|
||||
const create = async (args) => {
|
||||
try {
|
||||
// /////////////////////////////////////
|
||||
@@ -22,20 +22,7 @@ const create = async (args) => {
|
||||
// 2. Execute field-level policies
|
||||
// /////////////////////////////////////
|
||||
|
||||
// Field-level policies here
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 3. Validate incoming data
|
||||
// /////////////////////////////////////
|
||||
|
||||
await validateCreate(args.data, args.config.fields);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 4. Execute before create field-level hooks
|
||||
// /////////////////////////////////////
|
||||
|
||||
options.data = await executeFieldHooks(options, args.config.fields, args.data, 'beforeCreate', args.data);
|
||||
|
||||
options.data = await recurseFields(args.config, { ...options, hook: 'beforeCreate', operationName: 'create' });
|
||||
|
||||
// /////////////////////////////////////
|
||||
// 5. Upload and resize any files that may be present
|
||||
|
||||
100
src/fields/recurseBeforeOperation.js
Normal file
100
src/fields/recurseBeforeOperation.js
Normal file
@@ -0,0 +1,100 @@
|
||||
const { ValidationError } = require('../errors');
|
||||
|
||||
module.exports = async (config, operation) => {
|
||||
const {
|
||||
data: fullData,
|
||||
operationName,
|
||||
hook,
|
||||
} = operation;
|
||||
|
||||
// Maintain a top-level list of promises
|
||||
// so that all async field policies / validations / hooks
|
||||
// can run in tandem
|
||||
const validationPromises = [];
|
||||
const policyPromises = [];
|
||||
const hookPromises = [];
|
||||
const errors = [];
|
||||
|
||||
const createValidationPromise = async (data, field, path) => {
|
||||
const shouldValidate = field.validate && !field.condition;
|
||||
const dataToValidate = data || field.defaultValue;
|
||||
const result = shouldValidate ? await field.validate(dataToValidate, field) : true;
|
||||
|
||||
if (!result || typeof result === 'string') {
|
||||
errors.push({
|
||||
message: result,
|
||||
field: `${path}${field.name}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const createPolicyPromise = async (data, field) => {
|
||||
const resultingData = data;
|
||||
|
||||
if (field.policies && field.policies[operationName]) {
|
||||
const result = await field.policies[operationName](operation);
|
||||
|
||||
if (!result) {
|
||||
delete resultingData[field.name];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const createHookPromise = async (data, field) => {
|
||||
const resultingData = data;
|
||||
|
||||
if (field.hooks && field.hooks[hook]) {
|
||||
resultingData[field.name] = await field.hooks[hook](data[field.name]);
|
||||
}
|
||||
};
|
||||
|
||||
const traverseFields = (fields, data = {}, path) => {
|
||||
fields.forEach((field) => {
|
||||
policyPromises.push(createPolicyPromise(data, field));
|
||||
hookPromises.push(createHookPromise(data, field));
|
||||
|
||||
if (field.fields) {
|
||||
if (field.name === undefined) {
|
||||
traverseFields(field.fields, data, path);
|
||||
} else if (field.type === 'repeater' || field.type === 'flexible') {
|
||||
if (Array.isArray(data[field.name])) {
|
||||
data[field.name].forEach((rowData, i) => {
|
||||
traverseFields(field.fields, rowData, `${path}${field.name}.${i}.`);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
traverseFields(field.fields, data[field.name], `${path}${field.name}.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'repeater' || field.type === 'flexible') {
|
||||
const hasRowsOfData = Array.isArray(data[field.name]);
|
||||
const rowCount = hasRowsOfData ? data[field.name].length : 0;
|
||||
|
||||
validationPromises.push(createValidationPromise(rowCount, field, path));
|
||||
} else {
|
||||
validationPromises.push(createValidationPromise(data[field.name], field, path));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// //////////////////////////////////////////
|
||||
// Entry point for field validation
|
||||
// //////////////////////////////////////////
|
||||
|
||||
try {
|
||||
traverseFields(config.fields, fullData, '');
|
||||
await Promise.all(validationPromises);
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new ValidationError(errors);
|
||||
}
|
||||
|
||||
await Promise.all(policyPromises);
|
||||
await Promise.all(hookPromises);
|
||||
|
||||
return fullData;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user