gqty doesn't respect `prevSelection.unions` while composing `cacheKey`
Hi!
I have scheme like this (using Federation):
# type from another subgraph
type Product @key(fields: "id") {
id: String!
name: String!
slug: String!
}
# type from another subgraph
type Service @key(fields: "id") {
id: String!
name: String!
}
type BasketItemProduct {
id: String!
price: String!
count: Int!
product: Product
services: [Service!]!
}
type BasketItemPresent {
id: String!
price: String!
count: Int!
product: Product
}
union BasketItem =
| BasketItemProduct
| BasketItemPresent
type Basket {
items: [BasketItem!]!
}
I want to fetch query like this:
query {
basket {
items {
... on BasketItemProduct {
price
count
product {
name
slug
}
}
... on BasketItemPresent {
price
count
product {
name
slug
}
}
}
}
}
My code (simplified) looks like this:
function mapService(service: Service | null) {
return castNotSkeleton({
name: service,
});
}
function mapProduct(product: Product | null) {
return castNotSkeleton({
name: product.name,
slug: product.slug,
services: product.services.map(mapService),
});
}
function mapBasketItemProduct(itemProduct: BasketItemProduct | null) {
if (!itemProduct) {
return null;
}
return castNotSkeleton({
id: itemProduct,
price: itemProduct.price,
count: itemProduct.count,
product: mapProduct(itemProduct.product ?? null),
});
}
function mapBasketItemPresent(itemPresent: BasketItemPresent | null) {
if (! itemPresent) {
return null;
}
return castNotSkeleton({
id: itemPresent,
price: itemPresent.price,
count: itemPresent.count,
product: mapProduct(itemPresent.product ?? null),
});
}
export function api() {
return resolved(() => {
return query.basket.items.map((it) => ({
product: mapBasketItemProduct(it.$on.BasketItemProduct ?? null),
present: mapBasketItemProduct(it.$BasketItemPresent ?? null),
}));
});
}
and with this piece of code I've got query like this (simplified):
query {
basket {
items {
... on BasketItemProduct {
price
count
product {
name
slug
}
}
... on BasketItemPresent {
price
count
}
}
}
}
so second usage of mapproduct is ignored.
After some investigation I found that problem is in this piece of code:
https://github.com/gqty-dev/gqty/blob/f39bb45023613e0606bedb0b25dd3468da146b67/packages/gqty/src/Selection/SelectionManager.ts#L142-L158
because cacheKey for Product.slug (for example) looks like this: basket.items.0.product.slug and at the second pass it returns entry for BasketItemProduct and not creating seperate one for BasketItemPresent
My ugly fix for testing looks like this:
if (prevSelection?.unions?.length > 0) {
cacheKey += ";" + prevSelection.unions.join(";");
}
let selection = selectionCache.get(cacheKey);
if (selection == null || selection.prevSelection !== prevSelection) ...
I hope you can forward me to the right point for this issue! ❤️