types.lua 4.5 KB

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