More clean-up

This commit is contained in:
SachaG 2019-01-27 09:36:49 +09:00
parent 691e0623da
commit 8da17a8872

View file

@ -1,25 +1,29 @@
/* /*
Mutations have four steps: Mutations have five steps:
1. Validation 1. Validation
If the mutation call is not trusted (i.e. it comes from a GraphQL mutation), If the mutator call is not trusted (for example, it comes from a GraphQL mutation),
we'll run all validate steps: we'll run all validate steps:
- Check that the current user has permission to insert/edit each field. - Check that the current user has permission to insert/edit each field.
- Add userId to document (insert only). - Add userId to document (insert only).
- Run validation callbacks. - Run validation callbacks.
2. Sync Callbacks 2. Before Callbacks
The second step is to run the mutation argument through all the sync callbacks. The second step is to run the mutation argument through all the [before] callbacks.
3. Operation 3. Operation
We then perform the insert/update/remove operation. We then perform the insert/update/remove operation.
4. Async Callbacks 4. After Callbacks
We then run the mutation argument through all the [after] callbacks.
5. Async Callbacks
Finally, *after* the operation is performed, we execute any async callbacks. Finally, *after* the operation is performed, we execute any async callbacks.
Being async, they won't hold up the mutation and slow down its response time Being async, they won't hold up the mutation and slow down its response time
@ -28,12 +32,7 @@ to the client.
*/ */
import { runCallbacks, runCallbacksAsync } from '../modules/index.js'; import { runCallbacks, runCallbacksAsync } from '../modules/index.js';
import { import { validateDocument, validateData, dataToModifier, modifierToData } from '../modules/validation.js';
validateDocument,
validateData,
dataToModifier,
modifierToData,
} from '../modules/validation.js';
import { registerSetting } from '../modules/settings.js'; import { registerSetting } from '../modules/settings.js';
import { debug, debugGroup, debugGroupEnd } from '../modules/debug.js'; import { debug, debugGroup, debugGroupEnd } from '../modules/debug.js';
import { throwError } from '../modules/errors.js'; import { throwError } from '../modules/errors.js';
@ -44,7 +43,13 @@ import isEmpty from 'lodash/isEmpty';
registerSetting('database', 'mongo', 'Which database to use for your back-end'); registerSetting('database', 'mongo', 'Which database to use for your back-end');
export const createMutator = async ({ collection, document, data, currentUser, validate, context, }) => { /*
Create
*/
export const createMutator = async ({ collection, document, data, currentUser, validate, context }) => {
// OpenCRUD backwards compatibility: accept either data or document // OpenCRUD backwards compatibility: accept either data or document
// we don't want to modify the original document // we don't want to modify the original document
document = data || document; document = data || document;
@ -70,16 +75,23 @@ export const createMutator = async ({ collection, document, data, currentUser, v
let validationErrors = []; let validationErrors = [];
validationErrors = validationErrors.concat(validateDocument(document, collection, context)); validationErrors = validationErrors.concat(validateDocument(document, collection, context));
// run validation callbacks // run validation callbacks
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.create.validate`, iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.create.validate`, iterator: validationErrors, properties });
validationErrors = await runCallbacks({ name: '*.create.validate', iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: '*.create.validate', iterator: validationErrors, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.new.validate`, document, currentUser, validationErrors); document = await runCallbacks(`${collectionName.toLowerCase()}.new.validate`, document, currentUser, validationErrors);
if (validationErrors.length) { if (validationErrors.length) {
console.log(validationErrors); // eslint-disable-line no-console
throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } }); throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } });
} }
} }
// if user is logged in, check if userId field is in the schema and add it to document if needed /*
userId
If user is logged in, check if userId field is in the schema and add it to document if needed
*/
if (currentUser) { if (currentUser) {
const userIdInSchema = Object.keys(schema).find(key => key === 'userId'); const userIdInSchema = Object.keys(schema).find(key => key === 'userId');
if (!!userIdInSchema && !document.userId) document.userId = currentUser._id; if (!!userIdInSchema && !document.userId) document.userId = currentUser._id;
@ -99,12 +111,10 @@ export const createMutator = async ({ collection, document, data, currentUser, v
let autoValue; let autoValue;
if (schema[fieldName].onCreate) { if (schema[fieldName].onCreate) {
// OpenCRUD backwards compatibility: keep both newDocument and data for now, but phase out newDocument eventually // OpenCRUD backwards compatibility: keep both newDocument and data for now, but phase out newDocument eventually
// eslint-disable-next-line no-await-in-loop autoValue = await schema[fieldName].onCreate(properties); // eslint-disable-line no-await-in-loop
autoValue = await schema[fieldName].onCreate(properties);
} else if (schema[fieldName].onInsert) { } else if (schema[fieldName].onInsert) {
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
// eslint-disable-next-line no-await-in-loop autoValue = await schema[fieldName].onInsert(clone(document), currentUser); // eslint-disable-line no-await-in-loop
autoValue = await schema[fieldName].onInsert(clone(document), currentUser);
} }
if (typeof autoValue !== 'undefined') { if (typeof autoValue !== 'undefined') {
document[fieldName] = autoValue; document[fieldName] = autoValue;
@ -122,7 +132,7 @@ export const createMutator = async ({ collection, document, data, currentUser, v
Before Before
*/ */
document = await runCallbacks({name: `${typeName.toLowerCase()}.create.before`, iterator: document, properties, }); document = await runCallbacks({ name: `${typeName.toLowerCase()}.create.before`, iterator: document, properties });
document = await runCallbacks({ name: '*.create.before', iterator: document, properties }); document = await runCallbacks({ name: '*.create.before', iterator: document, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.new.before`, document, currentUser); document = await runCallbacks(`${collectionName.toLowerCase()}.new.before`, document, currentUser);
@ -141,7 +151,7 @@ export const createMutator = async ({ collection, document, data, currentUser, v
*/ */
// run any post-operation sync callbacks // run any post-operation sync callbacks
document = await runCallbacks({ name: `${typeName.toLowerCase()}.create.after`, iterator: document, properties, }); document = await runCallbacks({ name: `${typeName.toLowerCase()}.create.after`, iterator: document, properties });
document = await runCallbacks({ name: '*.create.after', iterator: document, properties }); document = await runCallbacks({ name: '*.create.after', iterator: document, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.new.after`, document, currentUser); document = await runCallbacks(`${collectionName.toLowerCase()}.new.after`, document, currentUser);
@ -155,7 +165,7 @@ export const createMutator = async ({ collection, document, data, currentUser, v
*/ */
// note: make sure properties.document is up to date // note: make sure properties.document is up to date
await runCallbacksAsync({ name: `${typeName.toLowerCase()}.create.async`, properties: { ...properties, document: document }, }); await runCallbacksAsync({ name: `${typeName.toLowerCase()}.create.async`, properties: { ...properties, document: document } });
await runCallbacksAsync({ name: '*.create.async', properties }); await runCallbacksAsync({ name: '*.create.async', properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
await runCallbacksAsync(`${collectionName.toLowerCase()}.new.async`, document, currentUser, collection); await runCallbacksAsync(`${collectionName.toLowerCase()}.new.async`, document, currentUser, collection);
@ -165,7 +175,13 @@ export const createMutator = async ({ collection, document, data, currentUser, v
return { data: document }; return { data: document };
}; };
export const updateMutator = async ({ collection, documentId, selector, data, set = {}, unset = {}, currentUser, validate, context, document: oldDocument, }) => { /*
Update
*/
export const updateMutator = async ({ collection, documentId, selector, data, set = {}, unset = {}, currentUser, validate, context, document: oldDocument }) => {
const { collectionName, typeName } = collection.options; const { collectionName, typeName } = collection.options;
const schema = collection.simpleSchema()._schema; const schema = collection.simpleSchema()._schema;
@ -182,7 +198,7 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
// get original document from database or arguments // get original document from database or arguments
oldDocument = oldDocument || (await Connectors.get(collection, selector)); oldDocument = oldDocument || (await Connectors.get(collection, selector));
if (!document) { if (!oldDocument) {
throw new Error(`Could not find document to update for selector: ${JSON.stringify(selector)}`); throw new Error(`Could not find document to update for selector: ${JSON.stringify(selector)}`);
} }
@ -207,16 +223,13 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
validationErrors = validationErrors.concat(validateData(data, document, collection, context)); validationErrors = validationErrors.concat(validateData(data, document, collection, context));
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.update.validate`, iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.update.validate`, iterator: validationErrors, properties });
validationErrors = await runCallbacks({ name: '*.update.validate', iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: '*.update.validate', iterator: validationErrors, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.validate`, dataToModifier(data), document, currentUser, validationErrors)); data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.validate`, dataToModifier(data), document, currentUser, validationErrors));
if (validationErrors.length) { if (validationErrors.length) {
// eslint-disable-next-line no-console console.log(validationErrors); // eslint-disable-line no-console
console.log('// validationErrors');
// eslint-disable-next-line no-console
console.log(validationErrors);
throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } }); throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } });
} }
} }
@ -229,12 +242,10 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
let autoValue; let autoValue;
if (schema[fieldName].onUpdate) { if (schema[fieldName].onUpdate) {
// eslint-disable-next-line no-await-in-loop autoValue = await schema[fieldName].onUpdate(properties); // eslint-disable-line no-await-in-loop
autoValue = await schema[fieldName].onUpdate(properties);
} else if (schema[fieldName].onEdit) { } else if (schema[fieldName].onEdit) {
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
// eslint-disable-next-line no-await-in-loop autoValue = await schema[fieldName].onEdit(dataToModifier(clone(data)), document, currentUser, document); // eslint-disable-line no-await-in-loop
autoValue = await schema[fieldName].onEdit(dataToModifier(clone(data)), document, currentUser, document);
} }
if (typeof autoValue !== 'undefined') { if (typeof autoValue !== 'undefined') {
data[fieldName] = autoValue; data[fieldName] = autoValue;
@ -246,21 +257,20 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
Before Before
*/ */
data = await runCallbacks({ name: `${typeName.toLowerCase()}.update.before`, iterator: data, properties, }); data = await runCallbacks({ name: `${typeName.toLowerCase()}.update.before`, iterator: data, properties });
data = await runCallbacks({ name: '*.update.before', iterator: data, properties }); data = await runCallbacks({ name: '*.update.before', iterator: data, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.before`, dataToModifier(data), document, currentUser, document)); data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.before`, dataToModifier(data), document, currentUser, document));
data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.sync`, dataToModifier(data), document, currentUser, document) data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.sync`, dataToModifier(data), document, currentUser, document));
);
// update connector requires a modifier, so get it from data // update connector requires a modifier, so get it from data
const modifier = dataToModifier(data); const modifier = dataToModifier(data);
// remove empty modifiers // remove empty modifiers
if (_.isEmpty(modifier.$set)) { if (isEmpty(modifier.$set)) {
delete modifier.$set; delete modifier.$set;
} }
if (_.isEmpty(modifier.$unset)) { if (isEmpty(modifier.$unset)) {
delete modifier.$unset; delete modifier.$unset;
} }
@ -269,7 +279,7 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
DB Operation DB Operation
*/ */
if (!_.isEmpty(modifier)) { if (!isEmpty(modifier)) {
// update document // update document
await Connectors.update(collection, selector, modifier, { removeEmptyStrings: false }); await Connectors.update(collection, selector, modifier, { removeEmptyStrings: false });
@ -289,8 +299,8 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
After After
*/ */
document = await runCallbacks({name: `${typeName.toLowerCase()}.update.after`, iterator: document, properties, }); document = await runCallbacks({ name: `${typeName.toLowerCase()}.update.after`, iterator: document, properties });
document = await runCallbacks({ name: '*.update.after', iterator: document, properties, }); document = await runCallbacks({ name: '*.update.after', iterator: document, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.edit.after`, document, oldDocument, currentUser); document = await runCallbacks(`${collectionName.toLowerCase()}.edit.after`, document, oldDocument, currentUser);
@ -310,7 +320,12 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
return { data: document }; return { data: document };
}; };
export const deleteMutator = async ({ collection, documentId, selector, currentUser, validate, context, document, }) => { /*
Delete
*/
export const deleteMutator = async ({ collection, documentId, selector, currentUser, validate, context, document }) => {
const { collectionName, typeName } = collection.options; const { collectionName, typeName } = collection.options;
const schema = collection.simpleSchema()._schema; const schema = collection.simpleSchema()._schema;
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
@ -341,16 +356,13 @@ export const deleteMutator = async ({ collection, documentId, selector, currentU
if (validate) { if (validate) {
let validationErrors = []; let validationErrors = [];
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.delete.validate`, iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.delete.validate`, iterator: validationErrors, properties });
validationErrors = await runCallbacks({ name: '*.delete.validate', iterator: validationErrors, properties, }); validationErrors = await runCallbacks({ name: '*.delete.validate', iterator: validationErrors, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.remove.validate`, document, currentUser); document = await runCallbacks(`${collectionName.toLowerCase()}.remove.validate`, document, currentUser);
if (validationErrors.length) { if (validationErrors.length) {
// eslint-disable-next-line no-console console.log(validationErrors); // eslint-disable-line no-console
console.log('// validationErrors');
// eslint-disable-next-line no-console
console.log(validationErrors);
throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } }); throwError({ id: 'app.validation_error', data: { break: true, errors: validationErrors } });
} }
} }
@ -362,12 +374,10 @@ export const deleteMutator = async ({ collection, documentId, selector, currentU
*/ */
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
if (schema[fieldName].onDelete) { if (schema[fieldName].onDelete) {
// eslint-disable-next-line no-await-in-loop await schema[fieldName].onDelete(properties); // eslint-disable-line no-await-in-loop
await schema[fieldName].onDelete(properties);
} else if (schema[fieldName].onRemove) { } else if (schema[fieldName].onRemove) {
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
// eslint-disable-next-line no-await-in-loop await schema[fieldName].onRemove(document, currentUser); // eslint-disable-line no-await-in-loop
await schema[fieldName].onRemove(document, currentUser);
} }
} }
@ -376,7 +386,7 @@ export const deleteMutator = async ({ collection, documentId, selector, currentU
Before Before
*/ */
await runCallbacks({ name: `${typeName.toLowerCase()}.delete.before`, iterator: document, properties, }); await runCallbacks({ name: `${typeName.toLowerCase()}.delete.before`, iterator: document, properties });
await runCallbacks({ name: '*.delete.before', iterator: document, properties }); await runCallbacks({ name: '*.delete.before', iterator: document, properties });
// OpenCRUD backwards compatibility // OpenCRUD backwards compatibility
await runCallbacks(`${collectionName.toLowerCase()}.remove.before`, document, currentUser); await runCallbacks(`${collectionName.toLowerCase()}.remove.before`, document, currentUser);