'use strict'; const knex = require('./knex'); function curateRelease(release, withMedia = false) { if (!release) { return null; } return { id: release.id, entryId: release.entry_id, shootId: release.shoot_id, title: release.title, url: release.url, date: release.date, description: release.description, duration: release.duration, entity: release.entity && { id: release.entity.id, name: release.entity.name, slug: release.entity.slug, parent: release.entity.parent && { id: release.entity.parent.id, name: release.entity.parent.name, slug: release.entity.parent.slug, }, }, actors: (release.actors || []).map(actor => ({ id: actor.id, name: actor.name, slug: actor.slug, gender: actor.gender, entityId: actor.entity_id, aliasFor: actor.alias_for, })), tags: (release.tags || []).map(tag => ({ id: tag.id, name: tag.name, slug: tag.slug, })), ...(withMedia && { poster: release.poster ? { id: release.poster.id, path: release.poster.path, width: release.poster.width, height: release.poster.height, size: release.poster.size, source: release.poster.source, } : null, photos: (release.photos || []).map(photo => ({ id: photo.id, path: photo.path, width: photo.width, height: photo.height, size: photo.size, source: photo.source, })), }), createdAt: release.created_at, }; } function withRelations(queryBuilder, withMedia = false) { queryBuilder .select(knex.raw(` releases.id, releases.entry_id, releases.shoot_id, releases.title, releases.url, releases.date, releases.description, releases.duration, releases.created_at, row_to_json(entities) as entity, row_to_json(parents) as parent, COALESCE(json_agg(DISTINCT actors) FILTER (WHERE actors.id IS NOT NULL), '[]') as actors, COALESCE(json_agg(DISTINCT tags) FILTER (WHERE tags.id IS NOT NULL), '[]') as tags `)) .leftJoin('entities', 'entities.id', 'releases.entity_id') .leftJoin('entities as parents', 'parents.id', 'entities.parent_id') .leftJoin('releases_actors', 'releases_actors.release_id', 'releases.id') .leftJoin('actors', 'actors.id', 'releases_actors.actor_id') .leftJoin('releases_tags', 'releases_tags.release_id', 'releases.id') .leftJoin('tags', 'tags.id', 'releases_tags.tag_id') .groupBy(knex.raw(` releases.id, releases.entry_id, releases.shoot_id, releases.title, releases.url, releases.date, releases.description, releases.duration, releases.created_at, entities.id, parents.id `)); if (withMedia) { queryBuilder .select(knex.raw(` row_to_json(posters) as poster, COALESCE(json_agg(DISTINCT photos) FILTER (WHERE photos.id IS NOT NULL), '[]') as photos `)) .leftJoin('releases_posters', 'releases_posters.release_id', 'releases.id') .leftJoin('media as posters', 'posters.id', 'releases_posters.media_id') .leftJoin('releases_photos', 'releases_photos.release_id', 'releases.id') .leftJoin('media as photos', 'photos.id', 'releases_photos.media_id') .groupBy('posters.id'); } } async function fetchRelease(releaseId) { const release = await knex('releases') .where('releases.id', releaseId) .modify(withRelations, true) .first(); return curateRelease(release, true); } async function fetchReleases(limit = 100) { const releases = await knex('releases') .modify(withRelations, false) .limit(Math.min(limit, 1000)); return releases.map(release => curateRelease(release)); } async function searchReleases(query, limit = 100) { const releases = await knex .from(knex.raw('search_releases(?) as releases', [query])) .modify(withRelations, false) .limit(Math.min(limit, 1000)); return releases.map(release => curateRelease(release)); } module.exports = { fetchRelease, fetchReleases, searchReleases, };