mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-01 10:22:25 +00:00
Add shared logger utility
This commit is contained in:
1 parent
a69012be3b
commit
44b8764e19
1 file changed
+162
@@ -0,0 +1,162 @@
|
||||
// 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 const devLogger = logger.dev;
|
||||
export const userLogger = logger.user;
|
||||
Reference in new issue
Block a user