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 | |
11 |
|
12 |
|
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 |
|
45 | import Path from 'path'
|
46 | import fs from 'fs'
|
47 |
|
48 | import { Deferred, joinLines } from './utils'
|
49 | import { typeOf } from 'ne-types'
|
50 | import { SyntaxTree } from './SyntaxTree'
|
51 | import { Properties } from './decorators/ModelProperties'
|
52 | import { GraphQLObjectType, GraphQLEnumType } from 'graphql'
|
53 | import { IDLFileHandler } from './IDLFileHandler'
|
54 | import { merge } from 'lodash'
|
55 | import { LatticeLogs as ll } from './utils'
|
56 | import { dedent } from 'ne-tag-fns'
|
57 |
|
58 | import AsyncFunctionExecutionError from './errors/AsyncFunctionExecutionError'
|
59 | import FunctionExecutionError from './errors/FunctionExecutionError'
|
60 | import AwaitingPromiseError from './errors/AwaitingPromiseError'
|
61 |
|
62 | import 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 */
|
66 | const hasProxy = typeof global.Proxy !== 'undefined';
|
67 |
|
68 | /* Internal Symbol referring to real accessor to GQLBase model object */
|
69 | const _MODEL_KEY = Symbol.for('data-model-contents-value');
|
70 |
|
71 | /* Internal Symbol referring to the static object containing a proxy handler */
|
72 | const _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 | */
|
91 | export function notDefined(
|
92 | keyToTest: string,
|
93 | keySupplied: Object | string,
|
94 | instance: Object
|
95 | ) {
|
96 | return (
|
97 | new RegExp("^" + keyToTest + "$").test(keySupplied.toString())
|
98 | && !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 | */
|
110 | export 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 | */
|
121 | export 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 | */
|
131 | export 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 | */
|
142 | export 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 <class>[META_KEY][GETTERS]
|
147 | *
|
148 | * @type {Symbol}
|
149 | * @const
|
150 | * @inner
|
151 | * @memberOf GQLBaseEnv
|
152 | */
|
153 | export 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 <class>[META_KEY][SETTERS]
|
158 | *
|
159 | * @type {Symbol}
|
160 | * @const
|
161 | * @inner
|
162 | * @memberOf GQLBaseEnv
|
163 | */
|
164 | export 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 <class>[META_KEY][PROPS]
|
169 | *
|
170 | * @type {Symbol}
|
171 | * @const
|
172 | * @inner
|
173 | * @memberOf GQLBaseEnv
|
174 | */
|
175 | export 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 | */
|
184 | export 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 && 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 && !(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 && !!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 && (
|
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<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<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<mixed>) {
|
507 | // $FlowFixMe
|
508 | let prop = this.getProp(propName, ...args);
|
509 | let result
|
510 |
|
511 | if (prop && 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 && 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<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<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 && 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 |
|
1385 | export 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>
|