Hi folks, when querying nested objects, Nexus-Pris...
# graphql-nexus
d
Hi folks, when querying nested objects, Nexus-Prisma seems to pull the related models out of prisma itself rather than allowing you to populate it yourself. Does anyone have any info on how this behavior works? I can't find any docs. Here is an example of what I mean:
Copy code
export const User = objectType({
  name: 'User',
  definition(t) {
    t.model.id();
    t.model.email();
    t.model.handle();
  },
});

export const Follow = objectType({
  name: 'Follow',
  definition(t) {
    t.model.id();
    t.model.createdAt();
    t.model.follower(); // This is a user
    t.model.following(); // This is a user
  },
});

export const FollowQuery = extendType({
  type: 'Query',
  definition(t) {
    t.list.field('followers', {
      type: 'Follows',
      resolve: async (_parent, args, context) => {
        const authedId = getUserId(context);

        let followers;
        try {
          followers = await context.prisma.follow.findMany({
            where: { following: { id: authedId } },
            select: {
              id: true,
              follower: {
                // THIS SELECT IS IGNORED. <-------------
                // User model is populated with all fields (including say the email we don't want to expose)
                select: {
                  handle: true
                },
              },
            },
          });
        } catch {
          throw new Error();
        }

        return followers;
      },
    });
  },
});

query followers {
  followers {
    id
    follower {
      handle
      # if I ask for email here it will return the email even though it wasn't selected
    }
  }
}
r
Hey @Dan Borstelmann 👋 I would need to check exactly where this is documented, but Nexus always takes the field automatically from the models that you specify. To add any extra filters, you would need to use the options that Nexus provides. By default, all fields that you define in your Nexus object model are exposed.
d
@Ryan thanks for the reply. The issue is if you fetch
Copy code
query followers {
  followers {
    id
    createdAt
  }
}
and this is a custom query like the above, if you don't select createdAt from prisma yourself from the follows table (and return from the query resolver that data) the api call will fail with Follow.createdAt is null or whatever. So it's not using the default model resolver for this, it expects you to do it (even though the return type is a prisma model). however the behavior is different on related fields, this is where it does automatically get the related model and fetch. I am curious why the discrepancy, and if there is any info on why/how this is implemented and how to work with it
@iki you had a similar problem I believe, do you have any insight here?
i
@Dan Borstelmann yes, solved it with custom resolver that first takes the field from parent resolver if it is defined, or calls default resolver otherwise https://prisma.slack.com/archives/CM2LEN7JL/p1604389069294000?thread_ts=1603802218.244800&amp;cid=CM2LEN7JL
In your case you can use it for field
follower
Alternative would be to handle query/field-level security on single place using e.g. https://github.com/maticzav/graphql-shield
d
@iki yup we are on the same page. I'm already using shield + I used your solution and that works great. It's two-fold reasoning, performance + security. Security was already handled by shield so ostensibly this was not an issue but for performance it's unnecessary to make the extra DB call if you already are doing the join. I wonder if there is anything else I'm missing here as to how to make sure you don't sacrifice performance with greater nesting
👍 1
i
Agree, makes sense to avoid Nexus resolving that again 👍
👍 1