Skip to content

Commit 3dec0e0

Browse files
authored
Merge ad477f3 into 42929e0
2 parents 42929e0 + ad477f3 commit 3dec0e0

File tree

9 files changed

+523
-505
lines changed

9 files changed

+523
-505
lines changed

package-lock.json

Lines changed: 463 additions & 475 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
"@graphql-tools/merge": "8.4.1",
2424
"@graphql-tools/schema": "9.0.4",
2525
"@graphql-tools/utils": "8.12.0",
26-
"@graphql-yoga/node": "2.6.0",
2726
"@parse/fs-files-adapter": "1.2.2",
2827
"@parse/push-adapter": "4.2.0",
28+
"@whatwg-node/fetch": "0.9.9",
2929
"bcryptjs": "2.4.3",
3030
"body-parser": "1.20.2",
3131
"commander": "10.0.1",
@@ -38,6 +38,7 @@
3838
"graphql-list-fields": "2.0.2",
3939
"graphql-relay": "0.10.0",
4040
"graphql-tag": "2.12.6",
41+
"graphql-yoga": "4.0.4",
4142
"intersect": "1.0.1",
4243
"ip-range-check": "0.2.0",
4344
"jsonwebtoken": "9.0.0",
@@ -126,11 +127,11 @@
126127
"test:mongodb:5.3.2": "npm run test:mongodb --dbversion=5.3.2",
127128
"test:mongodb:6.0.2": "npm run test:mongodb --dbversion=6.0.2",
128129
"posttest:mongodb": "mongodb-runner stop",
129-
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
130-
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
130+
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=6.0.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
131+
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=6.0.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
131132
"test": "npm run testonly",
132-
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner stop",
133-
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
133+
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=6.0.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner stop",
134+
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=6.0.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
134135
"start": "node ./bin/parse-server",
135136
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
136137
"prepare": "npm run build",

