浏览代码

Merge pull request #3 from ruslantalpa/fix_1_and_2

Fixes #1 and #2
Bjorn Swenson 9 年之前
父节点
当前提交
fdbbc737fa
共有 6 个文件被更改,包括 48 次插入29 次删除
  1. 2 3
      graphql/execute.lua
  2. 7 1
      graphql/rules.lua
  3. 3 0
      graphql/schema.lua
  4. 20 24
      graphql/types.lua
  5. 10 0
      graphql/util.lua
  6. 6 1
      graphql/validate.lua

+ 2 - 3
graphql/execute.lua

@@ -170,9 +170,8 @@ local function completeValue(fieldType, result, subSelections, context)
     end
 
     local values = {}
-
-    for i, value in ipairs(values) do
-      values[i] = completeValue(innerType, value, context)
+    for i, value in ipairs(result) do
+      values[i] = completeValue(innerType, value, subSelections, context)
     end
 
     return values

+ 7 - 1
graphql/rules.lua

@@ -186,7 +186,13 @@ end
 
 function rules.requiredArgumentsPresent(node, context)
   local arguments = node.arguments or {}
-  local parentField = context.objects[#context.objects - 1].fields[node.name.value]
+  local parentField
+  if context.objects[#context.objects - 1].__type == 'List' then
+    parentField = context.objects[#context.objects - 2].fields[node.name.value]
+  else
+    parentField = context.objects[#context.objects - 1].fields[node.name.value]
+  end
+
   for name, argument in pairs(parentField.arguments) do
     if argument.__type == 'NonNull' then
       local present = util.find(arguments, function(argument)

+ 3 - 0
graphql/schema.lua

@@ -24,6 +24,8 @@ function schema.create(config)
   self.directiveMap = {}
 
   local function generateTypeMap(node)
+    if self.typeMap[node.name] and self.typeMap[node.name] == node then return end
+
     if node.__type == 'NonNull' or node.__type == 'List' then
       return generateTypeMap(node.ofType)
     end
@@ -43,6 +45,7 @@ function schema.create(config)
     end
 
     if node.__type == 'Object' or node.__type == 'Interface' or node.__type == 'InputObject' then
+      if type(node.fields) == 'function' then node.fields = node.fields() end
       for fieldName, field in pairs(node.fields) do
         if field.arguments then
           for _, argument in pairs(field.arguments) do

+ 20 - 24
graphql/types.lua

@@ -1,3 +1,6 @@
+local path = (...):gsub('%.[^%.]+$', '')
+local util = require(path .. '.util')
+
 local types = {}
 
 function types.nonNull(kind)
@@ -47,24 +50,12 @@ function types.object(config)
   if config.isTypeOf then
     assert(type(config.isTypeOf) == 'function', 'must provide isTypeOf as a function')
   end
-  assert(type(config.fields) == 'table', 'fields table must be provided')
-
-  local fields = {}
-  for fieldName, field in pairs(config.fields) do
-    field = field.__type and { kind = field } or field
-    fields[fieldName] = {
-      name = fieldName,
-      kind = field.kind,
-      arguments = field.arguments or {},
-      resolve = field.resolve
-    }
-  end
 
   local instance = {
     __type = 'Object',
     name = config.name,
     isTypeOf = config.isTypeOf,
-    fields = fields,
+    fields = type(config.fields) == 'function' and util.compose(util.bind1(initFields, 'Object'), config.fields) or initFields('Object', config.fields),
     interfaces = config.interfaces
   }
 
@@ -80,21 +71,11 @@ function types.interface(config)
     assert(type(config.resolveType) == 'function', 'must provide resolveType as a function')
   end
 
-  local fields = {}
-  for fieldName, field in pairs(config.fields) do
-    field = field.__type and { kind = field } or field
-    fields[fieldName] = {
-      name = fieldName,
-      kind = field.kind,
-      arguments = field.arguments or {}
-    }
-  end
-
   local instance = {
     __type = 'Interface',
     name = config.name,
     description = config.description,
-    fields = fields,
+    fields = type(config.fields) == 'function' and util.compose(util.bind1(initFields, 'Interface'), config.fields) or initFields('Interface', config.fields),
     resolveType = config.resolveType
   }
 
@@ -103,6 +84,21 @@ function types.interface(config)
   return instance
 end
 
+function initFields(kind, flds)
+  assert(type(flds) == 'table', 'fields table must be provided')
+  local fields = {}
+  for fieldName, field in pairs(flds) do
+    field = field.__type and { kind = field } or field
+    fields[fieldName] = {
+      name = fieldName,
+      kind = field.kind,
+      arguments = field.arguments or {},
+      resolve = kind == 'Object' and field.resolve or nil
+    }
+  end
+  return fields
+end
+
 function types.enum(config)
   assert(type(config.name) == 'string', 'type name must be provided as a string')
   assert(type(config.values) == 'table', 'values table must be provided')

+ 10 - 0
graphql/util.lua

@@ -73,4 +73,14 @@ function util.coerceValue(node, schemaType, variables)
   end
 end
 
+function util.compose (f,g)
+    return function(...) return f(g(...)) end
+end
+
+function util.bind1(func, val1)
+  return function (val2)
+    return func(val1, val2)
+  end
+end
+
 return util

+ 6 - 1
graphql/validate.lua

@@ -58,7 +58,12 @@ local visitors = {
 
   field = {
     enter = function(node, context)
-      local parentField = context.objects[#context.objects].fields[node.name.value]
+      local parentField
+      if context.objects[#context.objects].__type == 'List' then
+        parentField = context.objects[#context.objects - 1].fields[node.name.value]
+      else
+        parentField = context.objects[#context.objects].fields[node.name.value]
+      end
 
       -- false is a special value indicating that the field was not present in the type definition.
       local field = parentField and parentField.kind or false