diff --git a/src/Item/Item.model.ts b/src/Item/Item.model.ts index 14989bff..9a069c3b 100644 --- a/src/Item/Item.model.ts +++ b/src/Item/Item.model.ts @@ -70,25 +70,38 @@ export class Item extends Model { // PAGINATED QUERIES - static findAllItemsByAddress( - thirdPartyIds: string[], + static findItemsByAddress( address: string, - limit: number = DEFAULT_LIMIT, - offset: number = 0 + thirdPartyIds: string[], + parmas: { + collectionId?: string + limit?: number + offset?: number + } ) { + const { collectionId, limit, offset } = parmas return this.query(SQL` SELECT items.*, count(*) OVER() AS total_count FROM ${raw(this.tableName)} items - JOIN ${raw( + LEFT JOIN ${raw( Collection.tableName )} collections ON collections.id = items.collection_id - WHERE - collections.third_party_id = ANY(${thirdPartyIds}) - OR - (items.eth_address = ${address} AND items.urn_suffix IS NULL) + WHERE + ( + collections.third_party_id = ANY(${thirdPartyIds}) + OR + (items.eth_address = ${address} AND items.urn_suffix IS NULL) + ) + ${ + collectionId + ? SQL`AND items.collection_id ${ + collectionId === 'null' ? SQL`is NULL` : SQL`= ${collectionId}` + }` + : SQL`` + } LIMIT ${limit} OFFSET ${offset} - `) + `) } static async findByCollectionIds( diff --git a/src/Item/Item.router.spec.ts b/src/Item/Item.router.spec.ts index 91351991..88803083 100644 --- a/src/Item/Item.router.spec.ts +++ b/src/Item/Item.router.spec.ts @@ -298,7 +298,7 @@ describe('Item router', () => { let allAddressItems: ItemAttributes[] beforeEach(() => { allAddressItems = [dbItem, dbItemNotPublished, dbTPItem] - ;(Item.findAllItemsByAddress as jest.Mock).mockResolvedValueOnce( + ;(Item.findItemsByAddress as jest.Mock).mockResolvedValueOnce( allAddressItems.map((item) => ({ ...item, total_count: allAddressItems.length, @@ -345,24 +345,28 @@ describe('Item router', () => { ], ok: true, }) - expect(Item.findAllItemsByAddress).toHaveBeenCalledWith( - [thirdPartyFragmentMock.id], + expect(Item.findItemsByAddress).toHaveBeenCalledWith( wallet.address, - undefined, - undefined + [thirdPartyFragmentMock.id], + { + page: undefined, + limit: undefined, + collecitonId: undefined, + } ) }) }) }) - describe('and pagination params are passed', () => { + describe('and pagination & collectionId params are passed', () => { let baseUrl: string let page: number let limit: number + let collectionId: string beforeEach(() => { - ;(page = 1), (limit = 1) + ;(page = 1), (limit = 1), (collectionId = 'null') baseUrl = `/${wallet.address}/items` - url = `${baseUrl}?limit=${limit}&page=${page}` + url = `${baseUrl}?limit=${limit}&page=${page}&collectionId=${collectionId}` }) it('should call the find method with the pagination params', () => { return server @@ -390,11 +394,14 @@ describe('Item router', () => { }, ok: true, }) - expect(Item.findAllItemsByAddress).toHaveBeenCalledWith( - [thirdPartyFragmentMock.id], + expect(Item.findItemsByAddress).toHaveBeenCalledWith( wallet.address, - limit, - page - 1 // it's the offset + [thirdPartyFragmentMock.id], + { + limit, + offset: page - 1, // it's the offset + collectionId, + } ) }) }) diff --git a/src/Item/Item.router.ts b/src/Item/Item.router.ts index e0e87924..491b2009 100644 --- a/src/Item/Item.router.ts +++ b/src/Item/Item.router.ts @@ -183,6 +183,10 @@ export class ItemRouter extends Router { ): Promise | FullItem[]> => { const { page, limit } = getPaginationParams(req) const eth_address = server.extractFromReq(req, 'address') + let collectionId: string | undefined + try { + collectionId = server.extractFromReq(req, 'collectionId') + } catch (error) {} const auth_address = req.auth.ethAddress if (eth_address !== auth_address) { @@ -194,11 +198,11 @@ export class ItemRouter extends Router { } const [allItemsWithCount, remoteItems, itemCurations] = await Promise.all([ - this.itemService.findAllItemsForAddress( - eth_address, + this.itemService.findItemsForAddress(eth_address, { + collectionId, limit, - page && limit ? getOffset(page, limit) : undefined - ), + offset: page && limit ? getOffset(page, limit) : undefined, + }), collectionAPI.fetchItemsByAuthorizedUser(eth_address), ItemCuration.find(), ]) @@ -207,12 +211,18 @@ export class ItemRouter extends Router { const allItems = allItemsWithCount.map((itemWithCount) => omit(itemWithCount, ['total_count']) ) + const dbBlockchainItemIds = allItems.map((item) => item.blockchain_item_id) const { items: dbItems, tpItems: dbTPItems } = this.itemService.splitItems( allItems ) const [items, tpItems] = await Promise.all([ - Bridge.consolidateItems(dbItems, remoteItems), + Bridge.consolidateItems( + dbItems, + remoteItems.filter((remoteItem) => + dbBlockchainItemIds.includes(remoteItem.blockchainId) + ) + ), Bridge.consolidateTPItems(dbTPItems, itemCurations), ]) diff --git a/src/Item/Item.service.ts b/src/Item/Item.service.ts index 2532eb70..11367764 100644 --- a/src/Item/Item.service.ts +++ b/src/Item/Item.service.ts @@ -163,10 +163,13 @@ export class ItemService { } } - public async findAllItemsForAddress( + public async findItemsForAddress( address: string, - limit?: number, - offset?: number + params: { + collectionId?: string + limit?: number + offset?: number + } ): Promise<(ItemAttributes & { total_count: number })[]> { const thirdParties = await thirdPartyAPI.fetchThirdPartiesByManager(address) if (thirdParties.length <= 0) { @@ -175,7 +178,7 @@ export class ItemService { const thirdPartyIds = thirdParties.map((thirdParty) => thirdParty.id) - return Item.findAllItemsByAddress(thirdPartyIds, address, limit, offset) + return Item.findItemsByAddress(address, thirdPartyIds, params) } /** diff --git a/src/ethereum/api/fragments.ts b/src/ethereum/api/fragments.ts index c8c89e69..dbeabe88 100644 --- a/src/ethereum/api/fragments.ts +++ b/src/ethereum/api/fragments.ts @@ -149,6 +149,7 @@ export type ItemFragment = { } export type CollectionFragment = { + /** Collection address */ id: string creator: string owner: string