Files
kami-parse-server/src/GraphQL/ParseGraphQLServer.js
Antonio Davi Macedo Coelho de Castro a754b883b2 Improve callCloudCode mutation to receive a CloudCodeFunction enum instead of a String (#6029)
* Add listing test

* Improvements

* Fixinf package.json

* Fix package.json

* Fix tests
2019-09-09 15:07:22 -07:00

149 lines
4.3 KiB
JavaScript

import corsMiddleware from 'cors';
import bodyParser from 'body-parser';
import { graphqlUploadExpress } from 'graphql-upload';
import { graphqlExpress } from 'apollo-server-express/dist/expressApollo';
import { renderPlaygroundPage } from '@apollographql/graphql-playground-html';
import { execute, subscribe } from 'graphql';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { handleParseErrors, handleParseHeaders } from '../middlewares';
import requiredParameter from '../requiredParameter';
import defaultLogger from '../logger';
import { ParseGraphQLSchema } from './ParseGraphQLSchema';
import ParseGraphQLController, {
ParseGraphQLConfig,
} from '../Controllers/ParseGraphQLController';
class ParseGraphQLServer {
parseGraphQLController: ParseGraphQLController;
constructor(parseServer, config) {
this.parseServer =
parseServer ||
requiredParameter('You must provide a parseServer instance!');
if (!config || !config.graphQLPath) {
requiredParameter('You must provide a config.graphQLPath!');
}
this.config = config;
this.parseGraphQLController = this.parseServer.config.parseGraphQLController;
this.log =
(this.parseServer.config && this.parseServer.config.loggerController) ||
defaultLogger;
this.parseGraphQLSchema = new ParseGraphQLSchema({
parseGraphQLController: this.parseGraphQLController,
databaseController: this.parseServer.config.databaseController,
log: this.log,
graphQLCustomTypeDefs: this.config.graphQLCustomTypeDefs,
appId: this.parseServer.config.appId,
});
}
async _getGraphQLOptions(req) {
try {
return {
schema: await this.parseGraphQLSchema.load(),
context: {
info: req.info,
config: req.config,
auth: req.auth,
},
};
} catch (e) {
this.log.error(
e.stack || (typeof e.toString === 'function' && e.toString()) || e
);
throw e;
}
}
_transformMaxUploadSizeToBytes(maxUploadSize) {
const unitMap = {
kb: 1,
mb: 2,
gb: 3,
};
return (
Number(maxUploadSize.slice(0, -2)) *
Math.pow(1024, unitMap[maxUploadSize.slice(-2).toLowerCase()])
);
}
applyGraphQL(app) {
if (!app || !app.use) {
requiredParameter('You must provide an Express.js app instance!');
}
app.use(
this.config.graphQLPath,
graphqlUploadExpress({
maxFileSize: this._transformMaxUploadSizeToBytes(
this.parseServer.config.maxUploadSize || '20mb'
),
})
);
app.use(this.config.graphQLPath, corsMiddleware());
app.use(this.config.graphQLPath, bodyParser.json());
app.use(this.config.graphQLPath, handleParseHeaders);
app.use(this.config.graphQLPath, handleParseErrors);
app.use(
this.config.graphQLPath,
graphqlExpress(async req => await this._getGraphQLOptions(req))
);
}
applyPlayground(app) {
if (!app || !app.get) {
requiredParameter('You must provide an Express.js app instance!');
}
app.get(
this.config.playgroundPath ||
requiredParameter(
'You must provide a config.playgroundPath to applyPlayground!'
),
(_req, res) => {
res.setHeader('Content-Type', 'text/html');
res.write(
renderPlaygroundPage({
endpoint: this.config.graphQLPath,
subscriptionEndpoint: this.config.subscriptionsPath,
headers: {
'X-Parse-Application-Id': this.parseServer.config.appId,
'X-Parse-Master-Key': this.parseServer.config.masterKey,
},
})
);
res.end();
}
);
}
createSubscriptions(server) {
SubscriptionServer.create(
{
execute,
subscribe,
onOperation: async (_message, params, webSocket) =>
Object.assign(
{},
params,
await this._getGraphQLOptions(webSocket.upgradeReq)
),
},
{
server,
path:
this.config.subscriptionsPath ||
requiredParameter(
'You must provide a config.subscriptionsPath to createSubscriptions!'
),
}
);
}
setGraphQLConfig(graphQLConfig: ParseGraphQLConfig): Promise {
return this.parseGraphQLController.updateGraphQLConfig(graphQLConfig);
}
}
export { ParseGraphQLServer };