@graphql-tools/utils 8.6.8 → 8.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +35 -12
  2. package/index.mjs +35 -12
  3. package/package.json +2 -2
package/index.js CHANGED
@@ -3287,11 +3287,13 @@ function visitSchema(schema) {
3287
3287
  return visitQueue(queue, schema);
3288
3288
  }
3289
3289
  function visitQueue(queue, schema, visited = new Set()) {
3290
+ // Interfaces encountered that are field return types need to be revisited to add their implementations
3291
+ const revisit = new Map();
3290
3292
  // Navigate all types starting with pre-queued types (root types)
3291
3293
  while (queue.length) {
3292
3294
  const typeName = queue.pop();
3293
- // Skip types we already visited
3294
- if (visited.has(typeName)) {
3295
+ // Skip types we already visited unless it is an interface type that needs revisiting
3296
+ if (visited.has(typeName) && revisit[typeName] !== true) {
3295
3297
  continue;
3296
3298
  }
3297
3299
  const type = schema.getType(typeName);
@@ -3300,6 +3302,17 @@ function visitQueue(queue, schema, visited = new Set()) {
3300
3302
  if (graphql.isUnionType(type)) {
3301
3303
  queue.push(...type.getTypes().map(type => type.name));
3302
3304
  }
3305
+ // If it is an interface and it is a returned type, grab all implementations so we can use proper __typename in fragments
3306
+ if (graphql.isInterfaceType(type) && revisit[typeName] === true) {
3307
+ queue.push(...getImplementingTypes(type.name, schema));
3308
+ // No need to revisit this interface again
3309
+ revisit[typeName] = false;
3310
+ }
3311
+ // Visit interfaces this type is implementing if they haven't been visited yet
3312
+ if ('getInterfaces' in type) {
3313
+ // Only pushes to queue to visit but not return types
3314
+ queue.push(...type.getInterfaces().map(iface => iface.name));
3315
+ }
3303
3316
  // If the type has files visit those field types
3304
3317
  if ('getFields' in type) {
3305
3318
  const fields = type.getFields();
@@ -3308,18 +3321,18 @@ function visitQueue(queue, schema, visited = new Set()) {
3308
3321
  continue;
3309
3322
  }
3310
3323
  for (const [, field] of entries) {
3311
- if (graphql.isInputObjectType(type)) {
3312
- for (const arg of field.args) {
3313
- queue.push(graphql.getNamedType(arg.type).name); // Visit arg types
3314
- }
3324
+ if (graphql.isObjectType(type)) {
3325
+ // Visit arg types
3326
+ queue.push(...field.args.map(arg => graphql.getNamedType(arg.type).name));
3327
+ }
3328
+ const namedType = graphql.getNamedType(field.type);
3329
+ queue.push(namedType.name);
3330
+ // Interfaces returned on fields need to be revisited to add their implementations
3331
+ if (graphql.isInterfaceType(namedType) && !(namedType.name in revisit)) {
3332
+ revisit[namedType.name] = true;
3315
3333
  }
3316
- queue.push(graphql.getNamedType(field.type).name);
3317
3334
  }
3318
3335
  }
3319
- // Visit interfaces this type is implementing if they haven't been visited yet
3320
- if ('getInterfaces' in type) {
3321
- queue.push(...type.getInterfaces().map(iface => iface.name));
3322
- }
3323
3336
  visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
3324
3337
  }
3325
3338
  }
@@ -4003,8 +4016,18 @@ function visitErrorsByType(errors, errorVisitorMap, errorInfo) {
4003
4016
  return newError;
4004
4017
  });
4005
4018
  }
4019
+ function getOperationRootType(schema, operationDef) {
4020
+ switch (operationDef.operation) {
4021
+ case 'query':
4022
+ return schema.getQueryType();
4023
+ case 'mutation':
4024
+ return schema.getMutationType();
4025
+ case 'subscription':
4026
+ return schema.getSubscriptionType();
4027
+ }
4028
+ }
4006
4029
  function visitRoot(root, operation, schema, fragments, variableValues, resultVisitorMap, errors, errorInfo) {
4007
- const operationRootType = graphql.getOperationRootType(schema, operation);
4030
+ const operationRootType = getOperationRootType(schema, operation);
4008
4031
  const collectedFields = collectFields(schema, fragments, variableValues, operationRootType, operation.selectionSet, new Map(), new Set());
4009
4032
  return visitObjectValue(root, operationRootType, collectedFields, schema, fragments, variableValues, resultVisitorMap, 0, errors, errorInfo);
4010
4033
  }
package/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { parse, GraphQLError, isNonNullType, Kind, valueFromAST, print, isObjectType, isListType, isSpecifiedDirective, astFromValue, isSpecifiedScalarType, isIntrospectionType, isInterfaceType, isUnionType, isInputObjectType, isEnumType, isScalarType, GraphQLDeprecatedDirective, specifiedRules, concatAST, validate, versionInfo, buildClientSchema, visit, TokenKind, Source, isTypeSystemDefinitionNode, getNamedType, GraphQLString, GraphQLNonNull, GraphQLList, GraphQLID, GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType, GraphQLDirective, GraphQLUnionType, GraphQLEnumType, GraphQLScalarType, isNamedType, getNullableType, isLeafType, GraphQLSchema, isDirective, isCompositeType, doTypesOverlap, getOperationAST, getDirectiveValues, GraphQLSkipDirective, GraphQLIncludeDirective, typeFromAST, isAbstractType, getOperationRootType, TypeNameMetaFieldDef, buildASTSchema } from 'graphql';
1
+ import { parse, GraphQLError, isNonNullType, Kind, valueFromAST, print, isObjectType, isListType, isSpecifiedDirective, astFromValue, isSpecifiedScalarType, isIntrospectionType, isInterfaceType, isUnionType, isInputObjectType, isEnumType, isScalarType, GraphQLDeprecatedDirective, specifiedRules, concatAST, validate, versionInfo, buildClientSchema, visit, TokenKind, Source, isTypeSystemDefinitionNode, getNamedType, GraphQLString, GraphQLNonNull, GraphQLList, GraphQLID, GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType, GraphQLDirective, GraphQLUnionType, GraphQLEnumType, GraphQLScalarType, isNamedType, getNullableType, isLeafType, GraphQLSchema, isDirective, isCompositeType, doTypesOverlap, getOperationAST, getDirectiveValues, GraphQLSkipDirective, GraphQLIncludeDirective, typeFromAST, isAbstractType, TypeNameMetaFieldDef, buildASTSchema } from 'graphql';
2
2
 
3
3
  const asArray = (fns) => (Array.isArray(fns) ? fns : fns ? [fns] : []);
4
4
  const invalidDocRegex = /\.[a-z0-9]+$/i;
@@ -3285,11 +3285,13 @@ function visitSchema(schema) {
3285
3285
  return visitQueue(queue, schema);
3286
3286
  }
3287
3287
  function visitQueue(queue, schema, visited = new Set()) {
3288
+ // Interfaces encountered that are field return types need to be revisited to add their implementations
3289
+ const revisit = new Map();
3288
3290
  // Navigate all types starting with pre-queued types (root types)
3289
3291
  while (queue.length) {
3290
3292
  const typeName = queue.pop();
3291
- // Skip types we already visited
3292
- if (visited.has(typeName)) {
3293
+ // Skip types we already visited unless it is an interface type that needs revisiting
3294
+ if (visited.has(typeName) && revisit[typeName] !== true) {
3293
3295
  continue;
3294
3296
  }
3295
3297
  const type = schema.getType(typeName);
@@ -3298,6 +3300,17 @@ function visitQueue(queue, schema, visited = new Set()) {
3298
3300
  if (isUnionType(type)) {
3299
3301
  queue.push(...type.getTypes().map(type => type.name));
3300
3302
  }
3303
+ // If it is an interface and it is a returned type, grab all implementations so we can use proper __typename in fragments
3304
+ if (isInterfaceType(type) && revisit[typeName] === true) {
3305
+ queue.push(...getImplementingTypes(type.name, schema));
3306
+ // No need to revisit this interface again
3307
+ revisit[typeName] = false;
3308
+ }
3309
+ // Visit interfaces this type is implementing if they haven't been visited yet
3310
+ if ('getInterfaces' in type) {
3311
+ // Only pushes to queue to visit but not return types
3312
+ queue.push(...type.getInterfaces().map(iface => iface.name));
3313
+ }
3301
3314
  // If the type has files visit those field types
3302
3315
  if ('getFields' in type) {
3303
3316
  const fields = type.getFields();
@@ -3306,18 +3319,18 @@ function visitQueue(queue, schema, visited = new Set()) {
3306
3319
  continue;
3307
3320
  }
3308
3321
  for (const [, field] of entries) {
3309
- if (isInputObjectType(type)) {
3310
- for (const arg of field.args) {
3311
- queue.push(getNamedType(arg.type).name); // Visit arg types
3312
- }
3322
+ if (isObjectType(type)) {
3323
+ // Visit arg types
3324
+ queue.push(...field.args.map(arg => getNamedType(arg.type).name));
3325
+ }
3326
+ const namedType = getNamedType(field.type);
3327
+ queue.push(namedType.name);
3328
+ // Interfaces returned on fields need to be revisited to add their implementations
3329
+ if (isInterfaceType(namedType) && !(namedType.name in revisit)) {
3330
+ revisit[namedType.name] = true;
3313
3331
  }
3314
- queue.push(getNamedType(field.type).name);
3315
3332
  }
3316
3333
  }
3317
- // Visit interfaces this type is implementing if they haven't been visited yet
3318
- if ('getInterfaces' in type) {
3319
- queue.push(...type.getInterfaces().map(iface => iface.name));
3320
- }
3321
3334
  visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
3322
3335
  }
3323
3336
  }
@@ -4001,6 +4014,16 @@ function visitErrorsByType(errors, errorVisitorMap, errorInfo) {
4001
4014
  return newError;
4002
4015
  });
4003
4016
  }
4017
+ function getOperationRootType(schema, operationDef) {
4018
+ switch (operationDef.operation) {
4019
+ case 'query':
4020
+ return schema.getQueryType();
4021
+ case 'mutation':
4022
+ return schema.getMutationType();
4023
+ case 'subscription':
4024
+ return schema.getSubscriptionType();
4025
+ }
4026
+ }
4004
4027
  function visitRoot(root, operation, schema, fragments, variableValues, resultVisitorMap, errors, errorInfo) {
4005
4028
  const operationRootType = getOperationRootType(schema, operation);
4006
4029
  const collectedFields = collectFields(schema, fragments, variableValues, operationRootType, operation.selectionSet, new Map(), new Set());
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@graphql-tools/utils",
3
- "version": "8.6.8",
3
+ "version": "8.6.11",
4
4
  "description": "Common package containing utils and types for GraphQL tools",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
10
- "tslib": "~2.3.0"
10
+ "tslib": "~2.4.0"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",