matcher/src/modules/database/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> {
2023-05-11 15:47:55 +00:00
protected model: string;
2023-04-06 09:12:49 +00:00
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([
2023-05-11 15:47:55 +00:00
this._prisma[this.model].findMany({
2023-04-06 09:12:49 +00:00
where,
include,
skip: (page - 1) * perPage,
take: perPage,
}),
2023-05-11 15:47:55 +00:00
this._prisma[this.model].count({
2023-04-06 09:12:49 +00:00
where,
}),
]);
return Promise.resolve({
data,
total,
});
}
async findOneByUuid(uuid: string): Promise<T> {
try {
2023-05-11 15:47:55 +00:00
const entity = await this._prisma[this.model].findUnique({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const entity = await this._prisma[this.model].findFirst({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const res = await this._prisma[this.model].create({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const updatedEntity = await this._prisma[this.model].update({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const updatedEntity = await this._prisma[this.model].update({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const entity = await this._prisma[this.model].delete({
2023-04-06 09:12:49 +00:00
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 {
2023-05-11 15:47:55 +00:00
const entity = await this._prisma[this.model].deleteMany({
2023-04-06 09:12:49 +00:00
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(
2023-04-26 12:14:46 +00:00
include: string[],
where: string[],
2023-04-06 09:12:49 +00:00
): Promise<ICollection<T>> {
const query = `SELECT ${include.join(',')} FROM ${
2023-05-11 15:47:55 +00:00
this.model
2023-04-06 09:12:49 +00:00
} WHERE ${where.join(' AND ')}`;
2023-04-26 12:14:46 +00:00
const data: T[] = await this._prisma.$queryRawUnsafe(query);
2023-04-06 09:12:49 +00:00
return Promise.resolve({
data,
total: data.length,
});
}
async createWithFields(fields: object): Promise<number> {
try {
2023-05-11 15:47:55 +00:00
const command = `INSERT INTO ${this.model} ("${Object.keys(fields).join(
'","',
)}") VALUES (${Object.values(fields).join(',')})`;
2023-04-06 09:12:49 +00:00
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: object): Promise<number> {
2023-04-06 09:12:49 +00:00
entity['"updatedAt"'] = `to_timestamp(${Date.now()} / 1000.0)`;
const values = Object.keys(entity).map((key) => `${key} = ${entity[key]}`);
try {
2023-05-11 15:47:55 +00:00
const command = `UPDATE ${this.model} SET ${values.join(
2023-04-06 09:12:49 +00:00
', ',
)} 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();
}
}
}
}