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
2023-05-25 07:07:31 +00:00
constructor(protected readonly prisma: PrismaService) {}
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
findAll = async (
2023-04-06 09:12:49 +00:00
page = 1,
perPage = 10,
where?: any,
include?: any,
2023-05-25 07:07:31 +00:00
): Promise<ICollection<T>> => {
const [data, total] = await this.prisma.$transaction([
this.prisma[this.model].findMany({
2023-04-06 09:12:49 +00:00
where,
include,
skip: (page - 1) * perPage,
take: perPage,
}),
2023-05-25 07:07:31 +00:00
this.prisma[this.model].count({
2023-04-06 09:12:49 +00:00
where,
}),
]);
return Promise.resolve({
data,
total,
});
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
findOneByUuid = async (uuid: string): Promise<T> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
findOne = async (where: any, include?: any): Promise<T> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
// 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-25 07:07:31 +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();
}
}
}
2023-05-25 07:07:31 +00:00
update = async (uuid: string, entity: Partial<T>): Promise<T> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
updateWhere = async (
2023-04-06 09:12:49 +00:00
where: any,
entity: Partial<T> | any,
include?: any,
2023-05-25 07:07:31 +00:00
): Promise<T> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
delete = async (uuid: string): Promise<T> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
deleteMany = async (where: any): Promise<void> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
findAllByQuery = async (
2023-04-26 12:14:46 +00:00
include: string[],
where: string[],
2023-05-25 07:07:31 +00:00
): Promise<ICollection<T>> => {
2023-04-06 09:12:49 +00:00
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-05-25 07:07:31 +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,
});
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
createWithFields = async (fields: object): Promise<number> => {
2023-04-06 09:12:49 +00:00
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-05-25 07:07:31 +00:00
return await this.prisma.$executeRawUnsafe(command);
2023-04-06 09:12:49 +00:00
} 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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
updateWithFields = async (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}'`;
2023-05-25 07:07:31 +00:00
return await this.prisma.$executeRawUnsafe(command);
2023-04-06 09:12:49 +00:00
} 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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
2023-05-25 07:07:31 +00:00
healthCheck = async (): Promise<boolean> => {
2023-04-06 09:12:49 +00:00
try {
2023-05-25 07:07:31 +00:00
await this.prisma.$queryRaw`SELECT 1`;
2023-04-06 09:12:49 +00:00
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();
}
}
2023-05-25 07:07:31 +00:00
};
2023-04-06 09:12:49 +00:00
}