schema.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. local path = (...):gsub('%.[^%.]+$', '')
  2. local types = require(path .. '.types')
  3. local introspection = require(path .. '.introspection')
  4. local schema = {}
  5. schema.__index = schema
  6. function schema.create(config)
  7. assert(type(config.query) == 'table', 'must provide query object')
  8. assert(not config.mutation or type(config.mutation) == 'table', 'mutation must be a table if provided')
  9. local self = setmetatable({}, schema)
  10. for k, v in pairs(config) do
  11. self[k] = v
  12. end
  13. self.typeMap = {}
  14. self.interfaceMap = {}
  15. self.directiveMap = {}
  16. local function generateTypeMap(node)
  17. if not node or (self.typeMap[node.name] and self.typeMap[node.name] == node) then return end
  18. if node.__type == 'NonNull' or node.__type == 'List' then
  19. return generateTypeMap(node.ofType)
  20. end
  21. if self.typeMap[node.name] and self.typeMap[node.name] ~= node then
  22. error('Encountered multiple types named "' .. node.name .. '"')
  23. end
  24. if type(node.fields) == 'function' then node.fields = node.fields() end
  25. self.typeMap[node.name] = node
  26. if node.__type == 'Object' and node.interfaces then
  27. for _, interface in ipairs(node.interfaces) do
  28. generateTypeMap(interface)
  29. self.interfaceMap[interface.name] = self.interfaceMap[interface.name] or {}
  30. self.interfaceMap[interface.name][node] = node
  31. end
  32. end
  33. if node.__type == 'Object' or node.__type == 'Interface' or node.__type == 'InputObject' then
  34. for fieldName, field in pairs(node.fields) do
  35. if field.arguments then
  36. for k, argument in pairs(field.arguments) do
  37. if argument.__type
  38. then generateTypeMap(argument)
  39. else
  40. assert(type(argument.kind) == 'table', 'kind of argument "'.. k ..'" for "' .. fieldName .. '" must be supplied')
  41. generateTypeMap(argument.kind)
  42. end
  43. end
  44. end
  45. generateTypeMap(field.kind)
  46. end
  47. end
  48. end
  49. generateTypeMap(self.query)
  50. generateTypeMap(self.mutation)
  51. generateTypeMap(introspection.__Schema)
  52. self.directives = self.directives or {
  53. types.include,
  54. types.skip
  55. }
  56. if self.directives then
  57. for _, directive in ipairs(self.directives) do
  58. self.directiveMap[directive.name] = directive
  59. end
  60. end
  61. return self
  62. end
  63. function schema:getType(name)
  64. if not name then return end
  65. return self.typeMap[name]
  66. end
  67. function schema:getImplementors(interface)
  68. local kind = self:getType(interface)
  69. local isInterface = kind and kind.__type == 'Interface'
  70. return self.interfaceMap[interface] or (isInterface and {} or nil)
  71. end
  72. function schema:getDirective(name)
  73. if not name then return false end
  74. return self.directiveMap[name]
  75. end
  76. function schema:getQueryType()
  77. return self.query
  78. end
  79. function schema:getMutationType()
  80. return self.mutation
  81. end
  82. function schema:getTypeMap()
  83. return self.typeMap
  84. end
  85. function schema:getPossibleTypes(abstractType)
  86. if abstractType.__type == 'Union' then
  87. return abstractType.types
  88. end
  89. return self:getImplementors(abstractType)
  90. end
  91. function schema.getParentField(context, name, count)
  92. local parent = nil
  93. if name == '__schema' then
  94. parent = introspection.SchemaMetaFieldDef
  95. elseif name == '__type' then
  96. parent = introspection.TypeMetaFieldDef
  97. elseif name == '__typename' then
  98. parent = introspection.TypeNameMetaFieldDef
  99. else
  100. count = count or 1
  101. local obj = context.objects[#context.objects - count]
  102. if obj.ofType then obj = obj.ofType end
  103. parent = obj.fields[name]
  104. end
  105. return parent
  106. end
  107. return schema