schema.lua 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. local path = (...):gsub('%.[^%.]+$', '')
  2. local types = require(path .. '.types')
  3. local schema = {}
  4. schema.__index = schema
  5. function schema.create(config)
  6. assert(type(config.query) == 'table', 'must provide query object')
  7. local self = {}
  8. for k, v in pairs(config) do
  9. self[k] = v
  10. end
  11. self.typeMap = {
  12. Int = types.int,
  13. Float = types.float,
  14. String = types.string,
  15. Boolean = types.boolean,
  16. ID = types.id
  17. }
  18. self.interfaceMap = {}
  19. self.directiveMap = {}
  20. local function generateTypeMap(node)
  21. if self.typeMap[node.name] and self.typeMap[node.name] == node then return end
  22. if node.__type == 'NonNull' or node.__type == 'List' then
  23. return generateTypeMap(node.ofType)
  24. end
  25. if self.typeMap[node.name] and self.typeMap[node.name] ~= node then
  26. error('Encountered multiple types named "' .. node.name .. '"')
  27. end
  28. self.typeMap[node.name] = node
  29. if node.__type == 'Object' and node.interfaces then
  30. for _, interface in ipairs(node.interfaces) do
  31. generateTypeMap(interface)
  32. self.interfaceMap[interface.name] = self.interfaceMap[interface.name] or {}
  33. self.interfaceMap[interface.name][node] = node
  34. end
  35. end
  36. if node.__type == 'Object' or node.__type == 'Interface' or node.__type == 'InputObject' then
  37. if type(node.fields) == 'function' then node.fields = node.fields() end
  38. for fieldName, field in pairs(node.fields) do
  39. if field.arguments then
  40. for _, argument in pairs(field.arguments) do
  41. generateTypeMap(argument)
  42. end
  43. end
  44. generateTypeMap(field.kind)
  45. end
  46. end
  47. end
  48. generateTypeMap(self.query)
  49. self.directives = self.directives or {
  50. types.include,
  51. types.skip
  52. }
  53. if self.directives then
  54. for _, directive in ipairs(self.directives) do
  55. self.directiveMap[directive.name] = directive
  56. end
  57. end
  58. return setmetatable(self, schema)
  59. end
  60. function schema:getType(name)
  61. if not name then return end
  62. return self.typeMap[name]
  63. end
  64. function schema:getImplementors(interface)
  65. local kind = self:getType(interface)
  66. local isInterface = kind and kind.__type == 'Interface'
  67. return self.interfaceMap[interface] or (isInterface and {} or nil)
  68. end
  69. function schema:getDirective(name)
  70. if not name then return false end
  71. return self.directiveMap[name]
  72. end
  73. return schema