reflectSchema function

GraphQLSchema reflectSchema (GraphQLSchema schema, List<GraphQLType> allTypes)

Performs introspection over a GraphQL schema, and returns a one, containing introspective information.

allTypes should contain all types, not directly defined in the schema, that you would like to have introspection available for.

Implementation

GraphQLSchema reflectSchema(GraphQLSchema schema, List<GraphQLType> allTypes) {
  for (var type in allTypes.toList()) {
    var custom = _fetchAllTypesFromType(type);

    for (var t in custom) {
      if (!allTypes.contains(t)) {
        allTypes.add(t);
      }
    }
  }

  var objectTypes = fetchAllTypes(schema, allTypes);

  var typeType = _reflectSchemaTypes();
  var directiveType = _reflectDirectiveType();
  allTypes.addAll(objectTypes);
  Set<GraphQLType> allTypeSet;

  var schemaType = objectType('__Schema', fields: [
    field(
      'types',
      listOf(typeType),
      resolve: (_, __) => allTypeSet ??= allTypes.toSet(),
    ),
    field(
      'queryType',
      typeType,
      resolve: (_, __) => schema.queryType,
    ),
    field(
      'mutationType',
      typeType,
      resolve: (_, __) => schema.mutationType,
    ),
    field(
      'subscriptionType',
      typeType,
      resolve: (_, __) => schema.subscriptionType,
    ),
    field(
      'directives',
      listOf(directiveType).nonNullable(),
      resolve: (_, __) => [], // TODO: Actually fetch directives
    ),
  ]);

  allTypes.addAll([
    graphQLBoolean,
    graphQLString,
    graphQLId,
    graphQLDate,
    graphQLFloat,
    graphQLInt,
    directiveType,
    typeType,
    schemaType,
    _typeKindType,
    _directiveLocationType,
    _reflectFields(),
    _reflectDirectiveType(),
    _reflectInputValueType(),
    _reflectEnumValueType(),
  ]);

  var fields = <GraphQLObjectField>[
    field(
      '__schema',
      schemaType,
      resolve: (_, __) => schemaType,
    ),
    field(
      '__type',
      typeType,
      inputs: [GraphQLFieldInput('name', graphQLString.nonNullable())],
      resolve: (_, args) {
        var name = args['name'] as String;
        return allTypes.firstWhere((t) => t.name == name,
            orElse: () => throw GraphQLException.fromMessage(
                'No type named "$name" exists.'));
      },
    ),
  ];

  fields.addAll(schema.queryType.fields);

  return GraphQLSchema(
    queryType: objectType(schema.queryType.name, fields: fields),
    mutationType: schema.mutationType,
    subscriptionType: schema.subscriptionType,
  );
}