graphql-tools icon indicating copy to clipboard operation
graphql-tools copied to clipboard

Custom directive getting dropped during filtering

Open AndreaCrotti opened this issue 1 year ago • 0 comments
trafficstars

Issue workflow progress

Progress of the issue based on the Contributor Workflow

  • [ ] 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox

    Make sure to fork this template and run yarn generate in the terminal.

    Please make sure the GraphQL Tools package versions under package.json matches yours.

  • [ ] 2. A failing test has been provided
  • [ ] 3. A local solution has been provided
  • [ ] 4. A pull request is pending review

Describe the bug

I'm using this tool to filter queries/mutations based on the existence of a custom directive. The code is simply

const { readFileSync, writeFileSync } = require("fs");
const { buildSchema, printSchema } = require("graphql");
const { mapSchema, getDirective, MapperKind } = require("@graphql-tools/utils");
const config = require("./config.json");
const toFilter = new Set(["Query", "Mutation"]);

function filterSchemaByDirective(schema, directiveName) {
    return mapSchema(schema, {
        [MapperKind.OBJECT_FIELD]: (fieldConfig, _fieldName, typeName, schema) => {
            if (!toFilter.has(typeName)) {
                return fieldConfig;
            }
            const directive = getDirective(schema, fieldConfig, directiveName);
            if (directive) {
                console.log(JSON.stringify(fieldConfig));
                return fieldConfig;
            }
            return null;
        },
    });
}

function filterFile(input, output, directive) {
    const schemaFileContent = readFileSync(input, "utf-8");
    const newSchema = filterSchemaByDirective(buildSchema(schemaFileContent), directive);
    writeFileSync(output, printSchema(newSchema));
}

if (require.main === module) {
    filterFile("transform/hello.graphql", "transform/out.graphql", "expose");
}

And if I feed this in to that code

directive @expose(
  reason: String = "hello"
) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION


input SpectaQLOption { key: String!, value: String! }
directive @spectaql(options: [SpectaQLOption]) on QUERY | MUTATION | FIELD | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

schema {
  query: Query
}

type Query  {
  ping: Status!
  getList: [String!] @expose @spectaql(options: [{ key: "some", value: "value" }])
  getListError: [String!] @expose @deprecated
  introspection: String
  error: String
  withExtensions: String @spectaql(options: [{ key: "undocumented", value: "true" }])
  iBlowUp: String
}

type Status {
  pong: String!
}

The custom directives expose and spectaql are just dropped:

directive @expose(reason: String = "hello") on FIELD_DEFINITION | INPUT_FIELD_DEFINITION

directive @spectaql(options: [SpectaQLOption]) on QUERY | MUTATION | FIELD | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION

input SpectaQLOption {
  key: String!
  value: String!
}

type Query {
  getList: [String!]
  getListError: [String!] @deprecated
}

type Status {
  pong: String!
}

I can see these directives are still in fieldConfig before I return it so I really don't get why they are dropped.

Expected behavior

I should still see the custom directives.

Environment:

  • OS: Mac
  • @graphql-tools/utils:^10.0.0"
  • NodeJS: 21.7.3

AndreaCrotti avatar Sep 10 '24 13:09 AndreaCrotti