diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 7718ad184b..fd0c6398d8 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -3069,57 +3069,65 @@ describe('ParseGraphQLServer', () => { describe_only_db('mongo')('read preferences', () => { it('should read from primary by default', async () => { - await prepareData(); + try { + await prepareData(); - await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); + await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); - const databaseAdapter = - parseServer.config.databaseController.adapter; - spyOn( - databaseAdapter.database.serverConfig, - 'cursor' - ).and.callThrough(); + const databaseAdapter = + parseServer.config.databaseController.adapter; + spyOn( + databaseAdapter.database.serverConfig, + 'cursor' + ).and.callThrough(); - await apolloClient.query({ - query: gql` - query GetSomeObject($id: ID!) { - graphQLClass(id: $id) { - pointerToUser { - username + await apolloClient.query({ + query: gql` + query GetSomeObject($id: ID!) { + graphQLClass(id: $id) { + pointerToUser { + username + } } } - } - `, - variables: { - id: object3.id, - }, - context: { - headers: { - 'X-Parse-Session-Token': user1.getSessionToken(), + `, + variables: { + id: object3.id, + }, + context: { + headers: { + 'X-Parse-Session-Token': user1.getSessionToken(), + }, }, - }, - }); - - let foundGraphQLClassReadPreference = false; - let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls - .all() - .forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { - foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe( - ReadPreference.PRIMARY - ); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { - foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe( - ReadPreference.PRIMARY - ); - } }); - expect(foundGraphQLClassReadPreference).toBe(true); - expect(foundUserClassReadPreference).toBe(true); + let foundGraphQLClassReadPreference = false; + let foundUserClassReadPreference = false; + databaseAdapter.database.serverConfig.cursor.calls + .all() + .forEach(call => { + if ( + call.args[0].ns.collection.indexOf('GraphQLClass') >= 0 + ) { + foundGraphQLClassReadPreference = true; + expect(call.args[0].options.readPreference.mode).toBe( + ReadPreference.PRIMARY + ); + } else if ( + call.args[0].ns.collection.indexOf('_User') >= 0 + ) { + foundUserClassReadPreference = true; + expect(call.args[0].options.readPreference.mode).toBe( + ReadPreference.PRIMARY + ); + } + }); + + expect(foundGraphQLClassReadPreference).toBe(true); + expect(foundUserClassReadPreference).toBe(true); + } catch (e) { + handleError(e); + } }); it('should support readPreference argument', async () => { @@ -3137,7 +3145,10 @@ describe('ParseGraphQLServer', () => { await apolloClient.query({ query: gql` query GetSomeObject($id: ID!) { - graphQLClass(id: $id, readPreference: SECONDARY) { + graphQLClass( + id: $id + options: { readPreference: SECONDARY } + ) { pointerToUser { username } @@ -3193,8 +3204,10 @@ describe('ParseGraphQLServer', () => { query GetSomeObject($id: ID!) { graphQLClass( id: $id - readPreference: SECONDARY - includeReadPreference: NEAREST + options: { + readPreference: SECONDARY + includeReadPreference: NEAREST + } ) { pointerToUser { username @@ -3904,7 +3917,9 @@ describe('ParseGraphQLServer', () => { await apolloClient.query({ query: gql` query FindSomeObjects { - find: graphQLClasses(readPreference: SECONDARY) { + find: graphQLClasses( + options: { readPreference: SECONDARY } + ) { results { pointerToUser { username @@ -3958,8 +3973,10 @@ describe('ParseGraphQLServer', () => { query: gql` query FindSomeObjects { graphQLClasses( - readPreference: SECONDARY - includeReadPreference: NEAREST + options: { + readPreference: SECONDARY + includeReadPreference: NEAREST + } ) { results { pointerToUser { @@ -4016,8 +4033,10 @@ describe('ParseGraphQLServer', () => { query FindSomeObjects($where: GraphQLClassWhereInput) { find: graphQLClasses( where: $where - readPreference: SECONDARY - subqueryReadPreference: NEAREST + options: { + readPreference: SECONDARY + subqueryReadPreference: NEAREST + } ) { results { id diff --git a/src/GraphQL/loaders/defaultGraphQLTypes.js b/src/GraphQL/loaders/defaultGraphQLTypes.js index 88a3f2c32a..dc357d49ee 100644 --- a/src/GraphQL/loaders/defaultGraphQLTypes.js +++ b/src/GraphQL/loaders/defaultGraphQLTypes.js @@ -483,6 +483,22 @@ const SUBQUERY_READ_PREFERENCE_ATT = { type: READ_PREFERENCE, }; +const READ_OPTIONS_INPUT = new GraphQLInputObjectType({ + name: 'ReadOptionsInput', + description: + 'The ReadOptionsInputt type is used in queries in order to set the read preferences.', + fields: { + readPreference: READ_PREFERENCE_ATT, + includeReadPreference: INCLUDE_READ_PREFERENCE_ATT, + subqueryReadPreference: SUBQUERY_READ_PREFERENCE_ATT, + }, +}); + +const READ_OPTIONS_ATT = { + description: 'The read options for the query to be executed.', + type: READ_OPTIONS_INPUT, +}; + const WHERE_ATT = { description: 'These are the conditions that the objects need to match in order to be found', @@ -1034,6 +1050,7 @@ const load = parseGraphQLSchema => { parseGraphQLSchema.addGraphQLType(GEO_POINT, true); parseGraphQLSchema.addGraphQLType(PARSE_OBJECT, true); parseGraphQLSchema.addGraphQLType(READ_PREFERENCE, true); + parseGraphQLSchema.addGraphQLType(READ_OPTIONS_INPUT, true); parseGraphQLSchema.addGraphQLType(SUBQUERY_INPUT, true); parseGraphQLSchema.addGraphQLType(SELECT_INPUT, true); parseGraphQLSchema.addGraphQLType(SEARCH_INPUT, true); @@ -1098,6 +1115,8 @@ export { READ_PREFERENCE_ATT, INCLUDE_READ_PREFERENCE_ATT, SUBQUERY_READ_PREFERENCE_ATT, + READ_OPTIONS_INPUT, + READ_OPTIONS_ATT, WHERE_ATT, SKIP_ATT, LIMIT_ATT, diff --git a/src/GraphQL/loaders/parseClassQueries.js b/src/GraphQL/loaders/parseClassQueries.js index cc33e73704..63041ad94d 100644 --- a/src/GraphQL/loaders/parseClassQueries.js +++ b/src/GraphQL/loaders/parseClassQueries.js @@ -14,7 +14,8 @@ const getParseClassQueryConfig = function( }; const getQuery = async (className, _source, args, context, queryInfo) => { - const { id, readPreference, includeReadPreference } = args; + const { id, options } = args; + const { readPreference, includeReadPreference } = options || {}; const { config, auth, info } = context; const selectedFields = getFieldNames(queryInfo); @@ -58,8 +59,7 @@ const load = function( description: `The ${getGraphQLQueryName} query can be used to get an object of the ${graphQLClassName} class by its id.`, args: { id: defaultGraphQLTypes.OBJECT_ID_ATT, - readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT, - includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT, + options: defaultGraphQLTypes.READ_OPTIONS_ATT, }, type: new GraphQLNonNull( classGraphQLOutputType || defaultGraphQLTypes.OBJECT @@ -86,15 +86,12 @@ const load = function( ), async resolve(_source, args, context, queryInfo) { try { + const { where, order, skip, limit, options } = args; const { - where, - order, - skip, - limit, readPreference, includeReadPreference, subqueryReadPreference, - } = args; + } = options || {}; const { config, auth, info } = context; const selectedFields = getFieldNames(queryInfo); diff --git a/src/GraphQL/loaders/parseClassTypes.js b/src/GraphQL/loaders/parseClassTypes.js index 6c6a6777e1..99a9df0eef 100644 --- a/src/GraphQL/loaders/parseClassTypes.js +++ b/src/GraphQL/loaders/parseClassTypes.js @@ -366,9 +366,7 @@ const load = ( }, skip: defaultGraphQLTypes.SKIP_ATT, limit: defaultGraphQLTypes.LIMIT_ATT, - readPreference: defaultGraphQLTypes.READ_PREFERENCE_ATT, - includeReadPreference: defaultGraphQLTypes.INCLUDE_READ_PREFERENCE_ATT, - subqueryReadPreference: defaultGraphQLTypes.SUBQUERY_READ_PREFERENCE_ATT, + options: defaultGraphQLTypes.READ_OPTIONS_ATT, }; const classGraphQLOutputTypeName = `${graphQLClassName}`; @@ -395,15 +393,12 @@ const load = ( type, async resolve(source, args, context, queryInfo) { try { + const { where, order, skip, limit, options } = args; const { - where, - order, - skip, - limit, readPreference, includeReadPreference, subqueryReadPreference, - } = args; + } = options || {}; const { config, auth, info } = context; const selectedFields = getFieldNames(queryInfo);