UNPKG

19.8 kBSource Map (JSON)View Raw
1{"version":3,"sources":["../es6/GQLExpressMiddleware.js"],"names":["GQLExpressMiddleware","EventEmitter","constructor","handlers","ast","clearCache","cache","clear","cached","get","schema","SchemaUtils","injectAll","set","generateSchemaSDL","rootValue","requestData","separateByType","root","createMergedRoot","middleware","customMiddleware","middlewareWithoutGraphiQL","graphiql","generateOptions","options","patchFn","optsFn","req","res","gql","opts","formatError","message","error","locations","stack","path","bind","generateApolloOptions","debug","resolvers","typeDefs","apolloMiddleware","apolloFn","apolloOpts","bodyParser","json","text","type","next","is","body","query","graphqlHttpOptions","schemaMiddleware","status","send","astMiddleware"],"mappings":"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","file":"GQLExpressMiddleware.js","sourceRoot":"es6","sourcesContent":["// @flow\n// @module GQLExpressMiddleware\n\nimport { SyntaxTree } from './SyntaxTree'\nimport { GQLBase } from './GQLBase'\nimport { GQLInterface } from './GQLInterface'\nimport { GQLScalar } from './GQLScalar'\nimport { typeOf } from 'ne-types'\nimport { SchemaUtils } from './SchemaUtils'\nimport _, { merge } from 'lodash'\nimport { makeExecutableSchema } from 'graphql-tools'\n\nimport {\n parse,\n print,\n buildSchema,\n GraphQLSchema,\n GraphQLInterfaceType,\n GraphQLEnumType,\n GraphQLScalarType\n} from 'graphql'\n\nimport bodyParser from 'body-parser'\nimport graphqlHTTP from 'express-graphql'\nimport EventEmitter from 'events'\nimport path from 'path'\n\n/**\n * A handler that exposes an express middleware function that mounts a\n * GraphQL I/O endpoint. Typical usage follows:\n *\n * ```js\n * const app = express();\n * app.use(/.../, new GQLExpressMiddleware([...classes]).middleware);\n * ```\n *\n * @class GQLExpressMiddleware\n */\nexport class GQLExpressMiddleware extends EventEmitter\n{\n handlers: Array<GQLBase>;\n\n schema: string;\n\n cache: Map<any, any> = new Map()\n\n /**\n * For now, takes an Array of classes extending from GQLBase. These are\n * parsed and a combined schema of all their individual schemas is generated\n * via the use of ASTs. This is passed off to express-graphql.\n *\n * @memberof GQLExpressMiddleware\n * @method ⎆⠀constructor\n * @constructor\n *\n * @param {Array<GQLBase>} handlers an array of GQLBase extended classes\n */\n constructor(handlers: Array<GQLBase>) {\n super()\n\n this.handlers = handlers\n\n // Generate and cache the schema SDL/IDL string and ast obj (GraphQLSchema)\n this.ast\n }\n\n /**\n * The Schema String and Schema AST/GraphQLSchema JavaScript objects are\n * cached after being processed once. If there is a runtime need to rebuild\n * these objects, calling `clearCache()` will allow their next usage to\n * rebuild them dynamically.\n *\n * @method clearCache\n * @memberof GQLExpressMiddleware\n *\n * @return {GQLExpressMiddleware} returns this so that it can be inlined; ala\n * `gqlExpressMiddleware.clearCache().ast`, for example\n */\n clearCache(): GQLExpressMiddleware {\n this.cache.clear()\n return this\n }\n\n /**\n * The schema property returns the textual Schema as it is generated based\n * on the various Lattice types, interfaces and enums defined in your\n * project. The ast property returns the JavaScript AST represenatation of\n * that schema with all injected modificiations detailed in your classes.\n */\n get ast(): GraphQLSchema {\n let cached: ?GraphQLSchema = this.cache.get('ast')\n\n if (cached) {\n return cached\n }\n\n let ast: GraphQLSchema = buildSchema(this.schema)\n\n SchemaUtils.injectAll(ast, this.handlers);\n\n this.cache.set('ast', ast)\n\n return ast;\n }\n\n /**\n * Generates the textual schema based on the registered `GQLBase` handlers\n * this instance represents.\n *\n * @method GQLExpressMiddleware#⬇︎⠀schema\n * @since 2.7.0\n *\n * @return {string} a generated schema string based on the handlers that\n * are registered with this `GQLExpressMiddleware` instance.\n */\n get schema(): string {\n let cached = this.cache.get('schema')\n let schema\n\n if (cached) return cached\n\n schema = SchemaUtils.generateSchemaSDL(this.handlers);\n this.cache.set('schema', schema)\n\n return schema\n }\n\n async rootValue(\n requestData: Object,\n separateByType: boolean = false\n ): Object {\n let root = await SchemaUtils.createMergedRoot(\n this.handlers, requestData, separateByType\n )\n\n return root;\n }\n\n /**\n * Using the express-graphql module, it returns an Express 4.x middleware\n * function.\n *\n * @instance\n * @memberof GQLExpressMiddleware\n * @method ⬇︎⠀middleware\n *\n * @return {Function} a function that expects request, response and next\n * parameters as all Express middleware functions.\n */\n get middleware(): Function {\n return this.customMiddleware();\n }\n\n /**\n * Using the express-graphql module, it returns an Express 4.x middleware\n * function. This version however, has graphiql disabled. Otherwise it is\n * identical to the `middleware` property\n *\n * @instance\n * @memberof GQLExpressMiddleware\n * @method ⬇︎⠀middlewareWithoutGraphiQL\n *\n * @return {Function} a function that expects request, response and next\n * parameters as all Express middleware functions.\n */\n get middlewareWithoutGraphiQL(): Function {\n return this.customMiddleware({graphiql: false});\n }\n\n /**\n * In order to ensure that Lattice functions receive the request data,\n * it is important to use the options function feature of both\n * `express-graphql` and `apollo-server-express`. This function will create\n * an options function that reflects that schema and Lattice types defined\n * in your project.\n *\n * Should you need to tailor the response before it is sent out, you may\n * supply a function as a second parameter that takes two parameters and\n * returns an options object. The patchFn callback signature looks like this\n *\n * ```patchFn(options, {req, res, next|gql})```\n *\n * When using the reference implementation, additional graphql request info\n * can be obtained in lieu of the `next()` function so typically found in\n * Express middleware. Apollo Server simply provides the next function in\n * this location.\n *\n * @param {Object} options any options, to either engine, that make the most\n * sense\n * @param {Function} patchFn see above\n */\n generateOptions(\n options: Object = { graphiql: true },\n patchFn: ?Function = null\n ): Function {\n const optsFn = async (req: mixed, res: mixed, gql: mixed) => {\n let schema = this.ast;\n let opts = {\n schema,\n rootValue: await this.rootValue({req, res, gql}),\n formatError: error => ({\n message: error.message,\n locations: error.locations,\n stack: error.stack,\n path: error.path\n })\n }\n\n merge(opts, options);\n if (patchFn && typeof patchFn === 'function') {\n merge(\n opts,\n (patchFn.bind(this)(opts, {req, res, gql})) || opts\n );\n }\n\n return opts;\n }\n\n return optsFn\n }\n\n /**\n * In order to ensure that Lattice functions receive the request data,\n * it is important to use the options function feature of both\n * `express-graphql` and `apollo-server-express`. This function will create\n * an options function that reflects that schema and Lattice types defined\n * in your project.\n *\n * Should you need to tailor the response before it is sent out, you may\n * supply a function as a second parameter that takes two parameters and\n * returns an options object. The patchFn callback signature looks like this\n *\n * ```patchFn(options, {req, res, next|gql})```\n *\n * When using the reference implementation, additional graphql request info\n * can be obtained in lieu of the `next()` function so typically found in\n * Express middleware. Apollo Server simply provides the next function in\n * this location.\n *\n * @param {Object} options any options, to either engine, that make the most\n * sense\n * @param {Function} patchFn see above\n */\n generateApolloOptions(\n options: Object = {\n formatError: error => ({\n message: error.message,\n locations: error.locations,\n stack: error.stack,\n path: error.path\n }),\n debug: true\n },\n patchFn: ?Function = null\n ): Function {\n const optsFn = async (req: mixed, res: mixed) => {\n let opts = {\n schema: this.ast,\n resolvers: await this.rootValue({req, res}, true)\n }\n\n opts.schema = makeExecutableSchema({\n typeDefs: [this.schema],\n resolvers: opts.resolvers\n })\n\n SchemaUtils.injectAll(opts.schema, this.handlers);\n\n merge(opts, options);\n if (patchFn && typeof patchFn === 'function') {\n merge(\n opts,\n (patchFn.bind(this)(opts, {req, res})) || opts\n );\n }\n\n return opts;\n }\n\n return optsFn\n }\n\n apolloMiddleware(\n apolloFn: Function,\n apolloOpts: Object = {},\n patchFn: ?Function = null\n ): Array<Function> {\n let opts = this.generateApolloOptions(apolloOpts, patchFn)\n\n return [\n bodyParser.json(),\n bodyParser.text({ type: 'application/graphql' }),\n (req, res, next) => {\n if (req.is('application/graphql')) {\n req.body = { query: req.body };\n }\n next();\n },\n apolloFn(opts)\n ]\n }\n\n /**\n * If your needs require you to specify different values to `graphqlHTTP`,\n * part of the `express-graphql` package, you can use the `customMiddleware`\n * function to do so.\n *\n * The first parameter is an object that should contain valid `graphqlHTTP`\n * options. See https://github.com/graphql/express-graphql#options for more\n * details. Validation is NOT performed.\n *\n * The second parameter is a function that will be called after any options\n * have been applied from the first parameter and the rest of the middleware\n * has been performed. This, if not modified, will be the final options\n * passed into `graphqlHTTP`. In your callback, it is expected that the\n * supplied object is to be modified and THEN RETURNED. Whatever is returned\n * will be used or passed on. If nothing is returned, the options supplied\n * to the function will be used instead.\n *\n * @method ⌾⠀customMiddleware\n * @memberof GQLExpressMiddleware\n * @instance\n *\n * @param {Object} [graphqlHttpOptions={graphiql: true}] standard set of\n * `express-graphql` options. See above.\n * @param {Function} patchFn see above\n\n * @return {Function} a middleware function compatible with Express\n */\n customMiddleware(\n graphqlHttpOptions: Object = {graphiql: true},\n patchFn?: Function\n ): Function {\n const optsFn = this.generateOptions(graphqlHttpOptions, patchFn)\n return graphqlHTTP(optsFn)\n }\n\n /**\n * An optional express middleware function that can be mounted to return\n * a copy of the generated schema string being used by GQLExpressMiddleware.\n *\n * @memberof GQLExpressMiddleware\n * @method schemaMiddleware\n * @instance\n *\n * @type {Function}\n */\n get schemaMiddleware(): Function {\n return (req: Object, res: Object, next: ?Function) => {\n res.status(200).send(this.schema);\n }\n }\n\n /**\n * An optional express middleware function that can be mounted to return\n * the JSON AST representation of the schema string being used by\n * GQLExpressMiddleware.\n *\n * @memberof GQLExpressMiddleware\n * @method astMiddleware\n * @instance\n *\n * @type {Function}\n */\n get astMiddleware(): Function {\n return (req: Object, res: Object, next: ?Function) => {\n res.status(200).send('Temporarily disabled in this version')\n\n // let cachedOutput = this.cache.get('astMiddlewareOutput')\n // if (cachedOutput) {\n // res\n // .status(302)\n // .set('Content-Type', 'application/json')\n // .send(cachedOutput)\n // }\n // else {\n // this.rootValue({req, res, next}, true)\n // .then(resolvers => {\n // let schema: GraphQLSchema = buildSchema(this.schema)\n\n // SchemaUtils.injectInterfaceResolvers(schema, this.handlers);\n // SchemaUtils.injectEnums(schema, this.handlers);\n // SchemaUtils.injectScalars(schema, this.handlers);\n // SchemaUtils.injectComments(schema, this.handlers);\n\n // function killToJSON(obj: any, path = 'obj.') {\n // for (let key in obj) {\n // try {\n // if (key == 'prev' || key == 'next' || key == 'ofType') continue;\n\n // if (key == 'toJSON') {\n // let success = delete obj.toJSON\n // //console.log(`Killing ${path}toJSON...${success ? 'success' : 'failure'}`)\n // continue\n // }\n\n // if (key == 'inspect') {\n // let success = delete obj.inspect\n // //console.log(`Killing ${path}inspect...${success ? 'success' : 'failure'}`)\n // continue\n // }\n\n // if (key == 'toString') {\n // obj.toString = Object.prototype.toString\n // //console.log(`Replacing ${path}toString with default`)\n // continue\n // }\n\n // if (typeof obj[key] == 'function') {\n // obj[key] = `[Function ${obj[key].name}]`\n // continue\n // }\n\n // if (typeof obj[key] == 'object') {\n // obj[key] = killToJSON(obj[key], `${path}${key}.`)\n // continue\n // }\n // }\n // catch (error) {\n // continue\n // }\n // }\n\n // return obj\n // }\n\n // // $FlowFixMe\n // schema = killToJSON(schema)\n\n // // Still do not know why/how they are preventing JSONifying the\n // // _typeMap keys. So aggravting\n // for (let typeKey of Object.keys(schema._typeMap)) {\n // let object = {}\n\n // // $FlowFixMe\n // for (let valKey of Object.keys(schema._typeMap[typeKey])) {\n // // $FlowFixMe\n // object[valKey] = schema._typeMap[typeKey][valKey]\n // }\n\n // // $FlowFixMe\n // schema._typeMap[typeKey] = object\n // }\n\n // let output = JSON.stringify(schema)\n // this.cache.delete('ast')\n // this.cache.set('astMiddlewareOutput', output)\n\n // res\n // .status(200)\n // .set('Content-Type', 'application/json')\n // .send(output)\n // })\n // .catch(error => {\n // console.error(error)\n\n // res\n // .status(500)\n // .json(error)\n // })\n // }\n }\n }\n}\n\nexport default GQLExpressMiddleware;\n"]}
\No newline at end of file