add base repository
This commit is contained in:
parent
68b06801d3
commit
9f88f9c731
98
src/modules/database/base/tree.repository.ts
Normal file
98
src/modules/database/base/tree.repository.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { isNil, pick, unset } from 'lodash';
|
||||
import {
|
||||
EntityManager,
|
||||
EntityTarget,
|
||||
FindOptionsUtils,
|
||||
FindTreeOptions,
|
||||
ObjectLiteral,
|
||||
QueryRunner,
|
||||
SelectQueryBuilder,
|
||||
TreeRepository,
|
||||
TreeRepositoryUtils,
|
||||
} from 'typeorm';
|
||||
|
||||
import { OrderType, TreeChildrenResolve } from '../constants';
|
||||
import { OrderQueryType, QueryParams } from '../types';
|
||||
import { getOrderByQuery } from '../utils';
|
||||
|
||||
export abstract class BaseTreeRepository<T extends ObjectLiteral> extends TreeRepository<T> {
|
||||
protected abstract _qbName: string;
|
||||
|
||||
protected _childrenResolve?: TreeChildrenResolve;
|
||||
|
||||
protected orderBy?: string | { name: string; order: `${OrderType}` };
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||
constructor(target: EntityTarget<T>, manager: EntityManager, queryRunner?: QueryRunner) {
|
||||
super(target, manager, queryRunner);
|
||||
}
|
||||
|
||||
get qbName() {
|
||||
return this._qbName;
|
||||
}
|
||||
|
||||
get childrenResolve() {
|
||||
return this._childrenResolve;
|
||||
}
|
||||
|
||||
buildBaseQB(qb?: SelectQueryBuilder<T>): SelectQueryBuilder<T> {
|
||||
const queryBuilder = qb ?? this.createQueryBuilder(this.qbName);
|
||||
return queryBuilder.leftJoinAndSelect(`${this.qbName}.parent`, 'parent');
|
||||
}
|
||||
|
||||
addOrderByQuery(qb: SelectQueryBuilder<T>, orderBy?: OrderQueryType) {
|
||||
const orderByQuery = orderBy ?? this.orderBy;
|
||||
return isNil(orderByQuery) ? qb : getOrderByQuery(qb, this.qbName, orderByQuery);
|
||||
}
|
||||
|
||||
async findTrees(options?: FindTreeOptions & QueryParams<T>) {
|
||||
const roots = await this.findRoots(options);
|
||||
await Promise.all(root.map((root) => this.findDescendantsTree(root, options)));
|
||||
return roots;
|
||||
}
|
||||
|
||||
async findDescendantsTree(entity: T, options?: FindTreeOptions & QueryParams<T>) {
|
||||
const { addQuery, orderBy, withTrashed, onlyTrashed } = options ?? {};
|
||||
let qb = this.buildBaseQB(
|
||||
this.createDescendantsQueryBuilder(this.qbName, 'treeClosure', entity),
|
||||
);
|
||||
qb = addQuery
|
||||
? await addQuery(this.addOrderByQuery(qb, orderBy))
|
||||
: this.addOrderByQuery(qb, orderBy);
|
||||
if (withTrashed) {
|
||||
qb.withDeleted();
|
||||
if (onlyTrashed) {
|
||||
qb.where(`${this.qbName}.deletedAt IS NOT NULL`);
|
||||
}
|
||||
}
|
||||
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, pick(options, ['relations', 'depth']));
|
||||
const entities = await qb.getRawAndEntities();
|
||||
const relationMaps = TreeRepositoryUtils.createRelationMaps(
|
||||
this.manager,
|
||||
this.metadata,
|
||||
this.qbName,
|
||||
entities.raw,
|
||||
);
|
||||
TreeRepositoryUtils.buildChildrenEntityTree(
|
||||
this.metadata,
|
||||
entity,
|
||||
entities.entities,
|
||||
relationMaps,
|
||||
{ depth: -1, ...pick(options, ['relations']) },
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
|
||||
async toFlatTrees(trees: T[], depth = 0, parent: T | null = null) {
|
||||
const data: Omit<T, 'children'>[] = [];
|
||||
for (const item of trees) {
|
||||
(item as any).depth = depth;
|
||||
(item as any).parent = parent;
|
||||
const { children } = item;
|
||||
unset(item, 'children');
|
||||
data.push(item);
|
||||
data.push(...(await this.toFlatTrees(children, depth + 1, item)));
|
||||
}
|
||||
return data as T[];
|
||||
}
|
||||
}
|
@ -13,3 +13,9 @@ export enum OrderType {
|
||||
ASC = 'ASC',
|
||||
DESC = 'DESC',
|
||||
}
|
||||
|
||||
export enum TreeChildrenResolve {
|
||||
DELETE = 'delete',
|
||||
UP = 'up',
|
||||
ROOT = 'root',
|
||||
}
|
||||
|
@ -28,3 +28,13 @@ export type OrderQueryType =
|
||||
| string
|
||||
| { name: string; order: `${OrderType}` }
|
||||
| Array<string | { name: string; order: `${OrderType}` }>;
|
||||
|
||||
export interface QueryParams<T extends ObjectLiteral> {
|
||||
addQuery?: QueryHook<T>;
|
||||
|
||||
orderBy?: OrderQueryType;
|
||||
|
||||
withTrashed?: boolean;
|
||||
|
||||
onlyTrashed?: boolean;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user