rewire.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { GraphQLDirective, GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLList, GraphQLObjectType, GraphQLNonNull, GraphQLScalarType, GraphQLUnionType, isInterfaceType, isEnumType, isInputObjectType, isListType, isNamedType, isNonNullType, isObjectType, isScalarType, isUnionType, isSpecifiedScalarType, isSpecifiedDirective, } from 'graphql';
  2. import { getBuiltInForStub, isNamedStub } from './stub.js';
  3. export function rewireTypes(originalTypeMap, directives) {
  4. const referenceTypeMap = Object.create(null);
  5. for (const typeName in originalTypeMap) {
  6. referenceTypeMap[typeName] = originalTypeMap[typeName];
  7. }
  8. const newTypeMap = Object.create(null);
  9. for (const typeName in referenceTypeMap) {
  10. const namedType = referenceTypeMap[typeName];
  11. if (namedType == null || typeName.startsWith('__')) {
  12. continue;
  13. }
  14. const newName = namedType.name;
  15. if (newName.startsWith('__')) {
  16. continue;
  17. }
  18. if (newTypeMap[newName] != null) {
  19. console.warn(`Duplicate schema type name ${newName} found; keeping the existing one found in the schema`);
  20. continue;
  21. }
  22. newTypeMap[newName] = namedType;
  23. }
  24. for (const typeName in newTypeMap) {
  25. newTypeMap[typeName] = rewireNamedType(newTypeMap[typeName]);
  26. }
  27. const newDirectives = directives.map(directive => rewireDirective(directive));
  28. return {
  29. typeMap: newTypeMap,
  30. directives: newDirectives,
  31. };
  32. function rewireDirective(directive) {
  33. if (isSpecifiedDirective(directive)) {
  34. return directive;
  35. }
  36. const directiveConfig = directive.toConfig();
  37. directiveConfig.args = rewireArgs(directiveConfig.args);
  38. return new GraphQLDirective(directiveConfig);
  39. }
  40. function rewireArgs(args) {
  41. const rewiredArgs = {};
  42. for (const argName in args) {
  43. const arg = args[argName];
  44. const rewiredArgType = rewireType(arg.type);
  45. if (rewiredArgType != null) {
  46. arg.type = rewiredArgType;
  47. rewiredArgs[argName] = arg;
  48. }
  49. }
  50. return rewiredArgs;
  51. }
  52. function rewireNamedType(type) {
  53. if (isObjectType(type)) {
  54. const config = type.toConfig();
  55. const newConfig = {
  56. ...config,
  57. fields: () => rewireFields(config.fields),
  58. interfaces: () => rewireNamedTypes(config.interfaces),
  59. };
  60. return new GraphQLObjectType(newConfig);
  61. }
  62. else if (isInterfaceType(type)) {
  63. const config = type.toConfig();
  64. const newConfig = {
  65. ...config,
  66. fields: () => rewireFields(config.fields),
  67. };
  68. if ('interfaces' in newConfig) {
  69. newConfig.interfaces = () => rewireNamedTypes(config.interfaces);
  70. }
  71. return new GraphQLInterfaceType(newConfig);
  72. }
  73. else if (isUnionType(type)) {
  74. const config = type.toConfig();
  75. const newConfig = {
  76. ...config,
  77. types: () => rewireNamedTypes(config.types),
  78. };
  79. return new GraphQLUnionType(newConfig);
  80. }
  81. else if (isInputObjectType(type)) {
  82. const config = type.toConfig();
  83. const newConfig = {
  84. ...config,
  85. fields: () => rewireInputFields(config.fields),
  86. };
  87. return new GraphQLInputObjectType(newConfig);
  88. }
  89. else if (isEnumType(type)) {
  90. const enumConfig = type.toConfig();
  91. return new GraphQLEnumType(enumConfig);
  92. }
  93. else if (isScalarType(type)) {
  94. if (isSpecifiedScalarType(type)) {
  95. return type;
  96. }
  97. const scalarConfig = type.toConfig();
  98. return new GraphQLScalarType(scalarConfig);
  99. }
  100. throw new Error(`Unexpected schema type: ${type}`);
  101. }
  102. function rewireFields(fields) {
  103. const rewiredFields = {};
  104. for (const fieldName in fields) {
  105. const field = fields[fieldName];
  106. const rewiredFieldType = rewireType(field.type);
  107. if (rewiredFieldType != null && field.args) {
  108. field.type = rewiredFieldType;
  109. field.args = rewireArgs(field.args);
  110. rewiredFields[fieldName] = field;
  111. }
  112. }
  113. return rewiredFields;
  114. }
  115. function rewireInputFields(fields) {
  116. const rewiredFields = {};
  117. for (const fieldName in fields) {
  118. const field = fields[fieldName];
  119. const rewiredFieldType = rewireType(field.type);
  120. if (rewiredFieldType != null) {
  121. field.type = rewiredFieldType;
  122. rewiredFields[fieldName] = field;
  123. }
  124. }
  125. return rewiredFields;
  126. }
  127. function rewireNamedTypes(namedTypes) {
  128. const rewiredTypes = [];
  129. for (const namedType of namedTypes) {
  130. const rewiredType = rewireType(namedType);
  131. if (rewiredType != null) {
  132. rewiredTypes.push(rewiredType);
  133. }
  134. }
  135. return rewiredTypes;
  136. }
  137. function rewireType(type) {
  138. if (isListType(type)) {
  139. const rewiredType = rewireType(type.ofType);
  140. return rewiredType != null ? new GraphQLList(rewiredType) : null;
  141. }
  142. else if (isNonNullType(type)) {
  143. const rewiredType = rewireType(type.ofType);
  144. return rewiredType != null ? new GraphQLNonNull(rewiredType) : null;
  145. }
  146. else if (isNamedType(type)) {
  147. let rewiredType = referenceTypeMap[type.name];
  148. if (rewiredType === undefined) {
  149. rewiredType = isNamedStub(type) ? getBuiltInForStub(type) : rewireNamedType(type);
  150. newTypeMap[rewiredType.name] = referenceTypeMap[type.name] = rewiredType;
  151. }
  152. return rewiredType != null ? newTypeMap[rewiredType.name] : null;
  153. }
  154. return null;
  155. }
  156. }