feat: support dot notation syntax for nested relations (#739)
This commit is contained in:
parent
2e376ad656
commit
6f6b4da9a9
@ -710,7 +710,7 @@ describe('paginate', () => {
|
||||
expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&search=Garfield')
|
||||
})
|
||||
|
||||
it('should load nested relations', async () => {
|
||||
it('should load nested relations (object notation)', async () => {
|
||||
const config: PaginateConfig<CatEntity> = {
|
||||
relations: { home: { pillows: true } },
|
||||
sortableColumns: ['id', 'name'],
|
||||
@ -743,6 +743,39 @@ describe('paginate', () => {
|
||||
expect(result.data[0].home.pillows).toStrictEqual(cat.home.pillows)
|
||||
})
|
||||
|
||||
it('should load nested relations (array notation)', async () => {
|
||||
const config: PaginateConfig<CatEntity> = {
|
||||
relations: ['home.pillows'],
|
||||
sortableColumns: ['id', 'name'],
|
||||
searchableColumns: ['name'],
|
||||
}
|
||||
const query: PaginateQuery = {
|
||||
path: '',
|
||||
search: 'Garfield',
|
||||
}
|
||||
|
||||
const result = await paginate<CatEntity>(query, catRepo, config)
|
||||
|
||||
const cat = clone(cats[1])
|
||||
const catHomesClone = clone(catHomes[1])
|
||||
const catHomePillowsClone3 = clone(catHomePillows[3])
|
||||
delete catHomePillowsClone3.home
|
||||
const catHomePillowsClone4 = clone(catHomePillows[4])
|
||||
delete catHomePillowsClone4.home
|
||||
const catHomePillowsClone5 = clone(catHomePillows[5])
|
||||
delete catHomePillowsClone5.home
|
||||
|
||||
catHomesClone.countCat = cats.filter((cat) => cat.id === catHomesClone.cat.id).length
|
||||
catHomesClone.pillows = [catHomePillowsClone3, catHomePillowsClone4, catHomePillowsClone5]
|
||||
cat.home = catHomesClone
|
||||
delete cat.home.cat
|
||||
|
||||
expect(result.meta.search).toStrictEqual('Garfield')
|
||||
expect(result.data).toStrictEqual([cat])
|
||||
expect(result.data[0].home).toBeDefined()
|
||||
expect(result.data[0].home.pillows).toStrictEqual(cat.home.pillows)
|
||||
})
|
||||
|
||||
it('should throw an error when nonexistent relation loaded', async () => {
|
||||
const config: PaginateConfig<CatEntity> = {
|
||||
relations: <any>['homee'],
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
FindOptionsRelations,
|
||||
ObjectLiteral,
|
||||
FindOptionsUtils,
|
||||
FindOptionsRelationByString,
|
||||
} from 'typeorm'
|
||||
import { PaginateQuery } from './decorator'
|
||||
import { ServiceUnavailableException, Logger } from '@nestjs/common'
|
||||
@ -28,6 +29,7 @@ import {
|
||||
getQueryUrlComponents,
|
||||
} from './helper'
|
||||
import { addFilter, FilterOperator, FilterSuffix } from './filter'
|
||||
import { OrmUtils } from 'typeorm/util/OrmUtils'
|
||||
|
||||
const logger: Logger = new Logger('nestjs-paginate')
|
||||
|
||||
@ -61,7 +63,7 @@ export enum PaginationType {
|
||||
}
|
||||
|
||||
export interface PaginateConfig<T> {
|
||||
relations?: FindOptionsRelations<T> | RelationColumn<T>[]
|
||||
relations?: FindOptionsRelations<T> | RelationColumn<T>[] | FindOptionsRelationByString
|
||||
sortableColumns: Column<T>[]
|
||||
nullSort?: 'first' | 'last'
|
||||
searchableColumns?: Column<T>[]
|
||||
@ -123,16 +125,9 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
}
|
||||
|
||||
if (config.relations) {
|
||||
// relations: ["relation"]
|
||||
if (Array.isArray(config.relations)) {
|
||||
config.relations.forEach((relation) => {
|
||||
queryBuilder.leftJoinAndSelect(
|
||||
`${queryBuilder.alias}.${relation}`,
|
||||
`${queryBuilder.alias}_${relation}_rel`
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// relations: {relation:true}
|
||||
const relations = Array.isArray(config.relations)
|
||||
? OrmUtils.propertyPathsToTruthyObject(config.relations)
|
||||
: config.relations
|
||||
const createQueryBuilderRelations = (
|
||||
prefix: string,
|
||||
relations: FindOptionsRelations<T> | RelationColumn<T>[],
|
||||
@ -148,16 +143,11 @@ export async function paginate<T extends ObjectLiteral>(
|
||||
)
|
||||
|
||||
if (typeof relationSchema === 'object') {
|
||||
createQueryBuilderRelations(
|
||||
relationName,
|
||||
relationSchema,
|
||||
`${alias ?? prefix}_${relationName}_rel`
|
||||
)
|
||||
createQueryBuilderRelations(relationName, relationSchema, `${alias ?? prefix}_${relationName}_rel`)
|
||||
}
|
||||
})
|
||||
}
|
||||
createQueryBuilderRelations(queryBuilder.alias, config.relations)
|
||||
}
|
||||
createQueryBuilderRelations(queryBuilder.alias, relations)
|
||||
}
|
||||
|
||||
let nullSort: 'NULLS LAST' | 'NULLS FIRST' | undefined = undefined
|
||||
|
Loading…
Reference in New Issue
Block a user