Files
Taekwondo-Admin/packages/api/src/services/db/prisma.ts
T
2026-03-15 15:39:45 +01:00

63 lines
1.9 KiB
TypeScript

import { PrismaPg } from "@prisma/adapter-pg";
import { type Request } from "express";
import { PrismaClient } from "../../generated/prisma/client.js";
import type { UserModel } from "../../generated/prisma/models.js";
import { Injectable } from "../../infrastructure/di/injectable-decorator.js";
type ExtendedClient = ReturnType<typeof createExtendedClient>;
export type SafeClient = Omit<
ExtendedClient,
| "$connect"
| "$disconnect"
| "$on"
| "$transaction"
| "$executeRaw"
| "$executeRawUnsafe"
| "$queryRaw"
| "$queryRawUnsafe"
| "$extends"
>;
function createExtendedClient(client: PrismaClient) {
return client.$extends({
client: {
async ensureUserKnown(userId: string): Promise<UserModel> {
let user = await client.user.findUnique({
where: { id: userId },
});
if (user == null) {
user = await client.user.create({ data: { id: userId } });
}
return user;
},
},
});
}
@Injectable()
export class DatabaseService {
private readonly prismaClient: ExtendedClient;
public constructor() {
const dbUser = process.env["TKD_DB_USER"]!;
const dbPassword = process.env["TKD_DB_PASSWORD"]!;
const dbHost = process.env["TKD_DB_HOST"]!;
const connectionString = `postgresql://${dbUser}:${dbPassword}@${dbHost}:5432/taekwondo?schema=public`;
const adapter = new PrismaPg({ connectionString });
this.prismaClient = createExtendedClient(new PrismaClient({ adapter }));
}
public async doRequest<T>(
command: (prisma: SafeClient) => Promise<T>,
request: Request | null,
): Promise<T> {
const transaction: SafeClient | null = (request as any | null)
?.transaction;
const effectiveClient = transaction ?? this.prismaClient;
return await command(effectiveClient);
}
}