mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
162 lines
4.0 KiB
JavaScript
162 lines
4.0 KiB
JavaScript
// js/utils/logger.js
|
|
// Provides frozen logger channels so both modules and inline scripts share
|
|
// consistent dev-vs-user logging semantics without duplicating feature gates.
|
|
|
|
import { isDevMode } from "../config.js";
|
|
|
|
const NOOP = () => {};
|
|
|
|
function resolveConsole() {
|
|
if (typeof console === "undefined" || console === null) {
|
|
return null;
|
|
}
|
|
return console;
|
|
}
|
|
|
|
/**
|
|
* Returns a console shim with safe wrappers for the standard log levels.
|
|
* Each method gracefully falls back to console.log or a noop when unavailable.
|
|
*/
|
|
function createConsoleAdapter() {
|
|
const consoleRef = resolveConsole();
|
|
if (!consoleRef) {
|
|
return {
|
|
log: NOOP,
|
|
info: NOOP,
|
|
warn: NOOP,
|
|
error: NOOP,
|
|
};
|
|
}
|
|
|
|
const fallback = typeof consoleRef.log === "function" ? consoleRef.log.bind(consoleRef) : NOOP;
|
|
|
|
return {
|
|
log: typeof consoleRef.log === "function" ? consoleRef.log.bind(consoleRef) : fallback,
|
|
info: typeof consoleRef.info === "function" ? consoleRef.info.bind(consoleRef) : fallback,
|
|
warn: typeof consoleRef.warn === "function" ? consoleRef.warn.bind(consoleRef) : fallback,
|
|
error: typeof consoleRef.error === "function" ? consoleRef.error.bind(consoleRef) : fallback,
|
|
};
|
|
}
|
|
|
|
const consoleAdapter = createConsoleAdapter();
|
|
const USER_PREFIX = "[bitvid]";
|
|
|
|
function extractForceFlag(args) {
|
|
if (args.length === 0) {
|
|
return { args, force: false };
|
|
}
|
|
|
|
const last = args[args.length - 1];
|
|
if (last && typeof last === "object" && !Array.isArray(last) && Object.prototype.hasOwnProperty.call(last, "force")) {
|
|
const cloned = [...args];
|
|
const options = cloned.pop();
|
|
return { args: cloned, force: Boolean(options.force) };
|
|
}
|
|
|
|
return { args, force: false };
|
|
}
|
|
|
|
const devLogger = Object.freeze({
|
|
log: (...args) => {
|
|
if (!isDevMode) return;
|
|
consoleAdapter.log(...args);
|
|
},
|
|
info: (...args) => {
|
|
if (!isDevMode) return;
|
|
consoleAdapter.info(...args);
|
|
},
|
|
warn: (...args) => {
|
|
if (!isDevMode) return;
|
|
consoleAdapter.warn(...args);
|
|
},
|
|
error: (...args) => {
|
|
if (!isDevMode) return;
|
|
consoleAdapter.error(...args);
|
|
},
|
|
});
|
|
|
|
const userLogger = Object.freeze({
|
|
log: (...rawArgs) => {
|
|
const { args, force } = extractForceFlag(rawArgs);
|
|
if (!force && args.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (force) {
|
|
consoleAdapter.log(USER_PREFIX, ...args);
|
|
return;
|
|
}
|
|
|
|
const [message, ...rest] = args;
|
|
if (typeof message === "string" && rest.length === 0) {
|
|
consoleAdapter.log(`${USER_PREFIX} ${message}`);
|
|
return;
|
|
}
|
|
|
|
if (message !== undefined) {
|
|
consoleAdapter.log(USER_PREFIX, message);
|
|
}
|
|
},
|
|
info: (...rawArgs) => {
|
|
const { args, force } = extractForceFlag(rawArgs);
|
|
if (!force && args.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (force) {
|
|
consoleAdapter.info(USER_PREFIX, ...args);
|
|
return;
|
|
}
|
|
|
|
const [message, ...rest] = args;
|
|
if (typeof message === "string" && rest.length === 0) {
|
|
consoleAdapter.info(`${USER_PREFIX} ${message}`);
|
|
return;
|
|
}
|
|
|
|
if (message !== undefined) {
|
|
consoleAdapter.info(USER_PREFIX, message);
|
|
}
|
|
},
|
|
warn: (...args) => {
|
|
consoleAdapter.warn(USER_PREFIX, ...args);
|
|
},
|
|
error: (...args) => {
|
|
consoleAdapter.error(USER_PREFIX, ...args);
|
|
},
|
|
});
|
|
|
|
const logger = Object.freeze({
|
|
dev: devLogger,
|
|
user: userLogger,
|
|
});
|
|
|
|
function isCompatibleLogger(candidate) {
|
|
if (!candidate || typeof candidate !== "object") {
|
|
return false;
|
|
}
|
|
|
|
const requiredChannels = ["dev", "user"];
|
|
const requiredMethods = ["log", "info", "warn", "error"];
|
|
|
|
return requiredChannels.every((channel) => {
|
|
const obj = candidate[channel];
|
|
return (
|
|
obj &&
|
|
typeof obj === "object" &&
|
|
requiredMethods.every((method) => typeof obj[method] === "function")
|
|
);
|
|
});
|
|
}
|
|
|
|
if (typeof window !== "undefined") {
|
|
if (!isCompatibleLogger(window.bitvidLogger)) {
|
|
window.bitvidLogger = logger;
|
|
}
|
|
}
|
|
|
|
Object.freeze(logger);
|
|
|
|
export default logger;
|
|
export { devLogger, userLogger };
|