Skip to content

Commit f9b77c1

Browse files
douglasmuraokadavimacedo
authored andcommitted
refactor(GraphQL): Pointer constraint input type as ID (#6020)
* refactor(GraphQL): Pointer constraint input type as ID Redefines the Pointer constraint input type from a custom scalar to a simple ID. * fix: PR review requested changes
1 parent 34f1bf3 commit f9b77c1

File tree

5 files changed

+68
-109
lines changed

5 files changed

+68
-109
lines changed

spec/ParseGraphQLServer.spec.js

+37-15
Original file line numberDiff line numberDiff line change
@@ -3384,11 +3384,7 @@ describe('ParseGraphQLServer', () => {
33843384
OR: [
33853385
{
33863386
pointerToUser: {
3387-
equalTo: {
3388-
__type: 'Pointer',
3389-
className: '_User',
3390-
objectId: user5.id,
3391-
},
3387+
equalTo: user5.id,
33923388
},
33933389
},
33943390
{
@@ -3413,6 +3409,40 @@ describe('ParseGraphQLServer', () => {
34133409
).toEqual(['someValue1', 'someValue3']);
34143410
});
34153411

3412+
it('should support in pointer operator using class specific query', async () => {
3413+
await prepareData();
3414+
3415+
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
3416+
3417+
const result = await apolloClient.query({
3418+
query: gql`
3419+
query FindSomeObjects($where: GraphQLClassWhereInput) {
3420+
graphQLClasses(where: $where) {
3421+
results {
3422+
someField
3423+
}
3424+
}
3425+
}
3426+
`,
3427+
variables: {
3428+
where: {
3429+
pointerToUser: {
3430+
in: [user5.id],
3431+
},
3432+
},
3433+
},
3434+
context: {
3435+
headers: {
3436+
'X-Parse-Master-Key': 'test',
3437+
},
3438+
},
3439+
});
3440+
3441+
const { results } = result.data.graphQLClasses;
3442+
expect(results.length).toBe(1);
3443+
expect(results[0].someField).toEqual('someValue3');
3444+
});
3445+
34163446
it('should support OR operation', async () => {
34173447
await prepareData();
34183448

@@ -3558,11 +3588,7 @@ describe('ParseGraphQLServer', () => {
35583588
OR: [
35593589
{
35603590
pointerToUser: {
3561-
equalTo: {
3562-
__type: 'Pointer',
3563-
className: '_User',
3564-
objectId: user5.id,
3565-
},
3591+
equalTo: user5.id,
35663592
},
35673593
},
35683594
{
@@ -3614,11 +3640,7 @@ describe('ParseGraphQLServer', () => {
36143640
OR: [
36153641
{
36163642
pointerToUser: {
3617-
equalTo: {
3618-
__type: 'Pointer',
3619-
className: '_User',
3620-
objectId: user5.id,
3621-
},
3643+
equalTo: user5.id,
36223644
},
36233645
},
36243646
{

src/GraphQL/helpers/objectsQueries.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ const findObjects = async (
6262
config,
6363
auth,
6464
info,
65-
selectedFields
65+
selectedFields,
66+
fields
6667
) => {
6768
if (!where) {
6869
where = {};
6970
}
70-
transformQueryInputToParse(where);
71+
transformQueryInputToParse(where, fields);
7172

7273
const options = {};
7374

src/GraphQL/loaders/parseClassQueries.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ const load = function(
120120
config,
121121
auth,
122122
info,
123-
selectedFields.map(field => field.split('.', 1)[0])
123+
selectedFields.map(field => field.split('.', 1)[0]),
124+
parseClass.fields
124125
);
125126
} catch (e) {
126127
parseGraphQLSchema.handleError(e);

src/GraphQL/loaders/parseClassTypes.js

+6-88
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import {
2-
Kind,
32
GraphQLID,
43
GraphQLObjectType,
54
GraphQLString,
65
GraphQLList,
76
GraphQLInputObjectType,
87
GraphQLNonNull,
9-
GraphQLScalarType,
108
GraphQLEnumType,
119
} from 'graphql';
1210
import getFieldNames from 'graphql-list-fields';
@@ -138,86 +136,6 @@ const load = (
138136
update: isUpdateEnabled = true,
139137
} = getParseClassMutationConfig(parseClassConfig);
140138

141-
const classGraphQLScalarTypeName = `${graphQLClassName}Pointer`;
142-
const parseScalarValue = value => {
143-
if (typeof value === 'string') {
144-
return {
145-
__type: 'Pointer',
146-
className: className,
147-
objectId: value,
148-
};
149-
} else if (
150-
typeof value === 'object' &&
151-
value.__type === 'Pointer' &&
152-
value.className === className &&
153-
typeof value.objectId === 'string'
154-
) {
155-
return { ...value, className };
156-
}
157-
158-
throw new defaultGraphQLTypes.TypeValidationError(
159-
value,
160-
classGraphQLScalarTypeName
161-
);
162-
};
163-
let classGraphQLScalarType = new GraphQLScalarType({
164-
name: classGraphQLScalarTypeName,
165-
description: `The ${classGraphQLScalarTypeName} is used in operations that involve ${graphQLClassName} pointers.`,
166-
parseValue: parseScalarValue,
167-
serialize(value) {
168-
if (typeof value === 'string') {
169-
return value;
170-
} else if (
171-
typeof value === 'object' &&
172-
value.__type === 'Pointer' &&
173-
value.className === className &&
174-
typeof value.objectId === 'string'
175-
) {
176-
return value.objectId;
177-
}
178-
179-
throw new defaultGraphQLTypes.TypeValidationError(
180-
value,
181-
classGraphQLScalarTypeName
182-
);
183-
},
184-
parseLiteral(ast) {
185-
if (ast.kind === Kind.STRING) {
186-
return parseScalarValue(ast.value);
187-
} else if (ast.kind === Kind.OBJECT) {
188-
const __type = ast.fields.find(field => field.name.value === '__type');
189-
const className = ast.fields.find(
190-
field => field.name.value === 'className'
191-
);
192-
const objectId = ast.fields.find(
193-
field => field.name.value === 'objectId'
194-
);
195-
if (
196-
__type &&
197-
__type.value &&
198-
className &&
199-
className.value &&
200-
objectId &&
201-
objectId.value
202-
) {
203-
return parseScalarValue({
204-
__type: __type.value.value,
205-
className: className.value.value,
206-
objectId: objectId.value.value,
207-
});
208-
}
209-
}
210-
211-
throw new defaultGraphQLTypes.TypeValidationError(
212-
ast.kind,
213-
classGraphQLScalarTypeName
214-
);
215-
},
216-
});
217-
classGraphQLScalarType =
218-
parseGraphQLSchema.addGraphQLType(classGraphQLScalarType) ||
219-
defaultGraphQLTypes.OBJECT;
220-
221139
const classGraphQLCreateTypeName = `Create${graphQLClassName}FieldsInput`;
222140
let classGraphQLCreateType = new GraphQLInputObjectType({
223141
name: classGraphQLCreateTypeName,
@@ -341,10 +259,10 @@ const load = (
341259
name: classGraphQLConstraintTypeName,
342260
description: `The ${classGraphQLConstraintTypeName} input type is used in operations that involve filtering objects by a pointer field to ${graphQLClassName} class.`,
343261
fields: {
344-
equalTo: defaultGraphQLTypes.equalTo(classGraphQLScalarType),
345-
notEqualTo: defaultGraphQLTypes.notEqualTo(classGraphQLScalarType),
346-
in: defaultGraphQLTypes.inOp(classGraphQLScalarType),
347-
notIn: defaultGraphQLTypes.notIn(classGraphQLScalarType),
262+
equalTo: defaultGraphQLTypes.equalTo(GraphQLID),
263+
notEqualTo: defaultGraphQLTypes.notEqualTo(GraphQLID),
264+
in: defaultGraphQLTypes.inOp(defaultGraphQLTypes.OBJECT_ID),
265+
notIn: defaultGraphQLTypes.notIn(defaultGraphQLTypes.OBJECT_ID),
348266
exists: defaultGraphQLTypes.exists,
349267
inQueryKey: defaultGraphQLTypes.inQueryKey,
350268
notInQueryKey: defaultGraphQLTypes.notInQueryKey,
@@ -519,7 +437,8 @@ const load = (
519437
config,
520438
auth,
521439
info,
522-
selectedFields.map(field => field.split('.', 1)[0])
440+
selectedFields.map(field => field.split('.', 1)[0]),
441+
parseClass.fields
523442
);
524443
} catch (e) {
525444
parseGraphQLSchema.handleError(e);
@@ -615,7 +534,6 @@ const load = (
615534
parseGraphQLSchema.parseClassTypes[className] = {
616535
classGraphQLPointerType,
617536
classGraphQLRelationType,
618-
classGraphQLScalarType,
619537
classGraphQLCreateType,
620538
classGraphQLUpdateType,
621539
classGraphQLConstraintType,

src/GraphQL/transformers/query.js

+20-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const parseConstraintMap = {
4545

4646
const transformQueryConstraintInputToParse = (
4747
constraints,
48+
fields,
4849
parentFieldName,
4950
parentConstraints
5051
) => {
@@ -92,6 +93,21 @@ const transformQueryConstraintInputToParse = (
9293
delete constraints[fieldName];
9394
fieldName = parseConstraintMap[fieldName];
9495
constraints[fieldName] = fieldValue;
96+
97+
// If parent field type is Pointer, changes constraint value to format expected
98+
// by Parse.
99+
if (
100+
fields[parentFieldName] &&
101+
fields[parentFieldName].type === 'Pointer' &&
102+
typeof fieldValue === 'string'
103+
) {
104+
const { targetClass } = fields[parentFieldName];
105+
constraints[fieldName] = {
106+
__type: 'Pointer',
107+
className: targetClass,
108+
objectId: fieldValue,
109+
};
110+
}
95111
}
96112
switch (fieldName) {
97113
case '$point':
@@ -151,6 +167,7 @@ const transformQueryConstraintInputToParse = (
151167
} else {
152168
transformQueryConstraintInputToParse(
153169
fieldValue,
170+
fields,
154171
fieldName,
155172
constraints
156173
);
@@ -159,7 +176,7 @@ const transformQueryConstraintInputToParse = (
159176
});
160177
};
161178

162-
const transformQueryInputToParse = constraints => {
179+
const transformQueryInputToParse = (constraints, fields) => {
163180
if (!constraints || typeof constraints !== 'object') {
164181
return;
165182
}
@@ -174,14 +191,14 @@ const transformQueryInputToParse = constraints => {
174191

175192
if (fieldName !== 'objectId') {
176193
fieldValue.forEach(fieldValueItem => {
177-
transformQueryInputToParse(fieldValueItem);
194+
transformQueryInputToParse(fieldValueItem, fields);
178195
});
179196
return;
180197
}
181198
}
182199

183200
if (typeof fieldValue === 'object') {
184-
transformQueryConstraintInputToParse(fieldValue, fieldName, constraints);
201+
transformQueryConstraintInputToParse(fieldValue, fields, fieldName, constraints);
185202
}
186203
});
187204
};

0 commit comments

Comments
 (0)