types.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. args = field.args or {}
  42. }
  43. end
  44. local instance = {
  45. __type = 'Object',
  46. name = config.name,
  47. isTypeOf = config.isTypeOf,
  48. fields = fields
  49. }
  50. instance.nonNull = types.nonNull(instance)
  51. return instance
  52. end
  53. function types.interface(config)
  54. assert(type(config.name) == 'string', 'type name must be provided as a string')
  55. assert(type(config.fields) == 'table', 'fields table must be provided')
  56. if config.resolveType then
  57. assert(type(config.resolveType) == 'function', 'must provide resolveType as a function')
  58. end
  59. local instance = {
  60. __type = 'Interface',
  61. name = config.name,
  62. description = config.description,
  63. fields = config.fields,
  64. resolveType = config.resolveType
  65. }
  66. instance.nonNull = types.nonNull(instance)
  67. return instance
  68. end
  69. function types.enum(config)
  70. assert(type(config.name) == 'string', 'type name must be provided as a string')
  71. assert(type(config.values) == 'table', 'values table must be provided')
  72. local instance = {
  73. __type = 'Enum',
  74. name = config.name,
  75. description = config.description,
  76. values = config.values
  77. }
  78. instance.nonNull = types.nonNull(instance)
  79. return instance
  80. end
  81. function types.union(config)
  82. assert(type(config.name) == 'string', 'type name must be provided as a string')
  83. assert(type(config.types) == 'table', 'types table must be provided')
  84. local instance = {
  85. __type = 'Union',
  86. name = config.name,
  87. types = config.types
  88. }
  89. instance.nonNull = types.nonNull(instance)
  90. return instance
  91. end
  92. local coerceInt = function(value)
  93. value = tonumber(value)
  94. if not value then return end
  95. if value == value and value < 2 ^ 32 and value >= -2 ^ 32 then
  96. return value < 0 and math.ceil(value) or math.floor(value)
  97. end
  98. end
  99. types.int = types.scalar({
  100. name = 'Int',
  101. serialize = coerceInt,
  102. parseValue = coerceInt,
  103. parseLiteral = function(node)
  104. if node.kind == 'int' then
  105. return coerceInt(node.value)
  106. end
  107. end
  108. })
  109. types.float = types.scalar({
  110. name = 'Float',
  111. serialize = tonumber,
  112. parseValue = tonumber,
  113. parseLiteral = function(node)
  114. if node.kind == 'float' or node.kind == 'int' then
  115. return tonumber(node.value)
  116. end
  117. end
  118. })
  119. types.string = types.scalar({
  120. name = 'String',
  121. serialize = tostring,
  122. parseValue = tostring,
  123. parseLiteral = function(node)
  124. if node.kind == 'string' then
  125. return node.value
  126. end
  127. end
  128. })
  129. local function toboolean(x)
  130. return x and true or false
  131. end
  132. types.boolean = types.scalar({
  133. name = 'Boolean',
  134. serialize = toboolean,
  135. parseValue = toboolean,
  136. parseLiteral = function(node)
  137. return node.kind == 'boolean' and node.value or nil
  138. end
  139. })
  140. types.id = types.scalar({
  141. name = 'ID',
  142. serialize = tostring,
  143. parseValue = tostring,
  144. parseLiteral = function(node)
  145. return node.kind == 'string' or node.kind == 'int' and node.value or nil
  146. end
  147. })
  148. return types