diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 36fc3070c7..8ef884875f 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -604,44 +604,6 @@ describe('ParseGraphQLServer', () => { ]); }); - it('should have CreateResult object type', async () => { - const createResultType = (await apolloClient.query({ - query: gql` - query CreateResultType { - __type(name: "CreateResult") { - kind - fields { - name - } - } - } - `, - })).data['__type']; - expect(createResultType.kind).toEqual('OBJECT'); - expect( - createResultType.fields.map(field => field.name).sort() - ).toEqual(['createdAt', 'id']); - }); - - it('should have UpdateResult object type', async () => { - const updateResultType = (await apolloClient.query({ - query: gql` - query UpdateResultType { - __type(name: "UpdateResult") { - kind - fields { - name - } - } - } - `, - })).data['__type']; - expect(updateResultType.kind).toEqual('OBJECT'); - expect(updateResultType.fields.map(field => field.name)).toEqual([ - 'updatedAt', - ]); - }); - it('should have Class interface type', async () => { const classType = (await apolloClient.query({ query: gql` @@ -740,12 +702,10 @@ describe('ParseGraphQLServer', () => { const expectedTypes = [ 'ParseObject', - 'CreateResult', 'Date', 'FileInfo', 'FindResult', 'ReadPreference', - 'UpdateResult', 'Upload', ]; expect( @@ -1376,78 +1336,86 @@ describe('ParseGraphQLServer', () => { })).data.superCar; expect(getSuperCar.id).toBe(superCar.id); }); - it('should only allow the supplied constraint fields for a class', async () => { - const schemaController = await parseServer.config.databaseController.loadSchema(); - await schemaController.addClassIfNotExists('SuperCar', { - model: { type: 'String' }, - engine: { type: 'String' }, - doors: { type: 'Number' }, - price: { type: 'String' }, - mileage: { type: 'Number' }, - insuranceCertificate: { type: 'String' }, - }); + it('should only allow the supplied constraint fields for a class', async () => { + try { + const schemaController = await parseServer.config.databaseController.loadSchema(); + + await schemaController.addClassIfNotExists('SuperCar', { + model: { type: 'String' }, + engine: { type: 'String' }, + doors: { type: 'Number' }, + price: { type: 'String' }, + mileage: { type: 'Number' }, + insuranceCertificate: { type: 'String' }, + }); - await new Parse.Object('SuperCar').save({ - model: 'McLaren', - engine: 'petrol', - doors: 3, - price: '£7500', - mileage: 0, - insuranceCertificate: 'private-file.pdf', - }); + await new Parse.Object('SuperCar').save({ + model: 'McLaren', + engine: 'petrol', + doors: 3, + price: '£7500', + mileage: 0, + insuranceCertificate: 'private-file.pdf', + }); - await parseGraphQLServer.setGraphQLConfig({ - classConfigs: [ - { - className: 'SuperCar', - type: { - constraintFields: ['engine', 'doors', 'price'], + await parseGraphQLServer.setGraphQLConfig({ + classConfigs: [ + { + className: 'SuperCar', + type: { + constraintFields: ['engine', 'doors', 'price'], + }, }, - }, - ], - }); + ], + }); - await resetGraphQLCache(); + await resetGraphQLCache(); - await expectAsync( - apolloClient.query({ - query: gql` - query FindSuperCar { - superCars( - where: { insuranceCertificate: { _eq: "private-file.pdf" } } - ) { - count + await expectAsync( + apolloClient.query({ + query: gql` + query FindSuperCar { + superCars( + where: { + insuranceCertificate: { equalTo: "private-file.pdf" } + } + ) { + count + } } - } - `, - }) - ).toBeRejected(); + `, + }) + ).toBeRejected(); - await expectAsync( - apolloClient.query({ - query: gql` - query FindSuperCar { - superCars(where: { mileage: { _eq: 0 } }) { - count + await expectAsync( + apolloClient.query({ + query: gql` + query FindSuperCar { + superCars(where: { mileage: { equalTo: 0 } }) { + count + } } - } - `, - }) - ).toBeRejected(); + `, + }) + ).toBeRejected(); - await expectAsync( - apolloClient.query({ - query: gql` - query FindSuperCar { - superCars(where: { engine: { _eq: "petrol" } }) { - count + await expectAsync( + apolloClient.query({ + query: gql` + query FindSuperCar { + superCars(where: { engine: { equalTo: "petrol" } }) { + count + } } - } - `, - }) - ).toBeResolved(); + `, + }) + ).toBeResolved(); + } catch (e) { + handleError(e); + } }); + it('should only allow the supplied sort fields for a class', async () => { const schemaController = await parseServer.config.databaseController.loadSchema(); @@ -3411,12 +3379,12 @@ describe('ParseGraphQLServer', () => { variables: { where: { someField: { - _in: ['someValue1', 'someValue2', 'someValue3'], + in: ['someValue1', 'someValue2', 'someValue3'], }, - _or: [ + OR: [ { pointerToUser: { - _eq: { + equalTo: { __type: 'Pointer', className: '_User', objectId: user5.id, @@ -3425,7 +3393,7 @@ describe('ParseGraphQLServer', () => { }, { id: { - _eq: object1.id, + equalTo: object1.id, }, }, ], @@ -3445,7 +3413,7 @@ describe('ParseGraphQLServer', () => { ).toEqual(['someValue1', 'someValue3']); }); - it('should support _or operation', async () => { + it('should support OR operation', async () => { await prepareData(); await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); @@ -3455,9 +3423,9 @@ describe('ParseGraphQLServer', () => { query { graphQLClasses( where: { - _or: [ - { someField: { _eq: "someValue1" } } - { someField: { _eq: "someValue2" } } + OR: [ + { someField: { equalTo: "someValue1" } } + { someField: { equalTo: "someValue2" } } ] } ) { @@ -3481,6 +3449,53 @@ describe('ParseGraphQLServer', () => { ).toEqual(['someValue1', 'someValue2']); }); + it('should support full text search', async () => { + try { + const obj = new Parse.Object('FullTextSearchTest'); + obj.set('field1', 'Parse GraphQL Server'); + obj.set('field2', 'It rocks!'); + await obj.save(); + + await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); + + const result = await apolloClient.query({ + query: gql` + query FullTextSearchTests( + $where: FullTextSearchTestWhereInput + ) { + fullTextSearchTests(where: $where) { + results { + id + } + } + } + `, + context: { + headers: { + 'X-Parse-Master-Key': 'test', + }, + }, + variables: { + where: { + field1: { + text: { + search: { + term: 'graphql', + }, + }, + }, + }, + }, + }); + + expect(result.data.fullTextSearchTests.results[0].id).toEqual( + obj.id + ); + } catch (e) { + handleError(e); + } + }); + it('should support order, skip and limit arguments', async () => { const promises = []; for (let i = 0; i < 100; i++) { @@ -3516,7 +3531,7 @@ describe('ParseGraphQLServer', () => { variables: { where: { someField: { - _regex: '^someValue', + matchesRegex: '^someValue', }, }, order: ['numberField_DESC', 'someField_ASC'], @@ -3538,12 +3553,12 @@ describe('ParseGraphQLServer', () => { const where = { someField: { - _in: ['someValue1', 'someValue2', 'someValue3'], + in: ['someValue1', 'someValue2', 'someValue3'], }, - _or: [ + OR: [ { pointerToUser: { - _eq: { + equalTo: { __type: 'Pointer', className: '_User', objectId: user5.id, @@ -3552,7 +3567,7 @@ describe('ParseGraphQLServer', () => { }, { id: { - _eq: object1.id, + equalTo: object1.id, }, }, ], @@ -3594,12 +3609,12 @@ describe('ParseGraphQLServer', () => { const where = { someField: { - _in: ['someValue1', 'someValue2', 'someValue3'], + in: ['someValue1', 'someValue2', 'someValue3'], }, - _or: [ + OR: [ { pointerToUser: { - _eq: { + equalTo: { __type: 'Pointer', className: '_User', objectId: user5.id, @@ -3608,7 +3623,7 @@ describe('ParseGraphQLServer', () => { }, { id: { - _eq: object1.id, + equalTo: object1.id, }, }, ], @@ -3654,7 +3669,7 @@ describe('ParseGraphQLServer', () => { query: gql` query FindSomeObjects($limit: Int) { find: someClasses( - where: { id: { _exists: true } } + where: { id: { exists: true } } limit: $limit ) { results { @@ -3695,7 +3710,7 @@ describe('ParseGraphQLServer', () => { `, variables: { where: { - id: { _eq: object3.id }, + id: { equalTo: object3.id }, }, }, context: { @@ -3720,7 +3735,7 @@ describe('ParseGraphQLServer', () => { `, variables: { where: { - id: { _eq: object3.id }, + id: { equalTo: object3.id }, }, }, context: { @@ -3743,7 +3758,7 @@ describe('ParseGraphQLServer', () => { const where = { id: { - _eq: object3.id, + equalTo: object3.id, }, }; @@ -3991,7 +4006,7 @@ describe('ParseGraphQLServer', () => { variables: { where: { pointerToUser: { - _inQuery: { where: {}, className: '_User' }, + inQuery: { where: {}, className: '_User' }, }, }, }, @@ -5326,7 +5341,9 @@ describe('ParseGraphQLServer', () => { someClass(id: $id) { someField } - someClasses(where: { someField: { _eq: $someFieldValue } }) { + someClasses( + where: { someField: { equalTo: $someFieldValue } } + ) { results { someField } @@ -5397,7 +5414,9 @@ describe('ParseGraphQLServer', () => { someClass(id: $id) { someField } - someClasses(where: { someField: { _eq: $someFieldValue } }) { + someClasses( + where: { someField: { equalTo: $someFieldValue } } + ) { results { someField } @@ -5468,7 +5487,9 @@ describe('ParseGraphQLServer', () => { someClass(id: $id) { someField } - someClasses(where: { someField: { _eq: $someFieldValue } }) { + someClasses( + where: { someField: { equalTo: $someFieldValue } } + ) { results { someField } @@ -5552,8 +5573,8 @@ describe('ParseGraphQLServer', () => { } someClasses( where: { - someFieldTrue: { _eq: $someFieldValueTrue } - someFieldFalse: { _eq: $someFieldValueFalse } + someFieldTrue: { equalTo: $someFieldValueTrue } + someFieldFalse: { equalTo: $someFieldValueFalse } } ) { results { @@ -5633,7 +5654,7 @@ describe('ParseGraphQLServer', () => { someClass(id: $id) { someField } - someClasses(where: { someField: { _exists: true } }) { + someClasses(where: { someField: { exists: true } }) { results { id } @@ -6101,7 +6122,7 @@ describe('ParseGraphQLServer', () => { variables: { where: { name: { - _eq: 'imACompany2', + equalTo: 'imACompany2', }, }, fields: { @@ -6198,7 +6219,7 @@ describe('ParseGraphQLServer', () => { variables: { id: country.id, where: { - name: { _eq: 'imACompany1' }, + name: { equalTo: 'imACompany1' }, }, }, }); @@ -6314,7 +6335,7 @@ describe('ParseGraphQLServer', () => { } } findSomeClass1: someClasses( - where: { someField: { _exists: true } } + where: { someField: { exists: true } } ) { results { someField { @@ -6324,7 +6345,7 @@ describe('ParseGraphQLServer', () => { } } findSomeClass2: someClasses( - where: { someField: { _exists: true } } + where: { someField: { exists: true } } ) { results { someField { @@ -6408,10 +6429,10 @@ describe('ParseGraphQLServer', () => { const where = { someField: { - _eq: { _key: 'foo.bar', _value: 'baz' }, - _ne: { _key: 'foo.bar', _value: 'bat' }, - _gt: { _key: 'number', _value: 9 }, - _lt: { _key: 'number', _value: 11 }, + equalTo: { key: 'foo.bar', value: 'baz' }, + notEqualTo: { key: 'foo.bar', value: 'bat' }, + greaterThan: { key: 'number', value: 9 }, + lessThan: { key: 'number', value: 11 }, }, }; const queryResult = await apolloClient.query({ @@ -6507,27 +6528,27 @@ describe('ParseGraphQLServer', () => { }); const where = { - _and: [ + AND: [ { someField: { - _gt: { _key: 'number', _value: 9 }, + greaterThan: { key: 'number', value: 9 }, }, }, { someField: { - _lt: { _key: 'number', _value: 11 }, + lessThan: { key: 'number', value: 11 }, }, }, { - _or: [ + OR: [ { someField: { - _eq: { _key: 'lorem', _value: 'ipsum' }, + equalTo: { key: 'lorem', value: 'ipsum' }, }, }, { someField: { - _eq: { _key: 'foo.test', _value: 'bar' }, + equalTo: { key: 'foo.test', value: 'bar' }, }, }, ], @@ -6627,7 +6648,7 @@ describe('ParseGraphQLServer', () => { } } } - someClasses(where: { someField: { _exists: true } }) { + someClasses(where: { someField: { exists: true } }) { results { id someField { @@ -6845,7 +6866,9 @@ describe('ParseGraphQLServer', () => { someClass(id: $id) { someField } - someClasses(where: { someField: { _eq: $someFieldValue } }) { + someClasses( + where: { someField: { equalTo: $someFieldValue } } + ) { results { id someField @@ -6927,7 +6950,7 @@ describe('ParseGraphQLServer', () => { longitude } } - someClasses(where: { someField: { _exists: true } }) { + someClasses(where: { someField: { exists: true } }) { results { id someField { @@ -7012,7 +7035,7 @@ describe('ParseGraphQLServer', () => { longitude } } - someClasses(where: { somePolygonField: { _exists: true } }) { + someClasses(where: { somePolygonField: { exists: true } }) { results { id somePolygonField { @@ -7133,7 +7156,7 @@ describe('ParseGraphQLServer', () => { variables: { where: { someField: { - _eq: updatedSomeFieldValue.base64, + equalTo: updatedSomeFieldValue.base64, }, }, }, diff --git a/src/GraphQL/loaders/defaultGraphQLTypes.js b/src/GraphQL/loaders/defaultGraphQLTypes.js index 2c57a2d065..88a3f2c32a 100644 --- a/src/GraphQL/loaders/defaultGraphQLTypes.js +++ b/src/GraphQL/loaders/defaultGraphQLTypes.js @@ -402,11 +402,6 @@ const CLASS_NAME_ATT = { type: new GraphQLNonNull(GraphQLString), }; -const FIELDS_ATT = { - description: 'These are the fields of the object.', - type: OBJECT, -}; - const OBJECT_ID_ATT = { description: 'This is the object id.', type: OBJECT_ID, @@ -437,24 +432,10 @@ const CREATE_RESULT_FIELDS = { createdAt: CREATED_AT_ATT, }; -const CREATE_RESULT = new GraphQLObjectType({ - name: 'CreateResult', - description: - 'The CreateResult object type is used in the create mutations to return the data of the recent created object.', - fields: CREATE_RESULT_FIELDS, -}); - const UPDATE_RESULT_FIELDS = { updatedAt: UPDATED_AT_ATT, }; -const UPDATE_RESULT = new GraphQLObjectType({ - name: 'UpdateResult', - description: - 'The UpdateResult object type is used in the update mutations to return the data of the recent updated object.', - fields: UPDATE_RESULT_FIELDS, -}); - const PARSE_OBJECT_FIELDS = { ...CREATE_RESULT_FIELDS, ...UPDATE_RESULT_FIELDS, @@ -473,16 +454,6 @@ const SESSION_TOKEN_ATT = { type: new GraphQLNonNull(GraphQLString), }; -const KEYS_ATT = { - description: 'The keys of the objects that will be returned.', - type: GraphQLString, -}; - -const INCLUDE_ATT = { - description: 'The pointers of the objects that will be returned.', - type: GraphQLString, -}; - const READ_PREFERENCE = new GraphQLEnumType({ name: 'ReadPreference', description: @@ -537,7 +508,7 @@ const COUNT_ATT = { const SUBQUERY_INPUT = new GraphQLInputObjectType({ name: 'SubqueryInput', description: - 'The SubqueryInput type is used to specific a different query to a different class.', + 'The SubqueryInput type is used to specify a sub query to another class.', fields: { className: CLASS_NAME_ATT, where: Object.assign({}, WHERE_ATT, { @@ -549,7 +520,7 @@ const SUBQUERY_INPUT = new GraphQLInputObjectType({ const SELECT_INPUT = new GraphQLInputObjectType({ name: 'SelectInput', description: - 'The SelectInput type is used to specify a $select operation on a constraint.', + 'The SelectInput type is used to specify an inQueryKey or a notInQueryKey operation on a constraint.', fields: { query: { description: 'This is the subquery to be executed.', @@ -566,23 +537,23 @@ const SELECT_INPUT = new GraphQLInputObjectType({ const SEARCH_INPUT = new GraphQLInputObjectType({ name: 'SearchInput', description: - 'The SearchInput type is used to specifiy a $search operation on a full text search.', + 'The SearchInput type is used to specifiy a search operation on a full text search.', fields: { - _term: { + term: { description: 'This is the term to be searched.', type: new GraphQLNonNull(GraphQLString), }, - _language: { + language: { description: 'This is the language to tetermine the list of stop words and the rules for tokenizer.', type: GraphQLString, }, - _caseSensitive: { + caseSensitive: { description: 'This is the flag to enable or disable case sensitive search.', type: GraphQLBoolean, }, - _diacriticSensitive: { + diacriticSensitive: { description: 'This is the flag to enable or disable diacritic sensitive search.', type: GraphQLBoolean, @@ -593,9 +564,9 @@ const SEARCH_INPUT = new GraphQLInputObjectType({ const TEXT_INPUT = new GraphQLInputObjectType({ name: 'TextInput', description: - 'The TextInput type is used to specify a $text operation on a constraint.', + 'The TextInput type is used to specify a text operation on a constraint.', fields: { - _search: { + search: { description: 'This is the search to be executed.', type: new GraphQLNonNull(SEARCH_INPUT), }, @@ -605,7 +576,7 @@ const TEXT_INPUT = new GraphQLInputObjectType({ const BOX_INPUT = new GraphQLInputObjectType({ name: 'BoxInput', description: - 'The BoxInput type is used to specifiy a $box operation on a within geo query.', + 'The BoxInput type is used to specifiy a box operation on a within geo query.', fields: { bottomLeft: { description: 'This is the bottom left coordinates of the box.', @@ -621,9 +592,9 @@ const BOX_INPUT = new GraphQLInputObjectType({ const WITHIN_INPUT = new GraphQLInputObjectType({ name: 'WithinInput', description: - 'The WithinInput type is used to specify a $within operation on a constraint.', + 'The WithinInput type is used to specify a within operation on a constraint.', fields: { - _box: { + box: { description: 'This is the box to be specified.', type: new GraphQLNonNull(BOX_INPUT), }, @@ -633,7 +604,7 @@ const WITHIN_INPUT = new GraphQLInputObjectType({ const CENTER_SPHERE_INPUT = new GraphQLInputObjectType({ name: 'CenterSphereInput', description: - 'The CenterSphereInput type is used to specifiy a $centerSphere operation on a geoWithin query.', + 'The CenterSphereInput type is used to specifiy a centerSphere operation on a geoWithin query.', fields: { center: { description: 'This is the center of the sphere.', @@ -649,13 +620,13 @@ const CENTER_SPHERE_INPUT = new GraphQLInputObjectType({ const GEO_WITHIN_INPUT = new GraphQLInputObjectType({ name: 'GeoWithinInput', description: - 'The GeoWithinInput type is used to specify a $geoWithin operation on a constraint.', + 'The GeoWithinInput type is used to specify a geoWithin operation on a constraint.', fields: { - _polygon: { + polygon: { description: 'This is the polygon to be specified.', type: POLYGON_INPUT, }, - _centerSphere: { + centerSphere: { description: 'This is the sphere to be specified.', type: CENTER_SPHERE_INPUT, }, @@ -665,90 +636,90 @@ const GEO_WITHIN_INPUT = new GraphQLInputObjectType({ const GEO_INTERSECTS_INPUT = new GraphQLInputObjectType({ name: 'GeoIntersectsInput', description: - 'The GeoIntersectsInput type is used to specify a $geoIntersects operation on a constraint.', + 'The GeoIntersectsInput type is used to specify a geoIntersects operation on a constraint.', fields: { - _point: { + point: { description: 'This is the point to be specified.', type: GEO_POINT_INPUT, }, }, }); -const _eq = type => ({ +const equalTo = type => ({ description: - 'This is the $eq operator to specify a constraint to select the objects where the value of a field equals to a specified value.', + 'This is the equalTo operator to specify a constraint to select the objects where the value of a field equals to a specified value.', type, }); -const _ne = type => ({ +const notEqualTo = type => ({ description: - 'This is the $ne operator to specify a constraint to select the objects where the value of a field do not equal to a specified value.', + 'This is the notEqualTo operator to specify a constraint to select the objects where the value of a field do not equal to a specified value.', type, }); -const _lt = type => ({ +const lessThan = type => ({ description: - 'This is the $lt operator to specify a constraint to select the objects where the value of a field is less than a specified value.', + 'This is the lessThan operator to specify a constraint to select the objects where the value of a field is less than a specified value.', type, }); -const _lte = type => ({ +const lessThanOrEqualTo = type => ({ description: - 'This is the $lte operator to specify a constraint to select the objects where the value of a field is less than or equal to a specified value.', + 'This is the lessThanOrEqualTo operator to specify a constraint to select the objects where the value of a field is less than or equal to a specified value.', type, }); -const _gt = type => ({ +const greaterThan = type => ({ description: - 'This is the $gt operator to specify a constraint to select the objects where the value of a field is greater than a specified value.', + 'This is the greaterThan operator to specify a constraint to select the objects where the value of a field is greater than a specified value.', type, }); -const _gte = type => ({ +const greaterThanOrEqualTo = type => ({ description: - 'This is the $gte operator to specify a constraint to select the objects where the value of a field is greater than or equal to a specified value.', + 'This is the greaterThanOrEqualTo operator to specify a constraint to select the objects where the value of a field is greater than or equal to a specified value.', type, }); -const _in = type => ({ +const inOp = type => ({ description: - 'This is the $in operator to specify a constraint to select the objects where the value of a field equals any value in the specified array.', + 'This is the in operator to specify a constraint to select the objects where the value of a field equals any value in the specified array.', type: new GraphQLList(type), }); -const _nin = type => ({ +const notIn = type => ({ description: - 'This is the $nin operator to specify a constraint to select the objects where the value of a field do not equal any value in the specified array.', + 'This is the notIn operator to specify a constraint to select the objects where the value of a field do not equal any value in the specified array.', type: new GraphQLList(type), }); -const _exists = { +const exists = { description: - 'This is the $exists operator to specify a constraint to select the objects where a field exists (or do not exist).', + 'This is the exists operator to specify a constraint to select the objects where a field exists (or do not exist).', type: GraphQLBoolean, }; -const _select = { +const inQueryKey = { description: - 'This is the $select operator to specify a constraint to select the objects where a field equals to a key in the result of a different query.', + 'This is the inQueryKey operator to specify a constraint to select the objects where a field equals to a key in the result of a different query.', type: SELECT_INPUT, }; -const _dontSelect = { +const notInQueryKey = { description: - 'This is the $dontSelect operator to specify a constraint to select the objects where a field do not equal to a key in the result of a different query.', + 'This is the notInQueryKey operator to specify a constraint to select the objects where a field do not equal to a key in the result of a different query.', type: SELECT_INPUT, }; -const _regex = { +const matchesRegex = { description: - 'This is the $regex operator to specify a constraint to select the objects where the value of a field matches a specified regular expression.', + 'This is the matchesRegex operator to specify a constraint to select the objects where the value of a field matches a specified regular expression.', type: GraphQLString, }; -const _options = { +const options = { description: - 'This is the $options operator to specify optional flags (such as "i" and "m") to be added to a $regex operation in the same set of constraints.', + 'This is the options operator to specify optional flags (such as "i" and "m") to be added to a matchesRegex operation in the same set of constraints.', type: GraphQLString, }; @@ -757,20 +728,20 @@ const STRING_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The StringWhereInput input type is used in operations that involve filtering objects by a field of type String.', fields: { - _eq: _eq(GraphQLString), - _ne: _ne(GraphQLString), - _lt: _lt(GraphQLString), - _lte: _lte(GraphQLString), - _gt: _gt(GraphQLString), - _gte: _gte(GraphQLString), - _in: _in(GraphQLString), - _nin: _nin(GraphQLString), - _exists, - _select, - _dontSelect, - _regex, - _options, - _text: { + equalTo: equalTo(GraphQLString), + notEqualTo: notEqualTo(GraphQLString), + lessThan: lessThan(GraphQLString), + lessThanOrEqualTo: lessThanOrEqualTo(GraphQLString), + greaterThan: greaterThan(GraphQLString), + greaterThanOrEqualTo: greaterThanOrEqualTo(GraphQLString), + in: inOp(GraphQLString), + notIn: notIn(GraphQLString), + exists, + inQueryKey, + notInQueryKey, + matchesRegex, + options, + text: { description: 'This is the $text operator to specify a full text search constraint.', type: TEXT_INPUT, @@ -783,17 +754,17 @@ const NUMBER_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The NumberWhereInput input type is used in operations that involve filtering objects by a field of type Number.', fields: { - _eq: _eq(GraphQLFloat), - _ne: _ne(GraphQLFloat), - _lt: _lt(GraphQLFloat), - _lte: _lte(GraphQLFloat), - _gt: _gt(GraphQLFloat), - _gte: _gte(GraphQLFloat), - _in: _in(GraphQLFloat), - _nin: _nin(GraphQLFloat), - _exists, - _select, - _dontSelect, + equalTo: equalTo(GraphQLFloat), + notEqualTo: notEqualTo(GraphQLFloat), + lessThan: lessThan(GraphQLFloat), + lessThanOrEqualTo: lessThanOrEqualTo(GraphQLFloat), + greaterThan: greaterThan(GraphQLFloat), + greaterThanOrEqualTo: greaterThanOrEqualTo(GraphQLFloat), + in: inOp(GraphQLFloat), + notIn: notIn(GraphQLFloat), + exists, + inQueryKey, + notInQueryKey, }, }); @@ -802,11 +773,11 @@ const BOOLEAN_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The BooleanWhereInput input type is used in operations that involve filtering objects by a field of type Boolean.', fields: { - _eq: _eq(GraphQLBoolean), - _ne: _ne(GraphQLBoolean), - _exists, - _select, - _dontSelect, + equalTo: equalTo(GraphQLBoolean), + notEqualTo: notEqualTo(GraphQLBoolean), + exists, + inQueryKey, + notInQueryKey, }, }); @@ -815,25 +786,25 @@ const ARRAY_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The ArrayWhereInput input type is used in operations that involve filtering objects by a field of type Array.', fields: { - _eq: _eq(ANY), - _ne: _ne(ANY), - _lt: _lt(ANY), - _lte: _lte(ANY), - _gt: _gt(ANY), - _gte: _gte(ANY), - _in: _in(ANY), - _nin: _nin(ANY), - _exists, - _select, - _dontSelect, - _containedBy: { + equalTo: equalTo(ANY), + notEqualTo: notEqualTo(ANY), + lessThan: lessThan(ANY), + lessThanOrEqualTo: lessThanOrEqualTo(ANY), + greaterThan: greaterThan(ANY), + greaterThanOrEqualTo: greaterThanOrEqualTo(ANY), + in: inOp(ANY), + notIn: notIn(ANY), + exists, + inQueryKey, + notInQueryKey, + containedBy: { description: - 'This is the $containedBy operator to specify a constraint to select the objects where the values of an array field is contained by another specified array.', + 'This is the containedBy operator to specify a constraint to select the objects where the values of an array field is contained by another specified array.', type: new GraphQLList(ANY), }, - _all: { + contains: { description: - 'This is the $all operator to specify a constraint to select the objects where the values of an array field contain all elements of another specified array.', + 'This is the contains operator to specify a constraint to select the objects where the values of an array field contain all elements of another specified array.', type: new GraphQLList(ANY), }, }, @@ -843,11 +814,11 @@ const KEY_VALUE_INPUT = new GraphQLInputObjectType({ name: 'KeyValueInput', description: 'An entry from an object, i.e., a pair of key and value.', fields: { - _key: { + key: { description: 'The key used to retrieve the value of this entry.', type: new GraphQLNonNull(GraphQLString), }, - _value: { + value: { description: 'The value of the entry. Could be any type of scalar data.', type: new GraphQLNonNull(ANY), }, @@ -859,17 +830,17 @@ const OBJECT_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The ObjectWhereInput input type is used in operations that involve filtering result by a field of type Object.', fields: { - _eq: _eq(KEY_VALUE_INPUT), - _ne: _ne(KEY_VALUE_INPUT), - _in: _in(KEY_VALUE_INPUT), - _nin: _nin(KEY_VALUE_INPUT), - _lt: _lt(KEY_VALUE_INPUT), - _lte: _lte(KEY_VALUE_INPUT), - _gt: _gt(KEY_VALUE_INPUT), - _gte: _gte(KEY_VALUE_INPUT), - _exists, - _select, - _dontSelect, + equalTo: equalTo(KEY_VALUE_INPUT), + notEqualTo: notEqualTo(KEY_VALUE_INPUT), + in: inOp(KEY_VALUE_INPUT), + notIn: notIn(KEY_VALUE_INPUT), + lessThan: lessThan(KEY_VALUE_INPUT), + lessThanOrEqualTo: lessThanOrEqualTo(KEY_VALUE_INPUT), + greaterThan: greaterThan(KEY_VALUE_INPUT), + greaterThanOrEqualTo: greaterThanOrEqualTo(KEY_VALUE_INPUT), + exists, + inQueryKey, + notInQueryKey, }, }); @@ -878,17 +849,17 @@ const DATE_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The DateWhereInput input type is used in operations that involve filtering objects by a field of type Date.', fields: { - _eq: _eq(DATE), - _ne: _ne(DATE), - _lt: _lt(DATE), - _lte: _lte(DATE), - _gt: _gt(DATE), - _gte: _gte(DATE), - _in: _in(DATE), - _nin: _nin(DATE), - _exists, - _select, - _dontSelect, + equalTo: equalTo(DATE), + notEqualTo: notEqualTo(DATE), + lessThan: lessThan(DATE), + lessThanOrEqualTo: lessThanOrEqualTo(DATE), + greaterThan: greaterThan(DATE), + greaterThanOrEqualTo: greaterThanOrEqualTo(DATE), + in: inOp(DATE), + notIn: notIn(DATE), + exists, + inQueryKey, + notInQueryKey, }, }); @@ -897,17 +868,17 @@ const BYTES_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The BytesWhereInput input type is used in operations that involve filtering objects by a field of type Bytes.', fields: { - _eq: _eq(BYTES), - _ne: _ne(BYTES), - _lt: _lt(BYTES), - _lte: _lte(BYTES), - _gt: _gt(BYTES), - _gte: _gte(BYTES), - _in: _in(BYTES), - _nin: _nin(BYTES), - _exists, - _select, - _dontSelect, + equalTo: equalTo(BYTES), + notEqualTo: notEqualTo(BYTES), + lessThan: lessThan(BYTES), + lessThanOrEqualTo: lessThanOrEqualTo(BYTES), + greaterThan: greaterThan(BYTES), + greaterThanOrEqualTo: greaterThanOrEqualTo(BYTES), + in: inOp(BYTES), + notIn: notIn(BYTES), + exists, + inQueryKey, + notInQueryKey, }, }); @@ -916,19 +887,19 @@ const FILE_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The FileWhereInput input type is used in operations that involve filtering objects by a field of type File.', fields: { - _eq: _eq(FILE), - _ne: _ne(FILE), - _lt: _lt(FILE), - _lte: _lte(FILE), - _gt: _gt(FILE), - _gte: _gte(FILE), - _in: _in(FILE), - _nin: _nin(FILE), - _exists, - _select, - _dontSelect, - _regex, - _options, + equalTo: equalTo(FILE), + notEqualTo: notEqualTo(FILE), + lessThan: lessThan(FILE), + lessThanOrEqualTo: lessThanOrEqualTo(FILE), + greaterThan: greaterThan(FILE), + greaterThanOrEqualTo: greaterThanOrEqualTo(FILE), + in: inOp(FILE), + notIn: notIn(FILE), + exists, + inQueryKey, + notInQueryKey, + matchesRegex, + options, }, }); @@ -937,40 +908,40 @@ const GEO_POINT_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The GeoPointWhereInput input type is used in operations that involve filtering objects by a field of type GeoPoint.', fields: { - _exists, - _nearSphere: { + exists, + nearSphere: { description: - 'This is the $nearSphere operator to specify a constraint to select the objects where the values of a geo point field is near to another geo point.', + 'This is the nearSphere operator to specify a constraint to select the objects where the values of a geo point field is near to another geo point.', type: GEO_POINT_INPUT, }, - _maxDistance: { + maxDistance: { description: - 'This is the $maxDistance operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', + 'This is the maxDistance operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', type: GraphQLFloat, }, - _maxDistanceInRadians: { + maxDistanceInRadians: { description: - 'This is the $maxDistanceInRadians operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', + 'This is the maxDistanceInRadians operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in radians) from the geo point specified in the $nearSphere operator.', type: GraphQLFloat, }, - _maxDistanceInMiles: { + maxDistanceInMiles: { description: - 'This is the $maxDistanceInMiles operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in miles) from the geo point specified in the $nearSphere operator.', + 'This is the maxDistanceInMiles operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in miles) from the geo point specified in the $nearSphere operator.', type: GraphQLFloat, }, - _maxDistanceInKilometers: { + maxDistanceInKilometers: { description: - 'This is the $maxDistanceInKilometers operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in kilometers) from the geo point specified in the $nearSphere operator.', + 'This is the maxDistanceInKilometers operator to specify a constraint to select the objects where the values of a geo point field is at a max distance (in kilometers) from the geo point specified in the $nearSphere operator.', type: GraphQLFloat, }, - _within: { + within: { description: - 'This is the $within operator to specify a constraint to select the objects where the values of a geo point field is within a specified box.', + 'This is the within operator to specify a constraint to select the objects where the values of a geo point field is within a specified box.', type: WITHIN_INPUT, }, - _geoWithin: { + geoWithin: { description: - 'This is the $geoWithin operator to specify a constraint to select the objects where the values of a geo point field is within a specified polygon or sphere.', + 'This is the geoWithin operator to specify a constraint to select the objects where the values of a geo point field is within a specified polygon or sphere.', type: GEO_WITHIN_INPUT, }, }, @@ -981,10 +952,10 @@ const POLYGON_WHERE_INPUT = new GraphQLInputObjectType({ description: 'The PolygonWhereInput input type is used in operations that involve filtering objects by a field of type Polygon.', fields: { - _exists, - _geoIntersects: { + exists, + geoIntersects: { description: - 'This is the $geoIntersects operator to specify a constraint to select the objects where the values of a polygon field intersect a specified point.', + 'This is the geoIntersects operator to specify a constraint to select the objects where the values of a polygon field intersect a specified point.', type: GEO_INTERSECTS_INPUT, }, }, @@ -1003,20 +974,9 @@ const FIND_RESULT = new GraphQLObjectType({ }, }); -const SIGN_UP_RESULT = new GraphQLObjectType({ - name: 'SignUpResult', - description: - 'The SignUpResult object type is used in the users sign up mutation to return the data of the recent created user.', - fields: { - ...CREATE_RESULT_FIELDS, - sessionToken: SESSION_TOKEN_ATT, - }, -}); - const ELEMENT = new GraphQLObjectType({ name: 'Element', - description: - 'The SignUpResult object type is used in the users sign up mutation to return the data of the recent created user.', + description: "The Element object type is used to return array items' value.", fields: { value: { description: 'Return the value of the element in the array', @@ -1072,8 +1032,6 @@ const load = parseGraphQLSchema => { parseGraphQLSchema.addGraphQLType(FILE_INFO, true); parseGraphQLSchema.addGraphQLType(GEO_POINT_INPUT, true); parseGraphQLSchema.addGraphQLType(GEO_POINT, true); - parseGraphQLSchema.addGraphQLType(CREATE_RESULT, true); - parseGraphQLSchema.addGraphQLType(UPDATE_RESULT, true); parseGraphQLSchema.addGraphQLType(PARSE_OBJECT, true); parseGraphQLSchema.addGraphQLType(READ_PREFERENCE, true); parseGraphQLSchema.addGraphQLType(SUBQUERY_INPUT, true); @@ -1097,7 +1055,6 @@ const load = parseGraphQLSchema => { parseGraphQLSchema.addGraphQLType(GEO_POINT_WHERE_INPUT, true); parseGraphQLSchema.addGraphQLType(POLYGON_WHERE_INPUT, true); parseGraphQLSchema.addGraphQLType(FIND_RESULT, true); - parseGraphQLSchema.addGraphQLType(SIGN_UP_RESULT, true); parseGraphQLSchema.addGraphQLType(ELEMENT, true); parseGraphQLSchema.addGraphQLType(OBJECT_ID, true); }; @@ -1127,21 +1084,16 @@ export { POLYGON, OBJECT_ID, CLASS_NAME_ATT, - FIELDS_ATT, OBJECT_ID_ATT, UPDATED_AT_ATT, CREATED_AT_ATT, ACL_ATT, INPUT_FIELDS, CREATE_RESULT_FIELDS, - CREATE_RESULT, UPDATE_RESULT_FIELDS, - UPDATE_RESULT, PARSE_OBJECT_FIELDS, PARSE_OBJECT, SESSION_TOKEN_ATT, - KEYS_ATT, - INCLUDE_ATT, READ_PREFERENCE, READ_PREFERENCE_ATT, INCLUDE_READ_PREFERENCE_ATT, @@ -1159,19 +1111,19 @@ export { CENTER_SPHERE_INPUT, GEO_WITHIN_INPUT, GEO_INTERSECTS_INPUT, - _eq, - _ne, - _lt, - _lte, - _gt, - _gte, - _in, - _nin, - _exists, - _select, - _dontSelect, - _regex, - _options, + equalTo, + notEqualTo, + lessThan, + lessThanOrEqualTo, + greaterThan, + greaterThanOrEqualTo, + inOp, + notIn, + exists, + inQueryKey, + notInQueryKey, + matchesRegex, + options, STRING_WHERE_INPUT, NUMBER_WHERE_INPUT, BOOLEAN_WHERE_INPUT, @@ -1184,7 +1136,6 @@ export { GEO_POINT_WHERE_INPUT, POLYGON_WHERE_INPUT, FIND_RESULT, - SIGN_UP_RESULT, ARRAY_RESULT, ELEMENT, load, diff --git a/src/GraphQL/loaders/parseClassTypes.js b/src/GraphQL/loaders/parseClassTypes.js index 69c529eb3a..b86bf9b264 100644 --- a/src/GraphQL/loaders/parseClassTypes.js +++ b/src/GraphQL/loaders/parseClassTypes.js @@ -341,21 +341,21 @@ const load = ( name: classGraphQLConstraintTypeName, description: `The ${classGraphQLConstraintTypeName} input type is used in operations that involve filtering objects by a pointer field to ${graphQLClassName} class.`, fields: { - _eq: defaultGraphQLTypes._eq(classGraphQLScalarType), - _ne: defaultGraphQLTypes._ne(classGraphQLScalarType), - _in: defaultGraphQLTypes._in(classGraphQLScalarType), - _nin: defaultGraphQLTypes._nin(classGraphQLScalarType), - _exists: defaultGraphQLTypes._exists, - _select: defaultGraphQLTypes._select, - _dontSelect: defaultGraphQLTypes._dontSelect, - _inQuery: { + equalTo: defaultGraphQLTypes.equalTo(classGraphQLScalarType), + notEqualTo: defaultGraphQLTypes.notEqualTo(classGraphQLScalarType), + in: defaultGraphQLTypes.inOp(classGraphQLScalarType), + notIn: defaultGraphQLTypes.notIn(classGraphQLScalarType), + exists: defaultGraphQLTypes.exists, + inQueryKey: defaultGraphQLTypes.inQueryKey, + notInQueryKey: defaultGraphQLTypes.notInQueryKey, + inQuery: { description: - 'This is the $inQuery operator to specify a constraint to select the objects where a field equals to any of the ids in the result of a different query.', + 'This is the inQuery operator to specify a constraint to select the objects where a field equals to any of the ids in the result of a different query.', type: defaultGraphQLTypes.SUBQUERY_INPUT, }, - _notInQuery: { + notInQuery: { description: - 'This is the $notInQuery operator to specify a constraint to select the objects where a field do not equal to any of the ids in the result of a different query.', + 'This is the notInQuery operator to specify a constraint to select the objects where a field do not equal to any of the ids in the result of a different query.', type: defaultGraphQLTypes.SUBQUERY_INPUT, }, }, @@ -370,6 +370,12 @@ const load = ( description: `The ${classGraphQLConstraintsTypeName} input type is used in operations that involve filtering objects of ${graphQLClassName} class.`, fields: () => ({ ...classConstraintFields.reduce((fields, field) => { + if (['OR', 'AND', 'NOR'].includes(field)) { + parseGraphQLSchema.log.warn( + `Field ${field} could not be added to the auto schema ${classGraphQLConstraintsTypeName} because it collided with an existing one.` + ); + return fields; + } const parseField = field === 'id' ? 'objectId' : field; const type = transformConstraintTypeToGraphQL( parseClass.fields[parseField].type, @@ -388,16 +394,16 @@ const load = ( return fields; } }, {}), - _or: { - description: 'This is the $or operator to compound constraints.', + OR: { + description: 'This is the OR operator to compound constraints.', type: new GraphQLList(new GraphQLNonNull(classGraphQLConstraintsType)), }, - _and: { - description: 'This is the $and operator to compound constraints.', + AND: { + description: 'This is the AND operator to compound constraints.', type: new GraphQLList(new GraphQLNonNull(classGraphQLConstraintsType)), }, - _nor: { - description: 'This is the $nor operator to compound constraints.', + NOR: { + description: 'This is the NOR operator to compound constraints.', type: new GraphQLList(new GraphQLNonNull(classGraphQLConstraintsType)), }, }), @@ -491,7 +497,7 @@ const load = ( return await objectsQueries.findObjects( source[field].className, { - _relatedTo: { + $relatedTo: { object: { __type: 'Pointer', className: className, diff --git a/src/GraphQL/transformers/query.js b/src/GraphQL/transformers/query.js index b33208c61a..06c4c0f1d6 100644 --- a/src/GraphQL/transformers/query.js +++ b/src/GraphQL/transformers/query.js @@ -1,54 +1,53 @@ -const parseMap = { +const parseQueryMap = { id: 'objectId', - _or: '$or', - _and: '$and', - _nor: '$nor', - _relatedTo: '$relatedTo', - _eq: '$eq', - _ne: '$ne', - _lt: '$lt', - _lte: '$lte', - _gt: '$gt', - _gte: '$gte', - _in: '$in', - _nin: '$nin', - _exists: '$exists', - _select: '$select', - _dontSelect: '$dontSelect', - _inQuery: '$inQuery', - _notInQuery: '$notInQuery', - _containedBy: '$containedBy', - _all: '$all', - _regex: '$regex', - _options: '$options', - _text: '$text', - _search: '$search', - _term: '$term', - _language: '$language', - _caseSensitive: '$caseSensitive', - _diacriticSensitive: '$diacriticSensitive', - _nearSphere: '$nearSphere', - _maxDistance: '$maxDistance', - _maxDistanceInRadians: '$maxDistanceInRadians', - _maxDistanceInMiles: '$maxDistanceInMiles', - _maxDistanceInKilometers: '$maxDistanceInKilometers', - _within: '$within', - _box: '$box', - _geoWithin: '$geoWithin', - _polygon: '$polygon', - _centerSphere: '$centerSphere', - _geoIntersects: '$geoIntersects', - _point: '$point', + OR: '$or', + AND: '$and', + NOR: '$nor', }; -const transformQueryInputToParse = ( +const parseConstraintMap = { + equalTo: '$eq', + notEqualTo: '$ne', + lessThan: '$lt', + lessThanOrEqualTo: '$lte', + greaterThan: '$gt', + greaterThanOrEqualTo: '$gte', + in: '$in', + notIn: '$nin', + exists: '$exists', + inQueryKey: '$select', + notInQueryKey: '$dontSelect', + inQuery: '$inQuery', + notInQuery: '$notInQuery', + containedBy: '$containedBy', + contains: '$all', + matchesRegex: '$regex', + options: '$options', + text: '$text', + search: '$search', + term: '$term', + language: '$language', + caseSensitive: '$caseSensitive', + diacriticSensitive: '$diacriticSensitive', + nearSphere: '$nearSphere', + maxDistance: '$maxDistance', + maxDistanceInRadians: '$maxDistanceInRadians', + maxDistanceInMiles: '$maxDistanceInMiles', + maxDistanceInKilometers: '$maxDistanceInKilometers', + within: '$within', + box: '$box', + geoWithin: '$geoWithin', + polygon: '$polygon', + centerSphere: '$centerSphere', + geoIntersects: '$geoIntersects', + point: '$point', +}; + +const transformQueryConstraintInputToParse = ( constraints, parentFieldName, parentConstraints ) => { - if (!constraints || typeof constraints !== 'object') { - return; - } Object.keys(constraints).forEach(fieldName => { let fieldValue = constraints[fieldName]; @@ -59,13 +58,13 @@ const transformQueryInputToParse = ( * From: * { * "someField": { - * "_lt": { - * "_key":"foo.bar", - * "_value": 100 + * "lessThan": { + * "key":"foo.bar", + * "value": 100 * }, - * "_gt": { - * "_key":"foo.bar", - * "_value": 10 + * "greaterThan": { + * "key":"foo.bar", + * "value": 10 * } * } * } @@ -79,19 +78,19 @@ const transformQueryInputToParse = ( * } */ if ( - fieldValue._key && - fieldValue._value && + fieldValue.key && + fieldValue.value && parentConstraints && parentFieldName ) { delete parentConstraints[parentFieldName]; - parentConstraints[`${parentFieldName}.${fieldValue._key}`] = { - ...parentConstraints[`${parentFieldName}.${fieldValue._key}`], - [parseMap[fieldName]]: fieldValue._value, + parentConstraints[`${parentFieldName}.${fieldValue.key}`] = { + ...parentConstraints[`${parentFieldName}.${fieldValue.key}`], + [parseConstraintMap[fieldName]]: fieldValue.value, }; - } else if (parseMap[fieldName]) { + } else if (parseConstraintMap[fieldName]) { delete constraints[fieldName]; - fieldName = parseMap[fieldName]; + fieldName = parseConstraintMap[fieldName]; constraints[fieldName] = fieldValue; } switch (fieldName) { @@ -147,9 +146,44 @@ const transformQueryInputToParse = ( break; } if (typeof fieldValue === 'object') { - transformQueryInputToParse(fieldValue, fieldName, constraints); + if (fieldName === 'where') { + transformQueryInputToParse(fieldValue); + } else { + transformQueryConstraintInputToParse( + fieldValue, + fieldName, + constraints + ); + } + } + }); +}; + +const transformQueryInputToParse = constraints => { + if (!constraints || typeof constraints !== 'object') { + return; + } + + Object.keys(constraints).forEach(fieldName => { + const fieldValue = constraints[fieldName]; + + if (parseQueryMap[fieldName]) { + delete constraints[fieldName]; + fieldName = parseQueryMap[fieldName]; + constraints[fieldName] = fieldValue; + + if (fieldName !== 'objectId') { + fieldValue.forEach(fieldValueItem => { + transformQueryInputToParse(fieldValueItem); + }); + return; + } + } + + if (typeof fieldValue === 'object') { + transformQueryConstraintInputToParse(fieldValue, fieldName, constraints); } }); }; -export { transformQueryInputToParse }; +export { transformQueryConstraintInputToParse, transformQueryInputToParse };