Browse Source

More validation rules;

bjorn 9 years ago
parent
commit
2fa1078b5d
1 changed files with 33 additions and 3 deletions
  1. 33 3
      validate.lua

+ 33 - 3
validate.lua

@@ -36,10 +36,22 @@ return function(schema, tree)
     end,
 
     field = function(node)
-      if context.typeStack[#context.typeStack].__type == 'Scalar' and node.selectionSet then
-        error('Scalar values cannot have selections')
+      local currentType = context.typeStack[#context.typeStack].__type
+      if currentType == 'Scalar' and node.selectionSet then
+        error('Scalar values cannot have subselections')
       end
 
+      local isCompositeType = currentType == 'Object' or currentType == 'Interface' or currentType == 'Union'
+      if isCompositeType and not node.selectionSet then
+        error('Composite types must have subselections')
+      end
+
+      if node.selectionSet then
+        return {node.selectionSet}
+      end
+    end,
+
+    inlineFragment = function(node)
       if node.selectionSet then
         return {node.selectionSet}
       end
@@ -53,7 +65,25 @@ return function(schema, tree)
         table.insert(context.typeStack, schema.query)
       elseif node.kind == 'field' then
         local parent = context.typeStack[#context.typeStack]
-        table.insert(context.typeStack, parent.fields[node.name.value].kind)
+        if parent.fields[node.name.value] then
+          table.insert(context.typeStack, parent.fields[node.name.value].kind)
+        else
+          error('Field "' .. node.name.value .. '" is not defined on type "' .. parent.name .. '"')
+        end
+      elseif node.kind == 'inlineFragment' then
+        if node.typeCondition then
+          local kind = schema:getType(node.typeCondition.name.value)
+
+          if not kind then
+            error('Inline fragment type condition refers to non-existent type')
+          end
+
+          if kind and kind.__type ~= 'Object' and kind.__type ~= 'Interface' and kind.__type ~= 'Union' then
+            error('Inline fragment type condition was not an Object, Interface, or Union')
+          end
+
+          table.insert(context.typeStack, kind)
+        end
       end
 
       local targets = visitors[node.kind](node)