Skip to content

Instantly share code, notes, and snippets.

@benmccallum
Last active January 19, 2022 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benmccallum/8afa7e921e7c8e631b4ad86b147ccf00 to your computer and use it in GitHub Desktop.
Save benmccallum/8afa7e921e7c8e631b4ad86b147ccf00 to your computer and use it in GitHub Desktop.
Remove internal GraphQL fields ITypeRewriter

Removes any fields that look to be internal based on presence of "dbId" in field name or arg.

services.
  .AddGraphQLServer()
  .AddTypeRewriter(new RemoveInternalFieldsRewriter())
using System;
using System.Collections.Generic;
using System.Linq;
using HotChocolate.Language;
using HotChocolate.Stitching.Merge;
using HotChocolate.Stitching.Merge.Rewriters;
using HotChocolate.Types;
namespace MyCompany.GraphQLService.Stitching
{
internal class RemoveInternalFieldsRewriter : ITypeRewriter
{
public ITypeDefinitionNode Rewrite(ISchemaInfo schema, ITypeDefinitionNode typeDefinition)
{
if (schema.Name.HasValue &&
typeDefinition is ObjectTypeDefinitionNode otd)
{
if (typeDefinition.Name.Value.Equals(GraphQLTypeNames.Query))
{
return RemoveFields(schema.Name, otd, _isInternalQueryTypeField, f => otd.WithFields(f));
}
}
return typeDefinition;
}
/// <summary>
/// Essentially any field that accepts an argument that's an internal database id
/// can be considered an internal field. This way the field name doesn't matter
/// too much but we can still blanket notice them.
/// </summary>
private static readonly Func<string, FieldDefinitionNode, bool> _isInternalQueryTypeField = (schemaName, field) =>
field.Arguments.Any(arg =>
arg.Name.Value.EndsWith("DbId", StringComparison.Ordinal) ||
arg.Name.Value.EndsWith("DbIds", StringComparison.Ordinal) ||
arg.Name.Value.Equals("dbId", StringComparison.Ordinal) ||
arg.Name.Value.Equals("dbIds", StringComparison.Ordinal)
) ||
field.Name.Value.Equals("brandByName") ||
(schemaName.StartsWith(SchemaNames.MyCompanyPrefix) && field.Name.Value.Equals("checksum")) ||
(schemaName.StartsWith(SchemaNames.MyCompanyPrefix) && field.Name.Value.EndsWith("node"));
//private static readonly Func<FieldDefinitionNode, bool> _isForeignKeyField = field =>
// field.Name.Value.StartsWith("_") &&
// (field.Name.Value.EndsWith("DbId") || field.Name.Value.EndsWith("DbIds"));
private static T RemoveFields<T>(
string schemaName,
T typeDefinition,
Func<string, FieldDefinitionNode, bool> shouldRemove,
RewriteFieldsDelegate<T> rewrite)
where T : ComplexTypeDefinitionNodeBase, ITypeDefinitionNode
{
var keptFields = new List<FieldDefinitionNode>();
foreach (var field in typeDefinition.Fields)
{
if (!shouldRemove(schemaName, field))
{
keptFields.Add(field);
}
}
return rewrite(keptFields);
}
internal delegate T RewriteFieldsDelegate<T>(
IReadOnlyList<FieldDefinitionNode> fields)
where T : ComplexTypeDefinitionNodeBase, ITypeDefinitionNode;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment