import knex from './knex.js'; import redis from './redis.js'; import initLogger from './logger.js'; const logger = initLogger(); export function curateEntity(entity, context) { if (!entity) { return null; } return { id: entity.id, name: entity.name, slug: entity.slug, type: entity.type, url: entity.url, isIndependent: entity.independent, hasLogo: entity.has_logo, parent: curateEntity(entity.parent, context), children: context?.children?.filter((child) => child.parent_id === entity.id).map((child) => curateEntity({ ...child, parent: entity }, { parent: entity })) || [], ...context?.append?.[entity.id], }; } export async function fetchEntities(options) { const entities = await knex('entities') .modify((builder) => { if (options.type === 'primary') { builder .where('type', 'network') .orWhere('independent', true) .orWhereNull('parent_id'); return; } if (options.type) { builder.where('type', options.type); } }) .orderBy(...(options.order || ['name', 'asc'])) .limit(options.limit || 1000); return entities.map((entityEntry) => curateEntity(entityEntry)); } export async function fetchEntitiesById(entityIds, options = {}) { const [entities, children] = await Promise.all([ knex('entities') .select('entities.*', knex.raw('row_to_json(parents) as parent')) .whereIn('entities.id', entityIds) .leftJoin('entities as parents', 'parents.id', 'entities.parent_id') .modify((builder) => { if (options.order) { builder.orderBy(...options.order); } }) .groupBy('entities.id', 'parents.id'), options.includeChildren ? knex('entities') .whereIn('entities.parent_id', entityIds) .orderBy('slug') : [], ]); if (options.order) { return entities.map((entityEntry) => curateEntity(entityEntry, { append: options.append, children, })); } const curatedEntities = entityIds.map((entityId) => { const entity = entities.find((entityEntry) => entityEntry.id === entityId); if (!entity) { console.warn(`Can't match entity ${entityId}`); return null; } return curateEntity(entity, { append: options.append, children, }); }).filter(Boolean); return curatedEntities; } export async function getEntityIdsBySlug(slugs, domain) { const ids = await Promise.all(slugs.map(async (slug) => { if (!slug) { return null; } if (Number(slug)) { return Number(slug); // already an ID or missing } const id = await redis.hGet(`traxxx:${domain}:id_by_slug`, slug); return Number(id); })); return ids.filter(Boolean); } export async function cacheEntityIds() { const entities = await knex('entities').select('id', 'slug', 'type'); await redis.del('traxxx:entities:id_by_slug'); await redis.hSet('traxxx:entities:id_by_slug', entities.map((entity) => [entity.type === 'network' ? `_${entity.slug}` : entity.slug, entity.id])); logger.info('Cached entity IDs by slug'); }