Просмотр исходного кода

Video 11: add an interface to a GraphQL schema.

Frederic G. MARAND 7 лет назад
Родитель
Сommit
9d9b5ef486
4 измененных файлов с 187 добавлено и 52 удалено
  1. 61 41
      .idea/workspace.xml
  2. 83 7
      doc/concepts.dot
  3. 17 4
      index.js
  4. 26 0
      src/node.js

+ 61 - 41
.idea/workspace.xml

@@ -3,6 +3,7 @@
   <component name="ChangeListManager">
     <list default="true" id="417b6c39-7b77-43c5-80fb-b9bf95b57f36" name="Default" comment="">
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/doc/concepts.dot" afterPath="$PROJECT_DIR$/doc/concepts.dot" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/index.js" afterPath="$PROJECT_DIR$/index.js" />
     </list>
     <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
@@ -21,8 +22,18 @@
       <file leaf-file-name="index.js" pinned="false" current-in-tab="true">
         <entry file="file://$PROJECT_DIR$/index.js">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="291">
-              <caret line="107" column="19" lean-forward="true" selection-start-line="107" selection-start-column="19" selection-end-line="107" selection-end-column="19" />
+            <state relative-caret-position="361">
+              <caret line="88" column="44" lean-forward="true" selection-start-line="88" selection-start-column="44" selection-end-line="88" selection-end-column="44" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="node.js" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/node.js">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="98">
+              <caret line="7" column="19" lean-forward="false" selection-start-line="7" selection-start-column="19" selection-end-line="7" selection-end-column="19" />
               <folding />
             </state>
           </provider>
@@ -31,8 +42,8 @@
       <file leaf-file-name="index.js" pinned="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/src/data/index.js">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="84">
-              <caret line="6" column="0" lean-forward="true" selection-start-line="6" selection-start-column="0" selection-end-line="6" selection-end-column="0" />
+            <state relative-caret-position="588">
+              <caret line="42" column="0" lean-forward="true" selection-start-line="42" selection-start-column="0" selection-end-line="42" selection-end-column="0" />
               <folding />
             </state>
           </provider>
@@ -40,6 +51,23 @@
       </file>
     </leaf>
   </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="JavaScript File" />
+      </list>
+    </option>
+  </component>
+  <component name="FindInProjectRecents">
+    <findStrings>
+      <find>&lt;reason</find>
+      <find>:reason</find>
+    </findStrings>
+    <replaceStrings>
+      <replace>&lt;deprReason</replace>
+      <replace>:deprReason</replace>
+    </replaceStrings>
+  </component>
   <component name="Git.Settings">
     <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
   </component>
@@ -47,9 +75,10 @@
     <option name="CHANGED_PATHS">
       <list>
         <option value="$PROJECT_DIR$/package.json" />
-        <option value="$PROJECT_DIR$/doc/concepts.dot" />
         <option value="$PROJECT_DIR$/src/data/index.js" />
+        <option value="$PROJECT_DIR$/src/node.js" />
         <option value="$PROJECT_DIR$/index.js" />
+        <option value="$PROJECT_DIR$/doc/concepts.dot" />
       </list>
     </option>
   </component>
@@ -111,10 +140,6 @@
               <option name="myItemId" value="src" />
               <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="data" />
-              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
@@ -126,25 +151,11 @@
               <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="node_modules" />
-              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="Egghead GraphQL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="egghead" />
-              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="node_modules" />
+              <option name="myItemId" value="src" />
               <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="graphql" />
+              <option name="myItemId" value="data" />
               <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
             </PATH_ELEMENT>
           </PATH>
@@ -290,6 +301,7 @@
     <option name="remove_strategy" value="false" />
   </component>
   <component name="StructureViewFactory">
+    <option name="AUTOSCROLL_FROM_SOURCE" value="true" />
     <option name="ACTIVE_ACTIONS" value=",HIDE_INHERITED_FROM_OBJECT,ALPHA_COMPARATOR,SHOW_CLASSES" />
   </component>
   <component name="TaskManager">
@@ -302,30 +314,30 @@
       <workItem from="1481822371153" duration="34000" />
       <workItem from="1481822430451" duration="270000" />
       <workItem from="1481969401352" duration="4966000" />
