express-graphql
Advanced tools
Comparing version 0.4.4 to 0.4.5
@@ -53,39 +53,52 @@ | ||
return function (request, response) { | ||
// Get GraphQL options given this request. | ||
// Higher scoped variables are referred to at various stages in the | ||
// asyncronous state machine below. | ||
var schema = undefined; | ||
var rootValue = undefined; | ||
var pretty = undefined; | ||
var graphiql = undefined; | ||
var showGraphiQL = undefined; | ||
var query = undefined; | ||
var variables = undefined; | ||
var operationName = undefined; | ||
var _getOptions = getOptions(options, request); | ||
// Use promises as a mechanism for capturing any thrown errors during the | ||
// asyncronous process. | ||
new Promise(function (resolve, reject) { | ||
var schema = _getOptions.schema; | ||
var rootValue = _getOptions.rootValue; | ||
var pretty = _getOptions.pretty; | ||
var graphiql = _getOptions.graphiql; | ||
// Get GraphQL options given this request. | ||
var optionsObj = getOptions(options, request); | ||
schema = optionsObj.schema; | ||
rootValue = optionsObj.rootValue; | ||
pretty = optionsObj.pretty; | ||
graphiql = optionsObj.graphiql; | ||
// GraphQL HTTP only supports GET and POST methods. | ||
if (request.method !== 'GET' && request.method !== 'POST') { | ||
response.set('Allow', 'GET, POST'); | ||
return sendError(response, (0, _httpErrors2['default'])(405, 'GraphQL only supports GET and POST requests.'), pretty); | ||
} | ||
// GraphQL HTTP only supports GET and POST methods. | ||
if (request.method !== 'GET' && request.method !== 'POST') { | ||
response.set('Allow', 'GET, POST'); | ||
throw (0, _httpErrors2['default'])(405, 'GraphQL only supports GET and POST requests.'); | ||
} | ||
// Parse the Request body. | ||
(0, _parseBody.parseBody)(request, function (parseError) { | ||
var data = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
// Parse the Request body. | ||
(0, _parseBody.parseBody)(request, function (parseError, data) { | ||
if (parseError) { | ||
reject(parseError); | ||
} else { | ||
resolve(data || {}); | ||
} | ||
}); | ||
}).then(function (data) { | ||
showGraphiQL = graphiql && canDisplayGraphiQL(request, data); | ||
// Format any request errors the same as GraphQL errors. | ||
if (parseError) { | ||
return sendError(response, parseError, pretty); | ||
} | ||
// Get GraphQL params from the request and POST body data. | ||
var params = getGraphQLParams(request, data); | ||
query = params.query; | ||
variables = params.variables; | ||
operationName = params.operationName; | ||
var _getGraphQLParams = getGraphQLParams(request, data); | ||
var query = _getGraphQLParams.query; | ||
var variables = _getGraphQLParams.variables; | ||
var operationName = _getGraphQLParams.operationName; | ||
// If there is no query, present an empty GraphiQL if possible, otherwise | ||
// return a 400 level error. | ||
// If there is no query, but GraphiQL will be displayed, do not produce | ||
// a result, otherwise return a 400: Bad Request. | ||
if (!query) { | ||
if (graphiql && canDisplayGraphiQL(request, data)) { | ||
return response.set('Content-Type', 'text/html').send((0, _renderGraphiQL.renderGraphiQL)()); | ||
if (showGraphiQL) { | ||
return null; | ||
} | ||
@@ -95,53 +108,66 @@ throw (0, _httpErrors2['default'])(400, 'Must provide query string.'); | ||
// Run GraphQL query. | ||
new Promise(function (resolve) { | ||
var source = new _graphqlLanguage.Source(query, 'GraphQL request'); | ||
var documentAST = (0, _graphqlLanguage.parse)(source); | ||
var validationErrors = (0, _graphqlValidation.validate)(schema, documentAST); | ||
if (validationErrors.length > 0) { | ||
resolve({ errors: validationErrors }); | ||
} else { | ||
// GraphQL source. | ||
var source = new _graphqlLanguage.Source(query, 'GraphQL request'); | ||
// Only query operations are allowed on GET requests. | ||
if (request.method === 'GET') { | ||
// Determine if this GET request will perform a non-query. | ||
var operationAST = (0, _graphqlUtilitiesGetOperationAST.getOperationAST)(documentAST, operationName); | ||
if (operationAST && operationAST.operation !== 'query') { | ||
// If GraphiQL can be shown, do not perform this query, but | ||
// provide it to GraphiQL so that the requester may perform it | ||
// themselves if desired. | ||
if (graphiql && canDisplayGraphiQL(request, data)) { | ||
return response.set('Content-Type', 'text/html').send((0, _renderGraphiQL.renderGraphiQL)({ query: query, variables: variables })); | ||
} | ||
// Parse source to AST, reporting any syntax error. | ||
var documentAST = undefined; | ||
try { | ||
documentAST = (0, _graphqlLanguage.parse)(source); | ||
} catch (syntaxError) { | ||
// Return 400: Bad Request if any syntax errors errors exist. | ||
response.status(400); | ||
return { errors: [syntaxError] }; | ||
} | ||
// Otherwise, report a 405 Method Not Allowed error. | ||
response.set('Allow', 'POST'); | ||
return sendError(response, (0, _httpErrors2['default'])(405, 'Can only perform a ' + operationAST.operation + ' operation ' + 'from a POST request.'), pretty); | ||
} | ||
// Validate AST, reporting any errors. | ||
var validationErrors = (0, _graphqlValidation.validate)(schema, documentAST); | ||
if (validationErrors.length > 0) { | ||
// Return 400: Bad Request if any validation errors exist. | ||
response.status(400); | ||
return { errors: validationErrors }; | ||
} | ||
// Only query operations are allowed on GET requests. | ||
if (request.method === 'GET') { | ||
// Determine if this GET request will perform a non-query. | ||
var operationAST = (0, _graphqlUtilitiesGetOperationAST.getOperationAST)(documentAST, operationName); | ||
if (operationAST && operationAST.operation !== 'query') { | ||
// If GraphiQL can be shown, do not perform this query, but | ||
// provide it to GraphiQL so that the requester may perform it | ||
// themselves if desired. | ||
if (showGraphiQL) { | ||
return null; | ||
} | ||
// Perform the execution. | ||
resolve((0, _graphqlExecution.execute)(schema, documentAST, rootValue, variables, operationName)); | ||
// Otherwise, report a 405: Method Not Allowed error. | ||
response.set('Allow', 'POST'); | ||
throw (0, _httpErrors2['default'])(405, 'Can only perform a ' + operationAST.operation + ' operation ' + 'from a POST request.'); | ||
} | ||
})['catch'](function (error) { | ||
return { errors: [error] }; | ||
}).then(function (result) { | ||
} | ||
// Format any encountered errors. | ||
if (result.errors) { | ||
result.errors = result.errors.map(_graphqlError.formatError); | ||
} | ||
// Perform the execution, reporting any errors creating the context. | ||
try { | ||
return (0, _graphqlExecution.execute)(schema, documentAST, rootValue, variables, operationName); | ||
} catch (contextError) { | ||
// Return 400: Bad Request if any execution context errors exist. | ||
response.status(400); | ||
return { errors: [contextError] }; | ||
} | ||
})['catch'](function (error) { | ||
// If an error was caught, report the httpError status, or 500. | ||
response.status(error.status || 500); | ||
return { errors: [error] }; | ||
}).then(function (result) { | ||
// Format any encountered errors. | ||
if (result && result.errors) { | ||
result.errors = result.errors.map(_graphqlError.formatError); | ||
} | ||
// Report 200:Success if a data key exists, | ||
// Otherwise 400:BadRequest if only errors exist. | ||
response.status(result.hasOwnProperty('data') ? 200 : 400); | ||
// If allowed to show GraphiQL, present it instead of JSON. | ||
if (graphiql && canDisplayGraphiQL(request, data)) { | ||
response.set('Content-Type', 'text/html').send((0, _renderGraphiQL.renderGraphiQL)({ query: query, variables: variables, result: result })); | ||
} else { | ||
// Otherwise, present JSON directly. | ||
response.set('Content-Type', 'application/json').send(JSON.stringify(result, null, pretty ? 2 : 0)); | ||
} | ||
}); | ||
// If allowed to show GraphiQL, present it instead of JSON. | ||
if (showGraphiQL) { | ||
response.set('Content-Type', 'text/html').send((0, _renderGraphiQL.renderGraphiQL)({ query: query, variables: variables, result: result })); | ||
} else { | ||
// Otherwise, present JSON directly. | ||
response.set('Content-Type', 'application/json').send(JSON.stringify(result, null, pretty ? 2 : 0)); | ||
} | ||
}); | ||
@@ -202,10 +228,2 @@ }; | ||
} | ||
/** | ||
* Helper for formatting errors | ||
*/ | ||
function sendError(response, error, pretty) { | ||
var errorResponse = { errors: [(0, _graphqlError.formatError)(error)] }; | ||
response.status(error.status || 500).set('Content-Type', 'application/json').send(JSON.stringify(errorResponse, null, pretty ? 2 : 0)); | ||
} | ||
module.exports = exports['default']; | ||
@@ -212,0 +230,0 @@ |
@@ -19,3 +19,3 @@ | ||
// Current latest version of GraphiQL. | ||
var GRAPHIQL_VERSION = '0.4.2'; | ||
var GRAPHIQL_VERSION = '0.4.4'; | ||
@@ -31,8 +31,8 @@ /** | ||
function renderGraphiQL(data) { | ||
var queryString = data ? data.query : null; | ||
var variablesString = data && data.variables ? JSON.stringify(data.variables, null, 2) : null; | ||
var resultString = data && data.result ? JSON.stringify(data.result, null, 2) : null; | ||
var queryString = data.query; | ||
var variablesString = data.variables ? JSON.stringify(data.variables, null, 2) : null; | ||
var resultString = data.result ? JSON.stringify(data.result, null, 2) : null; | ||
/* eslint-disable max-len */ | ||
return '<!--\nThe request to this GraphQL server provided the header "Accept: text/html"\nand as a result has been presented GraphiQL - an in-browser IDE for\nexploring GraphQL.\n\nIf you wish to receive JSON, provide the header "Accept: application/json" or\nadd "&raw" to the end of the URL within a browser.\n-->\n<!DOCTYPE html>\n<html>\n<head>\n <link href="//cdn.jsdelivr.net/graphiql/' + GRAPHIQL_VERSION + '/graphiql.css" rel="stylesheet" />\n <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/0.14.2/react.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/0.14.2/react-dom.min.js"></script>\n <script src="//cdn.jsdelivr.net/graphiql/' + GRAPHIQL_VERSION + '/graphiql.min.js"></script>\n</head>\n<body>\n <script>\n // Collect the URL parameters\n var parameters = {};\n window.location.search.substr(1).split(\'&\').forEach(function (entry) {\n var eq = entry.indexOf(\'=\');\n if (eq >= 0) {\n parameters[decodeURIComponent(entry.slice(0, eq))] =\n decodeURIComponent(entry.slice(eq + 1));\n }\n });\n\n // Produce a Location query string from a parameter object.\n function locationQuery(params) {\n return \'?\' + Object.keys(params).map(function (key) {\n return encodeURIComponent(key) + \'=\' +\n encodeURIComponent(params[key]);\n }).join(\'&\');\n }\n\n // Derive a fetch URL from the current URL, sans the GraphQL parameters.\n var graphqlParamNames = {\n query: true,\n variables: true,\n operationName: true\n };\n\n var otherParams = {};\n for (var k in parameters) {\n if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {\n otherParams[k] = parameters[k];\n }\n }\n var fetchURL = locationQuery(otherParams);\n\n // Defines a GraphQL fetcher using the fetch API.\n function graphQLFetcher(graphQLParams) {\n return fetch(fetchURL, {\n method: \'post\',\n headers: { \'Content-Type\': \'application/json\' },\n body: JSON.stringify(graphQLParams),\n credentials: \'include\',\n }).then(function (response) {\n return response.json()\n });\n }\n\n // When the query and variables string is edited, update the URL bar so\n // that it can be easily shared.\n function onEditQuery(newQuery) {\n parameters.query = newQuery;\n updateURL();\n }\n\n function onEditVariables(newVariables) {\n parameters.variables = newVariables;\n updateURL();\n }\n\n function updateURL() {\n history.replaceState(null, null, locationQuery(parameters));\n }\n\n // Render <GraphiQL /> into the body.\n React.render(\n React.createElement(GraphiQL, {\n fetcher: graphQLFetcher,\n onEditQuery: onEditQuery,\n onEditVariables: onEditVariables,\n query: ' + JSON.stringify(queryString) + ',\n response: ' + JSON.stringify(resultString) + ',\n variables: ' + JSON.stringify(variablesString) + '\n }),\n document.body\n );\n </script>\n</body>\n</html>'; | ||
return '<!--\nThe request to this GraphQL server provided the header "Accept: text/html"\nand as a result has been presented GraphiQL - an in-browser IDE for\nexploring GraphQL.\n\nIf you wish to receive JSON, provide the header "Accept: application/json" or\nadd "&raw" to the end of the URL within a browser.\n-->\n<!DOCTYPE html>\n<html>\n<head>\n <link href="//cdn.jsdelivr.net/graphiql/' + GRAPHIQL_VERSION + '/graphiql.css" rel="stylesheet" />\n <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/0.14.2/react.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/0.14.2/react-dom.min.js"></script>\n <script src="//cdn.jsdelivr.net/graphiql/' + GRAPHIQL_VERSION + '/graphiql.min.js"></script>\n</head>\n<body>\n <script>\n // Collect the URL parameters\n var parameters = {};\n window.location.search.substr(1).split(\'&\').forEach(function (entry) {\n var eq = entry.indexOf(\'=\');\n if (eq >= 0) {\n parameters[decodeURIComponent(entry.slice(0, eq))] =\n decodeURIComponent(entry.slice(eq + 1));\n }\n });\n\n // Produce a Location query string from a parameter object.\n function locationQuery(params) {\n return \'?\' + Object.keys(params).map(function (key) {\n return encodeURIComponent(key) + \'=\' +\n encodeURIComponent(params[key]);\n }).join(\'&\');\n }\n\n // Derive a fetch URL from the current URL, sans the GraphQL parameters.\n var graphqlParamNames = {\n query: true,\n variables: true,\n operationName: true\n };\n\n var otherParams = {};\n for (var k in parameters) {\n if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {\n otherParams[k] = parameters[k];\n }\n }\n var fetchURL = locationQuery(otherParams);\n\n // Defines a GraphQL fetcher using the fetch API.\n function graphQLFetcher(graphQLParams) {\n return fetch(fetchURL, {\n method: \'post\',\n headers: {\n \'Accept\': \'application/json\',\n \'Content-Type\': \'application/json\'\n },\n body: JSON.stringify(graphQLParams),\n credentials: \'include\',\n }).then(function (response) {\n return response.json();\n });\n }\n\n // When the query and variables string is edited, update the URL bar so\n // that it can be easily shared.\n function onEditQuery(newQuery) {\n parameters.query = newQuery;\n updateURL();\n }\n\n function onEditVariables(newVariables) {\n parameters.variables = newVariables;\n updateURL();\n }\n\n function updateURL() {\n history.replaceState(null, null, locationQuery(parameters));\n }\n\n // Render <GraphiQL /> into the body.\n React.render(\n React.createElement(GraphiQL, {\n fetcher: graphQLFetcher,\n onEditQuery: onEditQuery,\n onEditVariables: onEditVariables,\n query: ' + JSON.stringify(queryString) + ',\n response: ' + JSON.stringify(resultString) + ',\n variables: ' + JSON.stringify(variablesString) + '\n }),\n document.body\n );\n </script>\n</body>\n</html>'; | ||
} |
{ | ||
"name": "express-graphql", | ||
"version": "0.4.4", | ||
"version": "0.4.5", | ||
"description": "Create a GraphQL HTTP server with Express.", | ||
@@ -68,3 +68,3 @@ "contributors": [ | ||
"express3": "*", | ||
"flow-bin": "0.14.0", | ||
"flow-bin": "0.18.1", | ||
"graphql": "0.4.8", | ||
@@ -71,0 +71,0 @@ "isparta": "3.0.3", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26713
359
3