Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help] Using FilterRootFields and delegateToSchema() #1103

Closed
nicgene opened this issue Apr 14, 2019 · 3 comments
Closed

[Help] Using FilterRootFields and delegateToSchema() #1103

nicgene opened this issue Apr 14, 2019 · 3 comments

Comments

@nicgene
Copy link

nicgene commented Apr 14, 2019

I'm trying to use FilterRootFields() as one of my 'transforms' on a delegateToSchema() method. The schema delegation works fine however the filter isn't being applied to remove the 'userById' query from the graph. I also need to remove the 'userId' field from the 'AuthToken' type.

// userSchema.ts

import { makeExecutableSchema } from 'graphql-tools';

const typeDefs = `
  scalar Date
  scalar UUID

  type User {
    id: UUID!
    name: String!
    created: Date!
    updated: Date
  }

  type Query {
    userById(id: UUID!): User
  }
`;

const resolvers = {
  Query: {
    userById: (_, { id }) => ({
      id: 'a268697f-d6ae-4563-8f9b-9f27175ab29b',
      name: 'dupkey',
      created: new Date()
    })
  }
}

export default makeExecutableSchema({ typeDefs, resolvers });

// authTokenSchema.ts

import { makeExecutableSchema } from 'graphql-tools';

const typeDefs = `
  scalar Date
  scalar UUID

  type AuthToken {
    id: UUID!
    userId: UUID!
    accessToken: String!
    refreshToken: String!
    created: Date
  }

  input SigninUserInput {
    email: String!
    password: String!
  }

  type Mutation {
    signinUser(input: SigninUserInput!): AuthToken
  }
`;

const resolvers = {
  Mutation: {
    signinUser: (
      _, { input }: { input: { email: string, password: string } }
    ) => ({
      id: '7b67941d-9d54-4cbd-9250-e71822822a38'
      userId: 'a268697f-d6ae-4563-8f9b-9f27175ab29b'
      accessToken: '123'
      refreshToken: '456'
      created: new Date()
    })
  }
}

export default makeExecutableSchema({ typeDefs, resolvers });

// schema.ts

import { FilterRootFields, mergeSchemas, transformSchema } from 'graphql-tools';
import authTokenSchema from './graphql/authTokenSchema';
import scalarTypeDate from './graphql/scalarType/scalarTypeDate';
import scalarTypeUUID from './graphql/scalarType/scalarTypeUUID';
import userSchema from './graphql/userSchema';

const linkTypeDefs = `
  extend type AuthToken {
    user: User
  }
`;

const transformedUserSchema = transformSchema(userSchema, [
  new FilterRootFields((operation, fieldName, field) => {
    console.log(operation, fieldName);
    if (fieldName === 'userById') {
      return false;
    }
    return true;
  })
]);

export default mergeSchemas({
  schemas: [
    authTokenSchema,
    linkTypeDefs,
    scalarTypeDate,
    scalarTypeUUID,
    transformedUserSchema,
    userSchema,
  ],
  resolvers: {
    AuthToken: {
      user: {
        fragment: 'fragment AuthTokenFragment on AuthToken { userId }',
        resolve(authToken, args, context, info) {
          return info.mergeInfo.delegateToSchema({
            schema: userSchema,
            operation: 'query',
            fieldName: 'userById',
            args: {
              id: authToken.userId.toString(),
            },
            context,
            info,
            transforms: transformedUserSchema.transforms
          });
        }
      }
    }
  }
});
@yaacovCR
Copy link
Collaborator

export default mergeSchemas({
  schemas: [
    authTokenSchema,
    linkTypeDefs,
    scalarTypeDate,
    scalarTypeUUID,
    transformedUserSchema,
=>  userSchema,
  ],

Try removing the indicated line above. You are including the schema pre-transformation schema in the list of merged schemas, so anything filtered out is still included.

In terms of filtering out specific fields of objects, that has been requested in #819, you could track that. More tedious, but perhaps more practical, you could define a new AuthToken type which manually redefines all the fields except the ones you want to filter out, I think depending on the order included within mergeSchemas, your new type may win out, but I have to test out how that works now that onTypeConflict has been deprecated.

@yaacovCR
Copy link
Collaborator

From my testing, looks like whatever is last wins, so you would just change linkTypeDefs from:

  extend type AuthToken {
    user: User
  }

to:

  type AuthToken {
    id: UUID!
    user: User
    accessToken: String!
    refreshToken: String!
    created: Date
  }

I would also rename linkTypeDefs to overrideTypeDefs just to keep things straight. Kind of tedious, but if it works for you...

@nicgene
Copy link
Author

nicgene commented Apr 30, 2019

@yaacovCR Thanks for all your help! I took your advice and it works perfectly.

import { FilterRootFields, mergeSchemas, transformSchema } from 'graphql-tools';
import authTokenSchema from './graphql/authTokenSchema';
import scalarTypeDate from './graphql/scalarType/scalarTypeDate';
import scalarTypeUUID from './graphql/scalarType/scalarTypeUUID';
import userSchema from './graphql/userSchema';
import organizationSchema from './graphql/organizationSchema';

const overrideTypeDefs = `
  type AuthToken {
    id: UUID!
    user: User
    accessToken: String!
    refreshToken: String!
    created: Date
  }
`;

const transformedUserSchema = transformSchema(userSchema, [
  new FilterRootFields((operation, fieldName, field) => {
    // console.log(operation, fieldName);
    if (fieldName === 'userById') {
      return false;
    }
    return true;
  })
]);

export default mergeSchemas({
  schemas: [
    scalarTypeDate,
    scalarTypeUUID,
    authTokenSchema,
    organizationSchema,
    transformedUserSchema,  
    overrideTypeDefs
  ],
  resolvers: {
    AuthToken: {
      user: {
        fragment: 'fragment AuthTokenFragment on AuthToken { userId }',
        resolve(authToken, args, context, info) {
          return info.mergeInfo.delegateToSchema({
            schema: userSchema,
            operation: 'query',
            fieldName: 'userById',
            args: {
              id: authToken.userId.toString(),
            },
            context,
            info
          });
        }
      }
    }
  }
});

@nicgene nicgene closed this as completed Apr 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants