Add support for altStyleId to item search and appearance lookups

I'm not planning to port full Alt Style support over to the 2020
frontend, I really am winding that down, but adding a couple lil API
parameters are *by far* the easiest way to get Alt Styles working in
the main app because of how it calls the 2020 API.

So here we are, adding new API calls but not the frontend changes!
This commit is contained in:
Emi Matchu 2024-02-01 04:59:09 -08:00
parent 505f420d96
commit f566012386
2 changed files with 216 additions and 177 deletions

View file

@ -6,7 +6,7 @@ const buildClosetListLoader = (db) =>
const qs = ids.map((_) => "?").join(","); const qs = ids.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM closet_lists WHERE id IN (${qs})`, `SELECT * FROM closet_lists WHERE id IN (${qs})`,
ids ids,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -19,13 +19,13 @@ const buildClosetHangersForListLoader = (db) =>
const qs = closetListIds.map((_) => "?").join(","); const qs = closetListIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM closet_hangers WHERE list_id IN (${qs})`, `SELECT * FROM closet_hangers WHERE list_id IN (${qs})`,
closetListIds closetListIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return closetListIds.map((closetListId) => return closetListIds.map((closetListId) =>
entities.filter((e) => e.listId === closetListId) entities.filter((e) => e.listId === closetListId),
); );
}); });
@ -42,7 +42,7 @@ const buildClosetHangersForDefaultListLoader = (db) =>
.flat(); .flat();
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM closet_hangers WHERE ${conditions}`, `SELECT * FROM closet_hangers WHERE ${conditions}`,
values values,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -51,8 +51,8 @@ const buildClosetHangersForDefaultListLoader = (db) =>
entities.filter( entities.filter(
(e) => (e) =>
e.userId === userId && e.userId === userId &&
Boolean(e.owned) === (ownsOrWantsItems === "OWNS") Boolean(e.owned) === (ownsOrWantsItems === "OWNS"),
) ),
); );
}); });
@ -61,7 +61,7 @@ const buildColorLoader = (db) => {
const qs = colorIds.map((_) => "?").join(","); const qs = colorIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM colors WHERE id IN (${qs}) AND prank = 0`, `SELECT * FROM colors WHERE id IN (${qs}) AND prank = 0`,
colorIds colorIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -70,7 +70,7 @@ const buildColorLoader = (db) => {
return colorIds.map( return colorIds.map(
(colorId) => (colorId) =>
entitiesByColorId.get(String(colorId)) || entitiesByColorId.get(String(colorId)) ||
new Error(`could not find color ${colorId}`) new Error(`could not find color ${colorId}`),
); );
}); });
@ -94,7 +94,7 @@ const buildColorTranslationLoader = (db) =>
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM color_translations `SELECT * FROM color_translations
WHERE color_id IN (${qs}) AND locale = "en"`, WHERE color_id IN (${qs}) AND locale = "en"`,
colorIds colorIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -103,7 +103,7 @@ const buildColorTranslationLoader = (db) =>
return colorIds.map( return colorIds.map(
(colorId) => (colorId) =>
entitiesByColorId.get(String(colorId)) || entitiesByColorId.get(String(colorId)) ||
new Error(`could not find translation for color ${colorId}`) new Error(`could not find translation for color ${colorId}`),
); );
}); });
@ -112,7 +112,7 @@ const buildSpeciesLoader = (db) => {
const qs = speciesIds.map((_) => "?").join(","); const qs = speciesIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM species WHERE id IN (${qs})`, `SELECT * FROM species WHERE id IN (${qs})`,
speciesIds speciesIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -121,7 +121,7 @@ const buildSpeciesLoader = (db) => {
return speciesIds.map( return speciesIds.map(
(speciesId) => (speciesId) =>
entitiesBySpeciesId.get(String(speciesId)) || entitiesBySpeciesId.get(String(speciesId)) ||
new Error(`could not find color ${speciesId}`) new Error(`could not find color ${speciesId}`),
); );
}); });
@ -145,7 +145,7 @@ const buildSpeciesTranslationLoader = (db) =>
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM species_translations `SELECT * FROM species_translations
WHERE species_id IN (${qs}) AND locale = "en"`, WHERE species_id IN (${qs}) AND locale = "en"`,
speciesIds speciesIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -154,7 +154,7 @@ const buildSpeciesTranslationLoader = (db) =>
return speciesIds.map( return speciesIds.map(
(speciesId) => (speciesId) =>
entitiesBySpeciesId.get(String(speciesId)) || entitiesBySpeciesId.get(String(speciesId)) ||
new Error(`could not find translation for species ${speciesId}`) new Error(`could not find translation for species ${speciesId}`),
); );
}); });
@ -164,7 +164,7 @@ const buildTradeMatchesLoader = (db) =>
const conditions = userPairs const conditions = userPairs
.map( .map(
(_) => (_) =>
`(public_user_hangers.user_id = ? AND current_user_hangers.user_id = ? AND public_user_hangers.owned = ? AND current_user_hangers.owned = ?)` `(public_user_hangers.user_id = ? AND current_user_hangers.user_id = ? AND public_user_hangers.owned = ? AND current_user_hangers.owned = ?)`,
) )
.join(" OR "); .join(" OR ");
const conditionValues = userPairs const conditionValues = userPairs
@ -175,7 +175,7 @@ const buildTradeMatchesLoader = (db) =>
return [publicUserId, currentUserId, false, true]; return [publicUserId, currentUserId, false, true];
} else { } else {
throw new Error( throw new Error(
`unexpected user pair direction: ${JSON.stringify(direction)}` `unexpected user pair direction: ${JSON.stringify(direction)}`,
); );
} }
}) })
@ -217,7 +217,7 @@ const buildTradeMatchesLoader = (db) =>
) )
GROUP BY public_user_id, current_user_id; GROUP BY public_user_id, current_user_id;
`, `,
conditionValues conditionValues,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -227,7 +227,7 @@ const buildTradeMatchesLoader = (db) =>
(e) => (e) =>
e.publicUserId === publicUserId && e.publicUserId === publicUserId &&
e.currentUserId === currentUserId && e.currentUserId === currentUserId &&
e.direction === direction e.direction === direction,
); );
return entity ? entity.itemIds.split(",") : []; return entity ? entity.itemIds.split(",") : [];
}); });
@ -235,7 +235,7 @@ const buildTradeMatchesLoader = (db) =>
{ {
cacheKeyFn: ({ publicUserId, currentUserId, direction }) => cacheKeyFn: ({ publicUserId, currentUserId, direction }) =>
`${publicUserId}-${currentUserId}-${direction}`, `${publicUserId}-${currentUserId}-${direction}`,
} },
); );
const loadAllPetTypes = (db) => async () => { const loadAllPetTypes = (db) => async () => {
@ -249,7 +249,7 @@ const buildItemLoader = (db) =>
const qs = ids.map((_) => "?").join(","); const qs = ids.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM items WHERE id IN (${qs})`, `SELECT * FROM items WHERE id IN (${qs})`,
ids ids,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -258,7 +258,7 @@ const buildItemLoader = (db) =>
return ids.map( return ids.map(
(id) => (id) =>
entitiesById.get(String(id)) || entitiesById.get(String(id)) ||
new Error(`could not find item with ID: ${id}`) new Error(`could not find item with ID: ${id}`),
); );
}); });
@ -267,7 +267,7 @@ const buildItemTranslationLoader = (db) =>
const qs = itemIds.map((_) => "?").join(","); const qs = itemIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM item_translations WHERE item_id IN (${qs}) AND locale = "en"`, `SELECT * FROM item_translations WHERE item_id IN (${qs}) AND locale = "en"`,
itemIds itemIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -276,7 +276,7 @@ const buildItemTranslationLoader = (db) =>
return itemIds.map( return itemIds.map(
(itemId) => (itemId) =>
entitiesByItemId.get(String(itemId)) || entitiesByItemId.get(String(itemId)) ||
new Error(`could not find translation for item ${itemId}`) new Error(`could not find translation for item ${itemId}`),
); );
}); });
@ -293,7 +293,7 @@ const buildItemByNameLoader = (db, loaders) =>
WHERE name IN (${qs}) AND locale = "en"`, WHERE name IN (${qs}) AND locale = "en"`,
nestTables: true, nestTables: true,
}, },
normalizedNames normalizedNames,
); );
const entitiesByName = new Map(); const entitiesByName = new Map();
@ -309,10 +309,10 @@ const buildItemByNameLoader = (db, loaders) =>
return normalizedNames.map( return normalizedNames.map(
(name) => (name) =>
entitiesByName.get(name) || { item: null, itemTranslation: null } entitiesByName.get(name) || { item: null, itemTranslation: null },
); );
}, },
{ cacheKeyFn: (name) => name.trim().toLowerCase() } { cacheKeyFn: (name) => name.trim().toLowerCase() },
); );
const itemSearchKindConditions = { const itemSearchKindConditions = {
@ -409,18 +409,15 @@ const buildItemSearchNumTotalItemsLoader = (db) =>
currentUserId, currentUserId,
zoneIds = [], zoneIds = [],
}) => { }) => {
const { const { queryJoins, queryConditions, queryConditionValues } =
queryJoins, buildItemSearchConditions({
queryConditions, query,
queryConditionValues, bodyId,
} = buildItemSearchConditions({ itemKind,
query, currentUserOwnsOrWants,
bodyId, currentUserId,
itemKind, zoneIds,
currentUserOwnsOrWants, });
currentUserId,
zoneIds,
});
const [totalRows] = await db.execute( const [totalRows] = await db.execute(
` `
@ -428,12 +425,12 @@ const buildItemSearchNumTotalItemsLoader = (db) =>
${queryJoins} ${queryJoins}
WHERE ${queryConditions} WHERE ${queryConditions}
`, `,
queryConditionValues queryConditionValues,
); );
const { numTotalItems } = totalRows[0]; const { numTotalItems } = totalRows[0];
return numTotalItems; return numTotalItems;
} },
); );
const responses = await Promise.all(queryPromises); const responses = await Promise.all(queryPromises);
@ -459,18 +456,15 @@ const buildItemSearchItemsLoader = (db, loaders) =>
const actualOffset = offset || 0; const actualOffset = offset || 0;
const actualLimit = Math.min(limit || 30, 30); const actualLimit = Math.min(limit || 30, 30);
const { const { queryJoins, queryConditions, queryConditionValues } =
queryJoins, buildItemSearchConditions({
queryConditions, query,
queryConditionValues, bodyId,
} = buildItemSearchConditions({ itemKind,
query, currentUserOwnsOrWants,
bodyId, currentUserId,
itemKind, zoneIds,
currentUserOwnsOrWants, });
currentUserId,
zoneIds,
});
const [rows] = await db.execute( const [rows] = await db.execute(
` `
@ -480,7 +474,7 @@ const buildItemSearchItemsLoader = (db, loaders) =>
ORDER BY t.name ORDER BY t.name
LIMIT ? OFFSET ? LIMIT ? OFFSET ?
`, `,
[...queryConditionValues, actualLimit, actualOffset] [...queryConditionValues, actualLimit, actualOffset],
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -490,7 +484,7 @@ const buildItemSearchItemsLoader = (db, loaders) =>
} }
return entities; return entities;
} },
); );
const responses = await Promise.all(queryPromises); const responses = await Promise.all(queryPromises);
@ -504,12 +498,12 @@ const buildNewestItemsLoader = (db, loaders) =>
// loaders, even though there's only one query to run. // loaders, even though there's only one query to run.
if (keys.length !== 1 && keys[0] !== "all-newest") { if (keys.length !== 1 && keys[0] !== "all-newest") {
throw new Error( throw new Error(
`this loader can only be loaded with the key "all-newest"` `this loader can only be loaded with the key "all-newest"`,
); );
} }
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM items ORDER BY created_at DESC LIMIT 20;` `SELECT * FROM items ORDER BY created_at DESC LIMIT 20;`,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -616,7 +610,7 @@ async function runItemModelingQuery(db, filterToItemIds) {
-- take up a bunch of resources and crash the site? -- take up a bunch of resources and crash the site?
LIMIT 200; LIMIT 200;
`, `,
[...itemIdsValues] [...itemIdsValues],
); );
} }
@ -638,10 +632,10 @@ const buildSpeciesThatNeedModelsForItemLoader = (db) =>
// color built into the query (well, no row when no models needed!). So, // color built into the query (well, no row when no models needed!). So,
// find the right row for each color/item pair, or possibly null! // find the right row for each color/item pair, or possibly null!
return colorIdAndItemIdPairs.map(({ colorId, itemId }) => return colorIdAndItemIdPairs.map(({ colorId, itemId }) =>
entities.find((e) => e.itemId === itemId && e.colorId === colorId) entities.find((e) => e.itemId === itemId && e.colorId === colorId),
); );
}, },
{ cacheKeyFn: ({ colorId, itemId }) => `${colorId}-${itemId}` } { cacheKeyFn: ({ colorId, itemId }) => `${colorId}-${itemId}` },
); );
const buildItemsThatNeedModelsLoader = (db, loaders) => const buildItemsThatNeedModelsLoader = (db, loaders) =>
@ -661,7 +655,7 @@ const buildItemsThatNeedModelsLoader = (db, loaders) =>
for (const { colorId, itemId, ...entity } of entities) { for (const { colorId, itemId, ...entity } of entities) {
loaders.speciesThatNeedModelsForItemLoader.prime( loaders.speciesThatNeedModelsForItemLoader.prime(
{ colorId, itemId }, { colorId, itemId },
entity entity,
); );
if (!result.has(colorId)) { if (!result.has(colorId)) {
@ -697,7 +691,7 @@ const buildAllSpeciesIdsForColorLoader = (db) =>
) )
GROUP BY color_id; GROUP BY color_id;
`, `,
colorIds colorIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -705,7 +699,7 @@ const buildAllSpeciesIdsForColorLoader = (db) =>
return colorIds.map( return colorIds.map(
(colorId) => (colorId) =>
entities.find((e) => e.colorId === colorId)?.speciesIds?.split(",") || entities.find((e) => e.colorId === colorId)?.speciesIds?.split(",") ||
[] [],
); );
}); });
@ -731,7 +725,7 @@ const buildItemBodiesWithAppearanceDataLoader = (db) =>
ORDER BY ORDER BY
pet_types.species_id, pet_types.species_id,
colors.standard DESC`, colors.standard DESC`,
itemIds itemIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -749,7 +743,7 @@ const buildItemAllOccupiedZonesLoader = (db) =>
INNER JOIN swf_assets sa ON sa.id = psa.swf_asset_id INNER JOIN swf_assets sa ON sa.id = psa.swf_asset_id
WHERE items.id IN (${qs}) WHERE items.id IN (${qs})
GROUP BY items.id;`, GROUP BY items.id;`,
itemIds itemIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -787,7 +781,7 @@ const buildItemCompatibleBodiesAndTheirZonesLoader = (db) =>
-- matches no pet type. Huh! Well, ignore those bodies! -- matches no pet type. Huh! Well, ignore those bodies!
HAVING speciesId IS NOT NULL OR bodyId = 0; HAVING speciesId IS NOT NULL OR bodyId = 0;
`, `,
itemIds itemIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -829,7 +823,7 @@ const buildItemTradesLoader = (db, loaders) =>
`, `,
nestTables: true, nestTables: true,
}, },
values values,
); );
const entities = rows.map((row) => ({ const entities = rows.map((row) => ({
@ -848,16 +842,16 @@ const buildItemTradesLoader = (db, loaders) =>
.filter( .filter(
(e) => (e) =>
e.closetHanger.itemId === itemId && e.closetHanger.itemId === itemId &&
Boolean(e.closetHanger.owned) === isOwned Boolean(e.closetHanger.owned) === isOwned,
) )
.map((e) => ({ .map((e) => ({
id: e.closetHanger.id, id: e.closetHanger.id,
closetList: e.closetList.id ? e.closetList : null, closetList: e.closetList.id ? e.closetList : null,
user: e.user, user: e.user,
})) })),
); );
}, },
{ cacheKeyFn: ({ itemId, isOwned }) => `${itemId}-${isOwned}` } { cacheKeyFn: ({ itemId, isOwned }) => `${itemId}-${isOwned}` },
); );
const buildPetTypeLoader = (db, loaders) => const buildPetTypeLoader = (db, loaders) =>
@ -865,7 +859,7 @@ const buildPetTypeLoader = (db, loaders) =>
const qs = petTypeIds.map((_) => "?").join(","); const qs = petTypeIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM pet_types WHERE id IN (${qs})`, `SELECT * FROM pet_types WHERE id IN (${qs})`,
petTypeIds petTypeIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -873,12 +867,12 @@ const buildPetTypeLoader = (db, loaders) =>
for (const petType of entities) { for (const petType of entities) {
loaders.petTypeBySpeciesAndColorLoader.prime( loaders.petTypeBySpeciesAndColorLoader.prime(
{ speciesId: petType.speciesId, colorId: petType.colorId }, { speciesId: petType.speciesId, colorId: petType.colorId },
petType petType,
); );
} }
return petTypeIds.map((petTypeId) => return petTypeIds.map((petTypeId) =>
entities.find((e) => e.id === petTypeId) entities.find((e) => e.id === petTypeId),
); );
}); });
@ -894,12 +888,12 @@ const buildPetTypeBySpeciesAndColorLoader = (db, loaders) =>
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM pet_types WHERE ${conditions.join(" OR ")}`, `SELECT * FROM pet_types WHERE ${conditions.join(" OR ")}`,
values values,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
const entitiesBySpeciesAndColorPair = new Map( const entitiesBySpeciesAndColorPair = new Map(
entities.map((e) => [`${e.speciesId},${e.colorId}`, e]) entities.map((e) => [`${e.speciesId},${e.colorId}`, e]),
); );
for (const petType of entities) { for (const petType of entities) {
@ -907,10 +901,10 @@ const buildPetTypeBySpeciesAndColorLoader = (db, loaders) =>
} }
return speciesAndColorPairs.map(({ speciesId, colorId }) => return speciesAndColorPairs.map(({ speciesId, colorId }) =>
entitiesBySpeciesAndColorPair.get(`${speciesId},${colorId}`) entitiesBySpeciesAndColorPair.get(`${speciesId},${colorId}`),
); );
}, },
{ cacheKeyFn: ({ speciesId, colorId }) => `${speciesId},${colorId}` } { cacheKeyFn: ({ speciesId, colorId }) => `${speciesId},${colorId}` },
); );
const buildPetTypesForColorLoader = (db, loaders) => const buildPetTypesForColorLoader = (db, loaders) =>
@ -918,7 +912,7 @@ const buildPetTypesForColorLoader = (db, loaders) =>
const qs = colorIds.map((_) => "?").join(","); const qs = colorIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM pet_types WHERE color_id IN (${qs})`, `SELECT * FROM pet_types WHERE color_id IN (${qs})`,
colorIds colorIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -927,12 +921,27 @@ const buildPetTypesForColorLoader = (db, loaders) =>
loaders.petTypeLoader.prime(petType.id, petType); loaders.petTypeLoader.prime(petType.id, petType);
loaders.petTypeBySpeciesAndColorLoader.prime( loaders.petTypeBySpeciesAndColorLoader.prime(
{ speciesId: petType.speciesId, colorId: petType.colorId }, { speciesId: petType.speciesId, colorId: petType.colorId },
petType petType,
); );
} }
return colorIds.map((colorId) => return colorIds.map((colorId) =>
entities.filter((e) => e.colorId === colorId) entities.filter((e) => e.colorId === colorId),
);
});
const buildAltStyleLoader = (db) =>
new DataLoader(async (altStyleIds) => {
const qs = altStyleIds.map((_) => "?").join(",");
const [rows] = await db.execute(
`SELECT * FROM alt_styles WHERE id IN (${qs})`,
altStyleIds,
);
const entities = rows.map(normalizeRow);
return altStyleIds.map((altStyleId) =>
entities.find((e) => e.id === altStyleId),
); );
}); });
@ -941,13 +950,13 @@ const buildSwfAssetLoader = (db) =>
const qs = swfAssetIds.map((_) => "?").join(","); const qs = swfAssetIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM swf_assets WHERE id IN (${qs})`, `SELECT * FROM swf_assets WHERE id IN (${qs})`,
swfAssetIds swfAssetIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return swfAssetIds.map((swfAssetId) => return swfAssetIds.map((swfAssetId) =>
entities.find((e) => e.id === swfAssetId) entities.find((e) => e.id === swfAssetId),
); );
}); });
@ -960,7 +969,7 @@ const buildSwfAssetCountLoader = (db) =>
(manifest IS NOT NULL AND manifest != "") AS is_converted (manifest IS NOT NULL AND manifest != "") AS is_converted
FROM swf_assets FROM swf_assets
GROUP BY type, is_converted; GROUP BY type, is_converted;
` `,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -972,7 +981,7 @@ const buildSwfAssetCountLoader = (db) =>
} }
if (isConverted != null) { if (isConverted != null) {
matchingEntities = matchingEntities.filter( matchingEntities = matchingEntities.filter(
(e) => Boolean(e.isConverted) === isConverted (e) => Boolean(e.isConverted) === isConverted,
); );
} }
@ -982,7 +991,7 @@ const buildSwfAssetCountLoader = (db) =>
}, },
{ {
cacheKeyFn: ({ type, isConverted }) => `${type},${isConverted}`, cacheKeyFn: ({ type, isConverted }) => `${type},${isConverted}`,
} },
); );
const buildSwfAssetByRemoteIdLoader = (db) => const buildSwfAssetByRemoteIdLoader = (db) =>
@ -996,16 +1005,16 @@ const buildSwfAssetByRemoteIdLoader = (db) =>
.flat(); .flat();
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM swf_assets WHERE ${qs}`, `SELECT * FROM swf_assets WHERE ${qs}`,
values values,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return typeAndRemoteIdPairs.map(({ type, remoteId }) => return typeAndRemoteIdPairs.map(({ type, remoteId }) =>
entities.find((e) => e.type === type && e.remoteId === remoteId) entities.find((e) => e.type === type && e.remoteId === remoteId),
); );
}, },
{ cacheKeyFn: ({ type, remoteId }) => `${type},${remoteId}` } { cacheKeyFn: ({ type, remoteId }) => `${type},${remoteId}` },
); );
const buildItemSwfAssetLoader = (db, loaders) => const buildItemSwfAssetLoader = (db, loaders) =>
@ -1015,7 +1024,7 @@ const buildItemSwfAssetLoader = (db, loaders) =>
const values = []; const values = [];
for (const { itemId, bodyId } of itemAndBodyPairs) { for (const { itemId, bodyId } of itemAndBodyPairs) {
conditions.push( conditions.push(
"(rel.parent_id = ? AND (sa.body_id = ? OR sa.body_id = 0))" "(rel.parent_id = ? AND (sa.body_id = ? OR sa.body_id = 0))",
); );
values.push(itemId, bodyId); values.push(itemId, bodyId);
} }
@ -1026,7 +1035,7 @@ const buildItemSwfAssetLoader = (db, loaders) =>
rel.parent_type = "Item" AND rel.parent_type = "Item" AND
rel.swf_asset_id = sa.id rel.swf_asset_id = sa.id
WHERE ${conditions.join(" OR ")}`, WHERE ${conditions.join(" OR ")}`,
values values,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1038,11 +1047,11 @@ const buildItemSwfAssetLoader = (db, loaders) =>
return itemAndBodyPairs.map(({ itemId, bodyId }) => return itemAndBodyPairs.map(({ itemId, bodyId }) =>
entities.filter( entities.filter(
(e) => (e) =>
e.parentId === itemId && (e.bodyId === bodyId || e.bodyId === "0") e.parentId === itemId && (e.bodyId === bodyId || e.bodyId === "0"),
) ),
); );
}, },
{ cacheKeyFn: ({ itemId, bodyId }) => `${itemId},${bodyId}` } { cacheKeyFn: ({ itemId, bodyId }) => `${itemId},${bodyId}` },
); );
const buildPetSwfAssetLoader = (db, loaders) => const buildPetSwfAssetLoader = (db, loaders) =>
@ -1054,7 +1063,7 @@ const buildPetSwfAssetLoader = (db, loaders) =>
rel.parent_type = "PetState" AND rel.parent_type = "PetState" AND
rel.swf_asset_id = sa.id rel.swf_asset_id = sa.id
WHERE rel.parent_id IN (${qs})`, WHERE rel.parent_id IN (${qs})`,
petStateIds petStateIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1064,7 +1073,7 @@ const buildPetSwfAssetLoader = (db, loaders) =>
} }
return petStateIds.map((petStateId) => return petStateIds.map((petStateId) =>
entities.filter((e) => e.parentId === petStateId) entities.filter((e) => e.parentId === petStateId),
); );
}); });
@ -1073,7 +1082,7 @@ const buildNeopetsConnectionLoader = (db) =>
const qs = ids.map((_) => "?").join(", "); const qs = ids.map((_) => "?").join(", ");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM neopets_connections WHERE id IN (${qs})`, `SELECT * FROM neopets_connections WHERE id IN (${qs})`,
ids ids,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1086,7 +1095,7 @@ const buildOutfitLoader = (db) =>
const qs = outfitIds.map((_) => "?").join(","); const qs = outfitIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM outfits WHERE id IN (${qs})`, `SELECT * FROM outfits WHERE id IN (${qs})`,
outfitIds outfitIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1099,13 +1108,13 @@ const buildItemOutfitRelationshipsLoader = (db) =>
const qs = outfitIds.map((_) => "?").join(","); const qs = outfitIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM item_outfit_relationships WHERE outfit_id IN (${qs})`, `SELECT * FROM item_outfit_relationships WHERE outfit_id IN (${qs})`,
outfitIds outfitIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return outfitIds.map((outfitId) => return outfitIds.map((outfitId) =>
entities.filter((e) => e.outfitId === outfitId) entities.filter((e) => e.outfitId === outfitId),
); );
}); });
@ -1114,13 +1123,13 @@ const buildPetStateLoader = (db) =>
const qs = petStateIds.map((_) => "?").join(","); const qs = petStateIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM pet_states WHERE id IN (${qs})`, `SELECT * FROM pet_states WHERE id IN (${qs})`,
petStateIds petStateIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return petStateIds.map((petStateId) => return petStateIds.map((petStateId) =>
entities.find((e) => e.id === petStateId) entities.find((e) => e.id === petStateId),
); );
}); });
@ -1132,7 +1141,7 @@ const buildPetStatesForPetTypeLoader = (db, loaders) =>
WHERE pet_type_id IN (${qs}) WHERE pet_type_id IN (${qs})
ORDER BY (mood_id IS NULL) ASC, mood_id ASC, female DESC, ORDER BY (mood_id IS NULL) ASC, mood_id ASC, female DESC,
unconverted DESC, glitched ASC, id DESC`, unconverted DESC, glitched ASC, id DESC`,
petTypeIds petTypeIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1142,7 +1151,7 @@ const buildPetStatesForPetTypeLoader = (db, loaders) =>
} }
return petTypeIds.map((petTypeId) => return petTypeIds.map((petTypeId) =>
entities.filter((e) => e.petTypeId === petTypeId) entities.filter((e) => e.petTypeId === petTypeId),
); );
}); });
@ -1184,7 +1193,7 @@ const buildCanonicalPetStateForBodyLoader = (db, loaders) =>
preferredColorId || "<ignore>", preferredColorId || "<ignore>",
fallbackColorId, fallbackColorId,
gender === "fem", gender === "fem",
] ],
); );
const petState = normalizeRow(rows[0].pet_states); const petState = normalizeRow(rows[0].pet_states);
const petType = normalizeRow(rows[0].pet_types); const petType = normalizeRow(rows[0].pet_types);
@ -1196,13 +1205,13 @@ const buildCanonicalPetStateForBodyLoader = (db, loaders) =>
loaders.petTypeLoader.prime(petType.id, petType); loaders.petTypeLoader.prime(petType.id, petType);
return petState; return petState;
}) }),
); );
}, },
{ {
cacheKeyFn: ({ bodyId, preferredColorId, fallbackColorId }) => cacheKeyFn: ({ bodyId, preferredColorId, fallbackColorId }) =>
`${bodyId}-${preferredColorId}-${fallbackColorId}`, `${bodyId}-${preferredColorId}-${fallbackColorId}`,
} },
); );
const buildPetStateByPetTypeAndAssetsLoader = (db, loaders) => const buildPetStateByPetTypeAndAssetsLoader = (db, loaders) =>
@ -1216,7 +1225,7 @@ const buildPetStateByPetTypeAndAssetsLoader = (db, loaders) =>
.flat(); .flat();
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM pet_states WHERE ${qs}`, `SELECT * FROM pet_states WHERE ${qs}`,
values values,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1227,13 +1236,13 @@ const buildPetStateByPetTypeAndAssetsLoader = (db, loaders) =>
return petTypeIdAndAssetIdsPairs.map(({ petTypeId, swfAssetIds }) => return petTypeIdAndAssetIdsPairs.map(({ petTypeId, swfAssetIds }) =>
entities.find( entities.find(
(e) => e.petTypeId === petTypeId && e.swfAssetIds === swfAssetIds (e) => e.petTypeId === petTypeId && e.swfAssetIds === swfAssetIds,
) ),
); );
}, },
{ {
cacheKeyFn: ({ petTypeId, swfAssetIds }) => `${petTypeId}-${swfAssetIds}`, cacheKeyFn: ({ petTypeId, swfAssetIds }) => `${petTypeId}-${swfAssetIds}`,
} },
); );
const buildUserLoader = (db) => const buildUserLoader = (db) =>
@ -1241,7 +1250,7 @@ const buildUserLoader = (db) =>
const qs = ids.map((_) => "?").join(","); const qs = ids.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM users WHERE id IN (${qs})`, `SELECT * FROM users WHERE id IN (${qs})`,
ids ids,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1250,7 +1259,7 @@ const buildUserLoader = (db) =>
return ids.map( return ids.map(
(id) => (id) =>
entitiesById.get(String(id)) || entitiesById.get(String(id)) ||
new Error(`could not find user with ID: ${id}`) new Error(`could not find user with ID: ${id}`),
); );
}); });
@ -1259,13 +1268,13 @@ const buildUserByNameLoader = (db) =>
const qs = names.map((_) => "?").join(","); const qs = names.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM users WHERE name IN (${qs})`, `SELECT * FROM users WHERE name IN (${qs})`,
names names,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return names.map((name) => return names.map((name) =>
entities.find((e) => e.name.toLowerCase() === name.toLowerCase()) entities.find((e) => e.name.toLowerCase() === name.toLowerCase()),
); );
}); });
@ -1281,7 +1290,7 @@ const buildUserByEmailLoader = (db) =>
`, `,
nestTables: true, nestTables: true,
}, },
emails emails,
); );
const entities = rows.map((row) => ({ const entities = rows.map((row) => ({
@ -1302,12 +1311,12 @@ const buildUserClosetHangersLoader = (db) =>
item_translations.item_id = items.id AND locale = "en" item_translations.item_id = items.id AND locale = "en"
WHERE user_id IN (${qs}) WHERE user_id IN (${qs})
ORDER BY item_name`, ORDER BY item_name`,
userIds userIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return userIds.map((userId) => return userIds.map((userId) =>
entities.filter((e) => e.userId === String(userId)) entities.filter((e) => e.userId === String(userId)),
); );
}); });
@ -1321,12 +1330,12 @@ const buildUserItemClosetHangersLoader = (db) =>
.flat(); .flat();
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM closet_hangers WHERE ${conditions};`, `SELECT * FROM closet_hangers WHERE ${conditions};`,
params params,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
return userIdAndItemIdPairs.map(({ userId, itemId }) => return userIdAndItemIdPairs.map(({ userId, itemId }) =>
entities.filter((e) => e.userId === userId && e.itemId === itemId) entities.filter((e) => e.userId === userId && e.itemId === itemId),
); );
}); });
@ -1337,7 +1346,7 @@ const buildUserClosetListsLoader = (db, loaders) =>
`SELECT * FROM closet_lists `SELECT * FROM closet_lists
WHERE user_id IN (${qs}) WHERE user_id IN (${qs})
ORDER BY name`, ORDER BY name`,
userIds userIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1346,7 +1355,7 @@ const buildUserClosetListsLoader = (db, loaders) =>
} }
return userIds.map((userId) => return userIds.map((userId) =>
entities.filter((e) => e.userId === String(userId)) entities.filter((e) => e.userId === String(userId)),
); );
}); });
@ -1363,7 +1372,7 @@ const buildUserOutfitsLoader = (db, loaders) =>
WHERE user_id = ? WHERE user_id = ?
ORDER BY name ORDER BY name
LIMIT ? OFFSET ?`, LIMIT ? OFFSET ?`,
[userId, actualLimit, actualOffset] [userId, actualLimit, actualOffset],
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1382,7 +1391,7 @@ const buildUserNumTotalOutfitsLoader = (db) =>
`SELECT user_id, COUNT(*) as num_total_outfits FROM outfits `SELECT user_id, COUNT(*) as num_total_outfits FROM outfits
WHERE user_id IN (${qs}) WHERE user_id IN (${qs})
GROUP BY user_id`, GROUP BY user_id`,
userIds userIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1435,7 +1444,7 @@ const buildUserLastTradeActivityLoader = (db) =>
) )
GROUP BY closet_hangers.user_id GROUP BY closet_hangers.user_id
`, `,
userIds userIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1451,7 +1460,7 @@ const buildZoneLoader = (db) => {
const qs = ids.map((_) => "?").join(","); const qs = ids.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM zones WHERE id IN (${qs})`, `SELECT * FROM zones WHERE id IN (${qs})`,
ids ids,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1460,7 +1469,7 @@ const buildZoneLoader = (db) => {
return ids.map( return ids.map(
(id) => (id) =>
entitiesById.get(String(id)) || entitiesById.get(String(id)) ||
new Error(`could not find zone with ID: ${id}`) new Error(`could not find zone with ID: ${id}`),
); );
}); });
@ -1483,7 +1492,7 @@ const buildZoneTranslationLoader = (db) =>
const qs = zoneIds.map((_) => "?").join(","); const qs = zoneIds.map((_) => "?").join(",");
const [rows] = await db.execute( const [rows] = await db.execute(
`SELECT * FROM zone_translations WHERE zone_id IN (${qs}) AND locale = "en"`, `SELECT * FROM zone_translations WHERE zone_id IN (${qs}) AND locale = "en"`,
zoneIds zoneIds,
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
@ -1492,7 +1501,7 @@ const buildZoneTranslationLoader = (db) =>
return zoneIds.map( return zoneIds.map(
(zoneId) => (zoneId) =>
entitiesByZoneId.get(String(zoneId)) || entitiesByZoneId.get(String(zoneId)) ||
new Error(`could not find translation for zone ${zoneId}`) new Error(`could not find translation for zone ${zoneId}`),
); );
}); });
@ -1502,41 +1511,37 @@ function buildLoaders(db) {
loaders.closetListLoader = buildClosetListLoader(db); loaders.closetListLoader = buildClosetListLoader(db);
loaders.closetHangersForListLoader = buildClosetHangersForListLoader(db); loaders.closetHangersForListLoader = buildClosetHangersForListLoader(db);
loaders.closetHangersForDefaultListLoader = buildClosetHangersForDefaultListLoader( loaders.closetHangersForDefaultListLoader =
db buildClosetHangersForDefaultListLoader(db);
);
loaders.colorLoader = buildColorLoader(db); loaders.colorLoader = buildColorLoader(db);
loaders.colorTranslationLoader = buildColorTranslationLoader(db); loaders.colorTranslationLoader = buildColorTranslationLoader(db);
loaders.itemLoader = buildItemLoader(db); loaders.itemLoader = buildItemLoader(db);
loaders.itemTranslationLoader = buildItemTranslationLoader(db); loaders.itemTranslationLoader = buildItemTranslationLoader(db);
loaders.itemByNameLoader = buildItemByNameLoader(db, loaders); loaders.itemByNameLoader = buildItemByNameLoader(db, loaders);
loaders.itemSearchNumTotalItemsLoader = buildItemSearchNumTotalItemsLoader( loaders.itemSearchNumTotalItemsLoader =
db buildItemSearchNumTotalItemsLoader(db);
);
loaders.itemSearchItemsLoader = buildItemSearchItemsLoader(db, loaders); loaders.itemSearchItemsLoader = buildItemSearchItemsLoader(db, loaders);
loaders.newestItemsLoader = buildNewestItemsLoader(db, loaders); loaders.newestItemsLoader = buildNewestItemsLoader(db, loaders);
loaders.speciesThatNeedModelsForItemLoader = buildSpeciesThatNeedModelsForItemLoader( loaders.speciesThatNeedModelsForItemLoader =
db buildSpeciesThatNeedModelsForItemLoader(db);
);
loaders.itemsThatNeedModelsLoader = buildItemsThatNeedModelsLoader( loaders.itemsThatNeedModelsLoader = buildItemsThatNeedModelsLoader(
db, db,
loaders loaders,
); );
loaders.allSpeciesIdsForColorLoader = buildAllSpeciesIdsForColorLoader(db); loaders.allSpeciesIdsForColorLoader = buildAllSpeciesIdsForColorLoader(db);
loaders.itemBodiesWithAppearanceDataLoader = buildItemBodiesWithAppearanceDataLoader( loaders.itemBodiesWithAppearanceDataLoader =
db buildItemBodiesWithAppearanceDataLoader(db);
);
loaders.itemAllOccupiedZonesLoader = buildItemAllOccupiedZonesLoader(db); loaders.itemAllOccupiedZonesLoader = buildItemAllOccupiedZonesLoader(db);
loaders.itemCompatibleBodiesAndTheirZonesLoader = buildItemCompatibleBodiesAndTheirZonesLoader( loaders.itemCompatibleBodiesAndTheirZonesLoader =
db buildItemCompatibleBodiesAndTheirZonesLoader(db);
);
loaders.itemTradesLoader = buildItemTradesLoader(db, loaders); loaders.itemTradesLoader = buildItemTradesLoader(db, loaders);
loaders.petTypeLoader = buildPetTypeLoader(db, loaders); loaders.petTypeLoader = buildPetTypeLoader(db, loaders);
loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader( loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader(
db, db,
loaders loaders,
); );
loaders.petTypesForColorLoader = buildPetTypesForColorLoader(db, loaders); loaders.petTypesForColorLoader = buildPetTypesForColorLoader(db, loaders);
loaders.altStyleLoader = buildAltStyleLoader(db);
loaders.swfAssetLoader = buildSwfAssetLoader(db); loaders.swfAssetLoader = buildSwfAssetLoader(db);
loaders.swfAssetCountLoader = buildSwfAssetCountLoader(db); loaders.swfAssetCountLoader = buildSwfAssetCountLoader(db);
loaders.swfAssetByRemoteIdLoader = buildSwfAssetByRemoteIdLoader(db); loaders.swfAssetByRemoteIdLoader = buildSwfAssetByRemoteIdLoader(db);
@ -1544,22 +1549,19 @@ function buildLoaders(db) {
loaders.petSwfAssetLoader = buildPetSwfAssetLoader(db, loaders); loaders.petSwfAssetLoader = buildPetSwfAssetLoader(db, loaders);
loaders.neopetsConnectionLoader = buildNeopetsConnectionLoader(db); loaders.neopetsConnectionLoader = buildNeopetsConnectionLoader(db);
loaders.outfitLoader = buildOutfitLoader(db); loaders.outfitLoader = buildOutfitLoader(db);
loaders.itemOutfitRelationshipsLoader = buildItemOutfitRelationshipsLoader( loaders.itemOutfitRelationshipsLoader =
db buildItemOutfitRelationshipsLoader(db);
);
loaders.petStateLoader = buildPetStateLoader(db); loaders.petStateLoader = buildPetStateLoader(db);
loaders.petStatesForPetTypeLoader = buildPetStatesForPetTypeLoader( loaders.petStatesForPetTypeLoader = buildPetStatesForPetTypeLoader(
db, db,
loaders loaders,
); );
loaders.canonicalPetStateForBodyLoader = buildCanonicalPetStateForBodyLoader( loaders.canonicalPetStateForBodyLoader = buildCanonicalPetStateForBodyLoader(
db, db,
loaders loaders,
);
loaders.petStateByPetTypeAndAssetsLoader = buildPetStateByPetTypeAndAssetsLoader(
db,
loaders
); );
loaders.petStateByPetTypeAndAssetsLoader =
buildPetStateByPetTypeAndAssetsLoader(db, loaders);
loaders.speciesLoader = buildSpeciesLoader(db); loaders.speciesLoader = buildSpeciesLoader(db);
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db); loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);
loaders.tradeMatchesLoader = buildTradeMatchesLoader(db); loaders.tradeMatchesLoader = buildTradeMatchesLoader(db);

