From 0115951b68ba94d596cc1a47747f59363d809992 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 27 Jan 2020 12:06:19 +0100 Subject: [PATCH 1/5] wip --- src/GraphQL/loaders/usersMutations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GraphQL/loaders/usersMutations.js b/src/GraphQL/loaders/usersMutations.js index a25db157e1..3c95bcda1c 100644 --- a/src/GraphQL/loaders/usersMutations.js +++ b/src/GraphQL/loaders/usersMutations.js @@ -16,7 +16,7 @@ const load = parseGraphQLSchema => { description: 'The signUp mutation can be used to create and sign up a new user.', inputFields: { - userFields: { + fields: { descriptions: 'These are the fields of the new user to be created and signed up.', type: From 3a18acc42d59c464c364f67a42f0614d4e00b26b Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 27 Jan 2020 15:26:42 +0100 Subject: [PATCH 2/5] wip --- src/GraphQL/loaders/usersMutations.js | 104 +++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/src/GraphQL/loaders/usersMutations.js b/src/GraphQL/loaders/usersMutations.js index 3c95bcda1c..fd5fd92dae 100644 --- a/src/GraphQL/loaders/usersMutations.js +++ b/src/GraphQL/loaders/usersMutations.js @@ -1,7 +1,13 @@ -import { GraphQLNonNull, GraphQLString, GraphQLBoolean } from 'graphql'; +import { + GraphQLNonNull, + GraphQLString, + GraphQLBoolean, + GraphQLInputObjectType, +} from 'graphql'; import { mutationWithClientMutationId } from 'graphql-relay'; import UsersRouter from '../../Routers/UsersRouter'; import * as objectsMutations from '../helpers/objectsMutations'; +import { OBJECT } from './defaultGraphQLTypes'; import { getUserFromSessionToken } from './usersQueries'; const usersRouter = new UsersRouter(); @@ -32,12 +38,12 @@ const load = parseGraphQLSchema => { }, mutateAndGetPayload: async (args, context, mutationInfo) => { try { - const { userFields } = args; + const { fields } = args; const { config, auth, info } = context; const { sessionToken } = await objectsMutations.createObject( '_User', - userFields, + fields, config, auth, info @@ -67,6 +73,98 @@ const load = parseGraphQLSchema => { ); parseGraphQLSchema.addGraphQLType(signUpMutation.type, true, true); parseGraphQLSchema.addGraphQLMutation('signUp', signUpMutation, true, true); + console.log( + 'Class', + parseGraphQLSchema.parseClassTypes['_User'].classGraphQLCreateType._fields + ); + const logInWithMutation = mutationWithClientMutationId({ + name: 'LoginWith', + description: + 'The loginWith mutation can be used to signup, login user with 3rd party authentication system. This mutation create a user if the authData do not correspond to an existing one.', + inputFields: { + authData: { + descriptions: 'This is the auth data of your custom auth provider', + type: new GraphQLNonNull(OBJECT), + }, + fields: { + descriptions: + 'These are the fields of the user to be created/updated and logged in.', + type: new GraphQLInputObjectType({ + name: 'UserLoginWihInput', + fields: () => { + const classGraphQLCreateFields = parseGraphQLSchema.parseClassTypes[ + '_User' + ].classGraphQLCreateType._fields() + Object.keys( + parseGraphQLSchema.parseClassTypes[ + '_User' + ].classGraphQLCreateType._fields() + ).reduce((fields, fieldName) => { + if ( + fieldName !== 'password' && + fieldName !== 'username' && + fieldName !== 'authData' + ) { + fields[fieldName] = + parseGraphQLSchema.parseClassTypes[ + '_User' + ].classGraphQLCreateType._fields[fieldName]; + } + console.log(fields); + return fields; + }, {}), + }), + }, + }, + outputFields: { + viewer: { + description: + 'This is the new user that was created, signed up and returned as a viewer.', + type: new GraphQLNonNull(parseGraphQLSchema.viewerType), + }, + }, + mutateAndGetPayload: async (args, context, mutationInfo) => { + try { + const { fields, authData } = args; + const { config, auth, info } = context; + + const { sessionToken } = await objectsMutations.createObject( + '_User', + { ...fields, authData }, + config, + auth, + info + ); + + info.sessionToken = sessionToken; + + return { + viewer: await getUserFromSessionToken( + config, + info, + mutationInfo, + 'viewer.user.', + true + ), + }; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + }, + }); + + parseGraphQLSchema.addGraphQLType( + logInWithMutation.args.input.type.ofType, + true, + true + ); + parseGraphQLSchema.addGraphQLType(logInWithMutation.type, true, true); + parseGraphQLSchema.addGraphQLMutation( + 'loginWith', + logInWithMutation, + true, + true + ); const logInMutation = mutationWithClientMutationId({ name: 'LogIn', From cf0d4dff98d269d1f9b45867fb2f39c708f5f7f9 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 27 Jan 2020 16:46:07 +0100 Subject: [PATCH 3/5] tested --- spec/ParseGraphQLServer.spec.js | 62 ++++++++++++++++++++++++++- src/GraphQL/loaders/usersMutations.js | 46 ++++++++------------ 2 files changed, 79 insertions(+), 29 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 83c40b9fc4..4ad5249792 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -4,6 +4,7 @@ const req = require('../lib/request'); const fetch = require('node-fetch'); const FormData = require('form-data'); const ws = require('ws'); +require('./helper'); const pluralize = require('pluralize'); const { getMainDefinition } = require('apollo-utilities'); const { ApolloLink, split } = require('apollo-link'); @@ -907,7 +908,7 @@ describe('ParseGraphQLServer', () => { .map(field => field.name) .sort(); - expect(inputFields).toEqual(['clientMutationId', 'userFields']); + expect(inputFields).toEqual(['clientMutationId', 'fields']); }); it('should have clientMutationId in sign up mutation payload', async () => { @@ -7114,7 +7115,7 @@ describe('ParseGraphQLServer', () => { variables: { input: { clientMutationId, - userFields: { + fields: { username: 'user1', password: 'user1', someField: 'someValue', @@ -7129,6 +7130,63 @@ describe('ParseGraphQLServer', () => { expect(typeof result.data.signUp.viewer.sessionToken).toBe('string'); }); + it('should login with user', async () => { + const clientMutationId = uuidv4(); + const userSchema = new Parse.Schema('_User'); + parseServer = await global.reconfigureServer({ + publicServerURL: 'http://localhost:13377/parse', + auth: { + myAuth: { + module: global.mockCustomAuthenticator('parse', 'graphql'), + }, + }, + }); + + userSchema.addString('someField'); + await userSchema.update(); + await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); + const result = await apolloClient.mutate({ + mutation: gql` + mutation LogInWith($input: LogInWithInput!) { + logInWith(input: $input) { + clientMutationId + viewer { + sessionToken + user { + someField + } + } + } + } + `, + variables: { + input: { + clientMutationId, + authData: { + myAuth: { + id: 'parse', + password: 'graphql', + }, + }, + fields: { + someField: 'someValue', + }, + }, + }, + }); + + expect(result.data.logInWith.clientMutationId).toEqual( + clientMutationId + ); + expect(result.data.logInWith.viewer.sessionToken).toBeDefined(); + expect(result.data.logInWith.viewer.user.someField).toEqual( + 'someValue' + ); + expect(typeof result.data.logInWith.viewer.sessionToken).toBe( + 'string' + ); + }); + it('should log the user in', async () => { const clientMutationId = uuidv4(); const user = new Parse.User(); diff --git a/src/GraphQL/loaders/usersMutations.js b/src/GraphQL/loaders/usersMutations.js index fd5fd92dae..701929677e 100644 --- a/src/GraphQL/loaders/usersMutations.js +++ b/src/GraphQL/loaders/usersMutations.js @@ -73,14 +73,10 @@ const load = parseGraphQLSchema => { ); parseGraphQLSchema.addGraphQLType(signUpMutation.type, true, true); parseGraphQLSchema.addGraphQLMutation('signUp', signUpMutation, true, true); - console.log( - 'Class', - parseGraphQLSchema.parseClassTypes['_User'].classGraphQLCreateType._fields - ); const logInWithMutation = mutationWithClientMutationId({ - name: 'LoginWith', + name: 'LogInWith', description: - 'The loginWith mutation can be used to signup, login user with 3rd party authentication system. This mutation create a user if the authData do not correspond to an existing one.', + 'The logInWith mutation can be used to signup, login user with 3rd party authentication system. This mutation create a user if the authData do not correspond to an existing one.', inputFields: { authData: { descriptions: 'This is the auth data of your custom auth provider', @@ -90,29 +86,25 @@ const load = parseGraphQLSchema => { descriptions: 'These are the fields of the user to be created/updated and logged in.', type: new GraphQLInputObjectType({ - name: 'UserLoginWihInput', + name: 'UserLoginWithInput', fields: () => { const classGraphQLCreateFields = parseGraphQLSchema.parseClassTypes[ '_User' - ].classGraphQLCreateType._fields() - Object.keys( - parseGraphQLSchema.parseClassTypes[ - '_User' - ].classGraphQLCreateType._fields() - ).reduce((fields, fieldName) => { - if ( - fieldName !== 'password' && - fieldName !== 'username' && - fieldName !== 'authData' - ) { - fields[fieldName] = - parseGraphQLSchema.parseClassTypes[ - '_User' - ].classGraphQLCreateType._fields[fieldName]; - } - console.log(fields); - return fields; - }, {}), + ].classGraphQLCreateType.getFields(); + return Object.keys(classGraphQLCreateFields).reduce( + (fields, fieldName) => { + if ( + fieldName !== 'password' && + fieldName !== 'username' && + fieldName !== 'authData' + ) { + fields[fieldName] = classGraphQLCreateFields[fieldName]; + } + return fields; + }, + {} + ); + }, }), }, }, @@ -160,7 +152,7 @@ const load = parseGraphQLSchema => { ); parseGraphQLSchema.addGraphQLType(logInWithMutation.type, true, true); parseGraphQLSchema.addGraphQLMutation( - 'loginWith', + 'logInWith', logInWithMutation, true, true From 81fb19df4841ff874d0285358cbc18628c3763ce Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 27 Jan 2020 18:17:47 +0100 Subject: [PATCH 4/5] wip --- spec/ParseGraphQLServer.spec.js | 86 +++++++++++++++--- src/GraphQL/loaders/defaultGraphQLTypes.js | 16 ++++ src/GraphQL/loaders/filesMutations.js | 101 ++++++++++----------- src/GraphQL/transformers/inputType.js | 2 +- src/GraphQL/transformers/mutation.js | 47 ++++++---- 5 files changed, 171 insertions(+), 81 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 4ad5249792..e177be03a6 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -9174,7 +9174,7 @@ describe('ParseGraphQLServer', () => { } ); - it('should support files', async () => { + fit('should support files', async () => { try { parseServer = await global.reconfigureServer({ publicServerURL: 'http://localhost:13377/parse', @@ -9218,7 +9218,7 @@ describe('ParseGraphQLServer', () => { expect(res.status).toEqual(200); - const result = JSON.parse(await res.text()); + let result = JSON.parse(await res.text()); expect(result.data.createFile.fileInfo.name).toEqual( jasmine.stringMatching(/_myFileName.txt$/) @@ -9253,17 +9253,25 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear(); - const createResult = await apolloClient.mutate({ - mutation: gql` + const body2 = new FormData(); + body2.append( + 'operations', + JSON.stringify({ + query: ` mutation CreateSomeObject( $fields1: CreateSomeClassFieldsInput $fields2: CreateSomeClassFieldsInput + $fields3: CreateSomeClassFieldsInput ) { createSomeClass1: createSomeClass( input: { fields: $fields1 } ) { someClass { id + someField { + name + url + } } } createSomeClass2: createSomeClass( @@ -9271,19 +9279,73 @@ describe('ParseGraphQLServer', () => { ) { someClass { id + someField { + name + url + } + } + } + createSomeClass3: createSomeClass( + input: { fields: $fields3 } + ) { + someClass { + id + someField { + name + url + } } } } - `, - variables: { - fields1: { - someField: someFieldValue, - }, - fields2: { - someField: someFieldValue.name, + `, + variables: { + fields1: { + someField: { file: someFieldValue }, + }, + fields2: { + someField: { file: someFieldValue.name }, + }, + fields3: { + someField: { upload: null }, + }, }, - }, + }) + ); + body2.append( + 'map', + JSON.stringify({ 1: ['variables.fields3.someField.upload'] }) + ); + body2.append('1', 'My File Content', { + filename: 'myFileName.txt', + contentType: 'text/plain', + }); + + res = await fetch('http://localhost:13377/graphql', { + method: 'POST', + headers, + body: body2, }); + expect(res.status).toEqual(200); + result = JSON.parse(await res.text()); + console.log(JSON.stringify(result.errors)); + expect( + result.data.createSomeClass1.someClass.someField.name + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); + expect( + result.data.createSomeClass1.someClass.someField.url + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); + expect( + result.data.createSomeClass2.someClass.someField.name + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); + expect( + result.data.createSomeClass2.someClass.someField.url + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); + expect( + result.data.createSomeClass3.someClass.someField.name + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); + expect( + result.data.createSomeClass3.someClass.someField.url + ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); const schema = await new Parse.Schema('SomeClass').get(); expect(schema.fields.someField.type).toEqual('File'); diff --git a/src/GraphQL/loaders/defaultGraphQLTypes.js b/src/GraphQL/loaders/defaultGraphQLTypes.js index d9ddd67d76..581a59a45a 100644 --- a/src/GraphQL/loaders/defaultGraphQLTypes.js +++ b/src/GraphQL/loaders/defaultGraphQLTypes.js @@ -366,6 +366,20 @@ const FILE_INFO = new GraphQLObjectType({ }, }); +const FILE_INPUT = new GraphQLInputObjectType({ + name: 'FileInput', + fields: { + file: { + description: 'A File Scalar can be an url or a FileInfo object.', + type: FILE, + }, + upload: { + description: 'Use this field if you want to create a new file.', + type: GraphQLUpload, + }, + }, +}); + const GEO_POINT_FIELDS = { latitude: { description: 'This is the latitude.', @@ -1244,6 +1258,7 @@ const load = parseGraphQLSchema => { parseGraphQLSchema.addGraphQLType(BYTES, true); parseGraphQLSchema.addGraphQLType(FILE, true); parseGraphQLSchema.addGraphQLType(FILE_INFO, true); + parseGraphQLSchema.addGraphQLType(FILE_INPUT, true); parseGraphQLSchema.addGraphQLType(GEO_POINT_INPUT, true); parseGraphQLSchema.addGraphQLType(GEO_POINT, true); parseGraphQLSchema.addGraphQLType(PARSE_OBJECT, true); @@ -1301,6 +1316,7 @@ export { SELECT_INPUT, FILE, FILE_INFO, + FILE_INPUT, GEO_POINT_FIELDS, GEO_POINT_INPUT, GEO_POINT, diff --git a/src/GraphQL/loaders/filesMutations.js b/src/GraphQL/loaders/filesMutations.js index cf906a6898..7e3cef78c3 100644 --- a/src/GraphQL/loaders/filesMutations.js +++ b/src/GraphQL/loaders/filesMutations.js @@ -5,6 +5,53 @@ import Parse from 'parse/node'; import * as defaultGraphQLTypes from './defaultGraphQLTypes'; import logger from '../../logger'; +const handleUpload = async (upload, config) => { + const { createReadStream, filename, mimetype } = await upload; + let data = null; + if (createReadStream) { + const stream = createReadStream(); + data = await new Promise((resolve, reject) => { + const chunks = []; + stream + .on('error', reject) + .on('data', chunk => chunks.push(chunk)) + .on('end', () => resolve(Buffer.concat(chunks))); + }); + } + + 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 { + fileInfo: 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}.` + ); + } +}; + const load = parseGraphQLSchema => { const createMutation = mutationWithClientMutationId({ name: 'CreateFile', @@ -26,57 +73,7 @@ const load = parseGraphQLSchema => { 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) => { - const chunks = []; - stream - .on('error', reject) - .on('data', chunk => chunks.push(chunk)) - .on('end', () => resolve(Buffer.concat(chunks))); - }); - } - - 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 { - fileInfo: 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}.` - ); - } + return handleUpload(upload, config); } catch (e) { parseGraphQLSchema.handleError(e); } @@ -97,4 +94,4 @@ const load = parseGraphQLSchema => { ); }; -export { load }; +export { load, handleUpload }; diff --git a/src/GraphQL/transformers/inputType.js b/src/GraphQL/transformers/inputType.js index 87f690dfe0..29c91a65ea 100644 --- a/src/GraphQL/transformers/inputType.js +++ b/src/GraphQL/transformers/inputType.js @@ -45,7 +45,7 @@ const transformInputTypeToGraphQL = ( return defaultGraphQLTypes.OBJECT; } case 'File': - return defaultGraphQLTypes.FILE; + return defaultGraphQLTypes.FILE_INPUT; case 'GeoPoint': return defaultGraphQLTypes.GEO_POINT_INPUT; case 'Polygon': diff --git a/src/GraphQL/transformers/mutation.js b/src/GraphQL/transformers/mutation.js index 7bf55eee10..99b164262c 100644 --- a/src/GraphQL/transformers/mutation.js +++ b/src/GraphQL/transformers/mutation.js @@ -1,5 +1,6 @@ import Parse from 'parse/node'; import { fromGlobalId } from 'graphql-relay'; +import { handleUpload } from '../loaders/filesMutations'; import * as defaultGraphQLTypes from '../loaders/defaultGraphQLTypes'; import * as objectsMutations from '../helpers/objectsMutations'; @@ -40,6 +41,9 @@ const transformTypes = async ( case inputTypeField.type === defaultGraphQLTypes.POLYGON_INPUT: fields[field] = transformers.polygon(fields[field]); break; + case inputTypeField.type === defaultGraphQLTypes.FILE_INPUT: + fields[field] = await transformers.file(fields[field], req); + break; case parseClass.fields[field].type === 'Relation': fields[field] = await transformers.relation( parseClass.fields[field].targetClass, @@ -68,6 +72,15 @@ const transformTypes = async ( }; const transformers = { + file: async ({ file, upload }, { config }) => { + console.log('File', file, 'Upload', upload); + if (upload) { + return handleUpload(upload, config); + } else if (file) { + return file; + } + throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'Invalid file upload.'); + }, polygon: value => ({ __type: 'Polygon', coordinates: value.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]), @@ -122,22 +135,24 @@ const transformers = { let nestedObjectsToAdd = []; if (value.createAndAdd) { - nestedObjectsToAdd = (await Promise.all( - value.createAndAdd.map(async input => { - const parseFields = await transformTypes('create', input, { - className: targetClass, - parseGraphQLSchema, - req: { config, auth, info }, - }); - return objectsMutations.createObject( - targetClass, - parseFields, - config, - auth, - info - ); - }) - )).map(object => ({ + nestedObjectsToAdd = ( + await Promise.all( + value.createAndAdd.map(async input => { + const parseFields = await transformTypes('create', input, { + className: targetClass, + parseGraphQLSchema, + req: { config, auth, info }, + }); + return objectsMutations.createObject( + targetClass, + parseFields, + config, + auth, + info + ); + }) + ) + ).map(object => ({ __type: 'Pointer', className: targetClass, objectId: object.objectId, From 51e0b8b44253c1d176a497ff04b2fd1c8c95f6ac Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 27 Jan 2020 19:34:04 +0100 Subject: [PATCH 5/5] tested --- spec/ParseGraphQLServer.spec.js | 34 ++++++++++++++++------------ src/GraphQL/transformers/mutation.js | 8 +++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index e177be03a6..c9224592f1 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -9174,7 +9174,7 @@ describe('ParseGraphQLServer', () => { } ); - fit('should support files', async () => { + it('should support files', async () => { try { parseServer = await global.reconfigureServer({ publicServerURL: 'http://localhost:13377/parse', @@ -9218,7 +9218,7 @@ describe('ParseGraphQLServer', () => { expect(res.status).toEqual(200); - let result = JSON.parse(await res.text()); + const result = JSON.parse(await res.text()); expect(result.data.createFile.fileInfo.name).toEqual( jasmine.stringMatching(/_myFileName.txt$/) @@ -9228,6 +9228,7 @@ describe('ParseGraphQLServer', () => { ); const someFieldValue = result.data.createFile.fileInfo.name; + const someFieldObjectValue = result.data.createFile.fileInfo; await apolloClient.mutate({ mutation: gql` @@ -9303,7 +9304,13 @@ describe('ParseGraphQLServer', () => { someField: { file: someFieldValue }, }, fields2: { - someField: { file: someFieldValue.name }, + someField: { + file: { + name: someFieldObjectValue.name, + url: someFieldObjectValue.url, + __type: 'File', + }, + }, }, fields3: { someField: { upload: null }, @@ -9326,25 +9333,24 @@ describe('ParseGraphQLServer', () => { body: body2, }); expect(res.status).toEqual(200); - result = JSON.parse(await res.text()); - console.log(JSON.stringify(result.errors)); + const result2 = JSON.parse(await res.text()); expect( - result.data.createSomeClass1.someClass.someField.name + result2.data.createSomeClass1.someClass.someField.name ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); expect( - result.data.createSomeClass1.someClass.someField.url + result2.data.createSomeClass1.someClass.someField.url ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); expect( - result.data.createSomeClass2.someClass.someField.name + result2.data.createSomeClass2.someClass.someField.name ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); expect( - result.data.createSomeClass2.someClass.someField.url + result2.data.createSomeClass2.someClass.someField.url ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); expect( - result.data.createSomeClass3.someClass.someField.name + result2.data.createSomeClass3.someClass.someField.name ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); expect( - result.data.createSomeClass3.someClass.someField.url + result2.data.createSomeClass3.someClass.someField.url ).toEqual(jasmine.stringMatching(/_myFileName.txt$/)); const schema = await new Parse.Schema('SomeClass').get(); @@ -9386,7 +9392,7 @@ describe('ParseGraphQLServer', () => { } `, variables: { - id: createResult.data.createSomeClass1.someClass.id, + id: result2.data.createSomeClass1.someClass.id, }, }); @@ -9397,8 +9403,8 @@ describe('ParseGraphQLServer', () => { expect(getResult.data.someClass.someField.url).toEqual( result.data.createFile.fileInfo.url ); - expect(getResult.data.findSomeClass1.edges.length).toEqual(1); - expect(getResult.data.findSomeClass2.edges.length).toEqual(1); + expect(getResult.data.findSomeClass1.edges.length).toEqual(3); + expect(getResult.data.findSomeClass2.edges.length).toEqual(3); res = await fetch(getResult.data.someClass.someField.url); diff --git a/src/GraphQL/transformers/mutation.js b/src/GraphQL/transformers/mutation.js index 99b164262c..6d5dbc601d 100644 --- a/src/GraphQL/transformers/mutation.js +++ b/src/GraphQL/transformers/mutation.js @@ -73,11 +73,11 @@ const transformTypes = async ( const transformers = { file: async ({ file, upload }, { config }) => { - console.log('File', file, 'Upload', upload); if (upload) { - return handleUpload(upload, config); - } else if (file) { - return file; + const { fileInfo } = await handleUpload(upload, config); + return { name: fileInfo.name, __type: 'File' }; + } else if (file && file.name) { + return { name: file.name, __type: 'File' }; } throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'Invalid file upload.'); },