github ardatan/graphql-tools release-1723627814109
August 14, 2024

latest releases: release-1726086017332, @graphql-tools/federation@2.2.10, release-1724948218474...
one month ago

@graphql-tools/delegate@10.0.19

Patch Changes

  • #6437
    3188051
    Thanks @User, @(),
    @{, @{, @{,
    @{, @{! - Fix the bug happens when a merged field
    is a computed field requires another computed field requires a field from the initial subschema.

    In the following test case, totalOrdersPrices needs userOrders which needs lastName from
    initial Query.user. So the bug was skipping the dependencies of userOrders because it assumed
    lastName already there by mistake.

        const schema1 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type User {
              id: ID!
              firstName: String!
              lastName: String!
              address: String
            }
    
            type Query {
    
            }
          `,
          resolvers: {
            Query: {
     => {
                return {
                  id: 1,
                  firstName: 'Jake',
                  lastName: 'Dawkins',
                  address: 'everywhere',
                };
              },
            },
          },
        });
        const schema2 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type UserOrder {
              id: ID!
            }
    
            type User {
              id: ID!
              totalOrdersPrices: Int
              aggregatedOrdersByStatus: Int
            }
    
            type Query {
              userWithOrderDetails(userId: ID!, userOrderIds: [ID]): User
            }
          `,
          resolvers: {
            Query: {
              userWithOrderDetails: (_root, { userId, userOrderIds }) => {
                return {
                  id: userId,
                  userOrders: userOrderIds?.map((userOrderId: string) => ({ id: userOrderId })),
                };
              },
            },
    
              totalOrdersPrices(user) {
                if (user.userOrders instanceof Error) {
                  return user.userOrders;
                }
                if (!user.userOrders) {
                  throw new Error('UserOrders is required');
                }
                return 0;
              },
              aggregatedOrdersByStatus(user) {
                if (user.userOrders instanceof Error) {
                  return user.userOrders;
                }
                if (!user.userOrders) {
                  throw new Error('UserOrders is required');
                }
                return 1;
              },
            },
          },
        });
        const schema3 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type User {
              id: ID!
              userOrders: [UserOrder!]
            }
    
            type UserOrder {
              id: ID!
            }
    
            type Query {
              userWithOrders(id: ID!, lastName: String): User
            }
          `,
          resolvers: {
            Query: {
              userWithOrders: (_root, { id, lastName }) => {
                return {
                  id,
                  lastName,
                };
              },
            },
    
              userOrders(user) {
                if (!user.lastName) {
                  throw new Error('LastName is required');
                }
                return [
                  {
                    id: `${user.lastName}1`,
                  },
                ];
              },
            },
          },
        });
        const stitchedSchema = stitchSchemas({
          subschemas: [
            {
              schema: schema1,
            },
            {
              schema: schema2,
              merge: {
    
                  selectionSet: '{ id }',
                  fieldName: 'userWithOrderDetails',
                  args: ({ id, userOrders }: { id: string; userOrders: any[] }) => ({
                    userId: id,
                    userOrderIds: userOrders?.map?.(({ id }: { id: string }) => id),
                  }),
                  fields: {
                    totalOrdersPrices: {
                      selectionSet: '{ userOrders { id } }',
                      computed: true,
                    },
                    aggregatedOrdersByStatus: {
                      selectionSet: '{ userOrders { id } }',
                      computed: true,
                    },
                  },
                },
              },
            },
            {
              schema: schema3,
              merge: {
    
                  selectionSet: '{ id }',
                  fieldName: 'userWithOrders',
                  args: ({ id, lastName }: { id: string; lastName: string }) => ({
                    id,
                    lastName,
                  }),
                  fields: {
                    userOrders: {
                      selectionSet: '{ lastName }',
                      computed: true,
                    },
                  },
                },
              },
            },
          ],
        });
        const res = await normalizedExecutor({
          schema: stitchedSchema,
          document: parse(/* GraphQL */ `
            query User {
              user {
                aggregatedOrdersByStatus
                totalOrdersPrices
              }
            }
          `),
        });
        expect(res).toEqual({
          data: {
    
              aggregatedOrdersByStatus: 1,
              totalOrdersPrices: 0,
            },
          },
        });

@graphql-tools/federation@2.2.7

Patch Changes

  • #6437
    3188051
    Thanks @User, @(),
    @{, @{, @{,
    @{, @{! - Fix the bug happens when a merged field
    is a computed field requires another computed field requires a field from the initial subschema.

    In the following test case, totalOrdersPrices needs userOrders which needs lastName from
    initial Query.user. So the bug was skipping the dependencies of userOrders because it assumed
    lastName already there by mistake.

        const schema1 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type User {
              id: ID!
              firstName: String!
              lastName: String!
              address: String
            }
    
            type Query {
    
            }
          `,
          resolvers: {
            Query: {
     => {
                return {
                  id: 1,
                  firstName: 'Jake',
                  lastName: 'Dawkins',
                  address: 'everywhere',
                };
              },
            },
          },
        });
        const schema2 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type UserOrder {
              id: ID!
            }
    
            type User {
              id: ID!
              totalOrdersPrices: Int
              aggregatedOrdersByStatus: Int
            }
    
            type Query {
              userWithOrderDetails(userId: ID!, userOrderIds: [ID]): User
            }
          `,
          resolvers: {
            Query: {
              userWithOrderDetails: (_root, { userId, userOrderIds }) => {
                return {
                  id: userId,
                  userOrders: userOrderIds?.map((userOrderId: string) => ({ id: userOrderId })),
                };
              },
            },
    
              totalOrdersPrices(user) {
                if (user.userOrders instanceof Error) {
                  return user.userOrders;
                }
                if (!user.userOrders) {
                  throw new Error('UserOrders is required');
                }
                return 0;
              },
              aggregatedOrdersByStatus(user) {
                if (user.userOrders instanceof Error) {
                  return user.userOrders;
                }
                if (!user.userOrders) {
                  throw new Error('UserOrders is required');
                }
                return 1;
              },
            },
          },
        });
        const schema3 = makeExecutableSchema({
          typeDefs: /* GraphQL */ `
            type User {
              id: ID!
              userOrders: [UserOrder!]
            }
    
            type UserOrder {
              id: ID!
            }
    
            type Query {
              userWithOrders(id: ID!, lastName: String): User
            }
          `,
          resolvers: {
            Query: {
              userWithOrders: (_root, { id, lastName }) => {
                return {
                  id,
                  lastName,
                };
              },
            },
    
              userOrders(user) {
                if (!user.lastName) {
                  throw new Error('LastName is required');
                }
                return [
                  {
                    id: `${user.lastName}1`,
                  },
                ];
              },
            },
          },
        });
        const stitchedSchema = stitchSchemas({
          subschemas: [
            {
              schema: schema1,
            },
            {
              schema: schema2,
              merge: {
    
                  selectionSet: '{ id }',
                  fieldName: 'userWithOrderDetails',
                  args: ({ id, userOrders }: { id: string; userOrders: any[] }) => ({
                    userId: id,
                    userOrderIds: userOrders?.map?.(({ id }: { id: string }) => id),
                  }),
                  fields: {
                    totalOrdersPrices: {
                      selectionSet: '{ userOrders { id } }',
                      computed: true,
                    },
                    aggregatedOrdersByStatus: {
                      selectionSet: '{ userOrders { id } }',
                      computed: true,
                    },
                  },
                },
              },
            },
            {
              schema: schema3,
              merge: {
    
                  selectionSet: '{ id }',
                  fieldName: 'userWithOrders',
                  args: ({ id, lastName }: { id: string; lastName: string }) => ({
                    id,
                    lastName,
                  }),
                  fields: {
                    userOrders: {
                      selectionSet: '{ lastName }',
                      computed: true,
                    },
                  },
                },
              },
            },
          ],
        });
        const res = await normalizedExecutor({
          schema: stitchedSchema,
          document: parse(/* GraphQL */ `
            query User {
              user {
                aggregatedOrdersByStatus
                totalOrdersPrices
              }
            }
          `),
        });
        expect(res).toEqual({
          data: {
    
              aggregatedOrdersByStatus: 1,
              totalOrdersPrices: 0,
            },
          },
        });
  • Updated dependencies
    [3188051]:

    • @graphql-tools/delegate@10.0.19

Don't miss a new graphql-tools release

NewReleases is sending notifications on new releases.