Skip to content

Commit 21b474c

Browse files
committed
Client mutation id on updateClass mutation
1 parent 204dfff commit 21b474c

File tree

2 files changed

+188
-107
lines changed

2 files changed

+188
-107
lines changed

spec/ParseGraphQLServer.spec.js

Lines changed: 134 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,46 @@ describe('ParseGraphQLServer', () => {
10191019

10201020
expect(payloadFields).toEqual(['class', 'clientMutationId']);
10211021
});
1022+
1023+
it('should have clientMutationId in updateClass mutation input', async () => {
1024+
const inputFields = (await apolloClient.query({
1025+
query: gql`
1026+
query {
1027+
__type(name: "UpdateClassInput") {
1028+
inputFields {
1029+
name
1030+
}
1031+
}
1032+
}
1033+
`,
1034+
})).data['__type'].inputFields
1035+
.map(field => field.name)
1036+
.sort();
1037+
1038+
expect(inputFields).toEqual([
1039+
'clientMutationId',
1040+
'name',
1041+
'schemaFields',
1042+
]);
1043+
});
1044+
1045+
it('should have clientMutationId in updateClass mutation payload', async () => {
1046+
const payloadFields = (await apolloClient.query({
1047+
query: gql`
1048+
query {
1049+
__type(name: "UpdateClassPayload") {
1050+
fields {
1051+
name
1052+
}
1053+
}
1054+
}
1055+
`,
1056+
})).data['__type'].fields
1057+
.map(field => field.name)
1058+
.sort();
1059+
1060+
expect(payloadFields).toEqual(['class', 'clientMutationId']);
1061+
});
10221062
});
10231063

