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