import assert from 'assert'; import { union } from 'lodash'; import { AbstractRepository, EntityManager, EntityRepository, getCustomRepository, getManager, } from 'typeorm'; import { RawRetailerProduct } from '@/entities/RawRetailerProduct'; import { isValidRawRetailerData, RawRetailerDataV1, } from '@/entities/RawRetailerProduct/types'; import logger from '@/logger'; import { RetailerKind } from '@/types'; import { syncProductsToAlgolia } from '@/utils'; import { getRetailerKindFromUrl } from '@/utils/retailer'; import { RetailerProductVariantRepository } from '../RetailerProductVariantRepository'; import { getProductIdentifiersFromData, getVariantIdentifiersFromData, } from '../shared/identifiers'; import { getRetailerProductSourceFromRetailer } from './utils'; /** * Repository for the RawRetailerProduct entity. */ @EntityRepository(RawRetailerProduct) // eslint-disable-next-line max-len export default class RawRetailerProductRepository extends AbstractRepository { /** * Creates a raw product in the db and upserts a RetailerProduct based on the * data. */ async createFromData( { data, ingestionID, productIds, }: { data: RawRetailerDataV1; ingestionID?: string; productIds?: string[]; }, manager: EntityManager = getManager() ): Promise { assert(isValidRawRetailerData(data), 'Retailer data is invalid.'); const retailer = getRetailerKindFromUrl(data.url); const variantIdentifiers = getVariantIdentifiersFromData({ url: data.url, retailer, }); const productIdentifiers = getProductIdentifiersFromData({ url: data.url, retailer, }); if (!ingestionID && productIdentifiers.length === 0) { const errorMessage = 'Attempted to create Raw Retailer Product, but do not have sufficient unique identifiers'; logger.warn(errorMessage, { url: data.url, id: data.id, }); throw new Error(errorMessage); } const source = getRetailerProductSourceFromRetailer(retailer); const { aggregateProductId } = await getCustomRepository( RetailerProductVariantRepository ).upsert( { productIdentifiers: union([ ...productIdentifiers, ...(productIds ?? []), ]), variantIdentifiers: [ ...(ingestionID ? [`ingestionid:${ingestionID}`] : []), ...(retailer in RetailerKind ? variantIdentifiers : []), ], retailer, data, source, }, manager ); await syncProductsToAlgolia([aggregateProductId]); return manager.save( RawRetailerProduct, manager.create(RawRetailerProduct, { retailer, rawData: data, }) ); } }