Releases: ardatan/graphql-tools
September 11, 2024
August 29, 2024
August 26, 2024
August 26, 2024
@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 theauthor
field in thePost
type is merged with the selection set for theauthorId
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 theauthor
field in thePost
type is merged with the selection set for theauthorId
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
@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
August 14, 2024
August 14, 2024
August 14, 2024
@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
needsuserOrders
which needslastName
from
initialQuery.user
. So the bug was skipping the dependencies ofuserOrders
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
needsuserOrders
which needslastName
from
initialQuery.user
. So the bug was skipping the dependencies ofuserOrders
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...