-      <workItem from="1481993311649" duration="5771000" />
+      <workItem from="1481993311649" duration="8816000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="11566000" />
+    <option name="totallyTimeSpent" value="14611000" />
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="1435" height="877" extended-state="6" />
-    <editor active="false" />
+    <editor active="true" />
     <layout>
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
       <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2089172" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Mongo Explorer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.22929937" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.22929937" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Project" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.24011503" sideWeight="0.5" order="5" side_tool="false" content_ui="combo" />
       <window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
       <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3299363" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.22501798" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
-      <window_info id="Debug" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.27515924" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.27515924" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
       <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
@@ -422,34 +434,42 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/doc/concepts.dot">
+    <entry file="file://$PROJECT_DIR$/node_modules/graphql/index.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="70">
-          <caret line="5" column="36" lean-forward="false" selection-start-line="5" selection-start-column="36" selection-end-line="5" selection-end-column="36" />
+        <state relative-caret-position="193">
+          <caret line="53" column="31" lean-forward="false" selection-start-line="53" selection-start-column="31" selection-end-line="53" selection-end-column="31" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/node_modules/graphql/index.js">
+    <entry file="file://$PROJECT_DIR$/src/data/index.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="193">
-          <caret line="53" column="31" lean-forward="false" selection-start-line="53" selection-start-column="31" selection-end-line="53" selection-end-column="31" />
+        <state relative-caret-position="588">
+          <caret line="42" column="0" lean-forward="true" selection-start-line="42" selection-start-column="0" selection-end-line="42" selection-end-column="0" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/data/index.js">
+    <entry file="file://$PROJECT_DIR$/doc/concepts.dot">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="137">
+          <caret line="65" column="20" lean-forward="false" selection-start-line="65" selection-start-column="20" selection-end-line="65" selection-end-column="20" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/src/node.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="84">
-          <caret line="6" column="0" lean-forward="true" selection-start-line="6" selection-start-column="0" selection-end-line="6" selection-end-column="0" />
+        <state relative-caret-position="98">
+          <caret line="7" column="19" lean-forward="false" selection-start-line="7" selection-start-column="19" selection-end-line="7" selection-end-column="19" />
           <folding />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/index.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="291">
-          <caret line="107" column="19" lean-forward="true" selection-start-line="107" selection-start-column="19" selection-end-line="107" selection-end-column="19" />
+        <state relative-caret-position="361">
+          <caret line="88" column="44" lean-forward="true" selection-start-line="88" selection-start-column="44" selection-end-line="88" selection-end-column="44" />
           <folding />
         </state>
       </provider>

+ 83 - 7
doc/concepts.dot

