123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- local path = (...):gsub('%.[^%.]+$', '')
- local types = require(path .. '.types')
- local introspection = require(path .. '.introspection')
- local schema = {}
- schema.__index = schema
- function schema.create(config)
- assert(type(config.query) == 'table', 'must provide query object')
- if config.mutation then
- assert(type(config.mutation) == 'table', 'mutation must be a table')
- end
- if config.subscription then
- assert(type(config.subscription) == 'table', 'subscription must be a table')
- end
-
- local self = {}
- for k, v in pairs(config) do
- self[k] = v
- end
- self.typeMap = {
- }
- self.interfaceMap = {}
- self.directiveMap = {}
- local function generateTypeMap(node)
- if not node or (self.typeMap[node.name] and self.typeMap[node.name] == node) then return end
- if node.__type == 'NonNull' or node.__type == 'List' then
- return generateTypeMap(node.ofType)
- end
- if self.typeMap[node.name] and self.typeMap[node.name] ~= node then
- error('Encountered multiple types named "' .. node.name .. '"')
- end
- if type(node.fields) == 'function' then node.fields = node.fields() end
- self.typeMap[node.name] = node
- if node.__type == 'Object' and node.interfaces then
- for _, interface in ipairs(node.interfaces) do
- generateTypeMap(interface)
- self.interfaceMap[interface.name] = self.interfaceMap[interface.name] or {}
- self.interfaceMap[interface.name][node] = node
- end
- end
- if node.__type == 'Object' or node.__type == 'Interface' or node.__type == 'InputObject' then
- for fieldName, field in pairs(node.fields) do
- if field.arguments then
- for k, argument in pairs(field.arguments) do
- if argument.__type
- then generateTypeMap(argument)
- else
- assert(type(argument.kind) == 'table', 'kind of argument "'.. k ..'" for "' .. fieldName .. '" must be supplied')
- generateTypeMap(argument.kind)
- end
- end
- end
- generateTypeMap(field.kind)
- end
- end
- end
- generateTypeMap(self.query)
- generateTypeMap(self.mutation)
- generateTypeMap(self.subscription)
- generateTypeMap(introspection.__Schema)
- self.directives = self.directives or {
- types.include,
- types.skip
- }
- if self.directives then
- for _, directive in ipairs(self.directives) do
- self.directiveMap[directive.name] = directive
- end
- end
- return setmetatable(self, schema)
- end
- function schema:getType(name)
- if not name then return end
- return self.typeMap[name]
- end
- function schema:getImplementors(interface)
- local kind = self:getType(interface)
- local isInterface = kind and kind.__type == '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
- function schema:getQueryType()
- return self.query
- end
- function schema:getMutationType()
- return self.mutation
- end
- function schema:getSubscriptionType()
- return self.subscription
- end
- function schema:getTypeMap()
- return self.typeMap
- end
- function schema:getPossibleTypes(abstractType)
- if abstractType.__type == 'Union' then
- return abstractType.types;
- end
- return self:getImplementors(abstractType);
- end
- function schema.getParentField(context, name, count)
- local parent = nil
- if name == '__schema' then
- parent = introspection.SchemaMetaFieldDef
- elseif name == '__type' then
- parent = introspection.TypeMetaFieldDef
- elseif name == '__typename' then
- parent = introspection.TypeNameMetaFieldDef
- else
- count = count == nil and 1 or count
- local obj = context.objects[#context.objects - count]
- if obj.ofType then obj = obj.ofType end
- parent = obj.fields[name]
- end
- return parent
- end
- return schema
|