diff --git a/package.json b/package.json index f90eec5d..c226ee2d 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,6 @@ }, "version": "3.1.3", "dependencies": { - "chalk": "^5.0.0" + "chalk": "^4.1.2 <5.0.0" } } diff --git a/src/__tests__/mocks.ts b/src/__tests__/mocks.ts index 4142ba48..5390a32e 100644 --- a/src/__tests__/mocks.ts +++ b/src/__tests__/mocks.ts @@ -1,4 +1,3 @@ -import { async } from 'rxjs'; import { Repository, FindManyOptions } from 'typeorm'; export class MockRepository extends Repository { @@ -14,17 +13,17 @@ export class MockRepository extends Repository { return [await this.find(options), await this.count(options)]; }; - find = async (options?: FindManyOptions): Promise => { + find = jest.fn(async (options?: FindManyOptions): Promise => { const startIndex = options.skip; const endIndex = startIndex + options.take; const localItems = this.items.slice(startIndex, endIndex); return localItems; - }; + }); - count = async (options?: FindManyOptions): Promise => { + count = jest.fn(async (options?: FindManyOptions): Promise => { return this.items.length; - }; + }); } export class Entity {} diff --git a/src/__tests__/paginate.repository.spec.ts b/src/__tests__/paginate.repository.spec.ts index 4602b1ee..032670ea 100644 --- a/src/__tests__/paginate.repository.spec.ts +++ b/src/__tests__/paginate.repository.spec.ts @@ -19,6 +19,43 @@ describe('Test paginate function', () => { expect(results).toBeInstanceOf(Pagination); }); + it('Calls to `find` & `count` should be correct (with explicit `where` clause)', async () => { + const mockRepository = new MockRepository(0); + const paginateOpts = { + limit: 8, + page: 2, + }; + const findCondition = { + where: {foo: 'bar'}, + orderBy: { + foo: 'ASC' + } + } + + paginate(mockRepository, {...paginateOpts}, findCondition); + + expect(mockRepository.find).toHaveBeenCalledTimes(1); + expect(mockRepository.find).toHaveBeenCalledWith(expect.objectContaining({skip: 8, take: 8, ...findCondition})); + expect(mockRepository.count).toHaveBeenCalledTimes(1); + expect(mockRepository.count).toHaveBeenCalledWith(expect.objectContaining(findCondition.where)); + }); + + it('Calls to `find` & `count` should be correct (with implicit `where` clause)', async () => { + const mockRepository = new MockRepository(0); + const paginateOpts = { + limit: 8, + page: 2, + }; + const findCondition = {foo: 'bar'}; + + paginate(mockRepository, {...paginateOpts}, findCondition); + + expect(mockRepository.find).toHaveBeenCalledTimes(1); + expect(mockRepository.find).toHaveBeenCalledWith(expect.objectContaining({skip: 8, take: 8, where: findCondition})); + expect(mockRepository.count).toHaveBeenCalledTimes(1); + expect(mockRepository.count).toHaveBeenCalledWith(expect.objectContaining(findCondition)); + }); + it('Item length should be correct', async () => { const mockRepository = new MockRepository(10); diff --git a/src/paginate.ts b/src/paginate.ts index cb293970..bb6281d3 100644 --- a/src/paginate.ts +++ b/src/paginate.ts @@ -1,9 +1,9 @@ import { Repository, - FindManyOptions, SelectQueryBuilder, ObjectLiteral, FindConditions, + FindOneOptions, } from 'typeorm'; import { Pagination } from './pagination'; import { @@ -19,7 +19,7 @@ const DEFAULT_PAGE = 1; export async function paginate( repository: Repository, options: IPaginationOptions, - searchOptions?: FindConditions | FindManyOptions, + searchOptions?: FindConditions | FindOneOptions, ): Promise>; export async function paginate( queryBuilder: SelectQueryBuilder, @@ -29,7 +29,7 @@ export async function paginate( export async function paginate( repositoryOrQueryBuilder: Repository | SelectQueryBuilder, options: IPaginationOptions, - searchOptions?: FindConditions | FindManyOptions, + searchOptions?: FindConditions | FindOneOptions, ) { return repositoryOrQueryBuilder instanceof Repository ? paginateRepository( @@ -150,10 +150,17 @@ function resolveNumericOption( return defaultValue; } +const normalizeSearchOptions = (searchOptions?: FindConditions | FindOneOptions): FindOneOptions => { + if(searchOptions && typeof searchOptions === 'object' && ('where' in searchOptions || 'order' in searchOptions)){ + return searchOptions; + } else { + return {where: searchOptions}; + } +} async function paginateRepository( repository: Repository, options: IPaginationOptions, - searchOptions?: FindConditions | FindManyOptions, + searchOptions?: FindConditions | FindOneOptions, ): Promise> { const [page, limit, route, paginationType, countQueries] = resolveOptions(options); @@ -170,19 +177,18 @@ async function paginateRepository( }); } + const normalizedOpts = normalizeSearchOptions(searchOptions); const promises: [Promise, Promise | undefined] = [ repository.find({ skip: limit * (page - 1), take: limit, - ...searchOptions, + ...normalizedOpts, }), undefined, ]; if (countQueries) { - promises[1] = repository.count({ - ...searchOptions, - }); + promises[1] = repository.count(normalizedOpts.where as any); } const [items, total] = await Promise.all(promises); diff --git a/yarn.lock b/yarn.lock index 9e9f95ec..7ed3bab8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1274,7 +1274,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, "chalk@^4.1.2 <5.0.0": version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1282,11 +1282,6 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.0.tgz#bd96c6bb8e02b96e08c0c3ee2a9d90e050c7b832" - integrity sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ== - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"