types.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. local types = {}
  2. function types.nonNull(kind)
  3. assert(kind, 'Must provide a type')
  4. return {
  5. __type = 'NonNull',
  6. ofType = kind
  7. }
  8. end
  9. function types.list(kind)
  10. assert(kind, 'Must provide a type')
  11. return {
  12. __type = 'List',
  13. ofType = kind
  14. }
  15. end
  16. function types.scalar(config)
  17. assert(type(config.name) == 'string', 'type name must be provided as a string')
  18. assert(type(config.serialize) == 'function', 'serialize must be a function')
  19. if config.parseValue or config.parseLiteral then
  20. assert(
  21. type(config.parseValue) == 'function' and type(config.parseLiteral) == 'function',
  22. 'must provide both parseValue and parseLiteral to scalar type'
  23. )
  24. end
  25. local instance = {
  26. __type = 'Scalar',
  27. name = config.name,
  28. description = config.description,
  29. serialize = config.serialize,
  30. parseValue = config.parseValue,
  31. parseLiteral = config.parseLiteral
  32. }
  33. instance.nonNull = types.nonNull(instance)
  34. return instance
  35. end
  36. function types.object(config)
  37. assert(type(config.name) == 'string', 'type name must be provided as a string')
  38. if config.isTypeOf then
  39. assert(type(config.isTypeOf) == 'function', 'must provide isTypeOf as a function')
  40. end
  41. assert(type(config.fields) == 'table', 'fields table must be provided')
  42. local fields = {}
  43. for fieldName, field in pairs(config.fields) do
  44. field = field.__type and { kind = field } or field
  45. fields[fieldName] = {
  46. name = fieldName,
  47. kind = field.kind,
  48. arguments = field.arguments or {}
  49. }
  50. end
  51. local instance = {
  52. __type = 'Object',
  53. name = config.name,
  54. isTypeOf = config.isTypeOf,
  55. fields = fields,
  56. interfaces = config.interfaces
  57. }
  58. instance.nonNull = types.nonNull(instance)
  59. return instance
  60. end
  61. function types.interface(config)
  62. assert(type(config.name) == 'string', 'type name must be provided as a string')
  63. assert(type(config.fields) == 'table', 'fields table must be provided')
  64. if config.resolveType then
  65. assert(type(config.resolveType) == 'function', 'must provide resolveType as a function')
  66. end
  67. local fields = {}
  68. for fieldName, field in pairs(config.fields) do
  69. field = field.__type and { kind = field } or field
  70. fields[fieldName] = {
  71. name = fieldName,
  72. kind = field.kind,
  73. arguments = field.arguments or {}
  74. }
  75. end
  76. local instance = {
  77. __type = 'Interface',
  78. name = config.name,
  79. description = config.description,
  80. fields = fields,
  81. resolveType = config.resolveType
  82. }
  83. instance.nonNull = types.nonNull(instance)
  84. return instance
  85. end
  86. function types.enum(config)
  87. assert(type(config.name) == 'string', 'type name must be provided as a string')
  88. assert(type(config.values) == 'table', 'values table must be provided')
  89. local instance = {
  90. __type = 'Enum',
  91. name = config.name,
  92. description = config.description,
  93. values = config.values
  94. }
  95. instance.nonNull = types.nonNull(instance)
  96. return instance
  97. end
  98. function types.union(config)
  99. assert(type(config.name) == 'string', 'type name must be provided as a string')
  100. assert(type(config.types) == 'table', 'types table must be provided')
  101. local instance = {
  102. __type = 'Union',
  103. name = config.name,
  104. types = config.types
  105. }
  106. instance.nonNull = types.nonNull(instance)
  107. return instance
  108. end
  109. function types.inputObject(config)
  110. assert(type(config.name) == 'string', 'type name must be provided as a string')
  111. local fields = {}
  112. for fieldName, field in pairs(config.fields) do
  113. field = field.__type and { kind = field } or field
  114. fields[fieldName] = {
  115. name = fieldName,
  116. kind = field.kind
  117. }
  118. end
  119. local instance = {
  120. __type = 'InputObject',
  121. name = config.name,
  122. description = config.description,
  123. fields = fields
  124. }
  125. return instance
  126. end
  127. local coerceInt = function(value)
  128. value = tonumber(value)
  129. if not value then return end
  130. if value == value and value < 2 ^ 32 and value >= -2 ^ 32 then
  131. return value < 0 and math.ceil(value) or math.floor(value)
  132. end
  133. end
  134. types.int = types.scalar({
  135. name = 'Int',
  136. serialize = coerceInt,
  137. parseValue = coerceInt,
  138. parseLiteral = function(node)
  139. if node.kind == 'int' then
  140. return coerceInt(node.value)
  141. end
  142. end
  143. })
  144. types.float = types.scalar({
  145. name = 'Float',
  146. serialize = tonumber,
  147. parseValue = tonumber,
  148. parseLiteral = function(node)
  149. if node.kind == 'float' or node.kind == 'int' then
  150. return tonumber(node.value)
  151. end
  152. end
  153. })
  154. types.string = types.scalar({
  155. name = 'String',
  156. serialize = tostring,
  157. parseValue = tostring,
  158. parseLiteral = function(node)
  159. if node.kind == 'string' then
  160. return node.value
  161. end
  162. end
  163. })
  164. local function toboolean(x)
  165. return x and true or false
  166. end
  167. types.boolean = types.scalar({
  168. name = 'Boolean',
  169. serialize = toboolean,
  170. parseValue = toboolean,
  171. parseLiteral = function(node)
  172. return node.kind == 'boolean' and node.value or nil
  173. end
  174. })
  175. types.id = types.scalar({
  176. name = 'ID',
  177. serialize = tostring,
  178. parseValue = tostring,
  179. parseLiteral = function(node)
  180. return node.kind == 'string' or node.kind == 'int' and node.value or nil
  181. end
  182. })
  183. return types