forked from parse-community/parse-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilesMutations.js
More file actions
105 lines (101 loc) · 3.47 KB
/
Copy pathfilesMutations.js
File metadata and controls
105 lines (101 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { GraphQLNonNull } from 'graphql';
import { request } from 'http';
import { mutationWithClientMutationId } from 'graphql-relay';
import Parse from 'parse/node';
import * as defaultGraphQLTypes from './defaultGraphQLTypes';
import logger from '../../logger';
// Handle GraphQL file upload and proxy file upload to GraphQL server url specified in config;
// `createFile` is not directly called by Parse Server to leverage standard file upload mechanism
const handleUpload = async (upload, config) => {
const { createReadStream, filename, mimetype } = await upload;
const headers = { ...config.headers };
delete headers['accept-encoding'];
delete headers['accept'];
delete headers['connection'];
delete headers['host'];
delete headers['content-length'];
const stream = createReadStream();
const mime = (await import('mime')).default;
try {
const ext = mime.getExtension(mimetype);
const fullFileName = filename.endsWith(`.${ext}`) ? filename : `${filename}.${ext}`;
const encodedFileName = fullFileName.split('/').map(encodeURIComponent).join('/');
const serverUrl = new URL(config.serverURL);
const fileInfo = await new Promise((resolve, reject) => {
const req = request(
{
hostname: serverUrl.hostname,
port: serverUrl.port,
path: `${serverUrl.pathname}/files/${encodedFileName}`,
method: 'POST',
headers,
},
res => {
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
try {
const parsedData = JSON.parse(data);
if (res.statusCode < 200 || res.statusCode >= 400) {
reject(
new Parse.Error(
parsedData.code || Parse.Error.FILE_SAVE_ERROR,
parsedData.error || data
)
);
return;
}
resolve(parsedData);
} catch {
reject(new Parse.Error(Parse.error, data));
}
});
}
);
stream.pipe(req);
stream.on('end', () => {
req.end();
});
});
return {
fileInfo,
};
} catch (e) {
stream.destroy();
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',
description: 'The createFile mutation can be used to create and upload a new file.',
inputFields: {
upload: {
description: 'This is the new file to be created and uploaded.',
type: new GraphQLNonNull(defaultGraphQLTypes.GraphQLUpload),
},
},
outputFields: {
fileInfo: {
description: 'This is the created file info.',
type: new GraphQLNonNull(defaultGraphQLTypes.FILE_INFO),
},
},
mutateAndGetPayload: async (args, context) => {
try {
const { upload } = args;
const { config } = context;
return handleUpload(upload, config);
} catch (e) {
parseGraphQLSchema.handleError(e);
}
},
});
parseGraphQLSchema.addGraphQLType(createMutation.args.input.type.ofType, true, true);
parseGraphQLSchema.addGraphQLType(createMutation.type, true, true);
parseGraphQLSchema.addGraphQLMutation('createFile', createMutation, true, true);
};
export { load, handleUpload };