UNPKG

65.2 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width,initial-scale=1">
6 <title>GQLBase.js - Documentation</title>
7
8 <script src="scripts/prettify/prettify.js"></script>
9 <script src="scripts/prettify/lang-css.js"></script>
10 <!--[if lt IE 9]>
11 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
12 <![endif]-->
13 <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
14 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
15 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
16</head>
17<body>
18
19<input type="checkbox" id="nav-trigger" class="nav-trigger" />
20<label for="nav-trigger" class="navicon-button x">
21 <div class="navicon"></div>
22</label>
23
24<label for="nav-trigger" class="overlay"></label>
25
26<nav>
27 <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="AwaitingPromiseError.html">AwaitingPromiseError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="AwaitingPromiseError.html#%25E2%258C%25BE%25E2%25A0%2580asyncFn">⌾⠀asyncFn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="AwaitingPromiseError.html#%25E2%258C%25BE%25E2%25A0%2580setPromise">⌾⠀setPromise</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="AwaitingPromiseError_exports.AwaitingPromiseError.html">AwaitingPromiseError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="AwaitingPromiseError_exports.AwaitingPromiseError.html#setPromise">setPromise</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Deferred_exports.Deferred.html">Deferred</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="DirectTypeAdd.html">DirectTypeAdd</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="FunctionExecutionError_FunctionExecutionError.html">FunctionExecutionError</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLBase.html">GQLBase</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.apiDocs">apiDocs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580getMergedRoot">⌾⠀getMergedRoot</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580getProp">⌾⠀getProp</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580getResolver">⌾⠀getResolver</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580IDLFilePath">⌾⠀IDLFilePath</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580MUTATORS">⌾⠀MUTATORS</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580RESOLVERS">⌾⠀RESOLVERS</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%258C%25BE%25E2%25A0%2580setupModel">⌾⠀setupModel</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580handler">⬇︎⠀handler</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580SCHEMA">⬇︎⠀SCHEMA</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580applyAutoProps">⌾⠀applyAutoProps</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580callProp">⌾⠀callProp</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580extendModel">⌾⠀extendModel</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580getModel">⌾⠀getModel</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580getProp">⌾⠀getProp</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580getResolver">⌾⠀getResolver</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%258C%25BE%25E2%25A0%2580setModel">⌾⠀setModel</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%25AC%2586%25EF%25B8%258E%25E2%25A0%2580requestData">⬆︎⠀requestData</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580requestData">⬇︎⠀requestData</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#~deleteProperty">deleteProperty</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBase.html#~set">set</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLBase.%25E2%258E%2586%25E2%25A0%2580constructor.html">⎆⠀constructor</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLEnum.html">GQLEnum</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#..get">.get</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#..set">.set</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#.valueFor">valueFor</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580enums">⬇︎⠀enums</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580name">⬇︎⠀name</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580value">⬇︎⠀value</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#.%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580values">⬇︎⠀values</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLEnum.html#GenerateEnumsProxyHandler">GenerateEnumsProxyHandler</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html">GQLExpressMiddleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#.clearCache">clearCache</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#.%25E2%258C%25BE%25E2%25A0%2580generateSchemaSDL">⌾⠀generateSchemaSDL</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#astMiddleware">astMiddleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#schemaMiddleware">schemaMiddleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#%25E2%258C%25BE%25E2%25A0%2580customMiddleware">⌾⠀customMiddleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580middleware">⬇︎⠀middleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580middlewareWithoutGraphiQL">⬇︎⠀middlewareWithoutGraphiQL</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLExpressMiddleware.html#%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580schema">⬇︎⠀schema</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLExpressMiddleware.%25E2%258E%2586%25E2%25A0%2580constructor.html">⎆⠀constructor</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLInterface.html">GQLInterface</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLInterface.html#.%25E2%258C%25BE%25E2%25A0%2580resolveType">⌾⠀resolveType</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="GQLScalar.html">GQLScalar</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLScalar.html#.parseLiteral">parseLiteral</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLScalar.html#.parseValue">parseValue</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLScalar.html#.serialize">serialize</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="IDLFileHandler.html">IDLFileHandler</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IDLFileHandler.html#%25E2%258C%25BE%25E2%25A0%2580getFile">⌾⠀getFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IDLFileHandler.html#%25E2%258C%25BE%25E2%25A0%2580getSchema">⌾⠀getSchema</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="IDLFileHandler.html#%25E2%258C%25BE%25E2%25A0%2580getSyntaxTree">⌾⠀getSyntaxTree</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="IDLFileHandler.%25E2%258E%2586%25E2%25A0%2580constructor.html">⎆⠀constructor</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ModuleParser.html">ModuleParser</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#.%25E2%258C%25BE%25E2%25A0%2580arrayToPattern">⌾⠀arrayToPattern</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#.%25E2%258C%25BE%25E2%25A0%2580checkForPackageExtensions">⌾⠀checkForPackageExtensions</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#%25E2%258C%25BE%25E2%25A0%2580findGQLBaseClasses">⌾⠀findGQLBaseClasses</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#%25E2%258C%25BE%25E2%25A0%2580importClass">⌾⠀importClass</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#%25E2%258C%25BE%25E2%25A0%2580parse">⌾⠀parse</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#%25E2%258C%25BE%25E2%25A0%2580parseSync">⌾⠀parseSync</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#~%25E2%258C%25BE%25E2%25A0%2580walk">⌾⠀walk</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#~%25E2%258C%25BE%25E2%25A0%2580walkSync">⌾⠀walkSync</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="ModuleParser.html#~%25E2%258E%2586%25E2%25A0%2580constructor">⎆⠀constructor</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ModuleParser.exports.ModuleParser.html">exports.ModuleParser</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="SchemaUtils.html">SchemaUtils</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SchemaUtils.html#.%25E2%258C%25BE%25E2%25A0%2580createMergedRoot">⌾⠀createMergedRoot</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SchemaUtils.html#.%25E2%258C%25BE%25E2%25A0%2580injectComments">⌾⠀injectComments</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SchemaUtils.html#.%25E2%258C%25BE%25E2%25A0%2580injectEnums">⌾⠀injectEnums</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SchemaUtils.html#.%25E2%258C%25BE%25E2%25A0%2580injectInterfaceResolvers">⌾⠀injectInterfaceResolvers</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SchemaUtils.html#.%25E2%258C%25BE%25E2%25A0%2580injectScalars">⌾⠀injectScalars</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="SyntaxTree.html">SyntaxTree</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580EmptyDocument">⌾⠀EmptyDocument</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580EmptyMutation">⌾⠀EmptyMutation</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580EmptyQuery">⌾⠀EmptyQuery</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580findDefinition">⌾⠀findDefinition</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580findField">⌾⠀findField</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580findInASTArrayByNameValue">⌾⠀findInASTArrayByNameValue</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580from">⌾⠀from</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580fromAST">⌾⠀fromAST</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258C%25BE%25E2%25A0%2580fromSchema">⌾⠀fromSchema</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#.%25E2%258E%2586%25E2%25A0%2580constructor">⎆⠀constructor</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580appendDefinitions">⌾⠀appendDefinitions</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580consumeDefinition">⌾⠀consumeDefinition</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580find">⌾⠀find</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580findEnumDefinition">⌾⠀findEnumDefinition</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580setAST">⌾⠀setAST</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580toString">⌾⠀toString</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%258C%25BE%25E2%25A0%2580updateAST">⌾⠀updateAST</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%25AC%2586%25EF%25B8%258E%25E2%25A0%2580ast">⬆︎⠀ast</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="SyntaxTree.html#%25E2%25AC%2587%25EF%25B8%258E%25E2%25A0%2580ast">⬇︎⠀ast</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="utils.Deferred.html">Deferred</a></span></li><li class="nav-heading">Namespaces</li><li class="nav-heading"><span class="nav-item-type type-namespace">N</span><span class="nav-item-name"><a href="decorators.html">decorators</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#.%25E2%258C%25BE%25E2%25A0%2580extractBits">⌾⠀extractBits</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580AdjacentSchema">.🏷⠀AdjacentSchema</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580FileSchema">.🏷⠀FileSchema</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580Getters">.🏷⠀Getters</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580Properties">.🏷⠀Properties</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580Schema">.🏷⠀Schema</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#..%25F0%259F%258F%25B7%25E2%25A0%2580Setters">.🏷⠀Setters</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="decorators.html#~decorate">decorate</a></span></li><li class="nav-heading"><span class="nav-item-type type-namespace">N</span><span class="nav-item-name"><a href="GQLBaseEnv.html">GQLBaseEnv</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="GQLBaseEnv.html#~notDefined">notDefined</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#applyTags">applyTags</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#AsyncFunctionExecutionError">AsyncFunctionExecutionError</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#CHECK_API_DOCS">CHECK_API_DOCS</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#CHECK_RESOLVERS">CHECK_RESOLVERS</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#CHECK_SCHEMA">CHECK_SCHEMA</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#CHECKLIST">CHECKLIST</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#FunctionExecutionError">FunctionExecutionError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getChecklist">getChecklist</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#hasChecklist">hasChecklist</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#newChecklist">newChecklist</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setChecklist">setChecklist</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#types">types</a></span></li>
28</nav>
29
30<div id="main">
31
32 <h1 class="page-title">GQLBase.js</h1>
33
34
35
36
37
38
39
40 <section>
41 <article>
42 <pre class="prettyprint source linenums"><code>/** @namespace GQLBaseEnv */
43// @flow
44
45import Path from 'path'
46import fs from 'fs'
47
48import { Deferred, joinLines } from './utils'
49import { typeOf } from 'ne-types'
50import { SyntaxTree } from './SyntaxTree'
51import { Properties } from './decorators/ModelProperties'
52import { GraphQLObjectType, GraphQLEnumType } from 'graphql'
53import { IDLFileHandler } from './IDLFileHandler'
54import { merge } from 'lodash'
55import { LatticeLogs as ll } from './utils'
56import { dedent } from 'ne-tag-fns'
57
58import AsyncFunctionExecutionError from './errors/AsyncFunctionExecutionError'
59import FunctionExecutionError from './errors/FunctionExecutionError'
60import AwaitingPromiseError from './errors/AwaitingPromiseError'
61
62import EventEmitter from 'events'
63
64/* Internal implementation to detect the existence of proxies. When present
65 * additional functionality is enabled. Proxies are native in Node >= 6 */
66const hasProxy = typeof global.Proxy !== 'undefined';
67
68/* Internal Symbol referring to real accessor to GQLBase model object */
69const _MODEL_KEY = Symbol.for('data-model-contents-value');
70
71/* Internal Symbol referring to the static object containing a proxy handler */
72const _PROXY_HANDLER = Symbol.for('internal-base-proxy-handler')
73
74/**
75 * Simple function to check if a supplied key matches a string of your
76 * choosing and that string is not a defined property on the instance
77 * passed to the check.
78 *
79 * @method GQLBaseEnv~notDefined
80 * @memberof GQLBaseEnv
81 * @since 2.5.0
82 *
83 * @param {string} keyToTest a String denoting the property you wish to test
84 * @param {mixed} keySupplied a value, coerced `toString()`, to compare to
85 * `keyToTest`
86 * @param {mixed} instance an object instance to check `hasOwnProperty` on for
87 * the `keyToTest` supplied.
88 * @return {Boolean} true if the property matches the supplied key and that
89 * property is not an ownedProperty of the instance supplied.
90 */
91export function notDefined(
92 keyToTest: string,
93 keySupplied: Object | string,
94 instance: Object
95) {
96 return (
97 new RegExp("^" + keyToTest + "$").test(keySupplied.toString())
98 &amp;&amp; !instance.hasOwnProperty(keyToTest)
99 );
100}
101
102/**
103 * A `Symbol` used as a key to store the backing model data. Designed as a
104 * way to separate model data and GraphQL property accessors into logical bits.
105 *
106 * @type {Symbol}
107 * @memberof GQLBaseEnv
108 * @const
109 */
110export const MODEL_KEY = Symbol.for('data-model-contents-key');
111
112/**
113 * A `Symbol` used as a key to store the request data for an instance of the
114 * GQLBase object in question.
115 *
116 * @type {Symbol}
117 * @const
118 * @inner
119 * @memberof GQLBaseEnv
120 */
121export const REQ_DATA_KEY = Symbol.for('request-data-object-key');
122
123/**
124 * A nameless Symbol for use as a key to the internal decorator storage
125 *
126 * @type {Symbol}
127 * @const
128 * @inner
129 * @memberof GQLBaseEnv
130 */
131export const META_KEY = Symbol();
132
133/**
134 * A Symbol used to identify calls to @Properties for properties generated
135 * automatically upon instance creation.
136 *
137 * @type {Symbol}
138 * @const
139 * @inner
140 * @memberOf GQLBaseEnv
141 */
142export const AUTO_PROPS = Symbol.for('auto-props')
143
144/**
145 * A Symbol used to identify calls to @Getters for properties generated
146 * via decorator. These are stored in &lt;class>[META_KEY][GETTERS]
147 *
148 * @type {Symbol}
149 * @const
150 * @inner
151 * @memberOf GQLBaseEnv
152 */
153export const GETTERS = Symbol.for('getters')
154
155/**
156 * A Symbol used to identify calls to @Setters for properties generated
157 * via decorator. These are stored in &lt;class>[META_KEY][SETTERS]
158 *
159 * @type {Symbol}
160 * @const
161 * @inner
162 * @memberOf GQLBaseEnv
163 */
164export const SETTERS = Symbol.for('setters')
165
166/**
167 * A Symbol used to identify calls to @Properties for properties generated
168 * via decorator. These are stored in &lt;class>[META_KEY][PROPS]
169 *
170 * @type {Symbol}
171 * @const
172 * @inner
173 * @memberOf GQLBaseEnv
174 */
175export const PROPS = Symbol.for('props')
176
177/**
178 * All GraphQL Type objects used in this system are assumed to have extended
179 * from this class. An instance of this class can be used to wrap an existing
180 * structure if you have one.
181 *
182 * @class GQLBase
183 */
184export class GQLBase extends EventEmitter {
185 fileHandler: ?IDLFileHandler;
186
187 /**
188 * Request data is passed to this object when constructed. Typically these
189 * objects, and their children, are instantiated by its own static MUTATORS
190 * and RESOLVERS. They should contain request specific state if any is to
191 * be shared.
192 *
193 * These can be considered request specific controllers for the object in
194 * question. The base class takes a single object which should contain all
195 * the HTTP/S request data and the graphQLParams is provided as the object
196 * { query, variables, operationName, raw }.
197 *
198 * When used with express-graphql, the requestData object has the format
199 * { req, res, gql } where
200 * • req is an Express 4.x request object
201 * • res is an Express 4.x response object
202 * • gql is the graphQLParams object in the format of
203 * { query, variables, operationName, raw }
204 * See https://github.com/graphql/express-graphql for more info
205 *
206 * @memberof GQLBase
207 * @method ⎆⠀constructor
208 * @constructor
209 *
210 * @param {mixed} modelData this, typically an object, although anything
211 * really is supported, represents the model data for our GraphQL object
212 * instance.
213 * @param {Object} requestData see description above
214 */
215 constructor(
216 modelData: Object = {},
217 requestData: ?Object = null,
218 options: Object = { autoProps: true }
219 ) {
220 super();
221
222 const Class = this.constructor;
223 const tree = SyntaxTree.from(Class.SCHEMA);
224 const outline = tree &amp;&amp; tree.outline || null;
225
226 if (!outline) {
227 throw new FunctionExecutionError(
228 new Error(dedent`
229 The SDL is unparsable. Please check your SCHEMA and make sure
230 it is valid GraphQL SDL/IDL. Your SCHEMA is defined as:
231
232 ${this.SCHEMA}
233 `)
234 )
235 }
236
237 if (outline &amp;&amp; !(Class.name in outline)) {
238 throw new FunctionExecutionError(
239 new Error(dedent`
240 The class name "${Class.name}" does not match any of the types,
241 enums, scalars, unions or interfaces defined in the SCHEMA for
242 this class (${Object.keys(outline)}).
243
244 \x1b[1mIn most clases this is because your class name and SCHEMA
245 type do not match.\x1b[0m
246 `)
247 )
248 }
249
250 GQLBase.setupModel(this);
251 this.setModel(modelData);
252 this.requestData = requestData || {};
253 this.fileHandler = new IDLFileHandler(this.constructor);
254
255 if (options &amp;&amp; !!options.autoProps !== false) {
256 this.applyAutoProps()
257 }
258
259 // @ComputedType
260 return hasProxy ? new Proxy(this, GQLBase[_PROXY_HANDLER]) : this;
261 }
262
263 /**
264 * Since reading the Schema for a given GraphQL Lattice type or
265 * interface is simple enough, we should be able to automatically
266 * apply one to one GraphQL:Model properties.
267 *
268 * @instance
269 * @method ⌾⠀applyAutoProps
270 * @memberof GQLBase
271 */
272 applyAutoProps() {
273 if (!this.constructor.SCHEMA || !this.constructor.SCHEMA.length) {
274 ll.warn(joinLines`
275 There is no SCHEMA for ${this.constructor.name}!! This will likely
276 end in an error. Proceed with caution. Skipping \`applyAutoProps\`
277 `)
278 return
279 }
280
281 // Individual property getters do not need to be auto-created for enum
282 // types. Potentially do some checks for Interfaces and Unions as well
283 if (this.constructor.GQL_TYPE === GraphQLEnumType) {
284 return
285 }
286
287 let Class = this.constructor
288 let tree = SyntaxTree.from(Class.SCHEMA)
289 let outline = tree ? tree.outline : {}
290 let props = []
291
292 // $FlowFixMe
293 for (let propName of Object.keys(outline[Class.name])) {
294 // $FlowFixMe
295 let desc = Object.getOwnPropertyDescriptor(Class.prototype, propName)
296 let hasCustomImpl = !!(
297 // We have a descriptor for the property name
298 desc &amp;&amp; (
299 // We have a getter function defined
300 typeof desc.get !== 'undefined'
301 ||
302 // ...or we have a function, async or not, defined
303 typeof desc.value === 'function'
304 )
305 )
306
307 // Only create auto-props for non custom implementations
308 if (!hasCustomImpl) {
309 props.push(propName)
310 }
311 }
312
313 if (props.length) {
314 ll.info(`Creating auto-props for [${Class.name}]: `, props)
315 try {
316 Properties(...props)(Class, [AUTO_PROPS])
317 }
318 catch(error) {
319 let parsed = /Cannot redefine property: (\w+)/.exec(error.message)
320 if (parsed) {
321 ll.warn(`Skipping auto-prop '${Class.name}.${parsed[1]}'`)
322 }
323 else {
324 ll.error(`Failed to apply auto-properties\nReason: `)
325 ll.error(error);
326 }
327 }
328 }
329 }
330
331 /**
332 * Getter for the internally stored model data. The contents of this
333 * object are abstracted away behind a `Symbol` key to prevent collision
334 * between the underlying model and any GraphQL Object Definition properties.
335 *
336 * @instance
337 * @memberof GQLBase
338 * @method ⌾⠀getModel
339 * @since 2.5
340 *
341 * @param {Object} value any object you wish to use as a data store
342 */
343 getModel() {
344 // @ComputedType
345 return this[MODEL_KEY];
346 }
347
348 /**
349 * Setter for the internally stored model data. The contents of this
350 * object are abstracted away behind a `Symbol` key to prevent collision
351 * between the underlying model and any GraphQL Object Definition properties.
352 *
353 * @instance
354 * @memberof GQLBase
355 * @method ⌾⠀setModel
356 * @since 2.5
357 *
358 * @param {Object} value any object you wish to use as a data store
359 */
360 setModel(value: Object): GQLBase {
361 // @ComputedType
362 this[MODEL_KEY] = value;
363 return this;
364 }
365
366 /**
367 * Uses `_.merge()` to modify the internal backing data store for the
368 * object instance. This is a shortcut for
369 * `_.merge()(instance[MODEL_KEY], ...extensions)`
370 *
371 * @instance
372 * @memberof GQLBase
373 * @method ⌾⠀extendModel
374 * @since 2.5
375 *
376 * @param {mixed} extensions n-number of valid `_.merge()` parameters
377 * @return {GQLBase} this is returned
378 */
379 extendModel(...extensions: Array&lt;mixed>): GQLBase {
380 // $FlowFixMe
381 merge(this[MODEL_KEY], ...extensions);
382 return this;
383 }
384
385 /**
386 * A getter that retrieves the inner request data object. When used with
387 * GQLExpressMiddleware, this is an object matching {req, res, gql}.
388 *
389 * @instance
390 * @memberof GQLBase
391 * @method ⬇︎⠀requestData
392 *
393 * @return {Object} an object, usually matching { req, res, gql }
394 */
395 get requestData(): Object | null {
396 // @ComputedType
397 return this[REQ_DATA_KEY];
398 }
399
400 /**
401 * A setter that assigns a value to the inner request data object. When
402 * used with GQLExpressMiddleware, this is an object matching {req, res, gql}.
403 *
404 * @instance
405 * @memberof GQLBase
406 * @method ⬆︎⠀requestData
407 *
408 * @param {Object} value an object, usually matching { req, res, gql }
409 */
410 set requestData(value: Object): void {
411 // @ComputedType
412 this[REQ_DATA_KEY] = value;
413 }
414
415 /**
416 * Returns the `constructor` name. If invoked as the context, or `this`,
417 * object of the `toString` method of `Object`'s `prototype`, the resulting
418 * value will be `[object MyClass]`, given an instance of `MyClass`
419 *
420 * @method ⌾⠀[Symbol.toStringTag]
421 * @memberof ModuleParser
422 *
423 * @return {string} the name of the class this is an instance of
424 * @ComputedType
425 */
426 get [Symbol.toStringTag]() { return this.constructor.name }
427
428 /**
429 * Properties defined for GraphQL types in Lattice can be defined as
430 * a getter, a function or an async function. In the case of standard
431 * functions, if they return a promise they will be handled as though
432 * they were async
433 *
434 * Given the variety of things a GraphQL type can actually be, obtaining
435 * its value can annoying. This method tends to lessen that boilerplate.
436 * Errors raised will be thrown.
437 *
438 * @instance
439 * @memberof GQLBase
440 * @method ⌾⠀getProp
441 *
442 * @param {string|Symbol} propName the name of the property in question
443 * @param {boolean} bindGetters true, by default, if the `get` or
444 * `initializer` descriptor values should be bound to the current instance
445 * or an object of the programmers choice before returning
446 * @param {mixed} bindTo the `this` object to use for binding when
447 * `bindGetters` is set to true.
448 * @return {mixed} the value of the `propName` as a Function or something
449 * else when the requested property name exists
450 *
451 * @throws {Error} errors raised in awaiting results will be thrown
452 */
453 getProp(propName: string, bindGetters: boolean = true, bindTo: mixed) {
454 // $FlowFixMe
455 let proto = Object.getPrototypeOf(this)
456 let descriptor = Object.getOwnPropertyDescriptor(proto, propName)
457 let result
458
459 if (!descriptor) {
460 return null;
461 }
462
463 if (descriptor) {
464 if (descriptor.initializer || descriptor.get) {
465 let what = descriptor.initializer || descriptor.get
466
467 if (bindGetters) {
468 result = what.bind(bindTo || this)
469 }
470 else {
471 result = what
472 }
473 }
474 else if (descriptor.value) {
475 result = descriptor.value
476 }
477 }
478
479 return result
480 }
481
482 /**
483 * Properties defined for GraphQL types in Lattice can be defined as
484 * a getter, a function or an async function. In the case of standard
485 * functions, if they return a promise they will be handled as though
486 * they were async. In addition to fetching the property, or field
487 * resolver, its resulting function or getter will be invoked.
488 *
489 * Given the variety of things a GraphQL type can actually be, obtaining
490 * its value can annoying. This method tends to lessen that boilerplate.
491 * Errors raised will be thrown.
492 *
493 * @instance
494 * @memberof GQLBase
495 * @method ⌾⠀callProp
496 *
497 * @param {string} propName the name of the property in question
498 * @param {Array&lt;mixed>} args the arguments array that will be passed
499 * to `.apply()` should the property evaluate to a `function`
500 * @return {mixed} the return value of any resulting function or
501 * value returned by a getter; wrapped in a promise as all async
502 * functions do.
503 *
504 * @throws {Error} errors raised in awaiting results will be thrown
505 */
506 async callProp(propName: string, ...args: Array&lt;mixed>) {
507 // $FlowFixMe
508 let prop = this.getProp(propName, ...args);
509 let result
510
511 if (prop &amp;&amp; typeOf(prop) === 'AsyncFunction') {
512 try {
513 result = await prop.apply(this, args);
514 }
515 catch (error) {
516 throw new AsyncFunctionExecutionError(error, prop, args, result)
517 }
518 }
519 else if (prop &amp;&amp; typeOf(prop) === Function.name) {
520 try {
521 result = prop.apply(this, args)
522 }
523 catch (error) {
524 throw new FunctionExecutionError(error, prop, args, result)
525 }
526
527 if (typeOf(result) === Promise.name) {
528 try {
529 result = await result
530 }
531 catch (error) {
532 throw new AwaitingPromiseError(error).setPromise(result)
533 }
534 }
535 }
536
537 return result
538 }
539
540 /**
541 * A pass-thru method to the static function of the same name. The
542 * difference being that if `requestData` is not specified, the
543 * `requestData` object from this instance will be used to build the
544 * resolvers in question.
545 *
546 * @instance
547 * @method ⌾⠀getResolver
548 * @memberof GQLBase
549 *
550 * @param {string} resolverName the name of the resolver as a string
551 * @param {Object} requestData the requestData used to build the
552 * resolver methods from which to choose
553 * @return {Function} returns either a `function` representing the
554 * resolver requested or null if there wasn't one to be found
555 */
556 async getResolver(resolverName: string, requestData: Object) {
557 return await this.constructor.getResolver(
558 resolverName,
559 requestData || this.requestData
560 )
561 }
562
563 /**
564 * Resolvers are created in a number of different ways. OOP design
565 * dictates that instances of a created class will handle field
566 * resolvers, but query, mutation and subscription resolvers are
567 * typically what creates these instances.
568 *
569 * Since a resolver can be created using `@mutator/@subscriptor/@resolver`
570 * or via method on a object returned from `RESOLVERS()`, `MUTATORS()` or
571 * `SUBSCRIPTIONS()`, there should be an easy to use way to fetch a
572 * resolver by name; if for nothing else, code reuse.
573 *
574 * Pass the name of the resolver to the function and optionally pass a
575 * requestData object. The `getMergedRoot()` method will build an object
576 * containing all the root resolvers for the type, bound to the supplied
577 * `requestData` object. It is from this object that `resolverName` will
578 * be used to fetch the function in question. If one exists, it will be
579 * returned, ready for use. Otherwise, null will be your answer.
580 *
581 *
582 * @static
583 * @method ⌾⠀getResolver
584 * @memberof GQLBase
585 *
586 * @param {string} resolverName the name of the resolver as a string
587 * @param {Object} requestData the requestData used to build the
588 * resolver methods from which to choose
589 * @return {Function} returns either a `function` representing the
590 * resolver requested or null if there wasn't one to be found
591 */
592 static async getResolver(resolverName: string, requestData: Object) {
593 const reqData = requestData || null
594 const rootObj = await this.getMergedRoot(reqData)
595
596 return rootObj[resolverName] || null
597 }
598
599 /**
600 * The static version of getProp reads into the prototype to find the field
601 * that is desired. If the field is either a getter or a initializer (see
602 * class properties descriptors), then the option to bind that to either the
603 * prototype object or one of your choosing is available.
604 *
605 * @memberof GQLBase
606 * @method ⌾⠀getProp
607 * @static
608 *
609 * @param {string|Symbol} propName a string or Symbol denoting the name of
610 * the property or field you desire
611 * @param {boolean} bindGetters true if a resulting `getter` or `initializer`
612 * should be bound to the prototype or other object
613 * @param {mixed} bindTo the object to which to bind the `getter` or
614 * `initializer` functions to if other than the class prototype.
615 * @return {mixed} a `Function` or other mixed value making up the property
616 * name requested
617 */
618 static getProp(
619 propName: string,
620 bindGetters: boolean = false,
621 bindTo: mixed
622 ) {
623 let descriptor = Object.getOwnPropertyDescriptor(this.prototype, propName)
624
625 if (descriptor) {
626 if (descriptor.get || descriptor.initializer) {
627 let what = descriptor.initializer || descriptor.get
628
629 if (bindGetters) {
630 bindTo = bindTo || this.prototype
631
632 return what.bind(bindTo)
633 }
634 else {
635 return what
636 }
637 }
638 else {
639 return descriptor.value
640 }
641 }
642 else {
643 return null
644 }
645 }
646
647 /**
648 * Until such time as the reference implementation of Facebook's GraphQL
649 * SDL AST parser supports comments, or until we take advantage of Apollo's
650 * AST parser, this is how comments will be applied to a built schema.
651 *
652 * Several constants are defined on the GQLBase object itself, and thereby
653 * all its subclasses. They pertain to how to define description fields
654 * for various parts of your GQL implementation.
655 *
656 * ```
657 * // To define a description on the top level class
658 * [this.DOC_CLASS]: string
659 *
660 * // To define a description on a field (getter, function or async function)
661 * [this.DOC_FIELDS]: {
662 * fieldName: string
663 * }
664 *
665 * // To define a description on a query, mutation or subscription field
666 * [this.DOC_QUERIES || this.DOC_MUTATORS || this.DOC_SUBSCRIPTIONS]: {
667 * fieldName: string
668 * }
669 * ```
670 *
671 * To make writing code easier, the `joinLines()` template function is
672 * available so your source code can look nice and neat and your descriptions
673 * won't get annoying line breaks and spaces as part of that process.
674 *
675 * @static
676 * @memberof GQLBase
677 * @method apiDocs
678 *
679 * @return {Object} an object with various keys and values denoting
680 * description fields that should be applied to the final schema object
681 */
682 static apiDocs(): Object {
683 return {
684 [this.DOC_CLASS]: joinLines`
685 GQLBase class implementation. GQLBase is the root class used in
686 graphql-lattice to describe a GraphQLObjectType. If you are reading
687 this, the person using lattice failed to provide documentation for
688 their type. :)
689 `,
690
691 [this.DOC_QUERY]: joinLines`
692 ## Welcome to GraphQL Lattice
693 **Query**
694
695 You will want to define a \`DOC_QUERY\` apiDoc comment with something
696 more meaningful to your particular Schema here.
697 `,
698
699 [this.DOC_MUTATION]: joinLines`
700 ## Welcome to GraphQL Lattice
701 **Mutation**
702
703 You will want to define a \`DOC_MUTATION\` apiDoc comment with
704 something more meaningful to your particular Schema here.
705 `,
706
707 [this.DOC_SUBSCRIPTION]: joinLines`
708 ## Welcome to GraphQL Lattice
709 **Subscription**
710
711 You will want to define a \`DOC_SUBSCRIPTION\` apiDoc comment with
712 something more meaningful to your particular Schema here.
713 `,
714
715 [this.DOC_FIELDS]: {
716 // fieldName: `fieldDescription`,
717 },
718
719 [this.DOC_QUERIES]: {
720 // queryName: `queryDescription`,
721 },
722
723 [this.DOC_MUTATORS]: {
724 // mutatorName: `mutatorDescription`
725 },
726
727 [this.DOC_SUBSCRIPTIONS]: {
728 // subscriptionName: `subscriptionDescription`
729 }
730 }
731 }
732
733 /**
734 * Defined in a base class, this getter should return either a String
735 * detailing the full IDL schema of a GraphQL handler or one of two
736 * types of Symbols.
737 *
738 * The first Symbol type is the constant `ADJACENT_FILE`. If this Symbol is
739 * returned, the system assumes that next to the source file in question is
740 * a file of the same name with a .graphql extension. This file should be
741 * made of the GraphQL IDL schema definitions for the object types being
742 * created.
743 *
744 * Example:
745 * ```js
746 * static get SCHEMA(): string | Symbol {
747 * return GQLBase.ADJACENT_FILE
748 * }
749 * ```
750 *
751 * The primary advantage of this approach is allowing an outside editor that
752 * provides syntax highlighting rather than returning a string from the
753 * SCHEMA getter.
754 *
755 * Alternatively, the static method IDLFilePath can be used to point to an
756 * alternate location where the GraphQL IDL file resides. The extension can
757 * also be changed from .graphql to something else if need be using this
758 * method.
759 *
760 * Example:
761 * ```js
762 * static get SCHEMA(): string | Symbol {
763 * return GQLBase.IDLFilePath('/path/to/file', '.idl')
764 * }
765 * ```
766 *
767 * @instance
768 * @memberof GQLBase
769 * @method ⬇︎⠀SCHEMA
770 * @readonly
771 * @static
772 *
773 * @return {string|Symbol} a valid IDL string or one of the Symbols
774 * described above.
775 *
776 * @see {@link GQLBase#ADJACENT_FILE}
777 * @see {@link GQLBase#IDLFilePath}
778 */
779 static get SCHEMA(): string | Symbol {
780 return ''
781 }
782
783 /**
784 * This method should return a promise that resolves to an object of
785 * functions matching the names of the mutation operations. These are to be
786 * injected into the root object when used by `GQLExpressMiddleware`.
787 *
788 * @instance
789 * @memberof GQLBase
790 * @method ⌾⠀MUTATORS
791 * @readonly
792 * @static
793 *
794 * @param {Object} requestData typically an object containing three
795 * properties; {req, res, gql}
796 * @return {Promise} a promise that resolves to an object; see above for more
797 * information.
798 */
799 static async MUTATORS(requestData: Object): Promise&lt;Object> {
800 // define in base class
801 return {};
802 }
803
804 /**
805 * This method should return a promise that resolves to an object of
806 * functions matching the names of the query operations. These are to be
807 * injected into the root object when used by `GQLExpressMiddleware`.
808 *
809 * @instance
810 * @memberof GQLBase
811 * @method ⌾⠀RESOLVERS
812 * @readonly
813 * @static
814 *
815 * @param {Object} requestData typically an object containing three
816 * properties; {req, res, gql}
817 * @return {Promise} a promise that resolves to an object; see above for more
818 * information.
819 */
820 static async RESOLVERS(requestData: Object): Promise&lt;Object> {
821 // define in base class
822 return {};
823 }
824
825 /**
826 * @see {@link GQLBase#SCHEMA}
827 *
828 * @memberof GQLBase
829 * @method ⬇︎⠀ADJACENT_FILE
830 * @static
831 * @const
832 *
833 * @return {Symbol} the Symbol, when returned from SCHEMA, causes
834 * the logic to load an IDL Schema from an associated file with a .graphql
835 * extension and bearing the same name.
836 */
837 static get ADJACENT_FILE(): Symbol {
838 return Symbol.for('.graphql file located adjacent to source')
839 }
840
841 /**
842 * Determines the default type targeted by this GQLBase class. Any
843 * type will technically be valid but only will trigger special behavior
844 *
845 * @memberof GQLBase
846 * @method ⬇︎⠀GQL_TYPE
847 * @static
848 * @const
849 *
850 * @return {Function} a type, such as `GraphQLObjectType` or
851 * `GraphQLInterfaceType`
852 */
853 static get GQL_TYPE(): Function {
854 return GraphQLObjectType;
855 }
856
857 /**
858 * Creates an appropriate Symbol crafted with the right data for use by
859 * the IDLFileHandler class below.
860 *
861 * @static
862 * @memberof GQLBase
863 * @method ⌾⠀IDLFilePath
864 *
865 * @param {string} path a path to the IDL containing file
866 * @param {string} [extension='.graphql'] an extension, including the
867 * prefixed period, that will be added to the supplied path should it not
868 * already exist.
869 * @return Symbol
870 *
871 * @see {@link GQLBase#SCHEMA}
872 */
873 static IDLFilePath(path: string, extension: string = '.graphql'): Symbol {
874 return Symbol.for(`Path ${path} Extension ${extension}`);
875 }
876
877 /**
878 * A file handler for fetching the IDL schema string from the file system
879 * for those `GQLBase` extended classes that have indicated to do so by
880 * returning a `Symbol` for their `SCHEMA` property.
881 *
882 * @static
883 * @memberof GQLBase
884 * @method ⬇︎⠀handler
885 *
886 * @return {IDLFileHandler} instance of IDLFileHandler, created if one does
887 * not already exist, for fetching the contents from disk.
888 */
889 static get handler(): IDLFileHandler {
890 const key = Symbol.for(`${IDLFileHandler.name}.${this.name}`);
891
892 // @ComputedType
893 if (!this[key]) {
894 // @ComputedType
895 this[key] = new IDLFileHandler(this);
896 }
897
898 // @ComputedType
899 return this[key];
900 }
901
902 /**
903 * Returns the module object where your class is created. This needs to be
904 * defined on your class, as a static getter, in the FILE where you are
905 * defining your Class definition.
906 *
907 * @static
908 * @memberof GQLBase
909 * @method ⬇︎⠀module
910 * @const
911 *
912 * @return {Object} the reference to the module object defined and injected
913 * by node.js' module loading system.
914 *
915 * @see https://nodejs.org/api/modules.html
916 */
917 static get module(): Object {
918 return module;
919 }
920
921 /**
922 * The internal data model has some custom `EventEmitter` code wrapped
923 * it here. When the data model is set via `setModel` or by accessing it
924 * via `instance[MODEL_KEY]`, an event `EVENT_MODEL_SET` is emitted. Any
925 * listener listening for this event receives an object with two keys
926 * ```
927 * {
928 * model: The actual model being set; changes are persisted
929 * instance: The GQLBase instance the model is associated with
930 * }
931 * ```
932 *
933 * Subsequently, the events `EVENT_MODEL_PROP_CHANGE` and
934 * `EVENT_MODEL_PROP_DELETE` can be listened to if your version of node
935 * supports Proxy objects. They allow you to be notified whenever your
936 * model has a property changed or deleted, respectively.
937 *
938 * The callback for `change` receives an object with four properties
939 * ```
940 * {
941 * model: The model object the value is being changed on
942 * old: The old value being replaced; undefined if it is the first time
943 * key: The property key for the value being changed
944 * value: The new value being set
945 * }
946 * ```
947 *
948 * The callback for `delete` receives an object with four properties
949 * ```
950 * {
951 * model: The model object the value is deleted from
952 * key: The property key for the deleted value
953 * deleted: The deleted value
954 * }
955 * ```
956 *
957 * @static
958 * @memberof GQLBase
959 * @method ⌾⠀setupModel
960 *
961 * @param {GQLBase} instance typically `this` as passed in from a call in
962 * the constructor
963 */
964 static setupModel(instance: GQLBase) {
965 const changeHandler: Object = {
966 /**
967 * Proxy set() handler. This is where the change events are fired from
968 *
969 * @method GQLBase~set
970 * @param {Object} target the `GQLBase` model object
971 * @param {string} key the property name
972 * @param {mixed} value the new property value
973 */
974 set(target, key, value) {
975 const old = target[key];
976
977 target[key] = value;
978 instance.emit(GQLBase.EVENT_MODEL_PROP_CHANGE, {
979 model: target,
980 old,
981 key,
982 value
983 })
984 },
985
986 /**
987 * Proxy deleteProperty() handler. This is where the delete property
988 * events are fired from
989 *
990 * @method GQLBase~deleteProperty
991 * @param {Object} target the `GQLBase` model object
992 * @param {string} key the property name
993 */
994 deleteProperty(target, key) {
995 const deleted = target[key];
996
997 delete target[key];
998 instance.emit(GQLBase.EVENT_MODEL_PROP_DELETE, {
999 model: target,
1000 key,
1001 deleted
1002 })
1003 }
1004 }
1005
1006 /**
1007 * 'Publicly' the Symbol for accessing the `GQLBase` model is `MODEL_KEY`.
1008 * In truth it is stored under a Symbol defined in `setupModel` and
1009 * referred to as `_MODEL_KEY` in this code. This is done so a getter and
1010 * setter can be wrapped around the usage of the instance's data model.
1011 *
1012 * When being read, if `Proxy` exists in the node environment and if there
1013 * are any registered `EVENT_MODEL_PROP_CHANGE` or `EVENT_MODEL_PROP_DELETE`
1014 * events, then the returned model is a Proxy around the real model that
1015 * allows us to capture the changes and deletion of keys
1016 *
1017 * When being assigned, the event `EVENT_MODEL_WILL_BE_SET` and the event
1018 * `EVENT_MODEL_HAS_BEEN_SET` are emitted to allow listeners to modify and
1019 * see the final data around the setting of a model object. Both events
1020 * receive an object with two keys
1021 *
1022 * ```
1023 * {
1024 * model: The object being or having been set
1025 * instance: The GQLBase instance receiving the model
1026 * }
1027 * ```
1028 */
1029 Object.defineProperty(instance, MODEL_KEY, {
1030 get: function() {
1031 let model = this[_MODEL_KEY]
1032 let hasListeners =
1033 this.listenerCount(GQLBase.EVENT_MODEL_PROP_CHANGE) +
1034 this.listenerCount(GQLBase.EVENT_MODEL_PROP_DELETE)
1035
1036 if (hasProxy &amp;&amp; hasListeners) {
1037 model = new Proxy(model, changeHandler);
1038 }
1039
1040 return model
1041 },
1042
1043 set: function(model) {
1044 const instance = this;
1045
1046 this.emit(GQLBase.EVENT_MODEL_WILL_BE_SET, { model, instance });
1047 instance[_MODEL_KEY] = model;
1048 this.emit(GQLBase.EVENT_MODEL_HAS_BEEN_SET, { model, instance })
1049 }
1050 });
1051 }
1052
1053 /**
1054 * If ES6 Proxies are supported in your execution environment, all GQLBase
1055 * extended classes are also proxies. By default the internal proxy handler
1056 * provides backwards compatibility with the removal of the default getters
1057 * and setters for the 'model' property as long as you do not define a
1058 * top level 'model' property of your own.
1059 *
1060 * @method ⬇︎⠀[_PROXY_HANDLER]
1061 * @memberof GQLBase
1062 * @static
1063 * @const
1064 * @since 2.5.0
1065 *
1066 * @type {Object}
1067 * @ComputedType
1068 */
1069 static get [_PROXY_HANDLER]() {
1070 return {
1071 get(target, key, lastResult) {
1072 const model = target[_MODEL_KEY];
1073
1074 // Allow backwards compatibility for 'model' property if one is not
1075 // explicitly defined on your instance.
1076 if (notDefined('model', key, target)) {
1077 // Be sure to use the public MODEL_KEY to ensure events fire
1078 return target[MODEL_KEY];
1079 }
1080
1081 return target[key]
1082 }
1083 }
1084 }
1085
1086 /**
1087 * Applies the same logic as {@link #[Symbol.toStringTag]} but on a static
1088 * scale. So, if you perform `Object.prototype.toString.call(MyClass)`
1089 * the result would be `[object MyClass]`.
1090 *
1091 * @method ⌾⠀[Symbol.toStringTag]
1092 * @memberof ModuleParser
1093 * @static
1094 *
1095 * @return {string} the name of this class
1096 * @ComputedType
1097 */
1098 static get [Symbol.toStringTag]() { return this.name }
1099
1100 /**
1101 * A constant used to register an event listener for when the internal
1102 * model object is assigned a new value. This event fires before the model
1103 * is set. Changes to the model value at this point will affect the contents
1104 * before the value assignment takes place.
1105 *
1106 * @static
1107 * @memberof GQLBase
1108 * @method ⬇︎⠀EVENT_MODEL_WILL_BE_SET
1109 * @const
1110 *
1111 * @type {string}
1112 */
1113 static get EVENT_MODEL_WILL_BE_SET() { return 'E: Int. model will be set' }
1114
1115 /**
1116 * A constant used to register an event listener for when the internal
1117 * model object is assigned a new value. This event fires after the model
1118 * is set.
1119 *
1120 * @static
1121 * @memberof GQLBase
1122 * @method ⬇︎⠀EVENT_MODEL_HAS_BEEN_SET
1123 * @const
1124 *
1125 * @type {string}
1126 */
1127 static get EVENT_MODEL_HAS_BEEN_SET() { return 'E: Int. model has been set' }
1128
1129 /**
1130 * A constant used to register an event listener for when a property of the
1131 * internal model object is set to a new or intial value.
1132 *
1133 * @static
1134 * @memberof GQLBase
1135 * @method ⬇︎⠀EVENT_MODEL_PROP_CHANGE
1136 * @const
1137 *
1138 * @type {string}
1139 */
1140 static get EVENT_MODEL_PROP_CHANGE() { return 'E: Int. model prop changed' }
1141
1142 /**
1143 * A constant used to register an event listener for when a property of the
1144 * internal model object has been deleted. This event fires after the value
1145 * has been deleted.
1146 *
1147 * @static
1148 * @memberof GQLBase
1149 * @method ⬇︎⠀EVENT_MODEL_PROP_DELETE
1150 * @const
1151 *
1152 * @type {string}
1153 */
1154 static get EVENT_MODEL_PROP_DELETE() { return 'E: Int. model prop deleted' }
1155
1156 /**
1157 * A constant key used to identify a comment for a class description
1158 *
1159 * @static
1160 * @memberof GQLBase
1161 * @method ⬇︎⠀DOC_CLASS
1162 * @const
1163 *
1164 * @type {string}
1165 */
1166 static get DOC_CLASS() { return 'class' }
1167
1168 /**
1169 * A constant key used to identify a comment for a type field description
1170 *
1171 * @static
1172 * @memberof GQLBase
1173 * @method ⬇︎⠀DOC_FIELDS
1174 * @const
1175 *
1176 * @type {string}
1177 */
1178 static get DOC_FIELDS() { return 'fields' }
1179
1180 /**
1181 * A constant key used to identify a comment for the top level query
1182 * description
1183 *
1184 * @static
1185 * @memberof GQLBase
1186 * @method ⬇︎⠀DOC_QUERY
1187 * @const
1188 *
1189 * @type {string}
1190 */
1191 static get DOC_QUERY() { return 'query' }
1192
1193 /**
1194 * A constant key used to identify a comment for a query description
1195 *
1196 * @static
1197 * @memberof GQLBase
1198 * @method ⬇︎⠀DOC_QUERIES
1199 * @const
1200 *
1201 * @type {string}
1202 */
1203 static get DOC_QUERIES() { return 'queries' }
1204
1205 /**
1206 * A constant key used to identify a comment for the top level mutation
1207 * description
1208 *
1209 * @static
1210 * @memberof GQLBase
1211 * @method ⬇︎⠀DOC_MUTATION
1212 * @const
1213 *
1214 * @type {string}
1215 */
1216 static get DOC_MUTATION() { return 'mutation' }
1217
1218 /**
1219 * A constant key used to identify a comment for a mutator description
1220 *
1221 * @static
1222 * @memberof GQLBase
1223 * @method ⬇︎⠀DOC_MUTATORS
1224 * @const
1225 * @deprecated Use `DOC_MUTATIONS` instead
1226 *
1227 * @type {string}
1228 */
1229 static get DOC_MUTATORS() { return 'mutators' }
1230
1231 /**
1232 * A constant key used to identify a comment for a mutator description
1233 *
1234 * @static
1235 * @memberof GQLBase
1236 * @method ⬇︎⠀DOC_MUTATORS
1237 * @const
1238 *
1239 * @type {string}
1240 */
1241 static get DOC_MUTATIONS() { return 'mutators' }
1242
1243 /**
1244 * A constant key used to identify a comment for the top level subscription
1245 * description
1246 *
1247 * @static
1248 * @memberof GQLBase
1249 * @method ⬇︎⠀DOC_SUBSCRIPTION
1250 * @const
1251 *
1252 * @type {string}
1253 */
1254 static get DOC_SUBSCRIPTION() { return 'subscription' }
1255
1256 /**
1257 * A constant key used to identify a comment for a subscription description
1258 *
1259 * @static
1260 * @memberof GQLBase
1261 * @method ⬇︎⠀DOC_SUBSCRIPTIONS
1262 * @const
1263 *
1264 * @type {string}
1265 */
1266 static get DOC_SUBSCRIPTIONS() { return 'subscriptions' }
1267
1268 /**
1269 * A shortcut to the utils/joinLines function to make it easier to get
1270 * the tools to write docs for your types in a friendly fashion.
1271 *
1272 * @memberof GQLBase
1273 * @method ⬇︎⠀joinLines
1274 * @static
1275 * @const
1276 *
1277 * @type {Function}
1278 */
1279 static get joinLines(): Function { return joinLines }
1280
1281 /**
1282 * An simple pass-thru method for fetching a types merged root object.
1283 *
1284 * @method ⌾⠀getMergedRoot
1285 * @memberof GQLBase
1286 * @static
1287 *
1288 * @param {Object} requestData an object containing the request data such as
1289 * request, response or graphql context info that should be passed along to
1290 * each of the resolver creators
1291 * @return {Object} the merged root object with all the query, mutation and
1292 * subscription resolvers defined and created within.
1293 */
1294 static async getMergedRoot(
1295 requestData: Object,
1296 separateByType: boolean = false
1297 ): Object {
1298 const root = {};
1299 const Class = this;
1300
1301 let _ = {
1302 // $FlowFixMe
1303 resolvers: Class[META_KEY].resolvers || [],
1304 // $FlowFixMe
1305 mutators: Class[META_KEY].mutators || [],
1306 // $FlowFixMe
1307 subscriptors: Class[META_KEY].subscriptors || []
1308 }
1309
1310 let convert = f => {
1311 let isFactoryClass = (c) => {
1312 return !!Class[META_KEY][Symbol.for('Factory Class')]
1313 }
1314
1315 if (isFactoryClass(Class)) {
1316 return {
1317 [f.name]: function(...args) {
1318 return f.apply(Class, [Class, requestData, ...args])
1319 }
1320 }
1321 }
1322 else {
1323 return {
1324 [f.name]: function(...args) {
1325 return f.apply(Class, [requestData, ...args])
1326 }
1327 }
1328 }
1329 }
1330 let reduce = (p, c) => merge(p, c)
1331
1332 _.resolvers = _.resolvers.map(convert).reduce(reduce, {})
1333 _.mutators = _.mutators.map(convert).reduce(reduce, {})
1334 _.subscriptors = _.subscriptors.map(convert).reduce(reduce, {})
1335
1336 if (separateByType) {
1337 // Apollo wants all the resolvers to grouped by top level type.
1338 // The field resolvers aren't an issue in Lattice defined types
1339 // but the root types do need to be sorted; so let's do that here
1340 merge(
1341 root,
1342 { Query: await Class.RESOLVERS(requestData) },
1343 { Mutation: await Class.MUTATORS(requestData) },
1344 { Query: _.resolvers },
1345 { Mutation: _.mutators },
1346 { Subscription: _.subscriptors }
1347 );
1348
1349 // When using lattice with apollo server, it is quite particular about
1350 // empty Query, Mutation or Subscription resolver maps.
1351 if (!Object.keys(root.Query).length) delete root.Query
1352 if (!Object.keys(root.Mutation).length) delete root.Mutation
1353 if (!Object.keys(root.Subscription).length) delete root.Subscription
1354 }
1355 else {
1356 merge(
1357 root,
1358 await Class.RESOLVERS(requestData),
1359 await Class.MUTATORS(requestData),
1360 _.resolvers,
1361 _.mutators,
1362 _.subscriptors
1363 );
1364 }
1365
1366 return root;
1367 }
1368
1369 /**
1370 * An object used to store data used by decorators and other internal
1371 * proccesses.
1372 * @ComputedType
1373 */
1374 static get [META_KEY]() {
1375 let storage = this[Symbol.for(this.name)]
1376
1377 if (!storage) {
1378 storage = (this[Symbol.for(this.name)] = {})
1379 }
1380
1381 return storage;
1382 }
1383}
1384
1385export default GQLBase;
1386</code></pre>
1387 </article>
1388 </section>
1389
1390
1391
1392
1393</div>
1394
1395<br class="clear">
1396
1397<footer>
1398 Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Fri Jun 08 2018 19:28:39 GMT-0700 (PDT) using the Minami theme.
1399</footer>
1400
1401<script>prettyPrint();</script>
1402<script src="scripts/linenumber.js"></script>
1403</body>
1404</html>