Skip to content

Releases: ardatan/graphql-tools

September 11, 2024

11 Sep 20:20
c0592dc
Compare
Choose a tag to compare

@graphql-tools/federation@2.2.10

Patch Changes

August 29, 2024

29 Aug 16:16
f60ac88
Compare
Choose a tag to compare

@graphql-tools/merge@9.0.7

Patch Changes

August 26, 2024

26 Aug 09:56
511b2f1
Compare
Choose a tag to compare

@graphql-tools/delegate@10.0.21

Patch Changes

August 26, 2024

26 Aug 08:05
2198808
Compare
Choose a tag to compare

@graphql-tools/delegate@10.0.20

Patch Changes

  • #6469
    0e87805
    Thanks @User!! - Handle merged selection sets in the computed fields;

    When a selection set for a computed field needs to be merged, resolve that required selection set
    fully then resolve the computed field. In the following case, the selection set for the author
    field in the Post type is merged with the selection set for the authorId field in the
    Comment type.

    type Query {
      feed: [Post!]!
    }
    
    type Post {
      id: ID! @computed(selectionSet: "{ comments { authorId } }")
    }
    
    type Comment {
      id: ID!
      authorId: ID!
    }
    
    type User {
      id: ID!
      name: String!
    }
    type Post {
      id: ID!
      comments: [Comment!]!
    }
    
    type Comment {
      id: ID!
    }

@graphql-tools/federation@2.2.9

Patch Changes

  • #6469
    0e87805
    Thanks @User!! - Handle merged selection sets in the computed fields;

    When a selection set for a computed field needs to be merged, resolve that required selection set
    fully then resolve the computed field. In the following case, the selection set for the author
    field in the Post type is merged with the selection set for the authorId field in the
    Comment type.

    type Query {
      feed: [Post!]!
    }
    
    type Post {
      id: ID! @computed(selectionSet: "{ comments { authorId } }")
    }
    
    type Comment {
      id: ID!
      authorId: ID!
    }
    
    type User {
      id: ID!
      name: String!
    }
    type Post {
      id: ID!
      comments: [Comment!]!
    }
    
    type Comment {
      id: ID!
    }
  • Updated dependencies
    [0e87805]:

    • @graphql-tools/delegate@10.0.20

August 21, 2024

21 Aug 06:36
b6d05ee
Compare
Choose a tag to compare

@graphql-tools/executor-http@1.1.6

Patch Changes

  • f9dd3d6
    Thanks @ardatan! - Details in the extensions when an unexpected
    error occurs;

    {
      "request": {
        "url": "https://api.example.com/graphql",
        "method": "POST",
        "body": {
          "query": "query { hello }"
        }
      },
      "response": {
        "status": 500,
        "statusText": "Internal Server Error",
        "headers": {
          "content-type": "application/json"
        },
        "body": {
          "errors": [
            {
              "message": "Internal Server Error"
            }
          ]
        }
      }
    }

August 16, 2024

16 Aug 02:01
8b4f869
Compare
Choose a tag to compare

@graphql-tools/merge@9.0.6

Patch Changes

  • 0286437
    Thanks @ardatan! - Improve directive extraction

  • Updated dependencies
    [0286437]:

    • @graphql-tools/utils@10.5.4

@graphql-tools/schema@10.0.6

Patch Changes

  • 0286437
    Thanks @ardatan! - Improve directive extraction

  • Updated dependencies
    [0286437]:

    • @graphql-tools/merge@9.0.6
    • @graphql-tools/utils@10.5.4

@graphql-tools/utils@10.5.4

Patch Changes

August 14, 2024

14 Aug 11:33
600b2ce
Compare
Choose a tag to compare

@graphql-tools/federation@2.2.8

Patch Changes

  • #6441
    52a69ed
    Thanks @ardatan! - Filter errors as null in the projected key

    If the key field has Error, do not send them to the subgraphs as objects but null.

August 14, 2024

14 Aug 09:39
c1756d6
Compare
Choose a tag to compare

@graphql-tools/utils@10.5.3

Patch Changes

  • 2124d7d
    Thanks @ardatan! - Allow invalid path in `getDirectiveExtensions`

August 14, 2024

14 Aug 09:30
2124d7d
Compare
Choose a tag to compare

@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[] }) => ({
                    us...
Read more

August 12, 2024

12 Aug 21:10
d86f5b2
Compare
Choose a tag to compare

@graphql-tools/utils@10.5.2

Patch Changes

  • 07b87ed
    Thanks @ardatan! - Respect extensionASTNodes in directable
    GraphQLSchema object