GraphQL Configuration Options (#5782)
* add parse-graph-ql configuration for class schema customisation Not yet tested - essentially an RFC * refactor and add graphql router, controller and config cache * fix(GraphQLController): add missing check isEnabled * chore(GraphQLController): remove awaits from cache put * chore(GraphQLController): remove check for if its enabled * refactor(GraphQLController): only use cache if mounted * chore(GraphQLController): group all validation errors and throw at once * chore(GraphQLSchema): move transformations into controller validation * refactor(GraphQL): improve ctrl validation and fix schema usage of config * refactor(GraphQLSchema): remove code related to additional schema This code has been moved into a separate feature branch. * fix(GraphQLSchema): fix incorrect default return type for class configs * refactor(GraphQLSchema): update staleness check code to account for config * fix(GraphQLServer): fix regressed tests due to internal schema changes This will be followed up with a backwards compatability fix for the `ClassFields` issue to avoid breakages for our users * refactor: rename to ParseGraphQLController for consistency * fix(ParseGraphQLCtrl): numerous fixes for validity checking Also includes some minor code refactoring * chore(GraphQL): minor syntax cleanup * fix(SchemaController): add _GraphQLConfig to volatile classes * refactor(ParseGraphQLServer): return update config value in setGraphQLConfig * testing(ParseGraphQL): add test cases for new graphQLConfig * fix(GraphQLController): fix issue where config with multiple items was not being mapped to the db * fix(postgres): add _GraphQLConfig default schema on load fixes failing postgres tests * GraphQL @mock directive (#5836) * Add mock directive * Include tests for @mock directive * Fix existing tests due to the change from ClassFields to ClassCreateFields * fix(parseClassMutations): safer type transformation based on input type * fix(parseClassMutations): only define necessary input fields * fix(GraphQL): fix incorrect import paths
This commit is contained in:
committed by
Antonio Davi Macedo Coelho de Castro
parent
bbcc20fd60
commit
d3810c2eba
@@ -1,23 +1,58 @@
|
||||
import { GraphQLNonNull, GraphQLBoolean } from 'graphql';
|
||||
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
|
||||
import * as objectsMutations from './objectsMutations';
|
||||
import { ParseGraphQLClassConfig } from '../../Controllers/ParseGraphQLController';
|
||||
|
||||
const load = (parseGraphQLSchema, parseClass) => {
|
||||
const className = parseClass.className;
|
||||
const getParseClassMutationConfig = function(
|
||||
parseClassConfig: ?ParseGraphQLClassConfig
|
||||
) {
|
||||
return (parseClassConfig && parseClassConfig.mutation) || {};
|
||||
};
|
||||
|
||||
const classGraphQLInputType =
|
||||
parseGraphQLSchema.parseClassTypes[className].classGraphQLInputType;
|
||||
const fields = {
|
||||
description: 'These are the fields of the object.',
|
||||
type: classGraphQLInputType,
|
||||
const load = function(
|
||||
parseGraphQLSchema,
|
||||
parseClass,
|
||||
parseClassConfig: ?ParseGraphQLClassConfig
|
||||
) {
|
||||
const { className } = parseClass;
|
||||
const {
|
||||
create: isCreateEnabled = true,
|
||||
update: isUpdateEnabled = true,
|
||||
destroy: isDestroyEnabled = true,
|
||||
} = getParseClassMutationConfig(parseClassConfig);
|
||||
|
||||
const {
|
||||
classGraphQLCreateType,
|
||||
classGraphQLUpdateType,
|
||||
} = parseGraphQLSchema.parseClassTypes[className];
|
||||
|
||||
const createFields = {
|
||||
description: 'These are the fields used to create the object.',
|
||||
type: classGraphQLCreateType,
|
||||
};
|
||||
const updateFields = {
|
||||
description: 'These are the fields used to update the object.',
|
||||
type: classGraphQLUpdateType,
|
||||
};
|
||||
const classGraphQLInputTypeFields = classGraphQLInputType.getFields();
|
||||
|
||||
const transformTypes = fields => {
|
||||
const classGraphQLCreateTypeFields = isCreateEnabled
|
||||
? classGraphQLCreateType.getFields()
|
||||
: null;
|
||||
const classGraphQLUpdateTypeFields = isUpdateEnabled
|
||||
? classGraphQLUpdateType.getFields()
|
||||
: null;
|
||||
|
||||
const transformTypes = (inputType: 'create' | 'update', fields) => {
|
||||
if (fields) {
|
||||
Object.keys(fields).forEach(field => {
|
||||
if (classGraphQLInputTypeFields[field]) {
|
||||
switch (classGraphQLInputTypeFields[field].type) {
|
||||
let inputTypeField;
|
||||
if (inputType === 'create') {
|
||||
inputTypeField = classGraphQLCreateTypeFields[field];
|
||||
} else {
|
||||
inputTypeField = classGraphQLUpdateTypeFields[field];
|
||||
}
|
||||
if (inputTypeField) {
|
||||
switch (inputTypeField.type) {
|
||||
case defaultGraphQLTypes.GEO_POINT:
|
||||
fields[field].__type = 'GeoPoint';
|
||||
break;
|
||||
@@ -36,86 +71,92 @@ const load = (parseGraphQLSchema, parseClass) => {
|
||||
}
|
||||
};
|
||||
|
||||
const createGraphQLMutationName = `create${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[createGraphQLMutationName] = {
|
||||
description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${className} class.`,
|
||||
args: {
|
||||
fields,
|
||||
},
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.CREATE_RESULT),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { fields } = args;
|
||||
const { config, auth, info } = context;
|
||||
if (isCreateEnabled) {
|
||||
const createGraphQLMutationName = `create${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[createGraphQLMutationName] = {
|
||||
description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${className} class.`,
|
||||
args: {
|
||||
fields: createFields,
|
||||
},
|
||||
type: new GraphQLNonNull(defaultGraphQLTypes.CREATE_RESULT),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { fields } = args;
|
||||
const { config, auth, info } = context;
|
||||
|
||||
transformTypes(fields);
|
||||
transformTypes('create', fields);
|
||||
|
||||
return await objectsMutations.createObject(
|
||||
className,
|
||||
fields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
return await objectsMutations.createObject(
|
||||
className,
|
||||
fields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const updateGraphQLMutationName = `update${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[updateGraphQLMutationName] = {
|
||||
description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${className} class.`,
|
||||
args: {
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
fields,
|
||||
},
|
||||
type: defaultGraphQLTypes.UPDATE_RESULT,
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { objectId, fields } = args;
|
||||
const { config, auth, info } = context;
|
||||
if (isUpdateEnabled) {
|
||||
const updateGraphQLMutationName = `update${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[updateGraphQLMutationName] = {
|
||||
description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${className} class.`,
|
||||
args: {
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
fields: updateFields,
|
||||
},
|
||||
type: defaultGraphQLTypes.UPDATE_RESULT,
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { objectId, fields } = args;
|
||||
const { config, auth, info } = context;
|
||||
|
||||
transformTypes(fields);
|
||||
transformTypes('update', fields);
|
||||
|
||||
return await objectsMutations.updateObject(
|
||||
className,
|
||||
objectId,
|
||||
fields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
return await objectsMutations.updateObject(
|
||||
className,
|
||||
objectId,
|
||||
fields,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const deleteGraphQLMutationName = `delete${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[deleteGraphQLMutationName] = {
|
||||
description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${className} class.`,
|
||||
args: {
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
},
|
||||
type: new GraphQLNonNull(GraphQLBoolean),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { objectId } = args;
|
||||
const { config, auth, info } = context;
|
||||
if (isDestroyEnabled) {
|
||||
const deleteGraphQLMutationName = `delete${className}`;
|
||||
parseGraphQLSchema.graphQLObjectsMutations[deleteGraphQLMutationName] = {
|
||||
description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${className} class.`,
|
||||
args: {
|
||||
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
|
||||
},
|
||||
type: new GraphQLNonNull(GraphQLBoolean),
|
||||
async resolve(_source, args, context) {
|
||||
try {
|
||||
const { objectId } = args;
|
||||
const { config, auth, info } = context;
|
||||
|
||||
return await objectsMutations.deleteObject(
|
||||
className,
|
||||
objectId,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
return await objectsMutations.deleteObject(
|
||||
className,
|
||||
objectId,
|
||||
config,
|
||||
auth,
|
||||
info
|
||||
);
|
||||
} catch (e) {
|
||||
parseGraphQLSchema.handleError(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export { load };
|
||||
|
||||
Reference in New Issue
Block a user