GraphQL DX: Relation/Pointer (#5946)
* Add a test on deep complex GraphQL Query * Relation/Pointer new DX + deep nested mutations * Fix lint * Review * Remove unnecessary code * Fix objectId on update
This commit is contained in:
committed by
Antonio Davi Macedo Coelho de Castro
parent
89e8868a85
commit
5b3a492965
@@ -1,21 +1,184 @@
|
||||
const parseMap = {
|
||||
_op: '__op',
|
||||
};
|
||||
import * as defaultGraphQLTypes from '../loaders/defaultGraphQLTypes';
|
||||
import * as objectsMutations from '../loaders/objectsMutations';
|
||||
|
||||
const transformMutationInputToParse = fields => {
|
||||
if (!fields || typeof fields !== 'object') {
|
||||
return;
|
||||
const transformTypes = async (
|
||||
inputType: 'create' | 'update',
|
||||
fields,
|
||||
{ className, parseGraphQLSchema, req }
|
||||
) => {
|
||||
const {
|
||||
classGraphQLCreateType,
|
||||
classGraphQLUpdateType,
|
||||
config: { isCreateEnabled, isUpdateEnabled },
|
||||
} = parseGraphQLSchema.parseClassTypes[className];
|
||||
const parseClass = parseGraphQLSchema.parseClasses.find(
|
||||
clazz => clazz.className === className
|
||||
);
|
||||
if (fields) {
|
||||
const classGraphQLCreateTypeFields =
|
||||
isCreateEnabled && classGraphQLCreateType
|
||||
? classGraphQLCreateType.getFields()
|
||||
: null;
|
||||
const classGraphQLUpdateTypeFields =
|
||||
isUpdateEnabled && classGraphQLUpdateType
|
||||
? classGraphQLUpdateType.getFields()
|
||||
: null;
|
||||
const promises = Object.keys(fields).map(async field => {
|
||||
let inputTypeField;
|
||||
if (inputType === 'create' && classGraphQLCreateTypeFields) {
|
||||
inputTypeField = classGraphQLCreateTypeFields[field];
|
||||
} else if (classGraphQLUpdateTypeFields) {
|
||||
inputTypeField = classGraphQLUpdateTypeFields[field];
|
||||
}
|
||||
if (inputTypeField) {
|
||||
switch (true) {
|
||||
case inputTypeField.type === defaultGraphQLTypes.GEO_POINT_INPUT:
|
||||
fields[field] = transformers.geoPoint(fields[field]);
|
||||
break;
|
||||
case inputTypeField.type === defaultGraphQLTypes.POLYGON_INPUT:
|
||||
fields[field] = transformers.polygon(fields[field]);
|
||||
break;
|
||||
case parseClass.fields[field].type === 'Relation':
|
||||
fields[field] = await transformers.relation(
|
||||
parseClass.fields[field].targetClass,
|
||||
field,
|
||||
fields[field],
|
||||
parseGraphQLSchema,
|
||||
req
|
||||
);
|
||||
break;
|
||||
case parseClass.fields[field].type === 'Pointer':
|
||||
fields[field] = await transformers.pointer(
|
||||
parseClass.fields[field].targetClass,
|
||||
field,
|
||||
fields[field],
|
||||
parseGraphQLSchema,
|
||||
req
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
Object.keys(fields).forEach(fieldName => {
|
||||
const fieldValue = fields[fieldName];
|
||||
if (parseMap[fieldName]) {
|
||||
delete fields[fieldName];
|
||||
fields[parseMap[fieldName]] = fieldValue;
|
||||
}
|
||||
if (typeof fieldValue === 'object') {
|
||||
transformMutationInputToParse(fieldValue);
|
||||
}
|
||||
});
|
||||
return fields;
|
||||
};
|
||||
|
||||
export { transformMutationInputToParse };
|
||||
const transformers = {
|
||||
polygon: value => ({
|
||||
__type: 'Polygon',
|
||||
coordinates: value.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]),
|
||||
}),
|
||||
geoPoint: value => ({
|
||||
...value,
|
||||
__type: 'GeoPoint',
|
||||
}),
|
||||
relation: async (
|
||||
targetClass,
|
||||
field,
|
||||
value,
|
||||
parseGraphQLSchema,
|
||||
{ config, auth, info }
|
||||
) => {
|
||||
if (Object.keys(value) === 0)
|
||||
throw new Error(
|
||||
`You need to provide atleast one operation on the relation mutation of field ${field}`
|
||||
);
|
||||
|
||||
const op = {
|
||||
__op: 'Batch',
|
||||
ops: [],
|
||||
};
|
||||
let nestedObjectsToAdd = [];
|
||||
|
||||
if (value.createAndAdd) {
|
||||
nestedObjectsToAdd = (await Promise.all(
|
||||
value.createAndAdd.map(async input => {
|
||||
const parseFields = await transformTypes('create', input, {
|
||||
className: targetClass,
|
||||
parseGraphQLSchema,
|
||||
req: { config, auth, info },
|
||||
});
|
||||
return objectsMutations.createObject(
|
||||
targetClass,
|
||||
parseFields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
})
|
||||
)).map(object => ({
|
||||
__type: 'Pointer',
|
||||
className: targetClass,
|
||||
objectId: object.objectId,
|
||||
}));
|
||||
}
|
||||
|
||||
if (value.add || nestedObjectsToAdd.length > 0) {
|
||||
if (!value.add) value.add = [];
|
||||
value.add = value.add.map(input => ({
|
||||
__type: 'Pointer',
|
||||
className: targetClass,
|
||||
objectId: input.objectId,
|
||||
}));
|
||||
op.ops.push({
|
||||
__op: 'AddRelation',
|
||||
objects: [...value.add, ...nestedObjectsToAdd],
|
||||
});
|
||||
}
|
||||
|
||||
if (value.remove) {
|
||||
op.ops.push({
|
||||
__op: 'RemoveRelation',
|
||||
objects: value.remove.map(input => ({
|
||||
__type: 'Pointer',
|
||||
className: targetClass,
|
||||
objectId: input.objectId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
return op;
|
||||
},
|
||||
pointer: async (
|
||||
targetClass,
|
||||
field,
|
||||
value,
|
||||
parseGraphQLSchema,
|
||||
{ config, auth, info }
|
||||
) => {
|
||||
if (Object.keys(value) > 1 || Object.keys(value) === 0)
|
||||
throw new Error(
|
||||
`You need to provide link OR createLink on the pointer mutation of field ${field}`
|
||||
);
|
||||
|
||||
let nestedObjectToAdd;
|
||||
if (value.createAndLink) {
|
||||
const parseFields = await transformTypes('create', value.createAndLink, {
|
||||
className: targetClass,
|
||||
parseGraphQLSchema,
|
||||
req: { config, auth, info },
|
||||
});
|
||||
nestedObjectToAdd = await objectsMutations.createObject(
|
||||
targetClass,
|
||||
parseFields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
return {
|
||||
__type: 'Pointer',
|
||||
className: targetClass,
|
||||
objectId: nestedObjectToAdd.objectId,
|
||||
};
|
||||
}
|
||||
if (value.link && value.link.objectId) {
|
||||
return {
|
||||
__type: 'Pointer',
|
||||
className: targetClass,
|
||||
objectId: value.link.objectId,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export { transformTypes };
|
||||
|
||||
Reference in New Issue
Block a user