10241064
describe('Parse Class Types', () => {
@@ -3010,6 +3050,7 @@ describe('ParseGraphQLServer', () => {
30103050

30113051
it('should update an existing class', async () => {
30123052
try {
3053+
const clientMutationId = uuidv4();
30133054
const result = await apolloClient.mutate({
30143055
mutation: gql`
30153056
mutation {
@@ -3027,7 +3068,8 @@ describe('ParseGraphQLServer', () => {
30273068
}
30283069
}
30293070
}
3030-
updateClass(
3071+
updateClass(input: {
3072+
clientMutationId: "${clientMutationId}"
30313073
name: "MyNewClass"
30323074
schemaFields: {
30333075
addStrings: [
@@ -3102,16 +3144,19 @@ describe('ParseGraphQLServer', () => {
31023144
{ name: "doesNotExist" }
31033145
]
31043146
}
3105-
) {
3106-
name
3107-
schemaFields {
3147+
}) {
3148+
clientMutationId
3149+
class {
31083150
name
3109-
__typename
3110-
... on SchemaPointerField {
3111-
targetClassName
3112-
}
3113-
... on SchemaRelationField {
3114-
targetClassName
3151+
schemaFields {
3152+
name
3153+
__typename
3154+
... on SchemaPointerField {
3155+
targetClassName
3156+
}
3157+
... on SchemaRelationField {
3158+
targetClassName
3159+
}
31153160
}
31163161
}
31173162
}
@@ -3126,7 +3171,7 @@ describe('ParseGraphQLServer', () => {
31263171
result.data.createClass.class.schemaFields = result.data.createClass.class.schemaFields.sort(
31273172
(a, b) => (a.name > b.name ? 1 : -1)
31283173
);
3129-
result.data.updateClass.schemaFields = result.data.updateClass.schemaFields.sort(
3174+
result.data.updateClass.class.schemaFields = result.data.updateClass.class.schemaFields.sort(
31303175
(a, b) => (a.name > b.name ? 1 : -1)
31313176
);
31323177
expect(result).toEqual({
@@ -3149,56 +3194,72 @@ describe('ParseGraphQLServer', () => {
31493194
__typename: 'CreateClassPayload',
31503195
},
31513196
updateClass: {
3152-
name: 'MyNewClass',
3153-
schemaFields: [
3154-
{ name: 'ACL', __typename: 'SchemaACLField' },
3155-
{ name: 'arrayField1', __typename: 'SchemaArrayField' },
3156-
{ name: 'arrayField2', __typename: 'SchemaArrayField' },
3157-
{ name: 'booleanField1', __typename: 'SchemaBooleanField' },
3158-
{ name: 'booleanField2', __typename: 'SchemaBooleanField' },
3159-
{ name: 'bytesField1', __typename: 'SchemaBytesField' },
3160-
{ name: 'bytesField2', __typename: 'SchemaBytesField' },
3161-
{ name: 'createdAt', __typename: 'SchemaDateField' },
3162-
{ name: 'dateField1', __typename: 'SchemaDateField' },
3163-
{ name: 'dateField2', __typename: 'SchemaDateField' },
3164-
{ name: 'fileField1', __typename: 'SchemaFileField' },
3165-
{ name: 'fileField2', __typename: 'SchemaFileField' },
3166-
{
3167-
name: 'geoPointField',
3168-
__typename: 'SchemaGeoPointField',
3169-
},
3170-
{ name: 'numberField1', __typename: 'SchemaNumberField' },
3171-
{ name: 'numberField2', __typename: 'SchemaNumberField' },
3172-
{ name: 'objectField1', __typename: 'SchemaObjectField' },
3173-
{ name: 'objectField2', __typename: 'SchemaObjectField' },
3174-
{ name: 'objectId', __typename: 'SchemaStringField' },
3175-
{
3176-
name: 'pointerField1',
3177-
__typename: 'SchemaPointerField',
3178-
targetClassName: 'Class1',
3179-
},
3180-
{
3181-
name: 'pointerField2',
3182-
__typename: 'SchemaPointerField',
3183-
targetClassName: 'Class6',
3184-
},
3185-
{ name: 'polygonField1', __typename: 'SchemaPolygonField' },
3186-
{ name: 'polygonField2', __typename: 'SchemaPolygonField' },
3187-
{
3188-
name: 'relationField1',
3189-
__typename: 'SchemaRelationField',
3190-
targetClassName: 'Class1',
3191-
},
3192-
{
3193-
name: 'relationField2',
3194-
__typename: 'SchemaRelationField',
3195-
targetClassName: 'Class6',
3196-
},
3197-
{ name: 'stringField1', __typename: 'SchemaStringField' },
3198-
{ name: 'stringField2', __typename: 'SchemaStringField' },
3199-
{ name: 'updatedAt', __typename: 'SchemaDateField' },
3200-
],
3201-
__typename: 'Class',
3197+
clientMutationId,
3198+
class: {
3199+
name: 'MyNewClass',
3200+
schemaFields: [
3201+
{ name: 'ACL', __typename: 'SchemaACLField' },
3202+
{ name: 'arrayField1', __typename: 'SchemaArrayField' },
3203+
{ name: 'arrayField2', __typename: 'SchemaArrayField' },
3204+
{
3205+
name: 'booleanField1',
3206+
__typename: 'SchemaBooleanField',
3207+
},
3208+
{
3209+
name: 'booleanField2',
3210+
__typename: 'SchemaBooleanField',
3211+
},
3212+
{ name: 'bytesField1', __typename: 'SchemaBytesField' },
3213+
{ name: 'bytesField2', __typename: 'SchemaBytesField' },
3214+
{ name: 'createdAt', __typename: 'SchemaDateField' },
3215+
{ name: 'dateField1', __typename: 'SchemaDateField' },
3216+
{ name: 'dateField2', __typename: 'SchemaDateField' },
3217+
{ name: 'fileField1', __typename: 'SchemaFileField' },
3218+
{ name: 'fileField2', __typename: 'SchemaFileField' },
3219+
{
3220+
name: 'geoPointField',
3221+
__typename: 'SchemaGeoPointField',
3222+
},
3223+
{ name: 'numberField1', __typename: 'SchemaNumberField' },
3224+
{ name: 'numberField2', __typename: 'SchemaNumberField' },
3225+
{ name: 'objectField1', __typename: 'SchemaObjectField' },
3226+
{ name: 'objectField2', __typename: 'SchemaObjectField' },
3227+
{ name: 'objectId', __typename: 'SchemaStringField' },
3228+
{
3229+
name: 'pointerField1',
3230+
__typename: 'SchemaPointerField',
3231+
targetClassName: 'Class1',
3232+
},
3233+
{
3234+
name: 'pointerField2',
3235+
__typename: 'SchemaPointerField',
3236+
targetClassName: 'Class6',
3237+
},
3238+
{
3239+
name: 'polygonField1',
3240+
__typename: 'SchemaPolygonField',
3241+
},
3242+
{
3243+
name: 'polygonField2',
3244+
__typename: 'SchemaPolygonField',
3245+
},
3246+
{
3247+
name: 'relationField1',
3248+
__typename: 'SchemaRelationField',
3249+
targetClassName: 'Class1',
3250+
},
3251+
{
3252+
name: 'relationField2',
3253+
__typename: 'SchemaRelationField',
3254+
targetClassName: 'Class6',
3255+
},
3256+
{ name: 'stringField1', __typename: 'SchemaStringField' },
3257+
{ name: 'stringField2', __typename: 'SchemaStringField' },
3258+
{ name: 'updatedAt', __typename: 'SchemaDateField' },
3259+
],
3260+
__typename: 'Class',
3261+
},
3262+
__typename: 'UpdateClassPayload',
32023263
},
32033264
},
32043265
});
@@ -3313,8 +3374,8 @@ describe('ParseGraphQLServer', () => {
33133374
await apolloClient.mutate({
33143375
mutation: gql`
33153376
mutation {
3316-
updateClass(name: "SomeClass") {
3317-
name
3377+
updateClass(input: { name: "SomeClass" }) {
3378+
clientMutationId
33183379
}
33193380
}
33203381
`,
@@ -3360,10 +3421,12 @@ describe('ParseGraphQLServer', () => {
33603421
mutation: gql`
33613422
mutation {
33623423
updateClass(
3363-
name: "SomeClass"
3364-
schemaFields: { addNumbers: [{ name: "someField" }] }
3424+
input: {
3425+
name: "SomeClass"
3426+
schemaFields: { addNumbers: [{ name: "someField" }] }
3427+
}
33653428
) {
3366-
name
3429+
clientMutationId
33673430
}
33683431
}
33693432
`,
@@ -3390,10 +3453,12 @@ describe('ParseGraphQLServer', () => {
33903453
mutation: gql`
33913454
mutation {
33923455
updateClass(
3393-
name: "SomeInexistentClass"
3394-
schemaFields: { addNumbers: [{ name: "someField" }] }
3456+
input: {
3457+
name: "SomeInexistentClass"
3458+
schemaFields: { addNumbers: [{ name: "someField" }] }
3459+
}
33953460
) {
3396-
name
3461+
clientMutationId
33973462
}
33983463
}
33993464
`,

src/GraphQL/loaders/schemaMutations.js

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -71,51 +71,67 @@ const load = parseGraphQLSchema => {
7171
true
7272
);
7373

74-
parseGraphQLSchema.addGraphQLMutation(
75-
'updateClass',
76-
{
77-
description:
78-
'The updateClass mutation can be used to update the schema for an existing object class.',
79-
args: {
80-
name: schemaTypes.CLASS_NAME_ATT,
81-
schemaFields: {
82-
description: "These are the schema's fields of the object class.",
83-
type: schemaTypes.SCHEMA_FIELDS_INPUT,
84-
},
74+
const updateClassMutation = mutationWithClientMutationId({
75+
name: 'UpdateClass',
76+
description:
77+
'The updateClass mutation can be used to update the schema for an existing object class.',
78+
inputFields: {
79+
name: schemaTypes.CLASS_NAME_ATT,
80+
schemaFields: {
81+
description: "These are the schema's fields of the object class.",
82+
type: schemaTypes.SCHEMA_FIELDS_INPUT,
8583
},
86-
type: new GraphQLNonNull(schemaTypes.CLASS),
87-
resolve: async (_source, args, context) => {
88-
try {
89-
const { name, schemaFields } = args;
90-
const { config, auth } = context;
91-
92-
enforceMasterKeyAccess(auth);
84+
},
85+
outputFields: {
86+
class: {
87+
description: 'This is the created class.',
88+
type: new GraphQLNonNull(schemaTypes.CLASS),
89+
},
90+
},
91+
mutateAndGetPayload: async (args, context) => {
92+
try {
93+
const { name, schemaFields } = args;
94+
const { config, auth } = context;
9395

94-
if (auth.isReadOnly) {
95-
throw new Parse.Error(
96-
Parse.Error.OPERATION_FORBIDDEN,
97-
"read-only masterKey isn't allowed to update a schema."
98-
);
99-
}
96+
enforceMasterKeyAccess(auth);
10097

101-
const schema = await config.database.loadSchema({ clearCache: true });
102-
const existingParseClass = await getClass(name, schema);
103-
const parseClass = await schema.updateClass(
104-
name,
105-
transformToParse(schemaFields, existingParseClass.fields),
106-
undefined,
107-
undefined,
108-
config.database
98+
if (auth.isReadOnly) {
99+
throw new Parse.Error(
100+
Parse.Error.OPERATION_FORBIDDEN,
101+
"read-only masterKey isn't allowed to update a schema."
109102
);
110-
return {
103+
}
104+
105+
const schema = await config.database.loadSchema({ clearCache: true });
106+
const existingParseClass = await getClass(name, schema);
107+
const parseClass = await schema.updateClass(
108+
name,
109+
transformToParse(schemaFields, existingParseClass.fields),
110+
undefined,
111+
undefined,
112+
config.database
113+
);
114+
return {
115+
class: {
111116
name: parseClass.className,
112117
schemaFields: transformToGraphQL(parseClass.fields),
113-
};
114-
} catch (e) {
115-
parseGraphQLSchema.handleError(e);
116-
}
117-
},
118+
},
119+
};
120+
} catch (e) {
121+
parseGraphQLSchema.handleError(e);
122+
}
118123
},
124+
});
125+
126+
parseGraphQLSchema.addGraphQLType(
127+
updateClassMutation.args.input.type.ofType,
128+
true,
129+
true
130+
);
131+
parseGraphQLSchema.addGraphQLType(updateClassMutation.type, true, true);
132+
parseGraphQLSchema.addGraphQLMutation(
133+
'updateClass',
134+
updateClassMutation,
119135
true,
120136
true
121137
);

0 commit comments

Comments
 (0)