Home Reference Source

src/util/graphql.js

  1. import { Kind } from 'graphql';
  2. import includes from 'lodash.includes';
  3.  
  4. export const SCALAR_TYPE_NAMES = [
  5. 'Int',
  6. 'Float',
  7. 'String',
  8. 'Boolean',
  9. 'ID',
  10. 'ObjID'
  11. ];
  12.  
  13. export function getBaseType(type) {
  14. if (type.kind === 'ListType' || type.kind === 'NonNullType') {
  15. return getBaseType(type.type);
  16. }
  17. return type;
  18. }
  19.  
  20. export function argumentsToObject(argumentsAst) {
  21. const result = {};
  22. argumentsAst.forEach(argument => {
  23. result[argument.name.value] = argument.value.value;
  24. });
  25. return result;
  26. }
  27.  
  28. export function isScalarField(field) {
  29. return includes(SCALAR_TYPE_NAMES, getBaseType(field.type).name.value);
  30. }
  31.  
  32. export function buildName(name) {
  33. return { kind: 'Name', value: name };
  34. }
  35.  
  36. export function buildTypeDefinition(name, fields, kind, values) {
  37. return {
  38. kind: kind || 'ObjectTypeDefinition',
  39. name: buildName(name),
  40. interfaces: [],
  41. directives: [],
  42. fields,
  43. values: values || []
  44. };
  45. }
  46.  
  47. export function buildTypeExtension(type) {
  48. return {
  49. kind: Kind.TYPE_EXTENSION_DEFINITION,
  50. definition: type
  51. };
  52. }
  53.  
  54. export function buildTypeReference(name) {
  55. if (name[name.length - 1] === '!') {
  56. return {
  57. kind: 'NonNullType',
  58. type: buildTypeReference(name.substring(0, name.length - 1))
  59. };
  60. }
  61.  
  62. if (name[0] === '[' && name[name.length - 1] === ']') {
  63. return {
  64. kind: 'ListType',
  65. type: buildTypeReference(name.substring(1, name.length - 1))
  66. };
  67. }
  68.  
  69. return {
  70. kind: 'NamedType',
  71. name: buildName(name)
  72. };
  73. }
  74.  
  75. export function buildField(name, args, typeName) {
  76. return {
  77. kind: 'FieldDefinition',
  78. name: buildName(name),
  79. arguments: args,
  80. type: buildTypeReference(typeName)
  81. };
  82. }
  83.  
  84. export function buildValue(name, args) {
  85. return {
  86. kind: 'EnumValueDefinition',
  87. name: buildName(name),
  88. arguments: args
  89. };
  90. }
  91.  
  92. export function buildArgument(name, type) {
  93. return {
  94. kind: 'InputValueDefinition',
  95. name: buildName(name),
  96. type: buildTypeReference(type),
  97. defaultValue: null,
  98. directives: []
  99. };
  100. }
  101.  
  102. export function addPaginationArguments(field) {
  103. field.arguments.push(buildArgument('lastCreatedAt', 'Float'));
  104. field.arguments.push(buildArgument('limit', 'Int'));
  105. }
  106.  
  107. // Apply all the directives that modify the field's schema. At this stage
  108. // this is simply the pagination directives, which add pagination arguments
  109. // to the field.
  110. export function applyCustomDirectives(field) {
  111. field.directives.forEach(directive => {
  112. const directiveName = directive.name.value;
  113. const isPaginated = includes(
  114. ['hasMany', 'hasAndBelongsToMany', 'belongsToMany'],
  115. directiveName
  116. );
  117. if (isPaginated) {
  118. addPaginationArguments(field);
  119. }
  120. });
  121. }
  122.  
  123. export function idArgument() {
  124. return buildArgument('id', 'ObjID!');
  125. }
  126.  
  127. export function getType(level) {
  128. if (level.kind === 'NamedType') {
  129. return level.name.value;
  130. }
  131.  
  132. if (level.type) {
  133. return getType(level.type);
  134. }
  135.  
  136. return '';
  137. }