schema.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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.directives = self.directives or {
  14. types.include,
  15. types.skip
  16. }
  17. self.typeMap = {}
  18. self.interfaceMap = {}
  19. self.directiveMap = {}
  20. self:generateTypeMap(self.query)
  21. self:generateTypeMap(self.mutation)
  22. self:generateTypeMap(self.subscription)
  23. self:generateTypeMap(introspection.__Schema)
  24. self:generateDirectiveMap()
  25. return self
  26. end
  27. function schema:generateTypeMap(node)
  28. if not node or (self.typeMap[node.name] and self.typeMap[node.name] == node) then return end
  29. if node.__type == 'NonNull' or node.__type == 'List' then
  30. return self:generateTypeMap(node.ofType)
  31. end
  32. if self.typeMap[node.name] and self.typeMap[node.name] ~= node then
  33. error('Encountered multiple types named "' .. node.name .. '"')
  34. end
  35. node.fields = type(node.fields) == 'function' and node.fields() or node.fields
  36. self.typeMap[node.name] = node
  37. if node.__type == 'Object' and node.interfaces then
  38. for _, interface in ipairs(node.interfaces) do
  39. self:generateTypeMap(interface)
  40. self.interfaceMap[interface.name] = self.interfaceMap[interface.name] or {}
  41. self.interfaceMap[interface.name][node] = node
  42. end
  43. end
  44. if node.__type == 'Object' or node.__type == 'Interface' or node.__type == 'InputObject' then
  45. for fieldName, field in pairs(node.fields) do
  46. if field.arguments then
  47. for name, argument in pairs(field.arguments) do
  48. local argumentType = argument.__type and argument or argument.kind
  49. assert(argumentType, 'Must supply type for argument "' .. name .. '" on "' .. fieldName .. '"')
  50. self:generateTypeMap(argumentType)
  51. end
  52. end
  53. self:generateTypeMap(field.kind)
  54. end
  55. end
  56. end
  57. function schema:generateDirectiveMap()
  58. for _, directive in ipairs(self.directives) do
  59. self.directiveMap[directive.name] = directive
  60. end
  61. end
  62. function schema:getType(name)
  63. if not name then return end
  64. return self.typeMap[name]
  65. end
  66. function schema:getImplementors(interface)
  67. local kind = self:getType(interface)
  68. local isInterface = kind and kind.__type == 'Interface'
  69. return self.interfaceMap[interface] or (isInterface and {} or nil)
  70. end
  71. function schema:getDirective(name)
  72. if not name then return false end
  73. return self.directiveMap[name]
  74. end
  75. function schema:getQueryType()
  76. return self.query
  77. end
  78. function schema:getMutationType()
  79. return self.mutation
  80. end
  81. function schema:getSubscriptionType()
  82. return self.subscription
  83. end
  84. function schema:getTypeMap()
  85. return self.typeMap
  86. end
  87. function schema:getPossibleTypes(abstractType)
  88. if abstractType.__type == 'Union' then
  89. return abstractType.types
  90. end
  91. return self:getImplementors(abstractType)
  92. end
  93. return schema