fix: clean up
This commit is contained in:
parent
2a628e89af
commit
d7ccd914d4
@ -1,3 +1,2 @@
|
||||
export * from './decorator'
|
||||
export * from './paginate'
|
||||
export { FilterOperator, FilterComparator } from './operator'
|
||||
|
@ -1,65 +0,0 @@
|
||||
import { values } from 'lodash'
|
||||
import {
|
||||
Equal,
|
||||
FindOperator,
|
||||
In,
|
||||
MoreThan,
|
||||
MoreThanOrEqual,
|
||||
IsNull,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
Between,
|
||||
ILike,
|
||||
Not,
|
||||
} from 'typeorm'
|
||||
|
||||
export enum FilterOperator {
|
||||
EQ = '$eq',
|
||||
GT = '$gt',
|
||||
GTE = '$gte',
|
||||
IN = '$in',
|
||||
NULL = '$null',
|
||||
LT = '$lt',
|
||||
LTE = '$lte',
|
||||
BTW = '$btw',
|
||||
ILIKE = '$ilike',
|
||||
SW = '$sw',
|
||||
}
|
||||
|
||||
export function isOperator(value: unknown): value is FilterOperator {
|
||||
return values(FilterOperator).includes(value as any)
|
||||
}
|
||||
|
||||
export enum FilterSuffix {
|
||||
NOT = '$not',
|
||||
}
|
||||
|
||||
export function isSuffix(value: unknown): value is FilterSuffix {
|
||||
return values(FilterSuffix).includes(value as any)
|
||||
}
|
||||
|
||||
export enum FilterComparator {
|
||||
AND = '$and',
|
||||
OR = '$or',
|
||||
}
|
||||
|
||||
export function isComparator(value: unknown): value is FilterComparator {
|
||||
return values(FilterComparator).includes(value as any)
|
||||
}
|
||||
|
||||
export const OperatorSymbolToFunction = new Map<
|
||||
FilterOperator | FilterSuffix,
|
||||
(...args: any[]) => FindOperator<string>
|
||||
>([
|
||||
[FilterOperator.EQ, Equal],
|
||||
[FilterOperator.GT, MoreThan],
|
||||
[FilterOperator.GTE, MoreThanOrEqual],
|
||||
[FilterOperator.IN, In],
|
||||
[FilterOperator.NULL, IsNull],
|
||||
[FilterOperator.LT, LessThan],
|
||||
[FilterOperator.LTE, LessThanOrEqual],
|
||||
[FilterOperator.BTW, Between],
|
||||
[FilterOperator.ILIKE, ILike],
|
||||
[FilterSuffix.NOT, Not],
|
||||
[FilterOperator.SW, ILike],
|
||||
])
|
@ -1,6 +1,21 @@
|
||||
import { Brackets, FindOperator, SelectQueryBuilder } from 'typeorm'
|
||||
import { values } from 'lodash'
|
||||
import {
|
||||
Brackets,
|
||||
Equal,
|
||||
FindOperator,
|
||||
In,
|
||||
MoreThan,
|
||||
MoreThanOrEqual,
|
||||
IsNull,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
Between,
|
||||
ILike,
|
||||
Not,
|
||||
SelectQueryBuilder,
|
||||
} from 'typeorm'
|
||||
import { WherePredicateOperator } from 'typeorm/query-builder/WhereClause'
|
||||
import { PaginateQuery } from './decorator'
|
||||
import { PaginateQuery } from '../decorator'
|
||||
import {
|
||||
checkIsEmbedded,
|
||||
checkIsRelation,
|
||||
@ -8,16 +23,57 @@ import {
|
||||
fixColumnAlias,
|
||||
getPropertiesByColumnName,
|
||||
} from './helper'
|
||||
import {
|
||||
FilterComparator,
|
||||
FilterOperator,
|
||||
FilterSuffix,
|
||||
isComparator,
|
||||
isOperator,
|
||||
isSuffix,
|
||||
OperatorSymbolToFunction,
|
||||
} from './operator'
|
||||
import { PaginateConfig } from './paginate'
|
||||
|
||||
export enum FilterOperator {
|
||||
EQ = '$eq',
|
||||
GT = '$gt',
|
||||
GTE = '$gte',
|
||||
IN = '$in',
|
||||
NULL = '$null',
|
||||
LT = '$lt',
|
||||
LTE = '$lte',
|
||||
BTW = '$btw',
|
||||
ILIKE = '$ilike',
|
||||
SW = '$sw',
|
||||
}
|
||||
|
||||
export function isOperator(value: unknown): value is FilterOperator {
|
||||
return values(FilterOperator).includes(value as any)
|
||||
}
|
||||
|
||||
export enum FilterSuffix {
|
||||
NOT = '$not',
|
||||
}
|
||||
|
||||
export function isSuffix(value: unknown): value is FilterSuffix {
|
||||
return values(FilterSuffix).includes(value as any)
|
||||
}
|
||||
|
||||
export enum FilterComparator {
|
||||
AND = '$and',
|
||||
OR = '$or',
|
||||
}
|
||||
|
||||
export function isComparator(value: unknown): value is FilterComparator {
|
||||
return values(FilterComparator).includes(value as any)
|
||||
}
|
||||
|
||||
export const OperatorSymbolToFunction = new Map<
|
||||
FilterOperator | FilterSuffix,
|
||||
(...args: any[]) => FindOperator<string>
|
||||
>([
|
||||
[FilterOperator.EQ, Equal],
|
||||
[FilterOperator.GT, MoreThan],
|
||||
[FilterOperator.GTE, MoreThanOrEqual],
|
||||
[FilterOperator.IN, In],
|
||||
[FilterOperator.NULL, IsNull],
|
||||
[FilterOperator.LT, LessThan],
|
||||
[FilterOperator.LTE, LessThanOrEqual],
|
||||
[FilterOperator.BTW, Between],
|
||||
[FilterOperator.ILIKE, ILike],
|
||||
[FilterSuffix.NOT, Not],
|
||||
[FilterOperator.SW, ILike],
|
||||
])
|
||||
|
||||
type Filter = { comparator: FilterComparator; findOperator: FindOperator<string> }
|
||||
type ColumnsFilters = { [columnName: string]: Filter[] }
|
||||
@ -168,7 +224,7 @@ export function getFilterTokens(raw?: string): FilterToken | null {
|
||||
|
||||
export function parseFilter<T>(
|
||||
query: PaginateQuery,
|
||||
filterableColumns?: PaginateConfig<T>['filterableColumns']
|
||||
filterableColumns?: { [column: string]: (FilterOperator | FilterSuffix)[] }
|
||||
): ColumnsFilters {
|
||||
const filter: ColumnsFilters = {}
|
||||
if (!filterableColumns || !query.filter) {
|
||||
@ -237,7 +293,7 @@ export function parseFilter<T>(
|
||||
export function addFilter<T>(
|
||||
qb: SelectQueryBuilder<T>,
|
||||
query: PaginateQuery,
|
||||
filterableColumns?: PaginateConfig<T>['filterableColumns']
|
||||
filterableColumns?: { [column: string]: (FilterOperator | FilterSuffix)[] }
|
||||
): SelectQueryBuilder<T> {
|
||||
const filter = parseFilter(query, filterableColumns)
|
||||
return qb.andWhere(
|
@ -34,6 +34,10 @@ export type RelationColumn<T> = Extract<
|
||||
export type Order<T> = [Column<T>, 'ASC' | 'DESC']
|
||||
export type SortBy<T> = Order<T>[]
|
||||
|
||||
export function isEntityKey<T>(entityColumns: Column<T>[], column: string): column is Column<T> {
|
||||
return !!entityColumns.find((c) => c === column)
|
||||
}
|
||||
|
||||
export const positiveNumberOrDefault = (value: number | undefined, defaultValue: number, minValue: 0 | 1 = 0) =>
|
||||
value === undefined || value < minValue ? defaultValue : value
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { Repository, In, DataSource, TypeORMError } from 'typeorm'
|
||||
import { Paginated, paginate, PaginateConfig, NO_PAGINATION } from './paginate'
|
||||
import { PaginateQuery } from './decorator'
|
||||
import { Paginated, paginate, PaginateConfig, NO_PAGINATION } from '.'
|
||||
import { PaginateQuery } from '../decorator'
|
||||
import { HttpException } from '@nestjs/common'
|
||||
import { CatEntity } from './__tests__/cat.entity'
|
||||
import { CatToyEntity } from './__tests__/cat-toy.entity'
|
||||
import { CatHomeEntity } from './__tests__/cat-home.entity'
|
||||
import { CatHomePillowEntity } from './__tests__/cat-home-pillow.entity'
|
||||
import { CatEntity } from '../__tests__/cat.entity'
|
||||
import { CatToyEntity } from '../__tests__/cat-toy.entity'
|
||||
import { CatHomeEntity } from '../__tests__/cat-home.entity'
|
||||
import { CatHomePillowEntity } from '../__tests__/cat-home-pillow.entity'
|
||||
import { clone } from 'lodash'
|
||||
import {
|
||||
getFilterTokens,
|
||||
FilterComparator,
|
||||
FilterOperator,
|
||||
FilterSuffix,
|
||||
isOperator,
|
||||
isSuffix,
|
||||
OperatorSymbolToFunction,
|
||||
} from './operator'
|
||||
import { getFilterTokens } from './filter'
|
||||
} from './filter'
|
||||
|
||||
describe('paginate', () => {
|
||||
let dataSource: DataSource
|
@ -7,7 +7,7 @@ import {
|
||||
ObjectLiteral,
|
||||
FindOptionsUtils,
|
||||
} from 'typeorm'
|
||||
import { PaginateQuery } from './decorator'
|
||||
import { PaginateQuery } from '../decorator'
|
||||
import { ServiceUnavailableException, Logger } from '@nestjs/common'
|
||||
import { mapKeys } from 'lodash'
|
||||
import { stringify } from 'querystring'
|
||||
@ -25,12 +25,14 @@ import {
|
||||
SortBy,
|
||||
hasColumnWithPropertyPath,
|
||||
includesAllPrimaryKeyColumns,
|
||||
isEntityKey,
|
||||
} from './helper'
|
||||
import { FilterOperator, FilterSuffix } from './operator'
|
||||
import { addFilter } from './filter'
|
||||
import { addFilter, FilterOperator, FilterSuffix } from './filter'
|
||||
|
||||
const logger: Logger = new Logger('nestjs-paginate')
|
||||
|
||||
export { FilterOperator, FilterSuffix }
|
||||
|
||||
export class Paginated<T> {
|
||||
data: T[]
|
||||
meta: {
|
||||
@ -121,10 +123,6 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
path = queryOrigin + queryPath
|
||||
}
|
||||
|
||||
function isEntityKey(entityColumns: Column<T>[], column: string): column is Column<T> {
|
||||
return !!entityColumns.find((c) => c === column)
|
||||
}
|
||||
|
||||
if (config.sortableColumns.length < 1) {
|
||||
logger.debug("Missing required 'sortableColumns' config.")
|
||||
throw new ServiceUnavailableException()
|
||||
@ -142,18 +140,6 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
sortBy.push(...(config.defaultSortBy || [[config.sortableColumns[0], 'ASC']]))
|
||||
}
|
||||
|
||||
if (config.searchableColumns) {
|
||||
if (query.searchBy) {
|
||||
for (const column of query.searchBy) {
|
||||
if (isEntityKey(config.searchableColumns, column)) {
|
||||
searchBy.push(column)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
searchBy.push(...config.searchableColumns)
|
||||
}
|
||||
}
|
||||
|
||||
let [items, totalItems]: [T[], number] = [[], 0]
|
||||
|
||||
const queryBuilder = repo instanceof Repository ? repo.createQueryBuilder('__root') : repo
|
||||
@ -165,10 +151,12 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
}
|
||||
|
||||
if (isPaginated) {
|
||||
// Switch from take and skip to limit and offset
|
||||
// due to this problem https://github.com/typeorm/typeorm/issues/5670
|
||||
// (anyway this creates more clean query without double distinct)
|
||||
// queryBuilder.limit(limit).offset((page - 1) * limit)
|
||||
// Allow user to choose between limit/offset and take/skip.
|
||||
// However, using limit/offset can return unexpected results.
|
||||
// For more information see:
|
||||
// [#477](https://github.com/ppetzold/nestjs-paginate/issues/477)
|
||||
// [#4742](https://github.com/typeorm/typeorm/issues/4742)
|
||||
// [#5670](https://github.com/typeorm/typeorm/issues/5670)
|
||||
if (paginationType === PaginationType.LIMIT_AND_OFFSET) {
|
||||
queryBuilder.limit(limit).offset((page - 1) * limit)
|
||||
} else {
|
||||
@ -248,6 +236,18 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
queryBuilder.withDeleted()
|
||||
}
|
||||
|
||||
if (config.searchableColumns) {
|
||||
if (query.searchBy) {
|
||||
for (const column of query.searchBy) {
|
||||
if (isEntityKey(config.searchableColumns, column)) {
|
||||
searchBy.push(column)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
searchBy.push(...config.searchableColumns)
|
||||
}
|
||||
}
|
||||
|
||||
if (query.search && searchBy.length) {
|
||||
queryBuilder.andWhere(
|
||||
new Brackets((qb: SelectQueryBuilder<T>) => {
|
Loading…
Reference in New Issue
Block a user