matcher/src/modules/database/src/adapters/secondaries/prisma-repository.abstract.ts

260 lines
6.6 KiB
TypeScript
Raw Normal View History

2023-04-06 09:12:49 +00:00
import { Injectable } from '@nestjs/common';
2023-04-12 15:09:31 +00:00
import { Prisma } from '@prisma/client';
2023-04-06 09:12:49 +00:00
import { DatabaseException } from '../../exceptions/database.exception';
import { ICollection } from '../../interfaces/collection.interface';
import { IRepository } from '../../interfaces/repository.interface';
import { PrismaService } from './prisma-service';
/**
* Child classes MUST redefined _model property with appropriate model name
*/
@Injectable()
export abstract class PrismaRepository<T> implements IRepository<T> {
protected _model: string;
constructor(protected readonly _prisma: PrismaService) {}
async findAll(
page = 1,
perPage = 10,
where?: any,
include?: any,
): Promise<ICollection<T>> {
const [data, total] = await this._prisma.$transaction([
this._prisma[this._model].findMany({
where,
include,
skip: (page - 1) * perPage,
take: perPage,
}),
this._prisma[this._model].count({
where,
}),
]);
return Promise.resolve({
data,
total,
});
}
async findOneByUuid(uuid: string): Promise<T> {
try {
const entity = await this._prisma[this._model].findUnique({
where: { uuid },
});
return entity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async findOne(where: any, include?: any): Promise<T> {
try {
const entity = await this._prisma[this._model].findFirst({
where: where,
include: include,
});
return entity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
Prisma.PrismaClientKnownRequestError.name,
e.code,
);
2023-04-06 09:12:49 +00:00
} else {
throw new DatabaseException();
}
}
}
// TODO : using any is not good, but needed for nested entities
// TODO : Refactor for good clean architecture ?
async create(entity: Partial<T> | any, include?: any): Promise<T> {
try {
const res = await this._prisma[this._model].create({
data: entity,
include: include,
});
return res;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async update(uuid: string, entity: Partial<T>): Promise<T> {
try {
const updatedEntity = await this._prisma[this._model].update({
where: { uuid },
data: entity,
});
return updatedEntity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async updateWhere(
where: any,
entity: Partial<T> | any,
include?: any,
): Promise<T> {
try {
const updatedEntity = await this._prisma[this._model].update({
where: where,
data: entity,
include: include,
});
return updatedEntity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async delete(uuid: string): Promise<T> {
try {
const entity = await this._prisma[this._model].delete({
where: { uuid },
});
return entity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async deleteMany(where: any): Promise<void> {
try {
const entity = await this._prisma[this._model].deleteMany({
where: where,
});
return entity;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async findAllByQuery(
include: Array<string>,
where: Array<string>,
): Promise<ICollection<T>> {
const query = `SELECT ${include.join(',')} FROM ${
this._model
} WHERE ${where.join(' AND ')}`;
const data: Array<T> = await this._prisma.$queryRawUnsafe(query);
return Promise.resolve({
data,
total: data.length,
});
}
async createWithFields(fields: object): Promise<number> {
try {
const command = `INSERT INTO ${this._model} (${Object.keys(fields).join(
',',
)}) VALUES (${Object.values(fields).join(',')})`;
return await this._prisma.$executeRawUnsafe(command);
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async updateWithFields(uuid: string, entity: Partial<T>): Promise<number> {
entity['"updatedAt"'] = `to_timestamp(${Date.now()} / 1000.0)`;
const values = Object.keys(entity).map((key) => `${key} = ${entity[key]}`);
try {
const command = `UPDATE ${this._model} SET ${values.join(
', ',
)} WHERE uuid = '${uuid}'`;
return await this._prisma.$executeRawUnsafe(command);
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async healthCheck(): Promise<boolean> {
try {
await this._prisma.$queryRaw`SELECT 1`;
return true;
} catch (e) {
2023-04-12 15:09:31 +00:00
if (e instanceof Prisma.PrismaClientKnownRequestError) {
2023-04-06 09:12:49 +00:00
throw new DatabaseException(
2023-04-12 15:09:31 +00:00
Prisma.PrismaClientKnownRequestError.name,
2023-04-06 09:12:49 +00:00
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
}