|
@@ -2,12 +2,15 @@ local path = (...):gsub('%.[^%.]+$', '')
|
|
local types = require(path .. '.types')
|
|
local types = require(path .. '.types')
|
|
local util = require(path .. '.util')
|
|
local util = require(path .. '.util')
|
|
local cjson = require 'cjson' -- needs to be cloned from here https://github.com/openresty/lua-cjson for cjson.empty_array feature
|
|
local cjson = require 'cjson' -- needs to be cloned from here https://github.com/openresty/lua-cjson for cjson.empty_array feature
|
|
|
|
+
|
|
local function isNullish(value)
|
|
local function isNullish(value)
|
|
return value == nil
|
|
return value == nil
|
|
end
|
|
end
|
|
|
|
+
|
|
local function instanceof(t, s)
|
|
local function instanceof(t, s)
|
|
return t.__type == s
|
|
return t.__type == s
|
|
end
|
|
end
|
|
|
|
+
|
|
local function resolveDirective(directive)
|
|
local function resolveDirective(directive)
|
|
local res = {}
|
|
local res = {}
|
|
if directive.onQuery then table.insert(res, 'QUERY') end
|
|
if directive.onQuery then table.insert(res, 'QUERY') end
|
|
@@ -18,153 +21,168 @@ local function resolveDirective(directive)
|
|
if directive.onInlineFragment then table.insert(res, 'INLINE_FRAGMENT') end
|
|
if directive.onInlineFragment then table.insert(res, 'INLINE_FRAGMENT') end
|
|
return res
|
|
return res
|
|
end
|
|
end
|
|
|
|
+
|
|
local function mapToList(m)
|
|
local function mapToList(m)
|
|
local r = {}
|
|
local r = {}
|
|
|
|
+
|
|
for k,v in pairs(m) do
|
|
for k,v in pairs(m) do
|
|
table.insert(r, v)
|
|
table.insert(r, v)
|
|
end
|
|
end
|
|
|
|
+
|
|
return r
|
|
return r
|
|
end
|
|
end
|
|
-local __Schema, __Directive, __DirectiveLocation, __Type, __Field, __InputValue,__EnumValue, TypeKind, __TypeKind, SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef, astFromValue, printAst, printers
|
|
|
|
-local DirectiveLocation = {
|
|
|
|
- QUERY = 'QUERY', MUTATION = 'MUTATION', FIELD = 'FIELD', FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION', FRAGMENT_SPREAD = 'FRAGMENT_SPREAD', INLINE_FRAGMENT = 'INLINE_FRAGMENT'
|
|
|
|
-}
|
|
|
|
|
|
|
|
-__Schema = types.object({
|
|
|
|
|
|
+local __Directive, __DirectiveLocation, __Type, __Field, __InputValue,__EnumValue, TypeKind, __TypeKind, SchemaMetaFieldDef, TypeMetaFieldDef, TypeNameMetaFieldDef, astFromValue, printAst, printers
|
|
|
|
+
|
|
|
|
+local __Schema = types.object({
|
|
name = '__Schema',
|
|
name = '__Schema',
|
|
- description =
|
|
|
|
- 'A GraphQL Schema defines the capabilities of a GraphQL server. It ' ..
|
|
|
|
- 'exposes all available types and directives on the server, as well as ' ..
|
|
|
|
- 'the entry points for query and mutation operations.',
|
|
|
|
- fields = function() return {
|
|
|
|
- types = {
|
|
|
|
- description = 'A list of all types supported by this server.',
|
|
|
|
- kind = types.nonNull(types.list(types.nonNull(__Type))),
|
|
|
|
- resolve = function(schema)
|
|
|
|
- local typeMap = schema:getTypeMap(); local res = {}
|
|
|
|
- for k,v in pairs(typeMap) do table.insert(res, typeMap[k]) end; return res
|
|
|
|
- end
|
|
|
|
- },
|
|
|
|
- queryType = {
|
|
|
|
- description = 'The type that query operations will be rooted at.',
|
|
|
|
- kind = types.nonNull(__Type),
|
|
|
|
- resolve = function(schema) return schema:getQueryType() end
|
|
|
|
- },
|
|
|
|
- mutationType = {
|
|
|
|
- description = 'If this server supports mutation, the type that ' ..
|
|
|
|
- 'mutation operations will be rooted at.',
|
|
|
|
- kind = __Type,
|
|
|
|
- resolve = function(schema) return schema:getMutationType() end
|
|
|
|
- },
|
|
|
|
- directives = {
|
|
|
|
- description = 'A list of all directives supported by this server.',
|
|
|
|
- kind = types.nonNull(types.list(types.nonNull(__Directive))),
|
|
|
|
- resolve = function(schema) return schema.directives end
|
|
|
|
|
|
+
|
|
|
|
+ description = [[
|
|
|
|
+ A GraphQL Schema defines the capabilities of a GraphQL server. It
|
|
|
|
+ exposes all available types and directives on the server, as well as
|
|
|
|
+ the entry points for query and mutation operations.
|
|
|
|
+ ]],
|
|
|
|
+
|
|
|
|
+ fields = function()
|
|
|
|
+ return {
|
|
|
|
+ types = {
|
|
|
|
+ description = 'A list of all types supported by this server.',
|
|
|
|
+ kind = types.nonNull(types.list(types.nonNull(__Type))),
|
|
|
|
+ resolve = function(schema)
|
|
|
|
+ local typeMap = schema:getTypeMap()
|
|
|
|
+ local res = {}
|
|
|
|
+
|
|
|
|
+ for k, v in pairs(typeMap) do
|
|
|
|
+ table.insert(res, typeMap[k])
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ return res
|
|
|
|
+ end
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ queryType = {
|
|
|
|
+ description = 'The type that query operations will be rooted at.',
|
|
|
|
+ kind = types.nonNull(__Type),
|
|
|
|
+ resolve = function(schema)
|
|
|
|
+ return schema:getQueryType()
|
|
|
|
+ end
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ mutationType = {
|
|
|
|
+ description = 'If this server supports mutation, the type that mutation operations will be rooted at.',
|
|
|
|
+ kind = __Type,
|
|
|
|
+ resolve = function(schema)
|
|
|
|
+ return schema:getMutationType()
|
|
|
|
+ end
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ directives = {
|
|
|
|
+ description = 'A list of all directives supported by this server.',
|
|
|
|
+ kind = types.nonNull(types.list(types.nonNull(__Directive))),
|
|
|
|
+ resolve = function(schema)
|
|
|
|
+ return schema.directives
|
|
|
|
+ end
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- } end
|
|
|
|
-});
|
|
|
|
|
|
+ end
|
|
|
|
+})
|
|
|
|
|
|
__Directive = types.object({
|
|
__Directive = types.object({
|
|
name = '__Directive',
|
|
name = '__Directive',
|
|
- description =
|
|
|
|
- 'A Directive provides a way to describe alternate runtime execution and ' ..
|
|
|
|
- 'type validation behavior in a GraphQL document.' ..
|
|
|
|
- '\n\nIn some cases, you need to provide options to alter GraphQL’s ' ..
|
|
|
|
- 'execution behavior in ways field arguments will not suffice, such as ' ..
|
|
|
|
- 'conditionally including or skipping a field. Directives provide this by ' ..
|
|
|
|
- 'describing additional information to the executor.',
|
|
|
|
- fields = function() return {
|
|
|
|
- name = types.nonNull(types.string),
|
|
|
|
- description = types.string,
|
|
|
|
- locations = {
|
|
|
|
- kind = types.nonNull(types.list(types.nonNull(
|
|
|
|
- __DirectiveLocation
|
|
|
|
- ))), resolve = resolveDirective
|
|
|
|
- },
|
|
|
|
- args = {
|
|
|
|
- kind =
|
|
|
|
- types.nonNull(types.list(types.nonNull(__InputValue))),
|
|
|
|
- --resolve = function(directive) return directive.arguments or {} end
|
|
|
|
- resolve = function(field)
|
|
|
|
- local args = {}
|
|
|
|
- local transform = function(a, n)
|
|
|
|
- if a.__type then
|
|
|
|
- return {kind = a, name = n}
|
|
|
|
- else
|
|
|
|
- if not a.name then
|
|
|
|
- local r = {name = n}
|
|
|
|
|
|
+ description = [[
|
|
|
|
+ A Directive provides a way to describe alternate runtime execution and
|
|
|
|
+ type validation behavior in a GraphQL document.
|
|
|
|
+ \n\nIn some cases, you need to provide options to alter GraphQL’s
|
|
|
|
+ execution behavior in ways field arguments will not suffice, such as
|
|
|
|
+ conditionally including or skipping a field. Directives provide this by
|
|
|
|
+ describing additional information to the executor.
|
|
|
|
+ ]],
|
|
|
|
+
|
|
|
|
+ fields = function()
|
|
|
|
+ return {
|
|
|
|
+ name = types.nonNull(types.string),
|
|
|
|
+
|
|
|
|
+ description = types.string,
|
|
|
|
+
|
|
|
|
+ locations = {
|
|
|
|
+ kind = types.nonNull(types.list(types.nonNull(
|
|
|
|
+ __DirectiveLocation
|
|
|
|
+ )))
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ args = {
|
|
|
|
+ kind = types.nonNull(types.list(types.nonNull(__InputValue))),
|
|
|
|
+ resolve = function(field)
|
|
|
|
+ local args = {}
|
|
|
|
+ local transform = function(a, n)
|
|
|
|
+ if a.__type then
|
|
|
|
+ return { kind = a, name = n }
|
|
|
|
+ else
|
|
|
|
+ if a.name then return a end
|
|
|
|
+
|
|
|
|
+ local r = { name = n }
|
|
for k,v in pairs(a) do
|
|
for k,v in pairs(a) do
|
|
r[k] = v
|
|
r[k] = v
|
|
end
|
|
end
|
|
|
|
+
|
|
return r
|
|
return r
|
|
- else
|
|
|
|
- return a
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
+
|
|
|
|
+ for k, v in pairs(field.arguments or {}) do
|
|
|
|
+ table.insert(args, transform(v, k))
|
|
|
|
+ end
|
|
|
|
+
|
|
|
|
+ if #args > 0 then
|
|
|
|
+ return args
|
|
|
|
+ else
|
|
|
|
+ return cjson.empty_array
|
|
|
|
+ end
|
|
end
|
|
end
|
|
- for k, v in pairs(field.arguments or {}) do table.insert(args, transform(v, k)) end
|
|
|
|
- -- p(args)
|
|
|
|
- -- return args
|
|
|
|
- if #args > 0 then return args else return cjson.empty_array end
|
|
|
|
- end
|
|
|
|
- },
|
|
|
|
- -- NOTE = the following three fields are deprecated and are no longer part
|
|
|
|
- -- of the GraphQL specification.
|
|
|
|
- onOperation = {
|
|
|
|
- deprecationReason = 'Use `locations`.',
|
|
|
|
- kind = types.nonNull(types.boolean),
|
|
|
|
- resolve = function(d) return
|
|
|
|
- d.locations:find(DirectiveLocation.QUERY) ~= nil or
|
|
|
|
- d.locations:find(DirectiveLocation.MUTATION) ~= nil end
|
|
|
|
- },
|
|
|
|
- onFragment = {
|
|
|
|
- deprecationReason = 'Use `locations`.',
|
|
|
|
- kind = types.nonNull(types.boolean),
|
|
|
|
- resolve = function(d) return
|
|
|
|
- d.locations:find(DirectiveLocation.FRAGMENT_SPREAD) ~= nil or
|
|
|
|
- d.locations:find(DirectiveLocation.INLINE_FRAGMENT) ~= nil or
|
|
|
|
- d.locations:find(DirectiveLocation.FRAGMENT_DEFINITION) ~= nil end
|
|
|
|
- },
|
|
|
|
- onField = {
|
|
|
|
- deprecationReason = 'Use `locations`.',
|
|
|
|
- kind = types.nonNull(types.boolean),
|
|
|
|
- resolve = function(d) return d.locations:find(DirectiveLocation.FIELD) ~= nil end
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- } end
|
|
|
|
-});
|
|
|
|
|
|
+ end
|
|
|
|
+})
|
|
|
|
|
|
__DirectiveLocation = types.enum({
|
|
__DirectiveLocation = types.enum({
|
|
name = '__DirectiveLocation',
|
|
name = '__DirectiveLocation',
|
|
- description =
|
|
|
|
- 'A Directive can be adjacent to many parts of the GraphQL language, a ' ..
|
|
|
|
- '__DirectiveLocation describes one such possible adjacencies.',
|
|
|
|
|
|
+ description = [[
|
|
|
|
+ A Directive can be adjacent to many parts of the GraphQL language, a
|
|
|
|
+ __DirectiveLocation describes one such possible adjacencies.
|
|
|
|
+ ]],
|
|
|
|
+
|
|
values = {
|
|
values = {
|
|
QUERY = {
|
|
QUERY = {
|
|
- value = DirectiveLocation.QUERY,
|
|
|
|
|
|
+ value = 'QUERY',
|
|
description = 'Location adjacent to a query operation.'
|
|
description = 'Location adjacent to a query operation.'
|
|
},
|
|
},
|
|
|
|
+
|
|
MUTATION = {
|
|
MUTATION = {
|
|
- value = DirectiveLocation.MUTATION,
|
|
|
|
|
|
+ value = 'MUTATION',
|
|
description = 'Location adjacent to a mutation operation.'
|
|
description = 'Location adjacent to a mutation operation.'
|
|
},
|
|
},
|
|
|
|
+
|
|
FIELD = {
|
|
FIELD = {
|
|
- value = DirectiveLocation.FIELD,
|
|
|
|
|
|
+ value = 'FIELD',
|
|
description = 'Location adjacent to a field.'
|
|
description = 'Location adjacent to a field.'
|
|
},
|
|
},
|
|
|
|
+
|
|
FRAGMENT_DEFINITION = {
|
|
FRAGMENT_DEFINITION = {
|
|
- value = DirectiveLocation.FRAGMENT_DEFINITION,
|
|
|
|
|
|
+ value = 'FRAGMENT_DEFINITION',
|
|
description = 'Location adjacent to a fragment definition.'
|
|
description = 'Location adjacent to a fragment definition.'
|
|
},
|
|
},
|
|
|
|
+
|
|
FRAGMENT_SPREAD = {
|
|
FRAGMENT_SPREAD = {
|
|
- value = DirectiveLocation.FRAGMENT_SPREAD,
|
|
|
|
|
|
+ value = 'FRAGMENT_SPREAD',
|
|
description = 'Location adjacent to a fragment spread.'
|
|
description = 'Location adjacent to a fragment spread.'
|
|
},
|
|
},
|
|
|
|
+
|
|
INLINE_FRAGMENT = {
|
|
INLINE_FRAGMENT = {
|
|
- value = DirectiveLocation.INLINE_FRAGMENT,
|
|
|
|
|
|
+ value = 'INLINE_FRAGMENT',
|
|
description = 'Location adjacent to an inline fragment.'
|
|
description = 'Location adjacent to an inline fragment.'
|
|
- },
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-});
|
|
|
|
|
|
+})
|
|
|
|
|
|
__Type = types.object({
|
|
__Type = types.object({
|
|
name = '__Type',
|
|
name = '__Type',
|
|
@@ -212,7 +230,7 @@ __Type = types.object({
|
|
resolve = function(t, args)
|
|
resolve = function(t, args)
|
|
if instanceof(t, 'Object') or
|
|
if instanceof(t, 'Object') or
|
|
instanceof(t, 'Interface') then
|
|
instanceof(t, 'Interface') then
|
|
-
|
|
|
|
|
|
+
|
|
local fieldMap = t.fields;
|
|
local fieldMap = t.fields;
|
|
local fields = {}; for k,v in pairs(fieldMap) do table.insert(fields, fieldMap[k]) end
|
|
local fields = {}; for k,v in pairs(fieldMap) do table.insert(fields, fieldMap[k]) end
|
|
if not args.includeDeprecated then
|
|
if not args.includeDeprecated then
|