Using batchDelegateToSchema with Schemas Containing Union Type in GraphQL Tools

Using batchDelegateToSchema with Schemas Containing Union Type in GraphQL Tools


0

I’m working on a GraphQL project where I have multiple schemas, and one of the schemas includes a Union type (Site) which can represent different types, such as PhysicalSite and WaitingRoom.

I need to use batchDelegateToSchema to efficiently resolve the ‘sites’ field on the ‘Study’ type, which returns a SitesConnection that includes the Site Union type.

My current setup involves multiple subschemas, and I’m using batchDelegateToSchema to delegate parts of the query to the relevant subschemas. However, I’m facing challenges when working with the Union type within batchDelegateToSchema.

Example of the batchDelegateToSchema I’m using now:

Candidate: {
    site: {
      selectionSet: '{ siteId, studyId }',
      resolve(candidate, args, context, info) {
        return batchDelegateToSchema({
          schema: study,
          operation: 'query',
          fieldName: 'sites',
          key: { siteId: candidate.siteId, studyId: candidate.studyId },
          transforms: [transformSites(info)],
          argsFromKeys: keys => ({
            filter: {
              studyIds: keys
                .map(key => key.studyId)
                .filter(Boolean),
              siteIds: keys.map(key => key.siteId).filter(Boolean),
            },
          }),
          valuesFromResults: (results, keys) => {
            keys.map(findByStudyAndSiteId(results));
          },
          context,
          info,
        });
      },
    },

I was trying to implement a custom transform but I got an error when I try to use the query and the reason is that I have nodes from the connection and cannot find the nested values

"message": "No type was found for field node { kind: "Field", name: { kind: "Name", value: "id" } }.",  
query candidate($id: ID!) {
  candidate(id: $id) {
    siteId
       
    name
    site {
            ... on PhysicalSite {
                id
            }
        }
  }
}

The transform flow:

const extendedSelection =
  (...fields) =>
  (query = {}) => {
    console.log('FFF', JSON.stringify(fields, null, 2));
    console.log('QQQ', JSON.stringify(query, null, 2));
    return {
      ...query,
      selections: [
        ...(query.selections ?? []),
        ...fields.map(value => ({
          kind: Kind.FIELD,
          name: { kind: Kind.NAME, value },
        })),
      ],
    };
  };

const extendedInlineFragmentNodesSelection = (subtypeName, ...fields) => {
  const extendedSelectionSet = extendedSelection(...fields);
  return (query = {}) => {
    const result = {
      kind: Kind.SELECTION_SET,
      selections: [
        {
          kind: Kind.INLINE_FRAGMENT,
          typeCondition: {
            kind: Kind.NAMED_TYPE,
            name: {
              kind: Kind.NAME,
              value: subtypeName,
            },
          },
          selectionSet: extendedSelectionSet(query),
        },
        {
          kind: Kind.FIELD,
          name: {
            kind: Kind.NAME,
            value: 'nodes',
          },
          selectionSet: extendedSelectionSet(query),
        },
      ],
    };
    return result;
  };
};

export const transformSites = info => {
  let typeName = '';
  info.fieldNodes[0].selectionSet.selections.forEach(selection => {
    if (
      selection.kind === 'InlineFragment' &&
      (selection.typeCondition.name.value === 'PhysicalSite' ||
        selection.typeCondition.name.value === 'WaitingRoom')
    ) {
      typeName = selection.typeCondition.name.value;
    }
  });

  return new WrapQuery(
    ['sites'],
    extendedInlineFragmentNodesSelection(typeName, 'id', 'studyId'),
    result => {
      return result;
    },
  );
};

How can I use batchDelegateToSchema to resolve a field that returns a Union type?

How do I handle resolving Union type fields in different subschemas using batchDelegateToSchema?

Is it possible to merge the results of batchDelegateToSchema calls for a Union type like Site into a single Union type?

I’d appreciate any guidance or examples on how to efficiently use batchDelegateToSchema with schemas that contain a Union type like Site. Any code examples or best practices would be highly valuable.

Thank you in advance for your help!

My codes as a reference define the union in this way in the schema

union Site = PhysicalSite | WaitingRoom

type SitesConnection {
  nodes: [Site!]!
  totalCount: Int!
}

extend type Study {
  sites(
    siteIds: [ID!] # e.g. SWE-1 for PhysicalSite, WR:7 for WaitingRoom
    physicalSitesFilter: SiteFilterForPhysicalSites! = { include: true }
    waitingRoomsFilter: SiteFilterForWaitingRooms! = { include: true }
  ): SitesConnection!
}

input SiteFilterForPhysicalSites {
  include: Boolean! = true
  ids: [ID!]
  statuses: [PhysicalSiteStatus!]
  statusNot: PhysicalSiteStatus
}

input SiteFilterForWaitingRooms {
  include: Boolean! = true
  ids: [ID!]
}

type Query {
  sites(
    filter: SiteFilter
    pagination: Pagination! = { limit: 1000, skip: 0 }
  ): SitesConnection!
}

The resolver

export default {
  Query: {
    sites: (_, { filter, pagination }) => ({
      ...filter,
      ...pagination,
    }),
  },
  SitesConnection: {
    totalCount: ({ physicalSitesFilter, ...filter }, _, ctx) =>
      SiteService(ctx).countSites({ ...filter, ...physicalSitesFilter }),

    nodes: ({ physicalSitesFilter, ...filter }, _, ctx) => {
      console.log('Resolving SitesConnection nodes');
      return SiteService(ctx).getSites({ ...filter, ...physicalSitesFilter });
    },
  },
};


Load 5 more related questions


Show fewer related questions

0



Leave a Reply

Your email address will not be published. Required fields are marked *