A set of opinionated NestJS extensions and modules
- @nestjsx/common - A set of NestJs decorators, interfaces and configuration for application modules bootstraping.
npm run test
:page_with_curl: Pagination response object function + types for typeorm + nestjs
License: MIT License
A set of opinionated NestJS extensions and modules
npm run test
I want to sort the photo list by the name of the user which is related by userId. Right now, I could sort in only photo entity area, but sort by userId. How can I do that? Thanks
PhotoEntity = {
id: string,
photoName: string,
url: string,
userId: string
}
UserEntity = {
id: string,
name: string
}
const { page = 1, limit = 10 } = filters;
return paginate<Photo>( this.photoRepository,
{ page, limit },
{ order: { 'user.name': "DESC" }},
);
Looks like a 1.0.3 version on npmjs.com and yarnpkg.com contains files from the 1.0.1 version.
Is there a way to omit links object?
Thank you for a great library for pagination. However, I think I found some issues.
I am not sure if I understood why page 0 and page 1 are interchangeable.
In paginate.ts
function resolveOptions(options: IPaginationOptions): [number, number, string] {
const page =
options.page > 0 ? options.page - 1 : options.page < 0 ? 0 : options.page;
const limit = options.limit;
const route = options.route;
return [page, limit, route];
}
page 1 and page 0 both returns 0. Is that supposed to be correct?
This breaks the behavior of next as well.
function createPaginationObject<T>(
items: T[],
total: number,
page: number,
limit: number,
route?: string
) {
const isNext = route && total / limit >= page + 1;
const isPrevious = route && page > 0;
const routes = {
next: isNext ? `${route}?page=${page + 2}&limit=${limit}` : "",
previous: isPrevious ? `${route}?page=${page}&limit=${limit}` : ""
};
return new Pagination(
items,
items.length,
total,
Math.ceil(total / limit),
routes.next,
routes.previous
);
}
Let us say we have total 5 elements and limit to be 1.
At page 5, we would expect the next be blank because there is no next element.
However, since page becomes 4 due to resolveOptions
this will make next
with page=6&limit=1
.
I got an error invoice.total must be in the group by clause
invoice.service.ts
findSumPayment(option: PaginationOP) {
const queryBuilder = this.invoiceRepository
.createQueryBuilder('invoice')
.select([
'invoice.invoice_id AS invoice_id',
'invoice.total AS total',
'COAlESCE(SUM(payment.amount),0)::FLOAT AS paid',
'invoice.total - COAlESCE(SUM(payment.amount),0)::FLOAT AS due',
'invoice.invoice_date AS invoice_date',
])
.leftJoin('invoice.payment', 'payment')
.groupBy('invoice.invoice_id')
.orderBy('invoice.invoice_id', 'DESC');
#- without if statement paginationRaw work fine if I using if-statement will got an error with paginationRaw
if (option.enum === '=') {
queryBuilder.having(
`invoice.total - COAlESCE(SUM(payment.amount),0)::FLOAT = 0`
);
}
if (option.enum === '>') {
queryBuilder.having(
`invoice.total - COAlESCE(SUM(payment.amount),0)::FLOAT > 0`
);
}
#-returnwith paginationRaw **Error GROUP BY invoice.total**
return from(paginateRaw(queryBuilder, option));
#-return without paginationRaw **WORK FINE**
return from(queryBuilder.getRawMany());
}
Error Message when using return with paginationRaw
column "invoice.total" must appear in the GROUP BY clause or be used in an aggregate function
inside the function above when I use
InvoiceEntity
@Entity({ name: 'invoice' })
export class InvoiceEntity extends ShareEntity {
@PrimaryGeneratedColumn()
invoice_id: number;
@Column({ nullable: true, default: 0 })
total: number;
@Column({ type: 'date', default: () => 'NOW()' })
invoice_date: Date;
@OneToMany(() => OrderEntity, (entity) => entity.invoice)
order: OrderEntity;
@OneToMany(() => PaymentEntity, (entity) => entity.invoice)
payment: PaymentEntity;
@ManyToOne(() => CustomerEntity, (entity) => entity.invoice)
@JoinColumn({ name: 'customer_id', referencedColumnName: 'customer_id' })
customer: CustomerEntity;
@Column()
customer_id: number;
@OneToOne(() => DeliveryEntity, (entity) => entity.invoice)
delivery: DeliveryEntity;
}
PaymentEntity
@Entity({ name: 'payments' })
export class PaymentEntity extends ShareEntity {
@PrimaryGeneratedColumn()
payment_id: number;
@Column({ default: 0, nullable: true })
receive: number;
@Column()
amount: number;
@Column({ type: 'enum', enum: Money, default: Money.USD })
money: Money;
@Column({ default: 0, nullable: true })
payback: number;
@Column({ type: 'date', default: () => 'NOW()' })
payment_date: Date;
@ManyToOne(() => InvoiceEntity, (entity) => entity.payment)
@JoinColumn({ name: 'invoice_id', referencedColumnName: 'invoice_id' })
invoice: InvoiceEntity;
@Column()
invoice_id: number;
}
os: Mac BigSur
package.json
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.1",
"@nestjs/common": "^7.5.1",
"@nestjs/config": "^0.6.1",
"@nestjs/core": "^7.5.1",
"@nestjs/jwt": "^7.2.0",
"@nestjs/microservices": "^7.6.5",
"@nestjs/passport": "^7.1.5",
"@nestjs/platform-express": "^7.5.1",
"@nestjs/platform-fastify": "^7.5.5",
"@nestjs/platform-socket.io": "^7.6.15",
"@nestjs/terminus": "^7.1.2",
"@nestjs/typeorm": "^7.1.5",
"@nestjs/websockets": "^7.6.15",
"@types/compression": "^1.7.0",
"@types/passport-jwt": "^3.0.3",
"argon2": "^0.27.1",
"cache-manager": "^3.4.0",
"chalk": "^4.1.0",
"class-transformer": "^0.4.0",
"class-validator": "^0.12.2",
"date-fns": "^2.17.0",
"dotenv": "^8.2.0",
"env-cmd": "^10.1.0",
"fastify-compress": "^3.4.2",
"fastify-helmet": "^5.3.0",
"fastify-multer": "^2.0.2",
"fastify-multipart": "^4.0.3",
"fastify-static": "^4.0.1",
"fastify-swagger": "^4.4.1",
"graphql": "^15.5.0",
"nestjs-config": "^1.4.7",
"nestjs-typeorm-paginate": "2.2.6",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.6.3",
"socket.io-redis": "^6.1.0",
"typeorm": "^0.2.31",
"webpack": "^4.0.0"
},
"devDependencies": {
"@nestjs/cli": "^7.5.1",
"@nestjs/schematics": "^7.1.3",
"@nestjs/swagger": "^4.7.5",
"@nestjs/testing": "^7.5.1",
"@types/bcrypt": "^3.0.0",
"@types/busboy": "^0.2.3",
"@types/cache-manager": "^2.10.3",
"@types/express": "^4.17.8",
"@types/jest": "^26.0.15",
"@types/node": "^14.14.6",
"@types/passport-local": "^1.0.33",
"@types/socket.io": "^2.1.13",
"@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.6.1",
"eslint": "^7.12.1",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-nestjs": "^1.2.3",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^26.6.3",
"prettier": "^2.1.2",
"supertest": "^6.0.0",
"ts-jest": "^26.4.3",
"ts-loader": "^8.0.8",
"ts-node": "^9.0.0",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.0.5"
},
error in paginateRaw
const totalQueryBudiler=queryBuilder.clone() and use in Promise.all([queryBuilder.page(page-1).offset(limit),totalQueryBuilder.getCount)]
so error from totalQueryBuilder.getCount()
Hi
I'm trying to paginate a list of objects and also use some search options.
return paginate<MyEntity>(this.myEntityRepository, paginationOptions, params)
"params" is:
{ name: FindOperator { _type: 'like', _value: '%test%', _useParameter: true, _multipleParameters: false } }
"paginationOptions" is: { page: '1', limit: '10' }
The problem is that instead of returning only the elements that contain "test" in their name, it returns the whole list.
I also tried with params being {name: "test"}
, without the LIKE operator. Same result unfortunately...
Please update documentation for controller
@Get('')
async index(
@Query('page') page: number = 1,
@Query('limit') limit: number = 10,
): Pagination<CatEntity> { //The return type of an async function or method must be the global Promise<T> type.
limit = limit > 100 ? 100 : limit;
return this.catService.paginate({
page,
limit,
route: 'http://cats.com/cats',
});
}
to
Promise<Pagination<CatEntity>>
found bellow error when update 2.1.0 with no modified
` error TS2305: Module '"../../node_modules/nestjs-typeorm-paginate"' has no exported member 'paginate'.
5 import { paginate, IPaginationOptions} from 'nestjs-typeorm-paginate';
~~~~~~~~
error TS2305: Module '"../../node_modules/nestjs-typeorm-paginate"' has no exported member 'IPaginationOptions'.
5 import { paginate, IPaginationOptions} from 'nestjs-typeorm-paginate';`
Add the ability to use offset and limit instead of take and skip.
Please add the ability to change the selection of skip to offset and take to limit methods to the library.
Reason when there are a large number of records in the table (several million), distinct spoils the query.
Hello!
I'm trying to get some data from database and pass into paginate as follows:
const user = req.user;
const walletIds = await Wallet.find({
select: ['id'],
where: { userId: user.id },
});
const queryBuilder = await getConnection().createQueryBuilder();
queryBuilder.select(
'DATE_FORMAT(operations.date, "%Y-%m-%d") as date,' +
'SUM(operations.numberOfContracts) as numberOfContracts, SUM(operations.value) as value,' +
'(select name from wallets where wallets.id = operations.walletId) as walletName,' +
'(select ifnull(rates.bmf,0) from rates where rates.walletId = operations.walletId and DATE_FORMAT(date, "%Y-%m-%d") = DATE_FORMAT(operations.date, "%Y-%m-%d") limit 1) as bmf,' +
'(select ifnull(rates.brokerage,0) from rates where rates.walletId = operations.walletId and DATE_FORMAT(date, "%Y-%m-%d") = DATE_FORMAT(operations.date, "%Y-%m-%d") limit 1) as brokerage,' +
'(select ifnull(rates.emolument,0) from rates where rates.walletId = operations.walletId and DATE_FORMAT(date, "%Y-%m-%d") = DATE_FORMAT(operations.date, "%Y-%m-%d") limit 1) as emolument,' +
'(select ifnull(rates.irrf,0) from rates where rates.walletId = operations.walletId and DATE_FORMAT(date, "%Y-%m-%d") = DATE_FORMAT(operations.date, "%Y-%m-%d") limit 1) as irrf,' +
'(select ifnull(rates.otherCosts,0) from rates where rates.walletId = operations.walletId and DATE_FORMAT(date, "%Y-%m-%d") = DATE_FORMAT(operations.date, "%Y-%m-%d") limit 1) as otherCosts',
);
queryBuilder.from('operations', 'operations');
queryBuilder.where('operations.walletId IN (:...ids)', {
ids: walletIds.map(w => w.id),
});
queryBuilder.groupBy('date,operations.walletId');
console.log(await queryBuilder.execute());
return paginate<any>(queryBuilder, {
page,
limit,
});
If I do await queryBuilder.execute() I can see some data but paginate result is empty.
{
"items": [],
"meta": {
"totalItems": 74,
"itemCount": 0,
"itemsPerPage": 10,
"totalPages": 8,
"currentPage": 1
},
"links": {
"first": "",
"previous": "",
"next": "",
"last": ""
}
}
See that it counts in totalItems but items is empty.
Any help?
EDIT:
Using queryBuilder.execute() or "queryBuilder.getRawMany()" will return data but queryBuilder.getManyAndCount() will not.
Add the ? on the route if the base route in options does not contain the ?
nestjs-typeorm-paginate/src/paginate.ts
Line 47 in 021ffa1
let routes: IPaginationLinks;
if (route.include('?')) {
routes = {
first: hasFirstPage ? `${route}&limit=${limit}` : "",
previous: hasPreviousPage ? `${route}&page=${currentPage - 1}&limit=${limit}` : "",
next: hasNextPage ? `${route}&page=${currentPage + 1}&limit=${limit}` : "",
last: hasLastPage ? `${route}&page=${totalPages}&limit=${limit}` : ""
};
} else {
routes = {
first: hasFirstPage ? `${route}?limit=${limit}` : "",
previous: hasPreviousPage ? `${route}?page=${currentPage - 1}&limit=${limit}` : "",
next: hasNextPage ? `${route}?page=${currentPage + 1}&limit=${limit}` : "",
last: hasLastPage ? `${route}?page=${totalPages}&limit=${limit}` : ""
};
}
or
const quote = route.include('?') ? '&' : '?';
const routes = {
first: hasFirstPage ? `${route}${quote}limit=${limit}` : "",
previous: hasPreviousPage ? `${route}${quote}page=${currentPage - 1}&limit=${limit}` : "",
next: hasNextPage ? `${route}${quote}page=${currentPage + 1}&limit=${limit}` : "",
last: hasLastPage ? `${route}${quote}page=${totalPages}&limit=${limit}` : ""
};
For now the package only supports query builder usage for entity query buiders
async function paginateQueryBuilder<T>(
queryBuilder: SelectQueryBuilder<T>,
options: IPaginationOptions,
): Promise<Pagination<T>> {
const [page, limit, route] = resolveOptions(options);
const [items, total] = await queryBuilder
.take(limit)
.skip((page - 1) * limit)
.getManyAndCount();
return createPaginationObject<T>(items, total, page, limit, route);
}
We can discuss an way to use raw queries using something like:
qb.limit(limit)
.offset((page - 1) * limit)
.getRawMany();
3d8fcbe#diff-2433a58dd5b382f3ef0faf44d5ab97bf79428a0a1452d72934c9ca3c77a237bcR1 introduced new CustomMetaType
generic on IPaginationOptions
to support new optional metaTransformer
method, but appears to be required whether that method is used or not. Ideally could be updated to make the generic type optional as well, defaulting to whatever interface should be used when metaTransformer
is not defined.
Readme is unclear on how to use this, still reference old format without the provided generic type https://github.com/nestjsx/nestjs-typeorm-paginate/blame/2d108b00942b1ca4ecfcb4947e3232ddf305d704/README.md#L46
Automatically generate urls without manual pass route option is necessary,Has any solution for it current?
When paginating we are given a url to next page, that is pretty good. However if you hit the last page, you are still given the url for next page which upon visiting shows empty data.
itemCount | 2
totalItems | 4
pageCount | 2
next | "http://localhost:8000/v1/user?page=3&limit=2"
previous | "http://localhost:8000/v1/user?page=1&limit=2"
As you can see in the above output, I have 4 data and is using limit to 2, so logically i should only have 2 pages. But if i visit the last page, i am still given a link to 3rd page
Hello all!
When making queries grouping items, the TypeORM getCount
method used to count items on table apparently consider all items matching with where
conditions only, ignoring grouping, example:
const now = new Date();
const start = startOfMonth(now).toISOString();
const end = endOfMonth(now).toISOString();
const queryBuilder = this.exampleRepository
.createQueryBuilder()
.select('name as customer, round(sum(total)::numeric, 2)::float as total')
.groupBy('name')
.where(`usage between '${start}' and '${end}'`)
.orderBy('total', 'DESC');
return paginateRaw<T>(queryBuilder, paginationOptions);
This example fetch, for example, 7 items grouped by name and their total usage from 500 registers on database, instead of returning 7, count
returns 500.
To work around the problem I did this:
async function countItemsForComplexQueryBuilder(
queryBuilder: SelectQueryBuilder<any>,
) {
const query = queryBuilder.getQuery();
const connection = getConnection();
const { count } = await connection
.createQueryBuilder()
.select('count(t.*)', 'count')
.from(`(${query})`, 't')
.getRawOne<{ count: string }>();
return Number(count);
}
And used return of this function in counter
key.
it might be interesting to add some option in the library to count the items following the idea as above. The idea is pertinent to add to the codebase?
Congrats for the project
When I run the yarn run build command๏ผ
node_modules/nestjs-typeorm-paginate/dist/paginate.d.ts:1:22 - error TS2305: Module '"/node_modules/typeorm"' has no exported member 'FindConditions'.
1 import { Repository, FindConditions, FindManyOptions, SelectQueryBuilder } from "typeorm";
~~~~~~~~~~~~~~
node_modules/nestjs-typeorm-paginate/dist/paginate.d.ts:1:38 - error TS2305: Module '"node_modules/typeorm"' has no exported member 'FindManyOptions'.
1 import { Repository, FindConditions, FindManyOptions, SelectQueryBuilder } from "typeorm";
~~~~~~~~~~~~~~~
Found 2 errors.
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The pagination returns wrong totalItems, pageCount, next, previous page links even when coupled with a where clause.
When there are 4 rows in my table for user 1, and user 2
return await paginate<PayoutsEntity>(this.repo, options, {
user_id: 2,
});
This should return totalItems: 2
, pageCount: 2
, next: /payments?page=1&limit=1
, previous: ''
...but this is what i'm getting.
Extra optional parameters are not taken into account while the total pages are calculated? Why are total items showing 4 for user_id = 2
when it should be 2
instead.
//this not filtering, returning all rows
async paginate(
options: IPaginationOptions,
user: User,
): Promise<Pagination<Car>> {
const aux = await paginate<Car>(this.carRepository, options, { user });
return aux;
}
//this works
async find(user: User) {
return await this.carRepository.findAndCount({ where: { user } });
}
am i using find options param correctly? Or is it a bug?
great lib btw :)
Add variable limit to response.
Example:
{ "items": [ { "id": "8be4d71a-e76e-4ef1-8230-2c90e47f1eb1", "rol": "Gerencia", "createdAt": "2019-05-25T17:36:10.916Z", "updatedAt": "2019-05-25T17:56:38.152Z", "version": 4 }, { "id": "7e60ed59-0e8d-47ef-a863-5c0849107d25", "rol": "Administrador", "createdAt": "2019-05-25T23:39:31.811Z", "updatedAt": "2019-05-25T23:39:31.811Z", "version": 1 }, { "id": "542d7e39-b979-44ea-8e2c-04ff9e7d0228", "rol": "Administrador1", "createdAt": "2019-05-25T23:47:41.764Z", "updatedAt": "2019-05-25T23:47:41.764Z", "version": 1 } ], "itemCount": 3, "totalItems": 8, "pageCount": 3, "next": "http://localhost:3000/api/v1/admin/roles?limit=3?page=2&limit=3", "previous": "" }
I have a query where I need to add a custom column using addSelect .addSelect('membership.commissionPercentage', 'commissionPercentage')
and return paginated data but it does not work.
If I query result with queryBuilder.getRawMany()
I get commissionPercentage but not with
return paginate<User>(queryBuilder, {
page: query.queryOptions.page,
limit: query.queryOptions.limit,
route: query.queryOptions.route
});
const page = 1;
const limit = 25;
const pocConnection = getConnection('default');
const result = pocConnection.getRepository(Candidates).createQueryBuilder('candidate')
.leftJoinAndSelect('candidate.interviewSlots', 'interviewSlots')
.where('candidate.currentRound > :currentRound', {currentRound: 2})
.orderBy({
'candidate.createdAt': 'DESC',
'interviewSlots.createdAt': 'DESC'
})
const candidates = await paginate<Candidates>(result, {
page,
limit,
});
return candidates;
The following code returns 5 items, if I remove 'interviewSlots.createdAt': 'DESC' from orderBy it works fine
Hi. I've been using this lib in hobby project and faced the wrong page counting situation.
Total Items = 11;
Default limit = 10;
So there are supposed to be two page ( 0, 1) but there is only one.
I can probably try to fix it :p
Also I have a question, pagination should work something like:
71 items means we have 8 pages, where 8th page return array of single element.
Now it returns last 10 last items;
Hello
As we all know offset and limit based pagination have performance issue in large amount of data.
I think the best solution is Cursor-based pagination.
Do you have any plane to implement this type of pagination?
PaginateRaw
(and PaginateRawAndEntities) use .limit()
and .offset()
instead of .take()
and .skip()
, which cause some issues when using joins. Is there any particular reason why PaginateRaw uses limit/offset over take/skip?
Hi guys, will there be any way to paginate a model and bring the eager relationship?
Hello!
I'm trying to make an aggregate query and I'm having this error.
ER_BAD_FIELD_ERROR: Unknown column 'distinctAlias.operations_id' in 'field list'
Of course that operations.id doesn't exists because I'm not selecting it.
Check my query:
const queryBuilder = await Operation.createQueryBuilder('operations');
queryBuilder.select(
'DATE_FORMAT(operations.date, "%Y-%m-%d") as date,' +
'SUM(operations.numberOfContracts) as numberOfContracts, SUM(operations.value) as value,' +
'wallets.name as walletName, ifnull(SUM(rates.bmf),0) as bmf, ifnull(SUM(rates.brokerage),0) as brokerage,' +
'ifnull(SUM(rates.emolument),0) as emolument, ifnull(SUM(rates.irrf),0) as irrf, ifnull(SUM(rates.otherCosts),0) as otherCosts',
);
queryBuilder.innerJoin('operations.wallet', 'wallet');
queryBuilder.leftJoin('wallet.rates', 'rates');
queryBuilder.where('wallet.userId = :userId', { userId: user.id });
queryBuilder.groupBy('date, operations.walletId');
If I add operations.id as operations_id to the select, then I got this:
QueryFailedError: ER_WRONG_FIELD_WITH_GROUP: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'database.operations.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
The last error will desapear if I add operations.id to the group by... but, the returned list will be empty.
I don't know what I'm doing wrong, I'm not a sql expert.
Could you help me? thank you!
Dependabot couldn't authenticate with registry.npmjs.org.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
I just tried to update my version from 1.0.3
to 2.0.2
and I realized the project was failing. I tried with 2.0.1
and also with 2.0.0
and the result is the same: there is no dist
folder inside the node_modules/nestjs-typeorm-paginate
folder.
I wanted to ugrade to version 2.x as I'm experiencing the same problem described here: #258.
const filterOption = {
relations: ['someRelation'], // works well
where: {}, //works well
orderBy:{ created_at: 'desc'} //not working
};
return paginate(this.repo, options, filterOption);
am not sure is orderBy can use with this searchOptions ?
Please update dependency to NestJS 7.
I got a warning of wrong version when use with the new version of NestJS.
Regards.
Hello ,
i have 3 items and i want every page to have 1 item but as u can see the next link has page 21 which should be 2
i noticed that when it passed nestjs Query decorator turns to string again even though we typed it as number
@Query('limit') limit: number = 10
console.log(typeof limit) // string
I noticed that the source code of the version which is installed via npm is not the one in this repo. Both package.json state that it's version 1.0.0.
But in the one installed via npm the offset is set: queryBuilder.offset(page) and not .offset(page * limit).
Can you update that? Thanks!
Is it possible to give meta keys underscore separator to be more consistent with the rest of our API responses?
Example:
"meta": {
"item_count": 10,
"total_items": 20,
"items_per_page": 10,
"total_pages": 5,
"current_page": 2
}
I just upgraded to 2.0.3 and got a run time error when using paginate.
[Nest] 13668 - 04/14/2020, 11:21:00 AM [ExceptionsHandler] OFFSET must not be negative +79860ms
QueryFailedError: OFFSET must not be negative
at new QueryFailedError (C:\Users\Jeremy\Desktop\zl\im\active_repo\should\im\src\error\QueryFailedError.ts:9:9)
at Query.<anonymous> (C:\Users\Jeremy\Desktop\zl\im\active_repo\should\im\src\driver\postgres\PostgresQueryRunner.ts:178:30)
at Query.handleError (C:\Users\Jeremy\Desktop\zl\im\active_repo\should\im\node_modules\pg\lib\query.js:138:19)
at Connection.connectedErrorMessageHandler (C:\Users\Jeremy\Desktop\zl\im\active_repo\should\im\node_modules\pg\lib\client.js:223:17)
at Connection.emit (events.js:315:20)
at Socket.<anonymous> (C:\Users\Jeremy\Desktop\zl\im\active_repo\should\im\node_modules\pg\lib\connection.js:120:12)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:297:12)
at readableAddChunk (_stream_readable.js:273:9)
at Socket.Readable.push (_stream_readable.js:214:10)
Here is the only code I am running
// options = { page: 0, limit: 10 }
const queryBuilder = this.posRepo.createQueryBuilder('position').where(`position.listed = true`);
return await paginate<Position>(queryBuilder, options); // <- Error happens here
Was there a breaking change I am unaware of?
I tried my code on version 1.0.3 and verified I am not getting an error.
If the SelectQueryBuilder object passed into paginate has joins, the method does not work as expected. Perhaps .limit(limit)
should be replaced with .take(limit)
here?
Based off the note from typeorm/src/query-builder/SelectQueryBuilder.ts
The meta
object item should be configurable to allow API with other naming cases (especially snake_case) to use pagination and maintain consistency with the rest of their strategy.
Allow a configuration of paginate to return the meta
object with snake casing:
"meta": {
"item_count": 10,
"total_items": 20,
"items_per_page": 10,
"total_pages": 5,
"current_page": 2
},
The current behavior can be maintain using default config values
note: only meta
is relevant, since there are no multi word keys in the other return objects
I think it would be a good idea (albeit a breaking change) that responses follow the same naming convention as the ones returned by nestjs/crud. We use both in the same project and we had to rely on using an interceptor to have consistent responses.
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { GetManyDefaultResponse } from '@nestjsx/crud';
import { Pagination } from 'nestjs-typeorm-paginate';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class PaginateTransformInterceptor<T>
implements NestInterceptor<Pagination<T>, GetManyDefaultResponse<T>> {
intercept(
context: ExecutionContext,
next: CallHandler<Pagination<T>>,
): Observable<GetManyDefaultResponse<T>> {
return next.handle().pipe(
map(data => ({
count: data.itemCount,
data: data.items,
pageCount: data.itemCount,
page: data.pageCount,
total: data.totalItems,
})),
);
}
}
Please see - #6
That issue needs to be reopened.
Hello
{
"items": [
...
],
"meta": {
"totalItems": 22,
"itemCount": 9,
"itemsPerPage": "10",
"totalPages": 3,
"currentPage": "1"
}
}
I get an outcome like this. I guessed itemCount should same with itemsPerPage.
Here is my service code.
async findPaginatedBundles(
options: IPaginationOptions,
): Promise<Pagination<Bundle>> {
const queryBuilder = this.bundleRepository.createQueryBuilder('bundle');
await queryBuilder
.leftJoinAndSelect('bundle.articles', 'article')
.orderBy({ 'bundle.id': 'DESC' })
.addOrderBy('article.id')
.getMany();
return await paginate<Bundle>(queryBuilder, options);
}
And I found it does work when I use repository.
like
return await paginate<Bundle>(this.bundleRepository, options, {
relations: ['articles'],
where: { delete_date: null },
order: {
id: 'DESC',
// I need articles should be ordered by asc
},
});
However since typeorm doesn't support ordering relations loaded with find's "relations" option, using paginate method with queryBuilder is only way I can choose.
Is there anyone can help with this problem?
Hi, thanks for the good work !
I use this module in several pages but i can't find a way to properly mock the paginate method with jest
I've tried many ways, the nearest i think is that one :
const result = []
jest.mock('nestjs-typeorm-paginate', () => {
return jest.fn().mockImplementation(() => {
return {paginate: <T>(repo, options) => result};
});
});
but my mock is ignored,
Could you please tell me the best way to mock that ?
Thanks !
Is there any way to use this with GraphQL?
Currently, i am not able to select the correct Query Return Object
In the README the default value for page
is specified as 0. So I thought pages were counted from 0 onward. However when using 0 and 1 as page number I get the same result (in fact any value for page less than 1 seems to return the first page). Its actually when I use page 2 that I get the next page.
Just wondering if this is intended and what is the behavior for page 0.
I just tried the package. It looks very good.
But unfortunately, i just tested it and in the routes links, the "first" is not correct.
"first": "/client/paginated?limit=3",
The page parameter is missing.
Here is the received result a little more expanded.
"meta": {
"totalItems": 8,
"itemCount": 3,
"itemsPerPage": 3,
"totalPages": 3,
"currentPage": 2
},
"links": {
"first": "/client/paginated?limit=3",
"previous": "/client/paginated?page=1&limit=3",
"next": "/client/paginated?page=3&limit=3",
"last": "/client/paginated?page=3&limit=3"
}
I basically copy pasted the example of the readme file in a new nestjs project to test the package.
Here is the code that i used to try the package: sample-nestjs-typeorm-paginate
Hello i have following code
async paginate(options: IPaginationOptions): Promise<Pagination<MongoRepository<User>>> {
// return paginate<User>(this.usersRepository, options);
return paginate<MongoRepository<User>>(this.usersRepository, {});
}
But I'm not able to use with mongo Repository this is what i get:
Argument of type 'MongoRepository' is not assignable to parameter of type 'Repository<MongoRepository>' how to fix the part with Repository
Instead of paginating via page, use entity id instead to get the next 10 of object id
return paginate<ProductEntity>(this.repostiory, options, {
where: [
{
title: Like(`%${search}%`),
},
{
description: Like(`%${search}%`),
},
{
price: Like(`%${search}%`),
},
],
});
This is the syntax to use to run a search on more than one field.
Error Received:
QueryFailedError: operator does not exist: numeric ~~ unknown
at new QueryFailedError (/node_modules/typeorm/error/QueryFailedError.js:11:28)
at Query.callback (/node_modules/typeorm/driver/postgres/PostgresQueryRunner.js:176:38)
at Query.handleError (/node_modules/pg/lib/query.js:145:17)
at Connection.connectedErrorMessageHandler (/node_modules/pg/lib/client.js:214:17)
at Connection.emit (events.js:315:20)
at Socket.<anonymous> (/node_modules/pg/lib/connection.js:134:12)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:295:12)
at readableAddChunk (_stream_readable.js:271:9)
at Socket.Readable.push (_stream_readable.js:212:10)
Hi. I want to request feature to paginate arrays of entities that already somehow were extracted from database.
I see this something like this:
import { paginateArray, Pagination, IPaginationOptions } from 'nestjs-typeorm-paginate';
//
//
const usersArray : Array<User> = [{id: 1. name: "first}, ...];
return paginateArray<Users>(usersArray, options);
This would be useful if there are some data that needs to be modified somehow, before being paginatied.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.