@@ -1,19 +1,95 @@
 digraph graphql {
   rankdir=LR;
+  overlap=false;
+
+  // Primitive types.
+  node [ shape="ellipse" ];
+  Boolean;
+  String;
 
   node [ shape=record ];
 
-  field [label="<pk>field|<args>args|<resolve>resolve()|<type>type" ];
-  g_node [ label="<pk>node|id" ];
-  schema [ label="<pk>schema|<query>query|<mutation>mutation|<subscription>subscription" ];
-  type [ label="<pk>type|name|description|<fields>fields" ];
+  enumValue [ label="<pk>__EnumValue
+    |<deprReason>deprecationReason
+    |<desc>description
+    |<isDepr>isDeprecated!
+    |<name>name!
+  " ];
+  field [label="<pk>__Field
+    |<args>args[]!
+    |<deprReason>deprecationReason
+    |<desc>description
+    |<isDepr>isDeprecated!
+    |<name>name
+    |<resolve>resolve()
+    |<type>type!
+  "];
+  g_node [ label="<pk>Node" ];
+  inputValue [ label="<pk>__InputValue
+    |<default>defaultValue
+    |<desc>description
+    |<name>name
+    |<type>type
+  "];
+  kind [ label="<pk>__TypeKind
+    |ENUM
+    \nINPUT_OBJECT
+    \nINTERFACE
+    \nLIST
+    \nNON_NULL
+    \nOBJECT
+    \nSCALAR
+    \nUNION
+  "];
+  schema [ label="<pk>Schema|<query>query|<mutation>mutation|<subscription>subscription" ];
+  type [ label="<pk>__Type
+    |<desc>description
+    |<enum>enumValues(includeDeprecated: Boolean)[]
+    |<fields>fields(includeDeprecated: Boolean)[]
+    |<input>inputFields[]!
+    |<interfaces>interfaces[]!
+    |<kind>kind!
+    |<name>name
+    |<of>ofType
+    |<pTypes>possibleTypes[]!
+  "];
 
-  field:resolve -> g_node:pk;
+  edge [ label="is_a", color=silver];
+
+  enumValue:deprReason -> String;
+  enumValue:desc -> String;
+  enumValue:isDepr -> Boolean;
+  enumValue:name -> String;
+
+  field:args -> inputValue:pk;
+  field:deprReason -> String;
+  field:desc -> String;
+  field:isDepr -> Boolean;
+  field:name -> String;
   field:type -> type:pk;
 
+  inputValue:default -> String;
+  inputValue:desc -> String;
+  inputValue:name -> String;
+  inputValue:type -> type:pk;
+
   schema:mutation -> type:pk;
   schema:query -> type:pk;
-  schema:subscription -> type:pk; /* ? */
+  schema:subscription -> type:pk;
+
+  type:desc -> String;
+  type:enum -> enumValue:pk;
+  type:fields -> field:pk;
+  type:input -> inputValue:pk;
+  type:interfaces -> type:pk;
+  type:kind -> kind:pk;
+  type:name -> String;
+  type:of -> type:pk;
+  type:pTypes -> type:pk;
+
+  edge [ label="returns", color=lightblue ];
+  field:resolve -> g_node:pk;
+
+  edge [ style=solid; color=silver; label="extends"];
 
-  type:fields -> field:pk ;
 }

+ 17 - 4
index.js

@@ -11,18 +11,29 @@ const {
   GraphQLNonNull,
   GraphQLObjectType,
   GraphQLSchema,
-  GraphQLString,
+  GraphQLString
 } = require('graphql');
 const {
   createVideo,
   getVideoById,
   getVideos
 } = require('./src/data/index');
+const nodeInterface = require("./src/node");
 
 const PORT = process.env.PORT || 3000;
 
 const server = express();
 
+/* Example of interface reuse
+const instructorType = new GraphQLObjectType({
+  id: {
+    type: GraphQLID,
+    description: 'The ID of the video'
+  },
+  interfaces: [nodeInterface]
+});
+*/
+
 const videoInputType = new GraphQLInputObjectType({
   name: "VideoInput",
   fields: {
@@ -46,7 +57,7 @@ const videoType = new GraphQLObjectType({
   description: 'A video on egghead.io',
   fields: {
     id: {
-      type: GraphQLID,
+      type: new GraphQLNonNull(GraphQLID),
       description: 'The ID of the video'
     },
     title: {
@@ -55,14 +66,16 @@ const videoType = new GraphQLObjectType({
     },
     duration: {
       type: GraphQLInt,
-      description: 'The duration of the video, in seconds',
+      description: 'The duration of the video, in seconds'
     },
     watched: {
       type: GraphQLBoolean,
       description: 'Whether or not the viewer has watched the video'
     }
-  }
+  },
+  interfaces: [nodeInterface]
 });
+exports.videoType = videoType;
 
 const queryType = new GraphQLObjectType({
   name: 'QueryType',

+ 26 - 0
src/node.js

@@ -0,0 +1,26 @@
+'use strict';
+
+const {
+  GraphQLInterfaceType,
+  GraphQLNonNull,
+  GraphQLID
+} = require('graphql');
+const { videoType } = require('../index');
+
+const nodeInterface = new GraphQLInterfaceType({
+  name: 'Node',
+  fields: {
+    id: {
+      type: new GraphQLNonNull(GraphQLID)
+    }
+  },
+  resolveType: (object) => {
+    if (object.title) {
+      return videoType;
+    }
+
+    return null;
+  }
+});
+
+module.exports = nodeInterface;