Browse Source

Directive rules;

bjorn 9 years ago
parent
commit
733f1c1aff
4 changed files with 76 additions and 5 deletions
  1. 10 0
      rules.lua
  2. 11 0
      schema.lua
  3. 36 0
      types.lua
  4. 19 5
      validate.lua

+ 10 - 0
rules.lua

@@ -384,4 +384,14 @@ function rules.uniqueInputObjectFields(node, context)
   validateValue(node.value)
 end
 
+function rules.directivesAreDefined(node, context)
+  if not node.directives then return end
+
+  for _, directive in pairs(node.directives) do
+    if not context.schema:getDirective(directive.name.value) then
+      error('Unknown directive "' .. directive.name.value .. '"')
+    end
+  end
+end
+
 return rules

+ 11 - 0
schema.lua

@@ -11,6 +11,7 @@ function schema.create(config)
 
   self.typeMap = {}
   self.interfaceMap = {}
+  self.directiveMap = {}
 
   local function generateTypeMap(node)
     if node.__type == 'NonNull' or node.__type == 'List' then
@@ -46,10 +47,15 @@ function schema.create(config)
 
   generateTypeMap(self.query)
 
+  for _, directive in ipairs(self.directives) do
+    self.directiveMap[directive.name] = directive
+  end
+
   return setmetatable(self, schema)
 end
 
 function schema:getType(name)
+  if not name then return end
   return self.typeMap[name]
 end
 
@@ -59,4 +65,9 @@ function schema:getImplementors(interface)
   return self.interfaceMap[interface] or (isInterface and {} or nil)
 end
 
+function schema:getDirective(name)
+  if not name then return false end
+  return self.directiveMap[name]
+end
+
 return schema

+ 36 - 0
types.lua

@@ -220,4 +220,40 @@ types.id = types.scalar({
   end
 })
 
+function types.directive(config)
+  assert(type(config.name) == 'string', 'type name must be provided as a string')
+
+  local instance = {
+    __type = 'Directive',
+    name = config.name,
+    description = config.description,
+    arguments = config.arguments,
+    onOperation = config.onOperation or false,
+    onFragment = config.onOperation or false,
+    onField = config.onField or false
+  }
+
+  return instance
+end
+
+types.include = types.directive({
+  name = 'include',
+  arguments = {
+    ['if'] = types.boolean.nonNull
+  },
+  onOperation = false,
+  onFragment = true,
+  onField = true
+})
+
+types.skip = types.directive({
+  name = 'skip',
+  arguments = {
+    ['if'] = types.boolean.nonNull
+  },
+  onOperation = false,
+  onFragment = true,
+  onField = true
+})
+
 return types

+ 19 - 5
validate.lua

@@ -32,7 +32,8 @@ local visitors = {
 
     rules = {
       rules.uniqueOperationNames,
-      rules.loneAnonymousOperation
+      rules.loneAnonymousOperation,
+      rules.directivesAreDefined
     }
   },
 
@@ -81,7 +82,8 @@ local visitors = {
       rules.compositeFieldsAreNotLeaves,
       rules.uniqueArgumentNames,
       rules.argumentsOfCorrectType,
-      rules.requiredArgumentsPresent
+      rules.requiredArgumentsPresent,
+      rules.directivesAreDefined
     }
   },
 
@@ -106,7 +108,11 @@ local visitors = {
       end
     end,
 
-    rules = { rules.fragmentHasValidType, rules.fragmentSpreadIsPossible }
+    rules = {
+      rules.fragmentHasValidType,
+      rules.fragmentSpreadIsPossible,
+      rules.directivesAreDefined
+    }
   },
 
   fragmentSpread = {
@@ -119,7 +125,11 @@ local visitors = {
       table.insert(context.objects, fragmentType)
     end,
 
-    rules = { rules.fragmentSpreadTargetDefined, rules.fragmentSpreadIsPossible }
+    rules = {
+      rules.fragmentSpreadTargetDefined,
+      rules.fragmentSpreadIsPossible,
+      rules.directivesAreDefined
+    }
   },
 
   fragmentDefinition = {
@@ -136,7 +146,11 @@ local visitors = {
       return { node.selectionSet }
     end,
 
-    rules = { rules.fragmentHasValidType, rules.fragmentDefinitionHasNoCycles }
+    rules = {
+      rules.fragmentHasValidType,
+      rules.fragmentDefinitionHasNoCycles,
+      rules.directivesAreDefined
+    }
   },
 
   argument = {