在nestjs + prisma中,prisma的创建时间createdAt
和更新时间updatedAt
存储的是UTC时间,响应时需要返回时间戳,还有就是对分页进行封装。
下面代码参考:knotekbr 的代码,适用于prisma 5.x版本
分页处理
// src/modules/prisma/extensions/get-page.extension.ts
import { Prisma } from '@prisma/client';
import type { PrismaClient } from '@prisma/client';
import AppConfig from 'src/config';
type GetPageRes<T> = {
records: T;
total: number;
page: number;
size: number;
};
/**
* 查询并返回列表+总数
* @param prisma - PrismaClient实例
* @returns 返回一个包含getPage方法的对象
*/
export function createGetPageExtension<TModel = any, TArgs = any>(
prisma: PrismaClient,
) {
return {
name: 'getPage',
model: {
$allModels: {
async getPage(
this: TModel,
args?: Prisma.Exact<TArgs, Prisma.Args<TModel, 'findMany'>>,
limit?: { page?: number; size?: number },
): Promise<GetPageRes<Prisma.Result<TModel, TArgs, 'findMany'>>> {
const context = Prisma.getExtensionContext(this);
const { page = 1, size = AppConfig.defaultPageSize } = limit ?? {};
const [records, total] = await prisma.$transaction([
(context as any).findMany({
orderBy: { id: 'desc' },
skip: (page - 1) * size,
take: parseInt(size as unknown as string),
...((args ?? {}) as any),
}),
(context as any).count({ where: (args as any)?.where }),
]);
return {
records,
total,
page: page * 1,
size: size * 1,
};
},
},
},
};
}
export type GetPage<TModel, TArgs> = ReturnType<
typeof createGetPageExtension<TModel, TArgs>
>['model']['$allModels']['getPage'];
响应时间处理
// src/modules/prisma/extensions/result-timestamp.extension.ts
/**
* 响应创建时间、更新时间转为时间戳
*/
export function createResultTimestampExtension() {
return {
name: 'resultTimestamp',
result: {
$allModels: {
createdAt: {
compute(data: any) {
return new Date(data.createdAt).getTime();
},
},
updatedAt: {
compute(data: any) {
return new Date(data.updatedAt).getTime();
},
},
},
},
};
}
export type ResultTimestamp = ReturnType<
typeof createResultTimestampExtension
>['result']['$allModels']['createdAt'];
引入各个模块扩展
// src/modules/prisma/extended-client.ts
import { PrismaClient } from '@prisma/client';
import {
createGetPageExtension,
type GetPage,
} from './extensions/get-page.extension';
import { createResultTimestampExtension } from './extensions/result-timestamp.extension';
type ModelsWithExtensions = {
[Model in keyof PrismaClient]: PrismaClient[Model] extends {
findMany: (args: infer TArgs) => Promise<any>;
}
? {
getPage: GetPage<PrismaClient[Model], TArgs>;
} & PrismaClient[Model]
: PrismaClient[Model];
};
class UntypedExtendedClient extends PrismaClient {
constructor(options?: ConstructorParameters<typeof PrismaClient>[0]) {
super(options);
// 注入分页、result处理扩展
return this.$extends(createGetPageExtension(this)).$extends(
createResultTimestampExtension(),
) as this;
}
}
const ExtendedPrismaClient = UntypedExtendedClient as unknown as new (
options?: ConstructorParameters<typeof PrismaClient>[0],
) => PrismaClient & ModelsWithExtensions;
export { ExtendedPrismaClient };
注入扩展
// src/modules/prisma/prisma.service.ts
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { ExtendedPrismaClient } from './extended-client';
@Injectable()
export class PrismaService
extends ExtendedPrismaClient
implements OnModuleInit, OnModuleDestroy
{
async onModuleInit() {
await this.$connect();
}
async onModuleDestroy() {
await this.$disconnect();
}
}