/**
* Import dependencies
*/
'use strict';
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _Promise = require('babel-runtime/core-js/promise')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _this = this;
var _joi = require('joi');
var _joi2 = _interopRequireDefault(_joi);
var _boom = require('boom');
var _boom2 = _interopRequireDefault(_boom);
var _stream = require('stream');
var _graphql = require('graphql');
var _graphqlError = require('graphql/error');
var _packageJson = require('../package.json');
/**
* Define constants
*/
var optionsSchema = {
query: [_joi2['default'].func(), _joi2['default'].object({
schema: _joi2['default'].object().required(),
rootValue: _joi2['default'].object(),
pretty: _joi2['default'].boolean()
}).required()],
route: _joi2['default'].object().keys({
path: _joi2['default'].string().required(),
config: _joi2['default'].object()
}).required()
};
/**
* Define helper: get options from object/function
*/
var getOptions = function getOptions(options, request) {
// Get options
var optionsData = typeof options === 'function' ? options(request) : options;
// Validate options
var validation = _joi2['default'].validate(optionsData, optionsSchema.query);
if (validation.error) {
throw validation.error;
}
return validation.value;
};
/**
* Define helper: parse payload
*/
var parsePayload = function parsePayload(request) {
var result;
return _regeneratorRuntime.async(function parsePayload$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
if (!(request.mime === 'multipart/form-data')) {
context$1$0.next = 2;
break;
}
return context$1$0.abrupt('return', request.payload);
case 2:
context$1$0.next = 4;
return _regeneratorRuntime.awrap(new _Promise(function (resolve) {
if (request.payload instanceof _stream.Stream) {
(function () {
var data = '';
request.payload.on('data', function (chunk) {
return data += chunk;
});
request.payload.on('end', function () {
return resolve(data);
});
})();
} else {
resolve('{}');
}
}));
case 4:
result = context$1$0.sent;
return context$1$0.abrupt('return', request.mime === 'application/graphql' ? { query: result } : JSON.parse(result));
case 6:
case 'end':
return context$1$0.stop();
}
}, null, _this);
};
/**
* Define helper: get GraphQL parameters from query/payload
*/
var getGraphQLParams = function getGraphQLParams(request) {
var payload = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
// GraphQL Query string.
var query = request.query.query || payload.query;
if (!query) {
throw _boom2['default'].badRequest('Must provide query string.');
}
// Parse the variables if needed.
var variables = request.query.variables || payload.variables;
if (variables && typeof variables === 'string') {
try {
variables = JSON.parse(variables);
} catch (error) {
throw _boom2['default'].badRequest('Variables are invalid JSON.');
}
}
// Name of GraphQL operation to execute.
var operationName = request.query.operationName || payload.operationName;
// Return params
return { query: query, variables: variables, operationName: operationName };
};
/**
* Define GraphQL runner
*/
var runGraphQL = function runGraphQL(request, payload, schema, rootValue) {
var _getGraphQLParams,
// Get GraphQL params from the request and POST body data.
query, variables, operationName, result;
return _regeneratorRuntime.async(function runGraphQL$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_getGraphQLParams = getGraphQLParams(request, payload);
query = _getGraphQLParams.query;
variables = _getGraphQLParams.variables;
operationName = _getGraphQLParams.operationName;
context$1$0.next = 6;
return _regeneratorRuntime.awrap((0, _graphql.graphql)(schema, query, rootValue, variables, operationName));
case 6:
result = context$1$0.sent;
// Format any encountered errors.
if (result.errors) {
result.errors = result.errors.map(_graphqlError.formatError);
}
// Return GraphQL result
return context$1$0.abrupt('return', result);
case 9:
case 'end':
return context$1$0.stop();
}
}, null, _this);
};
/**
* Define handler
*/
var handler = function handler(route) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
return function callee$1$0(request, reply) {
var _getOptions,
// Get GraphQL options given this request.
schema, rootValue, pretty, payload, result;
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.prev = 0;
_getOptions = getOptions(options, request);
schema = _getOptions.schema;
rootValue = _getOptions.rootValue;
pretty = _getOptions.pretty;
// Set up JSON output settings
if (pretty) {
request.route.settings.json.space = 2;
}
// Parse payload
context$2$0.next = 8;
return _regeneratorRuntime.awrap(parsePayload(request));
case 8:
payload = context$2$0.sent;
context$2$0.next = 11;
return _regeneratorRuntime.awrap(runGraphQL(request, payload, schema, rootValue));
case 11:
result = context$2$0.sent;
return context$2$0.abrupt('return', reply(result).code(result.hasOwnProperty('data') ? 200 : 400));
case 15:
context$2$0.prev = 15;
context$2$0.t0 = context$2$0['catch'](0);
return context$2$0.abrupt('return', reply(context$2$0.t0));
case 18:
case 'end':
return context$2$0.stop();
}
}, null, _this, [[0, 15]]);
};
};
/**
* Define handler defaults
*/
handler.defaults = function (method) {
if (method === 'post') {
return {
payload: {
maxBytes: 1048576,
output: 'stream',
parse: true
}
};
}
return {};
};
/**
* Define plugin
*/
function register(server, options, next) {
if (options === undefined) options = {};
// Validate options
var validation = _joi2['default'].validate(options, optionsSchema);
if (validation.error) {
throw validation.error;
}
var _validation$value = validation.value;
var route = _validation$value.route;
var query = _validation$value.query;
// Register handler
server.handler('graphql', handler);
// Register route
server.route({
method: ['get', 'post'],
path: route.path,
config: route.config,
handler: {
graphql: query
}
});
// Done
return next();
}
/**
* Define plugin attributes
*/
register.attributes = { name: 'graphql', version: _packageJson.version };
/**
* Export plugin
*/
exports['default'] = register;
module.exports = exports['default'];
// Read stream
// Return normalized payload
// Run GraphQL query.
// Run GraphQL
// Return result
// Return error