import { UserInputError } from 'apollo-server'; import { merge } from 'lodash'; import { Arg, Query, Resolver } from 'type-graphql'; import { getManager, IsNull, Not, Transaction, TransactionManager, } from 'typeorm'; import { PageRepository } from '@/repositories'; import { Page } from '../../entities'; import { connectionFromQuery } from '../shared/pagination/utils'; import { PageConnection, PageInput, PagesInput, PAGES_INPUT_DEFAULTS, } from './types'; import { convertOrderByGraphQLToTypeormOrder } from './utils'; @Resolver(Page) export class PageResolver { @Query(() => Page, { nullable: false }) async page( @Arg('input') input: PageInput ): Promise { if ((!input.id && !input.firebaseId) || (input.id && input.firebaseId)) { throw new UserInputError('Must provide either firebaseId or id'); } return Page.findOneOrFail({ where: { // NOTE: in this instance, because the user is requesting a specific // page by ID, we are ok with returning pages that are undiscoverable // discoverable: true, ...(input.id ? { id: input.id, } : {}), ...(input.firebaseId ? { firebaseId: input.firebaseId, } : {}), }, }); } @Query(() => PageConnection, { nullable: false }) @Transaction() async pages( @Arg('input', { nullable: true }) inputWithoutDefaults?: PagesInput, @Arg('first', { nullable: true }) first?: number, @Arg('last', { nullable: true }) last?: number, @Arg('before', { nullable: true }) before?: string, @Arg('after', { nullable: true }) after?: string, @TransactionManager() manager = getManager() ): Promise { const input = merge({}, PAGES_INPUT_DEFAULTS, inputWithoutDefaults); const { retailer, hasImage, availability, url } = input; const orderBy = convertOrderByGraphQLToTypeormOrder(input.orderBy, 'Page'); let query = manager .getRepository(Page) .createQueryBuilder('Page') .where({ source: IsNull(), ...(retailer ? { retailer } : {}), ...(availability !== undefined ? { availability } : {}), ...(hasImage !== undefined ? { img: Not(IsNull()) } : {}), }) .orderBy(orderBy); if (url) { const productFirebaseId = ( await manager.getCustomRepository(PageRepository).getByUrl(url) ).productFirebaseId; if (!productFirebaseId) { throw new UserInputError('No product found for given url.'); } query = query.andWhere({ productFirebaseId, discoverable: true }); } return connectionFromQuery( { first, last, before, after, }, query ); } }