This commit is contained in:
liuyi 2025-05-19 11:12:36 +08:00
parent d264b515a1
commit 34c4ac8f86
4 changed files with 71 additions and 2 deletions

View File

@ -0,0 +1 @@
export const CUSTOM_REPOSITORY_METADATA = 'CUSTOM_REPOSITORY_METADATA';

View File

@ -1,5 +1,9 @@
import { DynamicModule, Module } from '@nestjs/common';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DynamicModule, Module, Provider, Type } from '@nestjs/common';
import { getDataSourceToken, TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DataSource, ObjectType } from 'typeorm';
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
@Module({})
export class DatabaseModule {
@ -10,4 +14,29 @@ export class DatabaseModule {
imports: [TypeOrmModule.forRoot(configRegister())],
};
}
static forRepository<T extends Type<any>>(
repositories: T[],
datasourceName?: string,
): DynamicModule {
const providers: Provider[] = [];
for (const Repository of repositories) {
const entity = Reflect.getMetadata(CUSTOM_REPOSITORY_METADATA, Repository);
if (!entity) {
continue;
}
providers.push({
inject: [getDataSourceToken(datasourceName)],
provide: Repository,
useFactory: (datasource: DataSource): InstanceType<typeof Repository> => {
const base = datasource.getRepository<ObjectType<any>>(entity);
return new Repository(base.target, base.manager, base.queryRunner);
},
});
}
return {
exports: providers,
module: DatabaseModule,
providers,
};
}
}

View File

@ -0,0 +1,7 @@
import { SetMetadata } from '@nestjs/common';
import { ObjectType } from 'typeorm';
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
export const CustomRepository = <T>(entity: ObjectType<T>): ClassDecorator =>
SetMetadata(CUSTOM_REPOSITORY_METADATA, entity);

View File

@ -0,0 +1,32 @@
import { isNil } from 'lodash';
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
import { PaginateOptions, PaginateReturn } from '@/modules/database/types';
export const paginate = async <T extends ObjectLiteral>(
qb: SelectQueryBuilder<T>,
options: PaginateOptions,
): Promise<PaginateReturn<T>> => {
const limit = isNil(options.limit) || options.limit < 1 ? 1 : options.limit;
const page = isNil(options.page) || options.page < 1 ? 1 : options.page;
const start = page >= 1 ? page - 1 : 0;
const totalItems = await qb.getCount();
qb.take(limit).skip(start * limit);
const items = await qb.getMany();
const totalPages =
totalItems % limit === 0
? Math.floor(totalItems / limit)
: Math.floor(totalItems / limit) + 1;
const remainder = totalItems % limit === 0 ? limit : totalItems % limit;
const itemCount = page < totalPages ? limit : remainder;
return {
items,
meta: {
totalItems,
itemCount,
perPage: limit,
totalPages,
currentPage: page,
},
};
};