impress-2020/src/server/loaders.js

136 lines
3.8 KiB
JavaScript
Raw Normal View History

const DataLoader = require("dataloader");
2020-04-22 11:51:36 -07:00
async function loadItems(db, ids) {
const qs = ids.map((_) => "?").join(",");
const [rows, _] = await db.execute(
`SELECT * FROM items WHERE id IN (${qs})`,
ids
);
2020-04-23 01:08:00 -07:00
const entities = rows.map(normalizeRow);
2020-04-22 14:55:12 -07:00
return entities;
2020-04-22 11:51:36 -07:00
}
const buildItemTranslationLoader = (db) =>
new DataLoader(async (itemIds) => {
const qs = itemIds.map((_) => "?").join(",");
const [rows, _] = await db.execute(
`SELECT * FROM item_translations WHERE item_id IN (${qs}) AND locale = "en"`,
itemIds
);
2020-04-22 11:51:36 -07:00
2020-04-23 01:08:00 -07:00
const entities = rows.map(normalizeRow);
2020-04-22 14:55:12 -07:00
const entitiesByItemId = new Map(entities.map((e) => [e.itemId, e]));
return itemIds.map(
(itemId) =>
2020-04-22 14:55:12 -07:00
entitiesByItemId.get(itemId) ||
new Error(`could not find translation for item ${itemId}`)
);
});
2020-04-22 11:51:36 -07:00
2020-04-23 01:08:00 -07:00
const buildPetTypeLoader = (db) =>
new DataLoader(async (speciesAndColorPairs) => {
const conditions = [];
const values = [];
for (const { speciesId, colorId } of speciesAndColorPairs) {
conditions.push("(species_id = ? AND color_id = ?)");
values.push(speciesId, colorId);
}
const [rows, _] = await db.execute(
`SELECT * FROM pet_types WHERE ${conditions.join(" OR ")}`,
values
);
const entities = rows.map(normalizeRow);
const entitiesBySpeciesAndColorPair = new Map(
entities.map((e) => [`${e.speciesId},${e.colorId}`, e])
);
return speciesAndColorPairs.map(({ speciesId, colorId }) =>
entitiesBySpeciesAndColorPair.get(`${speciesId},${colorId}`)
);
});
const buildSwfAssetLoader = (db) =>
new DataLoader(async (itemAndBodyPairs) => {
const conditions = [];
const values = [];
for (const { itemId, bodyId } of itemAndBodyPairs) {
conditions.push("(rel.parent_id = ? AND sa.body_id = ?)");
values.push(itemId, bodyId);
}
const [rows, _] = await db.execute(
`SELECT sa.*, rel.parent_id FROM swf_assets sa
INNER JOIN parents_swf_assets rel ON
rel.parent_type = "Item" AND
rel.swf_asset_id = sa.id
WHERE ${conditions.join(" OR ")}`,
values
);
const entities = rows.map(normalizeRow);
return itemAndBodyPairs.map(({ itemId, bodyId }) =>
entities.filter((e) => e.parentId === itemId && e.bodyId === bodyId)
);
});
const buildZoneLoader = (db) =>
new DataLoader(async (zoneIds) => {
const qs = zoneIds.map((_) => "?").join(",");
const [rows, _] = await db.execute(
`SELECT * FROM zones WHERE id IN (${qs})`,
zoneIds
);
const entities = rows.map(normalizeRow);
const entitiesById = new Map(entities.map((e) => [e.id, e]));
return zoneIds.map(
(zoneId) =>
entitiesById.get(zoneId) ||
new Error(`could not find zone with ID: ${zoneId}`)
);
});
const buildZoneTranslationLoader = (db) =>
new DataLoader(async (zoneIds) => {
const qs = zoneIds.map((_) => "?").join(",");
const [rows, _] = await db.execute(
`SELECT * FROM zone_translations WHERE zone_id IN (${qs}) AND locale = "en"`,
zoneIds
);
const entities = rows.map(normalizeRow);
const entitiesByZoneId = new Map(entities.map((e) => [e.zoneId, e]));
return zoneIds.map(
(zoneId) =>
entitiesByZoneId.get(zoneId) ||
new Error(`could not find translation for zone ${zoneId}`)
);
});
function normalizeRow(row) {
2020-04-22 14:55:12 -07:00
const normalizedRow = {};
2020-04-23 01:08:00 -07:00
for (let [key, value] of Object.entries(row)) {
key = key.replace(/_([a-z])/gi, (m) => m[1].toUpperCase());
if (key === "id" || key.endsWith("Id")) {
value = String(value);
}
normalizedRow[key] = value;
2020-04-22 14:55:12 -07:00
}
return normalizedRow;
}
2020-04-23 01:08:00 -07:00
module.exports = {
loadItems,
buildItemTranslationLoader,
buildPetTypeLoader,
buildSwfAssetLoader,
buildZoneLoader,
buildZoneTranslationLoader,
};