nestjs-paginate 12.10.1 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -7
- package/lib/__tests__/cat-home-pillow.entity.d.ts +1 -0
- package/lib/__tests__/cat-home-pillow.entity.js +4 -0
- package/lib/__tests__/cat-home-pillow.entity.js.map +1 -1
- package/lib/filter.d.ts +39 -3
- package/lib/filter.js +305 -60
- package/lib/filter.js.map +1 -1
- package/lib/helper.d.ts +21 -2
- package/lib/helper.js +72 -4
- package/lib/helper.js.map +1 -1
- package/lib/paginate.d.ts +3 -3
- package/lib/paginate.js +18 -14
- package/lib/paginate.js.map +1 -1
- package/lib/paginate.spec.js +299 -11
- package/lib/paginate.spec.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -516,6 +516,48 @@ const config: PaginateConfig<CatEntity> = {
|
|
|
516
516
|
const result = await paginate<CatEntity>(query, catRepo, config)
|
|
517
517
|
```
|
|
518
518
|
|
|
519
|
+
## Usage with to-many relationships
|
|
520
|
+
|
|
521
|
+
You can filter parents by conditions on their to-many relations (one-to-many or many-to-many) using quantifiers.
|
|
522
|
+
Quantifiers define how many related rows must satisfy the condition:
|
|
523
|
+
|
|
524
|
+
- `$any` (default): at least one related row matches the condition
|
|
525
|
+
- `$all`: all related rows match the condition
|
|
526
|
+
- `$none`: no related rows match the condition
|
|
527
|
+
|
|
528
|
+
### Examples
|
|
529
|
+
Assume `CatEntity` has a one‑to‑many relation `toys: CatToyEntity[]` where `CatToyEntity` has a string column `name`.
|
|
530
|
+
|
|
531
|
+
- At least one toy named exactly "Ball":
|
|
532
|
+
|
|
533
|
+
```url
|
|
534
|
+
GET /cats?filter.toys.name=$any:$eq:Ball
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
- At least one toy whose name contains "red" (case-insensitive):
|
|
538
|
+
|
|
539
|
+
```url
|
|
540
|
+
GET /cats?filter.toys.name=$any:$ilike:red
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
- All toys must have names that start with "Chew":
|
|
544
|
+
|
|
545
|
+
```url
|
|
546
|
+
GET /cats?filter.toys.name=$all:$sw:Chew
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
- No toys named "Squeaky", including cats without any toys:
|
|
550
|
+
|
|
551
|
+
```url
|
|
552
|
+
GET /cats?filter.toys.name=$none:$eq:Squeaky
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
- One or more toys not named "Squeaky":
|
|
556
|
+
|
|
557
|
+
```url
|
|
558
|
+
GET /cats?filter.toys.name=$any:$not:$eq:Squeaky
|
|
559
|
+
```
|
|
560
|
+
|
|
519
561
|
## Usage with Eager Loading
|
|
520
562
|
|
|
521
563
|
Eager loading should work with TypeORM's eager property out of the box:
|
|
@@ -589,18 +631,27 @@ const config: PaginateConfig<CatEntity> = {
|
|
|
589
631
|
|
|
590
632
|
`?filter.roles=$contains:moderator,admin` where column `roles` is an array and contains the values `moderator` and `admin`
|
|
591
633
|
|
|
592
|
-
## JSONB
|
|
634
|
+
## JSONB Support
|
|
593
635
|
|
|
594
|
-
You can filter on JSONB columns using dot notation to access nested fields.
|
|
636
|
+
You can sort, search, and filter on JSONB columns using dot notation to access nested fields.
|
|
595
637
|
|
|
596
|
-
###
|
|
638
|
+
### Database support matrix
|
|
639
|
+
|
|
640
|
+
| Feature | PostgreSQL / CockroachDB | MySQL / MariaDB | SQLite |
|
|
641
|
+
|---------|---|---|---|
|
|
642
|
+
| **Sorting** (`sortableColumns`) | Yes (`#>>`) | Yes (`JSON_UNQUOTE(JSON_EXTRACT(...))`) | Yes (`json_extract`) |
|
|
643
|
+
| **Searching** (`searchableColumns`) | Yes | Yes | Yes |
|
|
644
|
+
| **Filtering** (`$eq`, `$in`, `$contains`) | Yes (`@>` containment) | No | No |
|
|
645
|
+
|
|
646
|
+
> **Note:** Sorting and searching on JSONB paths is supported across all database engines — the library automatically uses the correct JSON extraction function for your DB. Filtering via `$eq`, `$in`, and `$contains` uses PostgreSQL's `@>` containment operator (via TypeORM's `JsonContains`) and is only supported on **PostgreSQL** and **CockroachDB**.
|
|
647
|
+
|
|
648
|
+
### Filtering operators (PostgreSQL / CockroachDB only)
|
|
597
649
|
|
|
598
650
|
| Operator | Description |
|
|
599
651
|
|----------|-------------|
|
|
600
|
-
| `$eq`
|
|
601
|
-
| `$in`
|
|
602
|
-
|
|
603
|
-
> **Note:** JSONB filtering is implemented using PostgreSQL's `@>` (containment) operator and is only supported by **PostgreSQL**.
|
|
652
|
+
| `$eq` | Exact match via containment (`col @> '{"key":"value"}'`) |
|
|
653
|
+
| `$in` | Match any of a comma-separated list of values |
|
|
654
|
+
| `$contains` | Match if a JSON array contains the value |
|
|
604
655
|
|
|
605
656
|
### Direct JSONB column
|
|
606
657
|
|
|
@@ -37,6 +37,10 @@ __decorate([
|
|
|
37
37
|
(0, typeorm_1.CreateDateColumn)(column_option_1.DateColumnNotNull),
|
|
38
38
|
__metadata("design:type", String)
|
|
39
39
|
], CatHomePillowEntity.prototype, "createdAt", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, typeorm_1.DeleteDateColumn)(column_option_1.DateColumnNotNull),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], CatHomePillowEntity.prototype, "deletedAt", void 0);
|
|
40
44
|
exports.CatHomePillowEntity = CatHomePillowEntity = __decorate([
|
|
41
45
|
(0, typeorm_1.Entity)()
|
|
42
46
|
], CatHomePillowEntity);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cat-home-pillow.entity.js","sourceRoot":"","sources":["../../src/__tests__/cat-home-pillow.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"cat-home-pillow.entity.js","sourceRoot":"","sources":["../../src/__tests__/cat-home-pillow.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAA+G;AAC/G,iFAAyE;AACzE,uDAAiD;AACjD,mDAAmD;AAG5C,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAkB/B,CAAA;AAlBY,kDAAmB;AAE5B;IADC,IAAA,gCAAsB,GAAE;;+CACf;AAGV;IADC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,+BAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;8BACjD,+BAAa;iDAAA;AAGnB;IADC,IAAA,gBAAM,GAAE;;kDACI;AAGb;IADC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,uDAAwB,CAAC;8BACnC,uDAAwB;kDAAA;AAG/B;IADC,IAAA,0BAAgB,EAAC,iCAAiB,CAAC;;sDACnB;AAGjB;IADC,IAAA,0BAAgB,EAAC,iCAAiB,CAAC;;sDACnB;8BAjBR,mBAAmB;IAD/B,IAAA,gBAAM,GAAE;GACI,mBAAmB,CAkB/B"}
|
package/lib/filter.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { FindOperator, SelectQueryBuilder } from 'typeorm';
|
|
1
|
+
import { EntityMetadata, FindOperator, SelectQueryBuilder } from 'typeorm';
|
|
2
2
|
import { WherePredicateOperator } from 'typeorm/query-builder/WhereClause';
|
|
3
3
|
import { PaginateQuery } from './decorator';
|
|
4
4
|
import { JoinMethod } from './helper';
|
|
5
|
+
import { EmbeddedMetadata } from 'typeorm/metadata/EmbeddedMetadata';
|
|
6
|
+
import { RelationMetadata } from 'typeorm/metadata/RelationMetadata';
|
|
5
7
|
export declare enum FilterOperator {
|
|
6
8
|
EQ = "$eq",
|
|
7
9
|
GT = "$gt",
|
|
@@ -20,6 +22,12 @@ export declare enum FilterSuffix {
|
|
|
20
22
|
NOT = "$not"
|
|
21
23
|
}
|
|
22
24
|
export declare function isSuffix(value: unknown): value is FilterSuffix;
|
|
25
|
+
export declare enum FilterQuantifier {
|
|
26
|
+
ALL = "$all",
|
|
27
|
+
ANY = "$any",
|
|
28
|
+
NONE = "$none"
|
|
29
|
+
}
|
|
30
|
+
export declare function isQuantifier(value: unknown): value is FilterQuantifier;
|
|
23
31
|
export declare enum FilterComparator {
|
|
24
32
|
AND = "$and",
|
|
25
33
|
OR = "$or"
|
|
@@ -27,6 +35,7 @@ export declare enum FilterComparator {
|
|
|
27
35
|
export declare function isComparator(value: unknown): value is FilterComparator;
|
|
28
36
|
export declare const OperatorSymbolToFunction: Map<FilterOperator | FilterSuffix, (...args: any[]) => FindOperator<string>>;
|
|
29
37
|
type Filter = {
|
|
38
|
+
quantifier: FilterQuantifier;
|
|
30
39
|
comparator: FilterComparator;
|
|
31
40
|
findOperator: FindOperator<string>;
|
|
32
41
|
};
|
|
@@ -37,6 +46,7 @@ type ColumnJoinMethods = {
|
|
|
37
46
|
[columnName: string]: JoinMethod;
|
|
38
47
|
};
|
|
39
48
|
export interface FilterToken {
|
|
49
|
+
quantifier: FilterQuantifier;
|
|
40
50
|
comparator: FilterComparator;
|
|
41
51
|
suffix?: FilterSuffix;
|
|
42
52
|
operator: FilterOperator;
|
|
@@ -51,9 +61,35 @@ export declare function generatePredicateCondition(qb: SelectQueryBuilder<unknow
|
|
|
51
61
|
export declare function addWhereCondition<T>(qb: SelectQueryBuilder<T>, column: string, filter: ColumnFilters): void;
|
|
52
62
|
export declare function parseFilterToken(raw?: string): FilterToken | null;
|
|
53
63
|
export declare function parseFilter<T>(query: PaginateQuery, filterableColumns?: {
|
|
54
|
-
[column: string]: (FilterOperator | FilterSuffix)[] | true;
|
|
64
|
+
[column: string]: (FilterOperator | FilterSuffix | FilterQuantifier)[] | true;
|
|
55
65
|
}, qb?: SelectQueryBuilder<T>): ColumnFilters;
|
|
66
|
+
/**
|
|
67
|
+
* Retrieves the relation path for a given column name within the provided metadata.
|
|
68
|
+
*
|
|
69
|
+
* This method analyzes the column name's segments to identify corresponding relations or embedded entities
|
|
70
|
+
* within the hierarchy described by the given metadata and returns a structured path.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} columnName - The dot-delimited name of the column whose relation path is to be determined.
|
|
73
|
+
* @param {EntityMetadata | EmbeddedMetadata} metadata - The metadata of the entity or embedded component
|
|
74
|
+
* which holds the relations or embedded items.
|
|
75
|
+
* @return {[string, RelationMetadata | EmbeddedMetadata][]} The ordered array describing the path,
|
|
76
|
+
* where each element contains a field name and its corresponding relation or embedded metadata.
|
|
77
|
+
* Throws an error if no matching relation or embedded metadata is found.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getRelationPath(columnName: string, metadata: EntityMetadata | EmbeddedMetadata): [string, RelationMetadata | EmbeddedMetadata][];
|
|
56
80
|
export declare function addFilter<T>(qb: SelectQueryBuilder<T>, query: PaginateQuery, filterableColumns?: {
|
|
57
|
-
[column: string]: (FilterOperator | FilterSuffix)[] | true;
|
|
81
|
+
[column: string]: (FilterOperator | FilterSuffix | FilterQuantifier)[] | true;
|
|
58
82
|
}): ColumnJoinMethods;
|
|
83
|
+
export declare function addDirectFilters<T>(qb: SelectQueryBuilder<T>, filter: ColumnFilters): void;
|
|
84
|
+
export declare function addToManySubFilters<T>(qb: SelectQueryBuilder<T>, filter: ColumnFilters, query: PaginateQuery, filterableColumns?: {
|
|
85
|
+
[column: string]: (FilterOperator | FilterSuffix | FilterQuantifier)[] | true;
|
|
86
|
+
}): void;
|
|
87
|
+
export declare function createSubFilter(query: PaginateQuery, filterableColumns: {
|
|
88
|
+
[column: string]: (FilterOperator | FilterSuffix | FilterQuantifier)[] | true;
|
|
89
|
+
}, column: string): {
|
|
90
|
+
subQuery: PaginateQuery;
|
|
91
|
+
subFilterableColumns: {
|
|
92
|
+
[column: string]: true | (FilterOperator | FilterSuffix | FilterQuantifier)[];
|
|
93
|
+
};
|
|
94
|
+
};
|
|
59
95
|
export {};
|