mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 01:35:39 -04:00
Add LOG_LEVEL logger helper with createLogger() utility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
isPasswordLoginDisabled,
|
||||
} from "@/lib/config";
|
||||
import { db } from "@/lib/db/client";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import {
|
||||
getUserCount,
|
||||
isRegistrationOpen,
|
||||
@@ -36,7 +37,18 @@ const oidcPlugin = isOidcConfigured()
|
||||
]
|
||||
: [];
|
||||
|
||||
const authLog = createLogger("auth");
|
||||
|
||||
export const auth = betterAuth({
|
||||
logger: {
|
||||
// Suppress unset secret/low entropy warnings during build
|
||||
disabled: process.env.NEXT_PHASE === "phase-production-build",
|
||||
level: "debug",
|
||||
log: (level, message, ...args) => {
|
||||
const fn = authLog[level as keyof typeof authLog];
|
||||
if (fn) fn(message, ...args);
|
||||
},
|
||||
},
|
||||
database: drizzleAdapter(db, {
|
||||
provider: "sqlite",
|
||||
}),
|
||||
|
||||
+7
-4
@@ -7,6 +7,7 @@ import {
|
||||
titles,
|
||||
userTitleStatus,
|
||||
} from "@/lib/db/schema";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import { refreshAvailability } from "@/lib/services/availability";
|
||||
import {
|
||||
cacheEpisodeStills,
|
||||
@@ -21,6 +22,8 @@ import {
|
||||
} from "@/lib/services/metadata";
|
||||
import { getTvDetails } from "@/lib/tmdb/client";
|
||||
|
||||
const log = createLogger("cron");
|
||||
|
||||
const DAY = 24 * 60 * 60 * 1000;
|
||||
const RATE_LIMIT_MS = 300;
|
||||
|
||||
@@ -42,13 +45,13 @@ function schedule(name: string, cron: string, handler: () => Promise<void>) {
|
||||
name,
|
||||
protect: true,
|
||||
catch: (err: unknown) => {
|
||||
console.error(`[scheduler] Job ${name} failed:`, err);
|
||||
log.error(`Job ${name} failed:`, err);
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
console.log(`[scheduler] Running job: ${name}`);
|
||||
log.info(`Running job: ${name}`);
|
||||
await handler();
|
||||
console.log(`[scheduler] Completed job: ${name}`);
|
||||
log.info(`Completed job: ${name}`);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -213,7 +216,7 @@ export function startJobs() {
|
||||
schedule("refreshTvChildren", "30 */12 * * *", refreshTvChildrenJob);
|
||||
schedule("cacheImages", "0 1,13 * * *", cacheImagesJob);
|
||||
|
||||
console.log(`[scheduler] Started ${jobs.size} jobs`);
|
||||
log.info(`Started ${jobs.size} jobs`);
|
||||
}
|
||||
|
||||
export function stopJobs() {
|
||||
|
||||
+5
-2
@@ -1,8 +1,11 @@
|
||||
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import { db } from "./client";
|
||||
|
||||
const log = createLogger("db");
|
||||
|
||||
export function runMigrations() {
|
||||
console.log("[migrate] Running database migrations...");
|
||||
log.info("Running database migrations...");
|
||||
migrate(db, { migrationsFolder: "./drizzle" });
|
||||
console.log("[migrate] Database migrations complete");
|
||||
log.info("Database migrations complete");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
const LEVELS = { error: 0, warn: 1, info: 2, debug: 3 } as const;
|
||||
type Level = keyof typeof LEVELS;
|
||||
|
||||
const currentLevel: Level =
|
||||
(process.env.LOG_LEVEL as Level) in LEVELS
|
||||
? (process.env.LOG_LEVEL as Level)
|
||||
: "info";
|
||||
|
||||
export function createLogger(prefix: string) {
|
||||
const fmt = (msg: string) => `[${prefix}] ${msg}`;
|
||||
return {
|
||||
error(msg: string, ...args: unknown[]) {
|
||||
if (LEVELS[currentLevel] >= LEVELS.error)
|
||||
console.error(fmt(msg), ...args);
|
||||
},
|
||||
warn(msg: string, ...args: unknown[]) {
|
||||
if (LEVELS[currentLevel] >= LEVELS.warn) console.warn(fmt(msg), ...args);
|
||||
},
|
||||
info(msg: string, ...args: unknown[]) {
|
||||
if (LEVELS[currentLevel] >= LEVELS.info) console.log(fmt(msg), ...args);
|
||||
},
|
||||
debug(msg: string, ...args: unknown[]) {
|
||||
if (LEVELS[currentLevel] >= LEVELS.debug)
|
||||
console.debug(fmt(msg), ...args);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { eq } from "drizzle-orm";
|
||||
import { Vibrant } from "node-vibrant/node";
|
||||
import { db } from "@/lib/db/client";
|
||||
import { titles } from "@/lib/db/schema";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import {
|
||||
downloadAndCacheImage,
|
||||
getLocalImagePath,
|
||||
@@ -10,6 +11,8 @@ import {
|
||||
isImageCached,
|
||||
} from "@/lib/services/image-cache";
|
||||
|
||||
const log = createLogger("colors");
|
||||
|
||||
export interface ColorPalette {
|
||||
vibrant: string | null;
|
||||
darkVibrant: string | null;
|
||||
@@ -58,7 +61,7 @@ export async function extractAndStoreColors(
|
||||
|
||||
return colors;
|
||||
} catch (err) {
|
||||
console.error(`Failed to extract colors for title ${titleId}:`, err);
|
||||
log.error(`Failed to extract colors for title ${titleId}:`, err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
titleRecommendations,
|
||||
titles,
|
||||
} from "@/lib/db/schema";
|
||||
import { createLogger } from "@/lib/logger";
|
||||
import {
|
||||
getMovieDetails,
|
||||
getRecommendations,
|
||||
@@ -29,6 +30,8 @@ import {
|
||||
imageCacheEnabled,
|
||||
} from "./image-cache";
|
||||
|
||||
const log = createLogger("metadata");
|
||||
|
||||
export async function importTitle(
|
||||
tmdbId: number,
|
||||
type: "movie" | "tv",
|
||||
@@ -277,10 +280,10 @@ export async function refreshTvChildren(
|
||||
})
|
||||
.run();
|
||||
}
|
||||
} catch {
|
||||
} catch (err) {
|
||||
// Skip this season and continue with the rest — partial data is
|
||||
// better than aborting entirely. The next refresh cycle will retry.
|
||||
console.error(`Failed to fetch season ${sn} for TMDB ${tmdbId}`);
|
||||
log.error(`Failed to fetch season ${sn} for TMDB ${tmdbId}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -457,8 +460,8 @@ export async function getTitleWithChildren(id: string): Promise<{
|
||||
.run();
|
||||
await refreshTvChildren(id, title.tmdbId, show.number_of_seasons);
|
||||
title = db.select().from(titles).where(eq(titles.id, id)).get() ?? title;
|
||||
} catch {
|
||||
// Continue with whatever data we have
|
||||
} catch (err) {
|
||||
log.debug(`Failed to hydrate shell TV title ${id}:`, err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,8 +486,8 @@ export async function getTitleWithChildren(id: string): Promise<{
|
||||
.where(eq(titles.id, id))
|
||||
.run();
|
||||
title = db.select().from(titles).where(eq(titles.id, id)).get() ?? title;
|
||||
} catch {
|
||||
// Continue with whatever data we have
|
||||
} catch (err) {
|
||||
log.debug(`Failed to hydrate shell movie title ${id}:`, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user