spec/ParseGraphQLServer.spec.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,10 @@ describe('ParseGraphQLServer', () => {
126126

127127
it("should return schema and context with req's info, config and auth", async () => {
128128
const options = await parseGraphQLServer._getGraphQLOptions();
129-
expect(options.multipart).toEqual({
130-
fileSize: 20971520,
129+
expect(new options.fetchApi.Body().options).toEqual({
130+
formDataLimits: {
131+
fileSize: 20971520,
132+
},
131133
});
132134
expect(options.schema).toEqual(parseGraphQLServer.parseGraphQLSchema.graphQLSchema);
133135
const contextResponse = options.context({ req });
@@ -6833,7 +6835,7 @@ describe('ParseGraphQLServer', () => {
68336835

68346836
describe('Files Mutations', () => {
68356837
describe('Create', () => {
6836-
it_only_node_version('<17')('should return File object', async () => {
6838+
it('should return File object', async () => {
68376839
const clientMutationId = uuidv4();
68386840

68396841
parseServer = await global.reconfigureServer({
@@ -9299,7 +9301,7 @@ describe('ParseGraphQLServer', () => {
92999301
expect(result6[0].node.name).toEqual('imACountry3');
93009302
});
93019303

9302-
it_only_node_version('<17')('should support files', async () => {
9304+
it('should support files', async () => {
93039305
try {
93049306
parseServer = await global.reconfigureServer({
93059307
publicServerURL: 'http://localhost:13377/parse',
@@ -9450,7 +9452,8 @@ describe('ParseGraphQLServer', () => {
94509452
body: body2,
94519453
});
94529454
expect(res.status).toEqual(200);
9453-
const result2 = JSON.parse(await res.text());
9455+
const resText = await res.text();
9456+
const result2 = JSON.parse(resText);
94549457
expect(result2.data.createSomeClass1.someClass.someField.name).toEqual(
94559458
jasmine.stringMatching(/_myFileName.txt$/)
94569459
);
@@ -9508,7 +9511,6 @@ describe('ParseGraphQLServer', () => {
95089511
id: result2.data.createSomeClass1.someClass.id,
95099512
},
95109513
});
9511-
95129514
expect(typeof getResult.data.someClass.someField).toEqual('object');
95139515
expect(getResult.data.someClass.someField.name).toEqual(
95149516
result.data.createFile.fileInfo.name
@@ -9547,9 +9549,14 @@ describe('ParseGraphQLServer', () => {
95479549
}
95489550
});
95499551

9550-
it_only_node_version('<17')('should not upload if file is too large', async () => {
9552+
it('should not upload if file is too large', async () => {
95519553
parseGraphQLServer.parseServer.config.maxUploadSize = '1kb';
9552-
9554+
const options = await parseGraphQLServer._getGraphQLOptions();
9555+
expect(new options.fetchApi.Body().options).toEqual({
9556+
formDataLimits: {
9557+
fileSize: 1024,
9558+
},
9559+
});
95539560
const body = new FormData();
95549561
body.append(
95559562
'operations',
@@ -9586,9 +9593,8 @@ describe('ParseGraphQLServer', () => {
95869593
headers,
95879594
body,
95889595
});
9589-
95909596
const result = JSON.parse(await res.text());
9591-
expect(res.status).toEqual(500);
9597+
expect(res.status).toEqual(413);
95929598
expect(result.errors[0].message).toEqual('File size limit exceeded: 1024 bytes');
95939599
});
95949600

src/GraphQL/ParseGraphQLServer.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import corsMiddleware from 'cors';
2-
import { createServer, renderGraphiQL } from '@graphql-yoga/node';
2+
import { createYoga, renderGraphiQL } from 'graphql-yoga';
3+
import { createFetch } from '@whatwg-node/fetch';
34
import { execute, subscribe } from 'graphql';
45
import { SubscriptionServer } from 'subscriptions-transport-ws';
56
import { handleParseErrors, handleParseHeaders, handleParseSession } from '../middlewares';
@@ -31,6 +32,11 @@ class ParseGraphQLServer {
3132

3233
async _getGraphQLOptions() {
3334
try {
35+
const formDataLimits = {
36+
fileSize: this._transformMaxUploadSizeToBytes(
37+
this.parseServer.config.maxUploadSize || '20mb'
38+
),
39+
};
3440
return {
3541
schema: await this.parseGraphQLSchema.load(),
3642
context: ({ req: { info, config, auth } }) => ({
@@ -39,11 +45,20 @@ class ParseGraphQLServer {
3945
auth,
4046
}),
4147
maskedErrors: false,
42-
multipart: {
43-
fileSize: this._transformMaxUploadSizeToBytes(
44-
this.parseServer.config.maxUploadSize || '20mb'
45-
),
46-
},
48+
// Needed to ensure formDataLimits since it seems to not working
49+
// this is a temporary fix until the issue is resolved
50+
// we need to ask graphql-yoga team
51+
plugins: [
52+
{
53+
onRequestParse: ({ request }) => {
54+
request.options.formDataLimits = formDataLimits;
55+
},
56+
},
57+
],
58+
fetchApi: createFetch({
59+
useNodeFetch: true,
60+
formDataLimits,
61+
}),
4762
};
4863
} catch (e) {
4964
this.log.error(e.stack || (typeof e.toString === 'function' && e.toString()) || e);
@@ -58,7 +73,7 @@ class ParseGraphQLServer {
5873
return this._server;
5974
}
6075
const options = await this._getGraphQLOptions();
61-
this._server = createServer(options);
76+
this._server = createYoga(options);
6277
return this._server;
6378
}
6479

src/GraphQL/loaders/filesMutations.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import * as defaultGraphQLTypes from './defaultGraphQLTypes';
55
import logger from '../../logger';
66

77
const handleUpload = async (upload, config) => {
8-
const data = Buffer.from(await upload.arrayBuffer());
8+
const data = await upload.buffer();
99
const fileName = upload.name;
1010
const type = upload.type;
11-
1211
if (!data || !data.length) {
1312
throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'Invalid file upload.');
1413
}

src/GraphQL/loaders/parseClassMutations.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ const load = function (parseGraphQLSchema, parseClass, parseClassConfig: ?ParseG
8282
const parseFields = await transformTypes('create', fields, {
8383
className,
8484
parseGraphQLSchema,
85+
originalFields: args.fields || {},
8586
req: { config, auth, info },
8687
});
8788

@@ -190,6 +191,7 @@ const load = function (parseGraphQLSchema, parseClass, parseClassConfig: ?ParseG
190191
const parseFields = await transformTypes('update', fields, {
191192
className,
192193
parseGraphQLSchema,
194+
originalFields: args.fields || {},
193195
req: { config, auth, info },
194196
});
195197

src/GraphQL/loaders/usersMutations.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const load = parseGraphQLSchema => {
3838
const parseFields = await transformTypes('create', fields, {
3939
className: '_User',
4040
parseGraphQLSchema,
41+
originalFields: args.fields || {},
4142
req: { config, auth, info },
4243
});
4344

@@ -114,6 +115,7 @@ const load = parseGraphQLSchema => {
114115
const parseFields = await transformTypes('create', fields, {
115116
className: '_User',
116117
parseGraphQLSchema,
118+
originalFields: args.fields || {},
117119
req: { config, auth, info },
118120
});
119121

src/GraphQL/parseGraphQLUtils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Parse from 'parse/node';
2-
import { GraphQLYogaError } from '@graphql-yoga/node';
2+
import { GraphQLError } from 'graphql';
33

44
export function enforceMasterKeyAccess(auth) {
55
if (!auth.isMaster) {
@@ -16,7 +16,7 @@ export function toGraphQLError(error) {
1616
code = Parse.Error.INTERNAL_SERVER_ERROR;
1717
message = 'Internal server error';
1818
}
19-
return new GraphQLYogaError(message, { code });
19+
return new GraphQLError(message, { extensions: { code } });
2020
}
2121

2222
export const extractKeysAndInclude = selectedFields => {

src/GraphQL/transformers/mutation.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { fromGlobalId } from 'graphql-relay';
33
import { handleUpload } from '../loaders/filesMutations';
44
import * as defaultGraphQLTypes from '../loaders/defaultGraphQLTypes';
55
import * as objectsMutations from '../helpers/objectsMutations';
6+
import deepcopy from 'deepcopy';
67

78
const transformTypes = async (
89
inputType: 'create' | 'update',
910
fields,
10-
{ className, parseGraphQLSchema, req }
11+
{ className, parseGraphQLSchema, req, originalFields }
1112
) => {
1213
const {
1314
classGraphQLCreateType,
@@ -44,7 +45,9 @@ const transformTypes = async (
4445
fields[field] = transformers.polygon(fields[field]);
4546
break;
4647
case inputTypeField.type === defaultGraphQLTypes.FILE_INPUT:
47-
fields[field] = await transformers.file(fields[field], req);
48+
// fields are a deepcopy, but we can't deepcopy a stream so
49+
// we use the original fields from the graphql request
50+
fields[field] = await transformers.file(originalFields[field], req);
4851
break;
4952
case parseClass.fields[field].type === 'Relation':
5053
fields[field] = await transformers.relation(
@@ -152,9 +155,10 @@ const transformers = {
152155
nestedObjectsToAdd = (
153156
await Promise.all(
154157
value.createAndAdd.map(async input => {
155-
const parseFields = await transformTypes('create', input, {
158+
const parseFields = await transformTypes('create', deepcopy(input), {
156159
className: targetClass,
157160
parseGraphQLSchema,
161+
originalFields: input || {},
158162
req: { config, auth, info },
159163
});
160164
return objectsMutations.createObject(targetClass, parseFields, config, auth, info);
@@ -213,9 +217,10 @@ const transformers = {
213217

214218
let nestedObjectToAdd;
215219
if (value.createAndLink) {
216-
const parseFields = await transformTypes('create', value.createAndLink, {
220+
const parseFields = await transformTypes('create', deepcopy(value.createAndLink), {
217221
className: targetClass,
218222
parseGraphQLSchema,
223+
originalFields: value.createAndLink || {},
219224
req: { config, auth, info },
220225
});
221226
nestedObjectToAdd = await objectsMutations.createObject(

0 commit comments

Comments
 (0)