UNPKG

@ozmap/logger

Version:
234 lines (233 loc) 7.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.host = exports.datetime = exports.output = exports.color = exports.level = exports.isJsonArray = exports.isJsonObject = exports.typeOf = exports.colorized = exports.normalize = exports.getCircularReplacer = exports.stringify = void 0; const util_1 = require("util"); const LogLevels_1 = require("./enum/LogLevels"); const Colors_1 = require("./enum/Colors"); const Outputs_1 = require("./enum/Outputs"); /** * Outputs the stringified version of the input data. * * @param data The data to stringify. * @returns The stringified data. */ function stringify(data) { if (typeof data === 'string') return data; if (isJsonObject(data) || isJsonArray(data)) { return JSON.stringify(data, null, 2); } return (0, util_1.format)('%O', data); } exports.stringify = stringify; /** * Creates a replacer function for JSON.stringify to handle circular references. * This version tracks parent objects (ancestors) to detect cycles. * When a circular reference is detected, it returns the string "[Circular]" for that property. * * @returns A replacer function that handles circular objects by returning "[Circular]". */ function getCircularReplacer() { const ancestors = []; /** * The replacer function to be used with JSON.stringify. * It checks for circular references by comparing the current value against its ancestors. * * @param key The key of the property being stringified. * @param value The value of the property being stringified. * @returns The original value if it's not part of a circular reference, * or the string "[Circular]" if a circular reference is detected. */ return function (key, value) { if (typeof value !== 'object' || value === null) { return value; } while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) { ancestors.pop(); } if (ancestors.includes(value)) { return '[Circular]'; } ancestors.push(value); return value; }; } exports.getCircularReplacer = getCircularReplacer; /** * Outputs the normalized version of the input data. * * @param data The data to normalize. * @returns The normalized data. */ function normalize(data) { const t = typeof data; if (t === 'string' || t === 'number' || t === 'boolean' || isJsonObject(data) || isJsonArray(data)) { return data; } return (0, util_1.format)('%O', data); } exports.normalize = normalize; /** * Factory function to create painter for log output coloring. * * @returns Readonly object with level tags as painter methods. */ function colorized() { const output = (c) => color() ? (text) => Colors_1.Colors[c] + text + '\x1b[0m' : (text) => text; return Object.freeze({ SILLY: output('magenta') /** @deprecated */, DEBUG: output('magenta'), AUDIT: output('blue'), HTTP: output('green') /** @deprecated */, INFO: output('green'), WARNING: output('yellow'), ERROR: output('red'), CRITICAL: output('red') /** @deprecated */ }); } exports.colorized = colorized; /** * Function for checking the data type without relying on * the generic typeof functionality. * * @param data The data being checked for its type. * @returns The internal tag that represents the data type. */ function typeOf(data) { var _a; let internalTag = `Unknown`; try { internalTag = (_a = Object.prototype.toString.call(data)) === null || _a === void 0 ? void 0 : _a.slice(8, -1); } catch (e) { internalTag = `Unknown`; } return internalTag; } exports.typeOf = typeOf; /** * Function for checking if data is a key/value pair object. * * @param data The data being checked. * @returns Whether or not the data is an object. */ function isJsonObject(data) { return typeOf(data) === 'Object'; } exports.isJsonObject = isJsonObject; /** * Function for checking if data is an array object. * * @param data The data being checked. * @returns Whether or not the data is an array. */ function isJsonArray(data) { return typeOf(data) === 'Array'; } exports.isJsonArray = isJsonArray; /** * Retrieve the current log level name. * * @returns The level name. */ function level() { var _a; const input = (((_a = process.env.OZLOGGER_LEVEL) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'debug'); return input in LogLevels_1.LogLevels ? input : 'audit'; } exports.level = level; /** * Check if the log outputs should be colorized. * * @returns Whether or not the output can be colorized. */ function color() { var _a; return !!((_a = process.env.OZLOGGER_COLORS) === null || _a === void 0 ? void 0 : _a.match(/true/i)); } exports.color = color; /** * Check which output should be used for logging. * * @returns Output name to be used. */ function output() { var _a; const input = (((_a = process.env.OZLOGGER_OUTPUT) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'json'); return Outputs_1.Outputs.indexOf(input) < 0 ? 'json' : input; } exports.output = output; /** * Return the current date and time closure. * * @returns The current datetime closure. */ function datetime() { var _a; const withDatetime = !!((_a = process.env.OZLOGGER_DATETIME) === null || _a === void 0 ? void 0 : _a.match(/true/i)); switch (output()) { case 'text': return withDatetime ? () => `${new Date().toISOString()} ` : () => ''; case 'json': return withDatetime ? () => ({ timestamp: new Date().toISOString() }) : () => ({}); } } exports.datetime = datetime; /** * Parse the log server port and interface to bind to. * * @returns The port number and interface address. */ function host() { const input = process.env.OZLOGGER_SERVER || '9898'; let port = 9898; let hostname = 'localhost'; // Format: '9898' if (/^\d+$/.test(input)) { port = parseInt(input); return [port, hostname]; } // Format: ':9898' if (/^:\d+$/.test(input)) { port = parseInt(input.slice(1)); return [port, hostname]; } // Format: '[::1]:9898' if (/^\[.*\]:\d+$/.test(input)) { const [ipv6, p] = input.slice(1, -1).split(']:'); hostname = ipv6; port = parseInt(p); return [port, hostname]; } // Format: '127.0.0.1:9898' if (/^\d+\.\d+\.\d+\.\d+:\d+$/.test(input)) { const [ipv4, p] = input.split(':'); hostname = ipv4; port = parseInt(p); return [port, hostname]; } // Format: 'localhost' or 'localhost:9898' if (/^[^\s:]+(:\d+)?$/.test(input)) { const [domain, p] = input.split(':'); if (domain) hostname = domain; if (p) port = parseInt(p); return [port, hostname]; } throw new Error(`Unsupported HTTP server address (${input})`); } exports.host = host;