diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 066b0f5..a8fd294 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,6 +1,6 @@ generator client { - provider = "prisma-client" - output = "../generated" + provider = "prisma-client-js" + output = "../server/generated" moduleFormat = "esm" } diff --git a/server/routes/metrics/daily.ts b/server/routes/metrics/daily.ts index 68c7793..05591d1 100644 --- a/server/routes/metrics/daily.ts +++ b/server/routes/metrics/daily.ts @@ -1,13 +1,25 @@ -import { getRegistry } from '../../utils/metrics'; +import { getRegistry, initializeAllMetrics } from '../../utils/metrics'; import { scopedLogger } from '../../utils/logger'; const log = scopedLogger('metrics-daily-endpoint'); +let isInitialized = false; + +async function ensureMetricsInitialized() { + if (!isInitialized) { + log.info('Initializing metrics from daily endpoint...', { evt: 'init_start' }); + await initializeAllMetrics(); + isInitialized = true; + log.info('Metrics initialized from daily endpoint', { evt: 'init_complete' }); + } +} + export default defineEventHandler(async event => { try { + await ensureMetricsInitialized(); // Get the daily registry const dailyRegistry = getRegistry('daily'); - + const metrics = await dailyRegistry.metrics(); event.node.res.setHeader('Content-Type', dailyRegistry.contentType); return metrics; diff --git a/server/routes/metrics/monthly.ts b/server/routes/metrics/monthly.ts index 94f5347..acb323b 100644 --- a/server/routes/metrics/monthly.ts +++ b/server/routes/metrics/monthly.ts @@ -1,13 +1,25 @@ -import { getRegistry } from '../../utils/metrics'; +import { getRegistry, initializeAllMetrics } from '../../utils/metrics'; import { scopedLogger } from '../../utils/logger'; const log = scopedLogger('metrics-monthly-endpoint'); +let isInitialized = false; + +async function ensureMetricsInitialized() { + if (!isInitialized) { + log.info('Initializing metrics from monthly endpoint...', { evt: 'init_start' }); + await initializeAllMetrics(); + isInitialized = true; + log.info('Metrics initialized from monthly endpoint', { evt: 'init_complete' }); + } +} + export default defineEventHandler(async event => { try { + await ensureMetricsInitialized(); // Get the monthly registry const monthlyRegistry = getRegistry('monthly'); - + const metrics = await monthlyRegistry.metrics(); event.node.res.setHeader('Content-Type', monthlyRegistry.contentType); return metrics; diff --git a/server/routes/metrics/weekly.ts b/server/routes/metrics/weekly.ts index e3237fa..4e66002 100644 --- a/server/routes/metrics/weekly.ts +++ b/server/routes/metrics/weekly.ts @@ -1,13 +1,25 @@ -import { getRegistry } from '../../utils/metrics'; +import { getRegistry, initializeAllMetrics } from '../../utils/metrics'; import { scopedLogger } from '../../utils/logger'; const log = scopedLogger('metrics-weekly-endpoint'); +let isInitialized = false; + +async function ensureMetricsInitialized() { + if (!isInitialized) { + log.info('Initializing metrics from weekly endpoint...', { evt: 'init_start' }); + await initializeAllMetrics(); + isInitialized = true; + log.info('Metrics initialized from weekly endpoint', { evt: 'init_complete' }); + } +} + export default defineEventHandler(async event => { try { + await ensureMetricsInitialized(); // Get the weekly registry const weeklyRegistry = getRegistry('weekly'); - + const metrics = await weeklyRegistry.metrics(); event.node.res.setHeader('Content-Type', weeklyRegistry.contentType); return metrics; diff --git a/server/routes/users/[id]/watch-history.ts b/server/routes/users/[id]/watch-history.ts index 426808e..a47b76c 100644 --- a/server/routes/users/[id]/watch-history.ts +++ b/server/routes/users/[id]/watch-history.ts @@ -76,118 +76,6 @@ export default defineEventHandler(async event => { })); } - if (event.path.includes('/watch-history/')) { - const segments = event.path.split('/'); - const tmdbId = segments[segments.length - 1]; - - if (method === 'PUT') { - const body = await readBody(event); - const validatedBody = watchHistoryItemSchema.parse(body); - - const watchedAt = defaultAndCoerceDateTime(validatedBody.watchedAt); - const now = new Date(); - - const existingItem = await prisma.watch_history.findUnique({ - where: { - tmdb_id_user_id_season_id_episode_id: { - tmdb_id: tmdbId, - user_id: userId, - season_id: validatedBody.seasonId || null, - episode_id: validatedBody.episodeId || null, - }, - }, - }); - - let watchHistoryItem; - - if (existingItem) { - watchHistoryItem = await prisma.watch_history.update({ - where: { - id: existingItem.id, - }, - data: { - duration: BigInt(validatedBody.duration), - watched: BigInt(validatedBody.watched), - watched_at: watchedAt, - completed: validatedBody.completed, - meta: validatedBody.meta, - updated_at: now, - }, - }); - } else { - watchHistoryItem = await prisma.watch_history.create({ - data: { - id: randomUUID(), - tmdb_id: tmdbId, - user_id: userId, - season_id: validatedBody.seasonId || null, - episode_id: validatedBody.episodeId || null, - season_number: validatedBody.seasonNumber || null, - episode_number: validatedBody.episodeNumber || null, - duration: BigInt(validatedBody.duration), - watched: BigInt(validatedBody.watched), - watched_at: watchedAt, - completed: validatedBody.completed, - meta: validatedBody.meta, - updated_at: now, - }, - }); - } - - return { - id: watchHistoryItem.id, - tmdbId: watchHistoryItem.tmdb_id, - userId: watchHistoryItem.user_id, - seasonId: watchHistoryItem.season_id, - episodeId: watchHistoryItem.episode_id, - seasonNumber: watchHistoryItem.season_number, - episodeNumber: watchHistoryItem.episode_number, - meta: watchHistoryItem.meta, - duration: Number(watchHistoryItem.duration), - watched: Number(watchHistoryItem.watched), - watchedAt: watchHistoryItem.watched_at.toISOString(), - completed: watchHistoryItem.completed, - updatedAt: watchHistoryItem.updated_at.toISOString(), - }; - } - - if (method === 'DELETE') { - const body = await readBody(event).catch(() => ({})); - - const whereClause: any = { - user_id: userId, - tmdb_id: tmdbId, - }; - - if (body.seasonId) whereClause.season_id = body.seasonId; - if (body.episodeId) whereClause.episode_id = body.episodeId; - - const itemsToDelete = await prisma.watch_history.findMany({ - where: whereClause, - }); - - if (itemsToDelete.length === 0) { - return { - count: 0, - tmdbId, - episodeId: body.episodeId, - seasonId: body.seasonId, - }; - } - - await prisma.watch_history.deleteMany({ - where: whereClause, - }); - - return { - count: itemsToDelete.length, - tmdbId, - episodeId: body.episodeId, - seasonId: body.seasonId, - }; - } - } - throw createError({ statusCode: 405, message: 'Method not allowed', diff --git a/server/utils/prisma.ts b/server/utils/prisma.ts index 0f6b09a..747890f 100644 --- a/server/utils/prisma.ts +++ b/server/utils/prisma.ts @@ -1,5 +1,5 @@ import { PrismaPg } from '@prisma/adapter-pg'; -import { PrismaClient } from '../../generated/client'; +import { PrismaClient } from '../generated'; const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL, @@ -9,6 +9,8 @@ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined; }; -export const prisma = new PrismaClient({ adapter }); +export const prisma = new PrismaClient({ + adapter, +} as any); if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;