Remove nested operations from GraphQL API (#5931)

* Remove nested operations

* Improve error log

* Fix bug schema to load

* Fix ParseGraphQLSchema tests

* Fix tests

* Fix failing tests

* Rename call to callCloudCode
This commit is contained in:
Antonio Davi Macedo Coelho de Castro
2019-08-17 11:02:19 -07:00
committed by Antoine Cormouls
parent 47d1a74ac0
commit ee5aeeaff5
14 changed files with 1157 additions and 1619 deletions

View File

@@ -211,7 +211,7 @@ describe('ParseGraphQLSchema', () => {
});
});
describe('addGraphQLObjectQuery', () => {
describe('addGraphQLQuery', () => {
it('should not load and warn duplicated queries', async () => {
let logged = false;
const parseGraphQLSchema = new ParseGraphQLSchema({
@@ -221,21 +221,19 @@ describe('ParseGraphQLSchema', () => {
warn: message => {
logged = true;
expect(message).toEqual(
'Object query someClasses could not be added to the auto schema because it collided with an existing field.'
'Query someClasses could not be added to the auto schema because it collided with an existing field.'
);
},
},
});
await parseGraphQLSchema.load();
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', field)
).toBe(field);
expect(parseGraphQLSchema.graphQLObjectsQueries['someClasses']).toBe(
expect(parseGraphQLSchema.addGraphQLQuery('someClasses', field)).toBe(
field
);
expect(parseGraphQLSchema.graphQLQueries['someClasses']).toBe(field);
expect(
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', {})
parseGraphQLSchema.addGraphQLQuery('someClasses', {})
).toBeUndefined();
expect(logged).toBeTruthy();
});
@@ -252,16 +250,14 @@ describe('ParseGraphQLSchema', () => {
});
await parseGraphQLSchema.load();
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', field)
).toBe(field);
expect(parseGraphQLSchema.graphQLObjectsQueries['someClasses']).toBe(
expect(parseGraphQLSchema.addGraphQLQuery('someClasses', field)).toBe(
field
);
expect(parseGraphQLSchema.graphQLQueries['someClasses']).toBe(field);
expect(() =>
parseGraphQLSchema.addGraphQLObjectQuery('someClasses', {}, true)
parseGraphQLSchema.addGraphQLQuery('someClasses', {}, true)
).toThrowError(
'Object query someClasses could not be added to the auto schema because it collided with an existing field.'
'Query someClasses could not be added to the auto schema because it collided with an existing field.'
);
});
@@ -274,15 +270,13 @@ describe('ParseGraphQLSchema', () => {
warn: message => {
logged = true;
expect(message).toEqual(
'Object query get could not be added to the auto schema because it collided with an existing field.'
'Query get could not be added to the auto schema because it collided with an existing field.'
);
},
},
});
await parseGraphQLSchema.load();
expect(
parseGraphQLSchema.addGraphQLObjectQuery('get', {})
).toBeUndefined();
expect(parseGraphQLSchema.addGraphQLQuery('get', {})).toBeUndefined();
expect(logged).toBeTruthy();
});
@@ -297,16 +291,16 @@ describe('ParseGraphQLSchema', () => {
},
});
await parseGraphQLSchema.load();
delete parseGraphQLSchema.graphQLObjectsQueries.get;
delete parseGraphQLSchema.graphQLQueries.get;
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectQuery('get', field, true, true)
).toBe(field);
expect(parseGraphQLSchema.graphQLObjectsQueries['get']).toBe(field);
expect(parseGraphQLSchema.addGraphQLQuery('get', field, true, true)).toBe(
field
);
expect(parseGraphQLSchema.graphQLQueries['get']).toBe(field);
});
});
describe('addGraphQLObjectMutation', () => {
describe('addGraphQLMutation', () => {
it('should not load and warn duplicated mutations', async () => {
let logged = false;
const parseGraphQLSchema = new ParseGraphQLSchema({
@@ -316,7 +310,7 @@ describe('ParseGraphQLSchema', () => {
warn: message => {
logged = true;
expect(message).toEqual(
'Object mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
'Mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
);
},
},
@@ -324,13 +318,13 @@ describe('ParseGraphQLSchema', () => {
await parseGraphQLSchema.load();
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', field)
parseGraphQLSchema.addGraphQLMutation('createSomeClass', field)
).toBe(field);
expect(parseGraphQLSchema.graphQLMutations['createSomeClass']).toBe(
field
);
expect(
parseGraphQLSchema.graphQLObjectsMutations['createSomeClass']
).toBe(field);
expect(
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', {})
parseGraphQLSchema.addGraphQLMutation('createSomeClass', {})
).toBeUndefined();
expect(logged).toBeTruthy();
});
@@ -348,15 +342,15 @@ describe('ParseGraphQLSchema', () => {
await parseGraphQLSchema.load();
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', field)
).toBe(field);
expect(
parseGraphQLSchema.graphQLObjectsMutations['createSomeClass']
parseGraphQLSchema.addGraphQLMutation('createSomeClass', field)
).toBe(field);
expect(parseGraphQLSchema.graphQLMutations['createSomeClass']).toBe(
field
);
expect(() =>
parseGraphQLSchema.addGraphQLObjectMutation('createSomeClass', {}, true)
parseGraphQLSchema.addGraphQLMutation('createSomeClass', {}, true)
).toThrowError(
'Object mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
'Mutation createSomeClass could not be added to the auto schema because it collided with an existing field.'
);
});
@@ -369,14 +363,14 @@ describe('ParseGraphQLSchema', () => {
warn: message => {
logged = true;
expect(message).toEqual(
'Object mutation create could not be added to the auto schema because it collided with an existing field.'
'Mutation create could not be added to the auto schema because it collided with an existing field.'
);
},
},
});
await parseGraphQLSchema.load();
expect(
parseGraphQLSchema.addGraphQLObjectMutation('create', {})
parseGraphQLSchema.addGraphQLMutation('create', {})
).toBeUndefined();
expect(logged).toBeTruthy();
});
@@ -392,12 +386,12 @@ describe('ParseGraphQLSchema', () => {
},
});
await parseGraphQLSchema.load();
delete parseGraphQLSchema.graphQLObjectsMutations.create;
delete parseGraphQLSchema.graphQLMutations.create;
const field = {};
expect(
parseGraphQLSchema.addGraphQLObjectMutation('create', field, true, true)
parseGraphQLSchema.addGraphQLMutation('create', field, true, true)
).toBe(field);
expect(parseGraphQLSchema.graphQLObjectsMutations['create']).toBe(field);
expect(parseGraphQLSchema.graphQLMutations['create']).toBe(field);
});
});
@@ -453,27 +447,27 @@ describe('ParseGraphQLSchema', () => {
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const types1 = parseGraphQLSchema.graphQLTypes;
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const user = new Parse.Object('User');
await user.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const types2 = parseGraphQLSchema.graphQLTypes;
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
const queries2 = parseGraphQLSchema.graphQLQueries;
const mutations2 = parseGraphQLSchema.graphQLMutations;
expect(schema1).not.toBe(schema2);
expect(types1).not.toBe(types2);
expect(types1.map(type => type.name).sort()).toEqual(
types2.map(type => type.name).sort()
);
expect(objectQueries1).not.toBe(objectQueries2);
expect(Object.keys(objectQueries1).sort()).toEqual(
Object.keys(objectQueries2).sort()
expect(queries1).not.toBe(queries2);
expect(Object.keys(queries1).sort()).toEqual(
Object.keys(queries2).sort()
);
expect(objectMutations1).not.toBe(objectMutations2);
expect(Object.keys(objectMutations1).sort()).toEqual(
Object.keys(objectMutations2).sort()
expect(mutations1).not.toBe(mutations2);
expect(Object.keys(mutations1).sort()).toEqual(
Object.keys(mutations2).sort()
);
});
@@ -488,27 +482,27 @@ describe('ParseGraphQLSchema', () => {
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const types1 = parseGraphQLSchema.graphQLTypes;
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const car2 = new Parse.Object('car');
await car2.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const types2 = parseGraphQLSchema.graphQLTypes;
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
const queries2 = parseGraphQLSchema.graphQLQueries;
const mutations2 = parseGraphQLSchema.graphQLMutations;
expect(schema1).not.toBe(schema2);
expect(types1).not.toBe(types2);
expect(types1.map(type => type.name).sort()).toEqual(
types2.map(type => type.name).sort()
);
expect(objectQueries1).not.toBe(objectQueries2);
expect(Object.keys(objectQueries1).sort()).toEqual(
Object.keys(objectQueries2).sort()
expect(queries1).not.toBe(queries2);
expect(Object.keys(queries1).sort()).toEqual(
Object.keys(queries2).sort()
);
expect(objectMutations1).not.toBe(objectMutations2);
expect(Object.keys(objectMutations1).sort()).toEqual(
Object.keys(objectMutations2).sort()
expect(mutations1).not.toBe(mutations2);
expect(Object.keys(mutations1).sort()).toEqual(
Object.keys(mutations2).sort()
);
});
@@ -522,25 +516,25 @@ describe('ParseGraphQLSchema', () => {
await car.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema1 = await parseGraphQLSchema.load();
const objectQueries1 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations1 = parseGraphQLSchema.graphQLObjectsMutations;
const queries1 = parseGraphQLSchema.graphQLQueries;
const mutations1 = parseGraphQLSchema.graphQLMutations;
const cars = new Parse.Object('cars');
await cars.save();
await parseGraphQLSchema.databaseController.schemaCache.clear();
const schema2 = await parseGraphQLSchema.load();
const objectQueries2 = parseGraphQLSchema.graphQLObjectsQueries;
const objectMutations2 = parseGraphQLSchema.graphQLObjectsMutations;
const queries2 = parseGraphQLSchema.graphQLQueries;
const mutations2 = parseGraphQLSchema.graphQLMutations;
expect(schema1).not.toBe(schema2);
expect(objectQueries1).not.toBe(objectQueries2);
expect(Object.keys(objectQueries1).sort()).toEqual(
Object.keys(objectQueries2).sort()
expect(queries1).not.toBe(queries2);
expect(Object.keys(queries1).sort()).toEqual(
Object.keys(queries2).sort()
);
expect(objectMutations1).not.toBe(objectMutations2);
expect(mutations1).not.toBe(mutations2);
expect(
Object.keys(objectMutations1)
Object.keys(mutations1)
.concat('createCars', 'updateCars', 'deleteCars')
.sort()
).toEqual(Object.keys(objectMutations2).sort());
).toEqual(Object.keys(mutations2).sort());
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -25,18 +25,21 @@ const RESERVED_GRAPHQL_TYPE_NAMES = [
'Query',
'Mutation',
'Subscription',
'ObjectsQuery',
'UsersQuery',
'ObjectsMutation',
'FilesMutation',
'UsersMutation',
'FunctionsMutation',
'Viewer',
'SignUpFieldsInput',
'LogInFieldsInput',
];
const RESERVED_GRAPHQL_OBJECT_QUERY_NAMES = ['get', 'find'];
const RESERVED_GRAPHQL_OBJECT_MUTATION_NAMES = ['create', 'update', 'delete'];
const RESERVED_GRAPHQL_QUERY_NAMES = ['health', 'viewer', 'get', 'find'];
const RESERVED_GRAPHQL_MUTATION_NAMES = [
'signUp',
'logIn',
'logOut',
'createFile',
'callCloudCode',
'create',
'update',
'delete',
];
class ParseGraphQLSchema {
databaseController: DatabaseController;
@@ -87,9 +90,7 @@ class ParseGraphQLSchema {
this.graphQLAutoSchema = null;
this.graphQLSchema = null;
this.graphQLTypes = [];
this.graphQLObjectsQueries = {};
this.graphQLQueries = {};
this.graphQLObjectsMutations = {};
this.graphQLMutations = {};
this.graphQLSubscriptions = {};
this.graphQLSchemaDirectivesDefinitions = null;
@@ -104,6 +105,7 @@ class ParseGraphQLSchema {
parseClassMutations.load(this, parseClass, parseClassConfig);
}
);
defaultGraphQLTypes.loadArrayResult(this, parseClasses);
defaultGraphQLQueries.load(this);
defaultGraphQLMutations.load(this);
@@ -211,29 +213,28 @@ class ParseGraphQLSchema {
return type;
}
addGraphQLObjectQuery(
addGraphQLQuery(
fieldName,
field,
throwError = false,
ignoreReserved = false
) {
if (
(!ignoreReserved &&
RESERVED_GRAPHQL_OBJECT_QUERY_NAMES.includes(fieldName)) ||
this.graphQLObjectsQueries[fieldName]
(!ignoreReserved && RESERVED_GRAPHQL_QUERY_NAMES.includes(fieldName)) ||
this.graphQLQueries[fieldName]
) {
const message = `Object query ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
const message = `Query ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
if (throwError) {
throw new Error(message);
}
this.log.warn(message);
return undefined;
}
this.graphQLObjectsQueries[fieldName] = field;
this.graphQLQueries[fieldName] = field;
return field;
}
addGraphQLObjectMutation(
addGraphQLMutation(
fieldName,
field,
throwError = false,
@@ -241,17 +242,17 @@ class ParseGraphQLSchema {
) {
if (
(!ignoreReserved &&
RESERVED_GRAPHQL_OBJECT_MUTATION_NAMES.includes(fieldName)) ||
this.graphQLObjectsMutations[fieldName]
RESERVED_GRAPHQL_MUTATION_NAMES.includes(fieldName)) ||
this.graphQLMutations[fieldName]
) {
const message = `Object mutation ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
const message = `Mutation ${fieldName} could not be added to the auto schema because it collided with an existing field.`;
if (throwError) {
throw new Error(message);
}
this.log.warn(message);
return undefined;
}
this.graphQLObjectsMutations[fieldName] = field;
this.graphQLMutations[fieldName] = field;
return field;
}

View File

@@ -47,7 +47,9 @@ class ParseGraphQLServer {
},
};
} catch (e) {
this.log.error(e);
this.log.error(
e.stack || (typeof e.toString === 'function' && e.toString()) || e
);
throw e;
}
}

View File

@@ -3,12 +3,17 @@ import * as objectsQueries from './objectsQueries';
import * as usersQueries from './usersQueries';
const load = parseGraphQLSchema => {
parseGraphQLSchema.graphQLQueries.health = {
description:
'The health query can be used to check if the server is up and running.',
type: new GraphQLNonNull(GraphQLBoolean),
resolve: () => true,
};
parseGraphQLSchema.addGraphQLQuery(
'health',
{
description:
'The health query can be used to check if the server is up and running.',
type: new GraphQLNonNull(GraphQLBoolean),
resolve: () => true,
},
true,
true
);
objectsQueries.load(parseGraphQLSchema);
usersQueries.load(parseGraphQLSchema);

View File

@@ -1,93 +1,83 @@
import { GraphQLObjectType, GraphQLNonNull } from 'graphql';
import { GraphQLNonNull } from 'graphql';
import { GraphQLUpload } from 'graphql-upload';
import Parse from 'parse/node';
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
import logger from '../../logger';
const load = parseGraphQLSchema => {
const fields = {};
parseGraphQLSchema.addGraphQLMutation(
'createFile',
{
description:
'The create mutation can be used to create and upload a new file.',
args: {
upload: {
description: 'This is the new file to be created and uploaded',
type: new GraphQLNonNull(GraphQLUpload),
},
},
type: new GraphQLNonNull(defaultGraphQLTypes.FILE_INFO),
async resolve(_source, args, context) {
try {
const { upload } = args;
const { config } = context;
fields.create = {
description:
'The create mutation can be used to create and upload a new file.',
args: {
upload: {
description: 'This is the new file to be created and uploaded',
type: new GraphQLNonNull(GraphQLUpload),
const { createReadStream, filename, mimetype } = await upload;
let data = null;
if (createReadStream) {
const stream = createReadStream();
data = await new Promise((resolve, reject) => {
let data = '';
stream
.on('error', reject)
.on('data', chunk => (data += chunk))
.on('end', () => resolve(data));
});
}
if (!data || !data.length) {
throw new Parse.Error(
Parse.Error.FILE_SAVE_ERROR,
'Invalid file upload.'
);
}
if (filename.length > 128) {
throw new Parse.Error(
Parse.Error.INVALID_FILE_NAME,
'Filename too long.'
);
}
if (!filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) {
throw new Parse.Error(
Parse.Error.INVALID_FILE_NAME,
'Filename contains invalid characters.'
);
}
try {
return await config.filesController.createFile(
config,
filename,
data,
mimetype
);
} catch (e) {
logger.error('Error creating a file: ', e);
throw new Parse.Error(
Parse.Error.FILE_SAVE_ERROR,
`Could not store file: ${filename}.`
);
}
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
type: new GraphQLNonNull(defaultGraphQLTypes.FILE_INFO),
async resolve(_source, args, context) {
try {
const { upload } = args;
const { config } = context;
const { createReadStream, filename, mimetype } = await upload;
let data = null;
if (createReadStream) {
const stream = createReadStream();
data = await new Promise((resolve, reject) => {
let data = '';
stream
.on('error', reject)
.on('data', chunk => (data += chunk))
.on('end', () => resolve(data));
});
}
if (!data || !data.length) {
throw new Parse.Error(
Parse.Error.FILE_SAVE_ERROR,
'Invalid file upload.'
);
}
if (filename.length > 128) {
throw new Parse.Error(
Parse.Error.INVALID_FILE_NAME,
'Filename too long.'
);
}
if (!filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) {
throw new Parse.Error(
Parse.Error.INVALID_FILE_NAME,
'Filename contains invalid characters.'
);
}
try {
return await config.filesController.createFile(
config,
filename,
data,
mimetype
);
} catch (e) {
logger.error('Error creating a file: ', e);
throw new Parse.Error(
Parse.Error.FILE_SAVE_ERROR,
`Could not store file: ${filename}.`
);
}
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
};
const filesMutation = new GraphQLObjectType({
name: 'FilesMutation',
description: 'FilesMutation is the top level type for files mutations.',
fields,
});
parseGraphQLSchema.addGraphQLType(filesMutation, true, true);
parseGraphQLSchema.graphQLMutations.files = {
description: 'This is the top level for files mutations.',
type: filesMutation,
resolve: () => new Object(),
};
true,
true
);
};
export { load };

View File

@@ -1,57 +1,46 @@
import { GraphQLObjectType, GraphQLNonNull, GraphQLString } from 'graphql';
import { GraphQLNonNull, GraphQLString } from 'graphql';
import { FunctionsRouter } from '../../Routers/FunctionsRouter';
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
const load = parseGraphQLSchema => {
const fields = {};
fields.call = {
description:
'The call mutation can be used to invoke a cloud code function.',
args: {
functionName: {
description: 'This is the name of the function to be called.',
type: new GraphQLNonNull(GraphQLString),
parseGraphQLSchema.addGraphQLMutation(
'callCloudCode',
{
description:
'The call mutation can be used to invoke a cloud code function.',
args: {
functionName: {
description: 'This is the name of the function to be called.',
type: new GraphQLNonNull(GraphQLString),
},
params: {
description: 'These are the params to be passed to the function.',
type: defaultGraphQLTypes.OBJECT,
},
},
params: {
description: 'These are the params to be passed to the function.',
type: defaultGraphQLTypes.OBJECT,
type: defaultGraphQLTypes.ANY,
async resolve(_source, args, context) {
try {
const { functionName, params } = args;
const { config, auth, info } = context;
return (await FunctionsRouter.handleCloudFunction({
params: {
functionName,
},
config,
auth,
info,
body: params,
})).response.result;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
type: defaultGraphQLTypes.ANY,
async resolve(_source, args, context) {
try {
const { functionName, params } = args;
const { config, auth, info } = context;
return (await FunctionsRouter.handleCloudFunction({
params: {
functionName,
},
config,
auth,
info,
body: params,
})).response.result;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
};
const functionsMutation = new GraphQLObjectType({
name: 'FunctionsMutation',
description:
'FunctionsMutation is the top level type for functions mutations.',
fields,
});
parseGraphQLSchema.addGraphQLType(functionsMutation, true, true);
parseGraphQLSchema.graphQLMutations.functions = {
description: 'This is the top level for functions mutations.',
type: functionsMutation,
resolve: () => new Object(),
};
true,
true
);
};
export { load };

View File

@@ -1,4 +1,4 @@
import { GraphQLNonNull, GraphQLBoolean, GraphQLObjectType } from 'graphql';
import { GraphQLNonNull, GraphQLBoolean } from 'graphql';
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
import rest from '../../rest';
import { transformMutationInputToParse } from '../transformers/mutation';
@@ -44,7 +44,7 @@ const deleteObject = async (className, objectId, config, auth, info) => {
};
const load = parseGraphQLSchema => {
parseGraphQLSchema.addGraphQLObjectMutation(
parseGraphQLSchema.addGraphQLMutation(
'create',
{
description:
@@ -69,7 +69,7 @@ const load = parseGraphQLSchema => {
true
);
parseGraphQLSchema.addGraphQLObjectMutation(
parseGraphQLSchema.addGraphQLMutation(
'update',
{
description:
@@ -102,7 +102,7 @@ const load = parseGraphQLSchema => {
true
);
parseGraphQLSchema.addGraphQLObjectMutation(
parseGraphQLSchema.addGraphQLMutation(
'delete',
{
description:
@@ -126,19 +126,6 @@ const load = parseGraphQLSchema => {
true,
true
);
const objectsMutation = new GraphQLObjectType({
name: 'ObjectsMutation',
description: 'ObjectsMutation is the top level type for objects mutations.',
fields: parseGraphQLSchema.graphQLObjectsMutations,
});
parseGraphQLSchema.addGraphQLType(objectsMutation, true, true);
parseGraphQLSchema.graphQLMutations.objects = {
description: 'This is the top level for objects mutations.',
type: objectsMutation,
resolve: () => new Object(),
};
};
export { createObject, updateObject, deleteObject, load };

View File

@@ -1,9 +1,4 @@
import {
GraphQLNonNull,
GraphQLBoolean,
GraphQLString,
GraphQLObjectType,
} from 'graphql';
import { GraphQLNonNull, GraphQLBoolean, GraphQLString } from 'graphql';
import getFieldNames from 'graphql-list-fields';
import Parse from 'parse/node';
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
@@ -134,7 +129,7 @@ const findObjects = async (
};
const load = parseGraphQLSchema => {
parseGraphQLSchema.addGraphQLObjectQuery(
parseGraphQLSchema.addGraphQLQuery(
'get',
{
description:
@@ -181,7 +176,7 @@ const load = parseGraphQLSchema => {
true
);
parseGraphQLSchema.addGraphQLObjectQuery(
parseGraphQLSchema.addGraphQLQuery(
'find',
{
description:
@@ -252,19 +247,6 @@ const load = parseGraphQLSchema => {
true,
true
);
const objectsQuery = new GraphQLObjectType({
name: 'ObjectsQuery',
description: 'ObjectsQuery is the top level type for objects queries.',
fields: parseGraphQLSchema.graphQLObjectsQueries,
});
parseGraphQLSchema.addGraphQLType(objectsQuery, true, true);
parseGraphQLSchema.graphQLQueries.objects = {
description: 'This is the top level for objects queries.',
type: objectsQuery,
resolve: () => new Object(),
};
};
export { getObject, findObjects, load };

View File

@@ -94,7 +94,7 @@ const load = function(
if (isCreateEnabled) {
const createGraphQLMutationName = `create${graphQLClassName}`;
parseGraphQLSchema.addGraphQLObjectMutation(createGraphQLMutationName, {
parseGraphQLSchema.addGraphQLMutation(createGraphQLMutationName, {
description: `The ${createGraphQLMutationName} mutation can be used to create a new object of the ${graphQLClassName} class.`,
args: {
fields: {
@@ -155,7 +155,7 @@ const load = function(
if (isUpdateEnabled) {
const updateGraphQLMutationName = `update${graphQLClassName}`;
parseGraphQLSchema.addGraphQLObjectMutation(updateGraphQLMutationName, {
parseGraphQLSchema.addGraphQLMutation(updateGraphQLMutationName, {
description: `The ${updateGraphQLMutationName} mutation can be used to update an object of the ${graphQLClassName} class.`,
args: {
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
@@ -215,7 +215,7 @@ const load = function(
if (isDestroyEnabled) {
const deleteGraphQLMutationName = `delete${graphQLClassName}`;
parseGraphQLSchema.addGraphQLObjectMutation(deleteGraphQLMutationName, {
parseGraphQLSchema.addGraphQLMutation(deleteGraphQLMutationName, {
description: `The ${deleteGraphQLMutationName} mutation can be used to delete an object of the ${graphQLClassName} class.`,
args: {
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,

View File

@@ -54,7 +54,7 @@ const load = function(
if (isGetEnabled) {
const getGraphQLQueryName =
graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1);
parseGraphQLSchema.addGraphQLObjectQuery(getGraphQLQueryName, {
parseGraphQLSchema.addGraphQLQuery(getGraphQLQueryName, {
description: `The ${getGraphQLQueryName} query can be used to get an object of the ${graphQLClassName} class by its id.`,
args: {
objectId: defaultGraphQLTypes.OBJECT_ID_ATT,
@@ -78,7 +78,7 @@ const load = function(
const findGraphQLQueryName = pluralize(
graphQLClassName.charAt(0).toLowerCase() + graphQLClassName.slice(1)
);
parseGraphQLSchema.addGraphQLObjectQuery(findGraphQLQueryName, {
parseGraphQLSchema.addGraphQLQuery(findGraphQLQueryName, {
description: `The ${findGraphQLQueryName} query can be used to find objects of the ${graphQLClassName} class.`,
args: classGraphQLFindArgs,
type: new GraphQLNonNull(

View File

@@ -3,7 +3,6 @@ import { SchemaDirectiveVisitor } from 'graphql-tools';
import { FunctionsRouter } from '../../Routers/FunctionsRouter';
export const definitions = gql`
directive @namespace on FIELD_DEFINITION
directive @resolve(to: String) on FIELD_DEFINITION
directive @mock(with: Any!) on FIELD_DEFINITION
`;
@@ -11,14 +10,6 @@ export const definitions = gql`
const load = parseGraphQLSchema => {
parseGraphQLSchema.graphQLSchemaDirectivesDefinitions = definitions;
class NamespaceDirectiveVisitor extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
field.resolve = () => ({});
}
}
parseGraphQLSchema.graphQLSchemaDirectives.namespace = NamespaceDirectiveVisitor;
class ResolveDirectiveVisitor extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
field.resolve = async (_source, args, context) => {

View File

@@ -1,4 +1,4 @@
import { GraphQLNonNull, GraphQLObjectType } from 'graphql';
import { GraphQLNonNull } from 'graphql';
import UsersRouter from '../../Routers/UsersRouter';
import * as objectsMutations from './objectsMutations';
import { getUserFromSessionToken } from './usersQueries';
@@ -9,110 +9,111 @@ const load = parseGraphQLSchema => {
if (parseGraphQLSchema.isUsersClassDisabled) {
return;
}
const fields = {};
fields.signUp = {
description: 'The signUp mutation can be used to sign the user up.',
args: {
fields: {
descriptions: 'These are the fields of the user.',
type: parseGraphQLSchema.parseClassTypes['_User'].signUpInputType,
parseGraphQLSchema.addGraphQLMutation(
'signUp',
{
description: 'The signUp mutation can be used to sign the user up.',
args: {
fields: {
descriptions: 'These are the fields of the user.',
type: parseGraphQLSchema.parseClassTypes['_User'].signUpInputType,
},
},
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, args, context, mutationInfo) {
try {
const { fields } = args;
const { config, auth, info } = context;
const { sessionToken } = await objectsMutations.createObject(
'_User',
fields,
config,
auth,
info
);
info.sessionToken = sessionToken;
return await getUserFromSessionToken(config, info, mutationInfo);
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, args, context, mutationInfo) {
try {
const { fields } = args;
true,
true
);
const { config, auth, info } = context;
parseGraphQLSchema.addGraphQLMutation(
'logIn',
{
description: 'The logIn mutation can be used to log the user in.',
args: {
fields: {
description: 'This is data needed to login',
type: parseGraphQLSchema.parseClassTypes['_User'].logInInputType,
},
},
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, args, context) {
try {
const {
fields: { username, password },
} = args;
const { config, auth, info } = context;
const { sessionToken } = await objectsMutations.createObject(
'_User',
fields,
config,
auth,
info
);
info.sessionToken = sessionToken;
return await getUserFromSessionToken(config, info, mutationInfo);
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
};
fields.logIn = {
description: 'The logIn mutation can be used to log the user in.',
args: {
fields: {
description: 'This is data needed to login',
type: parseGraphQLSchema.parseClassTypes['_User'].logInInputType,
return (await usersRouter.handleLogIn({
body: {
username,
password,
},
query: {},
config,
auth,
info,
})).response;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, args, context) {
try {
const {
fields: { username, password },
} = args;
const { config, auth, info } = context;
true,
true
);
return (await usersRouter.handleLogIn({
body: {
username,
password,
},
query: {},
config,
auth,
info,
})).response;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
parseGraphQLSchema.addGraphQLMutation(
'logOut',
{
description: 'The logOut mutation can be used to log the user out.',
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, _args, context, mutationInfo) {
try {
const { config, auth, info } = context;
const viewer = await getUserFromSessionToken(
config,
info,
mutationInfo
);
await usersRouter.handleLogOut({
config,
auth,
info,
});
return viewer;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
};
fields.logOut = {
description: 'The logOut mutation can be used to log the user out.',
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, _args, context, mutationInfo) {
try {
const { config, auth, info } = context;
const viewer = await getUserFromSessionToken(
config,
info,
mutationInfo
);
await usersRouter.handleLogOut({
config,
auth,
info,
});
return viewer;
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
};
const usersMutation = new GraphQLObjectType({
name: 'UsersMutation',
description: 'UsersMutation is the top level type for files mutations.',
fields,
});
parseGraphQLSchema.addGraphQLType(usersMutation, true, true);
parseGraphQLSchema.graphQLMutations.users = {
description: 'This is the top level for users mutations.',
type: usersMutation,
resolve: () => new Object(),
};
true,
true
);
};
export { load };

View File

@@ -1,4 +1,4 @@
import { GraphQLNonNull, GraphQLObjectType } from 'graphql';
import { GraphQLNonNull } from 'graphql';
import getFieldNames from 'graphql-list-fields';
import Parse from 'parse/node';
import rest from '../../rest';
@@ -49,34 +49,25 @@ const load = parseGraphQLSchema => {
if (parseGraphQLSchema.isUsersClassDisabled) {
return;
}
const fields = {};
fields.viewer = {
description:
'The viewer query can be used to return the current user data.',
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, _args, context, queryInfo) {
try {
const { config, info } = context;
return await getUserFromSessionToken(config, info, queryInfo);
} catch (e) {
parseGraphQLSchema.handleError(e);
}
parseGraphQLSchema.addGraphQLQuery(
'viewer',
{
description:
'The viewer query can be used to return the current user data.',
type: new GraphQLNonNull(parseGraphQLSchema.viewerType),
async resolve(_source, _args, context, queryInfo) {
try {
const { config, info } = context;
return await getUserFromSessionToken(config, info, queryInfo);
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
},
};
const usersQuery = new GraphQLObjectType({
name: 'UsersQuery',
description: 'UsersQuery is the top level type for users queries.',
fields,
});
parseGraphQLSchema.addGraphQLType(usersQuery, true, true);
parseGraphQLSchema.graphQLQueries.users = {
description: 'This is the top level for users queries.',
type: usersQuery,
resolve: () => new Object(),
};
true,
true
);
};
export { load, getUserFromSessionToken };