View file

@ -70,7 +70,11 @@ const typeDefs = gql`
How this item appears on the given species/color combo. If it does not How this item appears on the given species/color combo. If it does not
fit the pet, we'll return an empty ItemAppearance with no layers. fit the pet, we'll return an empty ItemAppearance with no layers.
""" """
appearanceOn(speciesId: ID!, colorId: ID!): ItemAppearance! @cacheControl(maxAge: 1, staleWhileRevalidate: ${oneDay}) appearanceOn(
speciesId: ID!,
colorId: ID!,
altStyleId: ID,
): ItemAppearance! @cacheControl(maxAge: 1, staleWhileRevalidate: ${oneDay})
""" """
This is set manually by Support users, when the pet is only for e.g. This is set manually by Support users, when the pet is only for e.g.
@ -176,6 +180,7 @@ const typeDefs = gql`
input FitsPetSearchFilter { input FitsPetSearchFilter {
speciesId: ID! speciesId: ID!
colorId: ID! colorId: ID!
altStyleId: ID
} }
enum ItemKindSearchFilter { enum ItemKindSearchFilter {
@ -527,9 +532,18 @@ const resolvers = {
appearanceOn: async ( appearanceOn: async (
{ id }, { id },
{ speciesId, colorId }, { speciesId, colorId, altStyleId },
{ petTypeBySpeciesAndColorLoader }, { altStyleLoader, petTypeBySpeciesAndColorLoader },
) => { ) => {
// Load based on the alt style's body ID, if present.
if (altStyleId) {
const altStyle = await altStyleLoader.load(altStyleId);
if (altStyle != null) {
return { item: { id }, bodyId: altStyle.bodyId };
}
}
// If not, load based on the species/color combo's body ID.
const petType = await petTypeBySpeciesAndColorLoader.load({ const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId, speciesId,
colorId, colorId,
@ -763,6 +777,7 @@ const resolvers = {
itemSearchNumTotalItemsLoader, itemSearchNumTotalItemsLoader,
itemSearchItemsLoader, itemSearchItemsLoader,
petTypeBySpeciesAndColorLoader, petTypeBySpeciesAndColorLoader,
altStyleLoader,
currentUserId, currentUserId,
}, },
{ cacheControl }, { cacheControl },
@ -773,17 +788,28 @@ const resolvers = {
let bodyId = null; let bodyId = null;
if (fitsPet) { if (fitsPet) {
const petType = await petTypeBySpeciesAndColorLoader.load({ // Load based on the alt style's body ID, if present.
speciesId: fitsPet.speciesId, if (fitsPet.altStyleId != null) {
colorId: fitsPet.colorId, const altStyle = altStyleLoader.load(fitsPet.altStyleId);
}); if (altStyle) {
if (!petType) { bodyId = altStyle.bodyId;
throw new Error( }
`pet type not found: speciesId=${fitsPet.speciesId}, ` + }
`colorId: ${fitsPet.colorId}`,
); // If not, load based on the species/color combo's body ID.
if (bodyId == null) {
const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId: fitsPet.speciesId,
colorId: fitsPet.colorId,
});
if (!petType) {
throw new Error(
`pet type not found: speciesId=${fitsPet.speciesId}, ` +
`colorId: ${fitsPet.colorId}`,
);
}
bodyId = petType.bodyId;
} }
bodyId = petType.bodyId;
} }
const [items, numTotalItems] = await Promise.all([ const [items, numTotalItems] = await Promise.all([
itemSearchItemsLoader.load({ itemSearchItemsLoader.load({
@ -811,21 +837,32 @@ const resolvers = {
itemSearchV2: async ( itemSearchV2: async (
_, _,
{ query, fitsPet, itemKind, currentUserOwnsOrWants, zoneIds = [] }, { query, fitsPet, itemKind, currentUserOwnsOrWants, zoneIds = [] },
{ petTypeBySpeciesAndColorLoader }, { petTypeBySpeciesAndColorLoader, altStyleLoader },
) => { ) => {
let bodyId = null; let bodyId = null;
if (fitsPet) { if (fitsPet) {
const petType = await petTypeBySpeciesAndColorLoader.load({ // Load based on the alt style's body ID, if present.
speciesId: fitsPet.speciesId, if (fitsPet.altStyleId != null) {
colorId: fitsPet.colorId, const altStyle = await altStyleLoader.load(fitsPet.altStyleId);
}); if (altStyle != null) {
if (!petType) { bodyId = altStyle.bodyId;
throw new Error( }
`pet type not found: speciesId=${fitsPet.speciesId}, ` + }
`colorId: ${fitsPet.colorId}`,
); // If not, load based on the species/color combo's body ID.
if (bodyId == null) {
const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId: fitsPet.speciesId,
colorId: fitsPet.colorId,
});
if (!petType) {
throw new Error(
`pet type not found: speciesId=${fitsPet.speciesId}, ` +
`colorId: ${fitsPet.colorId}`,
);
}
bodyId = petType.bodyId;
} }
bodyId = petType.bodyId;
} }
// These are the fields that define the search! We provide them to the // These are the fields that define the search! We provide them to the