express-graphql
Advanced tools
Comparing version 0.4.13 to 0.5.0
@@ -14,2 +14,5 @@ | ||
* and other configuration options. | ||
* | ||
* Options can be provided as an Object, a Promise for an Object, or a Function | ||
* that returns an Object or a Promise for an Object. | ||
*/ | ||
@@ -49,2 +52,3 @@ 'use strict'; | ||
var schema = undefined; | ||
var context = undefined; | ||
var rootValue = undefined; | ||
@@ -60,17 +64,30 @@ var pretty = undefined; | ||
// Use promises as a mechanism for capturing any thrown errors during the | ||
// asyncronous process. | ||
new Promise(function (resolve, reject) { | ||
// Promises are used as a mechanism for capturing any thrown errors during | ||
// the asyncronous process below. | ||
// Get GraphQL options given this request. | ||
var optionsObj = getOptions(options, request); | ||
schema = optionsObj.schema; | ||
rootValue = optionsObj.rootValue; | ||
pretty = optionsObj.pretty; | ||
graphiql = optionsObj.graphiql; | ||
formatErrorFn = optionsObj.formatError; | ||
// Resolve the Options to get OptionsData. | ||
new Promise(function (resolve) { | ||
resolve(typeof options === 'function' ? options(request) : options); | ||
}).then(function (optionsData) { | ||
// Assert that optionsData is in fact an Object. | ||
if (!optionsData || typeof optionsData !== 'object') { | ||
throw new Error('GraphQL middleware option function must return an options object.'); | ||
} | ||
// Assert that schema is required. | ||
if (!optionsData.schema) { | ||
throw new Error('GraphQL middleware options must contain a schema.'); | ||
} | ||
// Collect information from the options data object. | ||
schema = optionsData.schema; | ||
context = optionsData.context; | ||
rootValue = optionsData.rootValue; | ||
pretty = optionsData.pretty; | ||
graphiql = optionsData.graphiql; | ||
formatErrorFn = optionsData.formatError; | ||
validationRules = _graphql.specifiedRules; | ||
if (optionsObj.validationRules) { | ||
validationRules = validationRules.concat(optionsObj.validationRules); | ||
if (optionsData.validationRules) { | ||
validationRules = validationRules.concat(optionsData.validationRules); | ||
} | ||
@@ -85,9 +102,3 @@ | ||
// Parse the Request body. | ||
(0, _parseBody.parseBody)(request, function (parseError, data) { | ||
if (parseError) { | ||
reject(parseError); | ||
} else { | ||
resolve(data || {}); | ||
} | ||
}); | ||
return (0, _parseBody.parseBody)(request); | ||
}).then(function (data) { | ||
@@ -149,6 +160,5 @@ showGraphiQL = graphiql && canDisplayGraphiQL(request, data); | ||
} | ||
// Perform the execution, reporting any errors creating the context. | ||
try { | ||
return (0, _graphql.execute)(schema, documentAST, rootValue, variables, operationName); | ||
return (0, _graphql.execute)(schema, documentAST, rootValue, context, variables, operationName); | ||
} catch (contextError) { | ||
@@ -181,20 +191,2 @@ // Return 400: Bad Request if any execution context errors exist. | ||
/** | ||
* Get the options that the middleware was configured with, sanity | ||
* checking them. | ||
*/ | ||
function getOptions(options, request) { | ||
var optionsData = typeof options === 'function' ? options(request) : options; | ||
if (!optionsData || typeof optionsData !== 'object') { | ||
throw new Error('GraphQL middleware option function must return an options object.'); | ||
} | ||
if (!optionsData.schema) { | ||
throw new Error('GraphQL middleware options must contain a schema.'); | ||
} | ||
return optionsData; | ||
} | ||
/** | ||
* Helper function to get the GraphQL params from the request. | ||
@@ -239,2 +231,6 @@ */ | ||
/** | ||
* A value to pass as the context to the graphql() function. | ||
*/ | ||
/** | ||
* An object to pass as the rootValue to the graphql() function. | ||
@@ -241,0 +237,0 @@ */ |
@@ -40,7 +40,7 @@ | ||
function parseBody(req, next) { | ||
try { | ||
function parseBody(req) { | ||
return new Promise(function (resolve, reject) { | ||
// If express has already parsed a body as a keyed object, use it. | ||
if (typeof req.body === 'object' && !(req.body instanceof Buffer)) { | ||
return next(null, req.body); | ||
return resolve(req.body); | ||
} | ||
@@ -50,3 +50,3 @@ | ||
if (req.headers['content-type'] === undefined) { | ||
return next(); | ||
return resolve({}); | ||
} | ||
@@ -59,3 +59,3 @@ | ||
if (typeof req.body === 'string' && typeInfo.type === 'application/graphql') { | ||
return next(null, graphqlParser(req.body)); | ||
return resolve(graphqlParser(req.body)); | ||
} | ||
@@ -65,3 +65,3 @@ | ||
if (req.body) { | ||
return next(); | ||
return resolve({}); | ||
} | ||
@@ -72,14 +72,12 @@ | ||
case 'application/graphql': | ||
return read(req, typeInfo, graphqlParser, next); | ||
return read(req, typeInfo, graphqlParser, resolve, reject); | ||
case 'application/json': | ||
return read(req, typeInfo, jsonEncodedParser, next); | ||
return read(req, typeInfo, jsonEncodedParser, resolve, reject); | ||
case 'application/x-www-form-urlencoded': | ||
return read(req, typeInfo, urlEncodedParser, next); | ||
return read(req, typeInfo, urlEncodedParser, resolve, reject); | ||
} | ||
// If no Content-Type header matches, parse nothing. | ||
return next(); | ||
} catch (error) { | ||
return next(error); | ||
} | ||
return resolve({}); | ||
}); | ||
} | ||
@@ -120,3 +118,3 @@ | ||
// Read and parse a request body. | ||
function read(req, typeInfo, parseFn, next) { | ||
function read(req, typeInfo, parseFn, resolve, reject) { | ||
var charset = (typeInfo.parameters.charset || 'utf-8').toLowerCase(); | ||
@@ -138,3 +136,3 @@ | ||
if (err) { | ||
return next(err.type === 'encoding.unsupported' ? (0, _httpErrors2['default'])(415, 'Unsupported charset "' + charset.toUpperCase() + '".') : (0, _httpErrors2['default'])(400, 'Invalid body: ' + err.message + '.')); | ||
return reject(err.type === 'encoding.unsupported' ? (0, _httpErrors2['default'])(415, 'Unsupported charset "' + charset.toUpperCase() + '".') : (0, _httpErrors2['default'])(400, 'Invalid body: ' + err.message + '.')); | ||
} | ||
@@ -144,5 +142,5 @@ | ||
// Decode and parse body. | ||
return next(null, parseFn(body)); | ||
return resolve(parseFn(body)); | ||
} catch (error) { | ||
return next(error); | ||
return reject(error); | ||
} | ||
@@ -149,0 +147,0 @@ }); |
@@ -19,3 +19,3 @@ | ||
// Current latest version of GraphiQL. | ||
var GRAPHIQL_VERSION = '0.6.6'; | ||
var GRAPHIQL_VERSION = '0.7.0'; | ||
@@ -42,3 +42,3 @@ // Ensures string values are save to be used within a <script> tag. | ||
/* 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 <style>\n html, body {\n height: 100%;\n margin: 0;\n overflow: hidden;\n width: 100%;\n }\n </style>\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.7/react.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/0.14.7/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.text();\n }).then(function (responseBody) {\n try {\n return JSON.parse(responseBody);\n } catch (error) {\n return responseBody;\n }\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 onEditOperationName(newOperationName) {\n parameters.operationName = newOperationName;\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 onEditOperationName: onEditOperationName,\n query: ' + safeSerialize(queryString) + ',\n response: ' + safeSerialize(resultString) + ',\n variables: ' + safeSerialize(variablesString) + ',\n operationName: ' + safeSerialize(operationName) + ',\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 <style>\n html, body {\n height: 100%;\n margin: 0;\n overflow: hidden;\n width: 100%;\n }\n </style>\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/15.0.0/react.min.js"></script>\n <script src="//cdn.jsdelivr.net/react/15.0.0/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.text();\n }).then(function (responseBody) {\n try {\n return JSON.parse(responseBody);\n } catch (error) {\n return responseBody;\n }\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 onEditOperationName(newOperationName) {\n parameters.operationName = newOperationName;\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 onEditOperationName: onEditOperationName,\n query: ' + safeSerialize(queryString) + ',\n response: ' + safeSerialize(resultString) + ',\n variables: ' + safeSerialize(variablesString) + ',\n operationName: ' + safeSerialize(operationName) + ',\n }),\n document.body\n );\n </script>\n</body>\n</html>'; | ||
} |
{ | ||
"name": "express-graphql", | ||
"version": "0.4.13", | ||
"version": "0.5.0", | ||
"description": "Create a GraphQL HTTP server with Express.", | ||
@@ -53,5 +53,2 @@ "contributors": [ | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.4.16" | ||
}, | ||
"devDependencies": { | ||
@@ -70,3 +67,3 @@ "babel": "5.8.21", | ||
"flow-bin": "0.21.0", | ||
"graphql": "0.4.16", | ||
"graphql": "0.5.0", | ||
"isparta": "3.0.3", | ||
@@ -78,3 +75,6 @@ "mocha": "2.2.5", | ||
"supertest-as-promised": "2.0.2" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.5.0" | ||
} | ||
} |
@@ -31,5 +31,8 @@ GraphQL Express Middleware | ||
* **`rootValue`**: A value to pass as the rootValue to the `graphql()` | ||
* **`context`**: A value to pass as the `context` to the `graphql()` | ||
function from [`graphql-js`][]. | ||
* **`rootValue`**: A value to pass as the `rootValue` to the `graphql()` | ||
function from [`graphql-js`][]. | ||
* **`pretty`**: If `true`, any JSON response will be pretty-printed. | ||
@@ -113,6 +116,7 @@ | ||
express-graphql allows options to be provided as a function of each | ||
express request. | ||
express request, and that function may return either an options object, or a | ||
Promise for an options object. | ||
This example uses [`express-session`][] to run GraphQL on a rootValue based on | ||
the currently logged-in session. | ||
This example uses [`express-session`][] to provide GraphQL with the currently | ||
logged-in session as the `context` of the query execution. | ||
@@ -129,3 +133,3 @@ ```js | ||
schema: MySessionAwareGraphQLSchema, | ||
rootValue: { session: request.session }, | ||
context: request.session, | ||
graphiql: true | ||
@@ -135,3 +139,4 @@ }))); | ||
Then in your type definitions, access `session` from the rootValue: | ||
Then in your type definitions, access via the third "context" argument in your | ||
`resolve` function: | ||
@@ -144,3 +149,3 @@ ```js | ||
type: GraphQLString, | ||
resolve(parentValue, _, { rootValue: { session } }) { | ||
resolve(parentValue, args, session) { | ||
// use `session` here | ||
@@ -147,0 +152,0 @@ } |
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
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
29049
158
373