11import debug from 'debug' ;
2- import prisma from '@umami/prisma-client' ;
2+ import { PrismaClient } from '@prisma/client' ;
3+ import { readReplicas } from '@prisma/extension-read-replicas' ;
34import { formatInTimeZone } from 'date-fns-tz' ;
45import { MYSQL , POSTGRESQL , getDatabaseType } from '@/lib/db' ;
56import { SESSION_COLUMNS , OPERATORS , DEFAULT_PAGE_SIZE } from './constants' ;
@@ -10,6 +11,16 @@ import { filtersToArray } from './params';
1011
1112const log = debug ( 'umami:prisma' ) ;
1213
14+ const PRISMA = 'prisma' ;
15+ const PRISMA_LOG_OPTIONS = {
16+ log : [
17+ {
18+ emit : 'event' ,
19+ level : 'query' ,
20+ } ,
21+ ] ,
22+ } ;
23+
1324const MYSQL_DATE_FORMATS = {
1425 minute : '%Y-%m-%dT%H:%i:00' ,
1526 hour : '%Y-%m-%d %H:00:00' ,
@@ -234,14 +245,16 @@ async function rawQuery(sql: string, data: object): Promise<any> {
234245 return db === MYSQL ? '?' : `$${ params . length } ${ type ?? '' } ` ;
235246 } ) ;
236247
237- return prisma . rawQuery ( query , params ) ;
248+ return process . env . DATABASE_REPLICA_URL
249+ ? client . $replica ( ) . $queryRawUnsafe ( query , params )
250+ : client . $queryRawUnsafe ( query , params ) ;
238251}
239252
240253async function pagedQuery < T > ( model : string , criteria : T , pageParams : PageParams ) {
241254 const { page = 1 , pageSize, orderBy, sortDescending = false } = pageParams || { } ;
242255 const size = + pageSize || DEFAULT_PAGE_SIZE ;
243256
244- const data = await prisma . client [ model ] . findMany ( {
257+ const data = await client [ model ] . findMany ( {
245258 ...criteria ,
246259 ...{
247260 ...( size > 0 && { take : + size , skip : + size * ( + page - 1 ) } ) ,
@@ -255,7 +268,7 @@ async function pagedQuery<T>(model: string, criteria: T, pageParams: PageParams)
255268 } ,
256269 } ) ;
257270
258- const count = await prisma . client [ model ] . count ( { where : ( criteria as any ) . where } ) ;
271+ const count = await client [ model ] . count ( { where : ( criteria as any ) . where } ) ;
259272
260273 return { data, count, page : + page , pageSize : size , orderBy } ;
261274}
@@ -323,8 +336,51 @@ function getSearchParameters(query: string, filters: { [key: string]: any }[]) {
323336 } ;
324337}
325338
339+ function transaction ( input : any , options ?: any ) {
340+ return client . $transaction ( input , options ) ;
341+ }
342+
343+ function getClient ( params ?: {
344+ logQuery ?: boolean ;
345+ queryLogger ?: ( ) => void ;
346+ replicaUrl ?: string ;
347+ options ?: any ;
348+ } ) : PrismaClient {
349+ const {
350+ logQuery = ! ! process . env . LOG_QUERY ,
351+ queryLogger,
352+ replicaUrl = process . env . DATABASE_REPLICA_URL ,
353+ options,
354+ } = params || { } ;
355+
356+ const prisma = new PrismaClient ( {
357+ errorFormat : 'pretty' ,
358+ ...( logQuery && PRISMA_LOG_OPTIONS ) ,
359+ ...options ,
360+ } ) ;
361+
362+ if ( replicaUrl ) {
363+ prisma . $extends (
364+ readReplicas ( {
365+ url : replicaUrl ,
366+ } ) ,
367+ ) ;
368+ }
369+
370+ if ( logQuery ) {
371+ prisma . $on ( 'query' as never , queryLogger || log ) ;
372+ }
373+
374+ log ( 'Prisma initialized' ) ;
375+
376+ return prisma ;
377+ }
378+
379+ const client = global [ PRISMA ] || getClient ( ) ;
380+
326381export default {
327- ...prisma ,
382+ client,
383+ transaction,
328384 getAddIntervalQuery,
329385 getCastColumnQuery,
330386 getDayDiffQuery,
0 commit comments