2
0

schema.lua 3.2 KB

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