UNPKG

takin

Version:

Front end engineering base toolchain and scaffold

417 lines 14.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = exports.createLogger = exports.enableDebugger = exports.createDebugger = exports.COLORS = exports.LogLevels = exports.FILTER_LOGGER_PARAMETERS = void 0; const chalk_1 = __importDefault(require("chalk")); const debug_1 = __importDefault(require("debug")); const lodash_1 = __importStar(require("lodash")); const readline_1 = __importDefault(require("readline")); const util_1 = require("util"); const constants_1 = require("../constants"); const colorModifierSupport_1 = require("../utils/colorModifierSupport"); const isUnicodeSupported_1 = require("../utils/isUnicodeSupported"); const table_1 = require("./table"); __exportStar(require("./table"), exports); /** * 用于过滤日志参数, 并替换为 ******** */ exports.FILTER_LOGGER_PARAMETERS = new Set(); exports.LogLevels = { silent: 0, error: 1, warn: 2, success: 3, info: 4 }; const COLOR_NAMES = { error: 'redBright', warn: 'yellowBright', success: 'greenBright', info: 'cyanBright' }; exports.COLORS = { error: chalk_1.default[COLOR_NAMES.error], warn: chalk_1.default[COLOR_NAMES.warn], success: chalk_1.default[COLOR_NAMES.success], info: chalk_1.default[COLOR_NAMES.info] }; const STREAM = process.stdout; // 日志符号 const LOG_SYMBOLS = (0, isUnicodeSupported_1.isUnicodeSupported)() ? { info: 'ℹ', success: '✔', warn: '⚠', error: '✖' } : { info: 'i', success: '√', warn: '‼', error: '×' }; let currentSpinner = 0; const SPINNERS = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; /** * 创建 debugger * @param namespace - 命名空间 * @returns debugger */ function createDebugger(namespace) { return (0, debug_1.default)(namespace); } exports.createDebugger = createDebugger; /** * 开启特定命名空间的 debugger * @param namespaces - 需要开启 debug 的命名空间 */ function enableDebugger(namespaces) { debug_1.default.enable(namespaces); } exports.enableDebugger = enableDebugger; let lastType; let lastMsg; let sameCount = 0; let isLastUpdate = false; function clearScreen() { const repeatCount = STREAM.rows - 2; const blank = repeatCount > 0 ? '\n'.repeat(repeatCount) : ''; console.log(blank); readline_1.default.cursorTo(STREAM, 0, 0); readline_1.default.clearScreenDown(STREAM); } /** * 清理单行, 仅当上一次 logger 为 update 的情况下 */ function clearScreenLine() { if (isLastUpdate) { STREAM.clearLine(0); STREAM.cursorTo(0); STREAM.moveCursor(0, -1); STREAM.clearLine(0); } } const FILTER_PARAMETERS_REPLACER = '********'; /** * 过滤日志参数,替换为 ********,避免敏感信息泄露,仅支持 对象和 Map * @param obj - 需要过滤的对象 * @param depth - 对象层级 * @returns 过滤后的对象 */ function filterParameters(obj, depth = 10) { if (exports.FILTER_LOGGER_PARAMETERS.size === 0) return obj; if (depth <= 0) return obj; const restDepth = depth - 1; if (lodash_1.default.isMap(obj)) { const map = new Map(); obj.forEach(function (value, key) { if (exports.FILTER_LOGGER_PARAMETERS.has(key)) { map.set(key, FILTER_PARAMETERS_REPLACER); } else { map.set(key, filterParameters(value, restDepth)); } }); return map; } if (lodash_1.default.isPlainObject(obj)) { const newObj = {}; for (const key in obj) { if (exports.FILTER_LOGGER_PARAMETERS.has(key)) { newObj[key] = FILTER_PARAMETERS_REPLACER; } else { newObj[key] = filterParameters(obj[key], restDepth); } } return newObj; } return obj; } /** * 格式化 message, 将非 string 对象转换为字符串 */ function formatMessage(msg, opts) { return typeof msg === 'string' ? msg : (0, util_1.inspect)(filterParameters(msg, (opts === null || opts === void 0 ? void 0 : opts.depth) == null ? undefined : opts === null || opts === void 0 ? void 0 : opts.depth), { depth: opts === null || opts === void 0 ? void 0 : opts.depth }); } /** * 创建日志 * @param level - 日志级别 * @param options - 日志创建选项 * @returns logger 实例 */ function createLogger(level = 'info', options = {}) { if (options.customLogger) { return options.customLogger; } const loggedErrors = new WeakSet(); const warnedMessages = new Set(); const loggerTimes = new Map(); let prefix; let debugPrefix; let allowClearScreen; let thresh; let outputDebug; let allowClear; let clear; let clearLine; // 执行 logger 初始化 init(level, options); /** * 初始化 logger * 允许重复初始化以方便使用方定制 logger 输出格式和信息 */ function init(level = 'info', options = {}) { var _a, _b; prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : `[${constants_1.DEFAULT_NAME}]`; debugPrefix = options.debugPrefix; allowClearScreen = (_b = options.allowClearScreen) !== null && _b !== void 0 ? _b : true; thresh = exports.LogLevels[level]; outputDebug = createDebugger(debugPrefix || prefix); allowClear = allowClearScreen && process.stdout.isTTY && !process.env.CI; clear = allowClear ? clearScreen : () => { }; clearLine = allowClear ? clearScreenLine : () => { }; } function output(type, message, options = {}) { if (thresh >= exports.LogLevels[type]) { const msg = formatMessage(message, options); const method = type === 'info' || type === 'success' ? 'log' : type; let symbol; if ((0, lodash_1.isString)(options.symbol)) { symbol = options.symbol; } else { if (options.update && type !== 'success' && type !== 'error') { symbol = SPINNERS[currentSpinner % SPINNERS.length]; } else { symbol = LOG_SYMBOLS[type]; } } const format = () => { const fullPrefix = options.symbol === false ? prefix : `${prefix} ${symbol}`; const tag = (0, colorModifierSupport_1.isSupportColorModifier)() ? exports.COLORS[type].bold(fullPrefix) : exports.COLORS[type](fullPrefix); let _msg = msg; // 多行对齐 if (options.align) { _msg = _msg .split('\n') .map(function (msgItem, index) { if (index === 0) return msgItem; return ''.padStart(fullPrefix.length + 1, ' ') + msgItem; }) .join('\n'); } if (options.update && allowClear) { isLastUpdate = true; let maxLength = STREAM.columns - fullPrefix.length - 8; maxLength = maxLength < 20 ? 20 : maxLength; _msg = (0, lodash_1.truncate)(_msg, { length: maxLength, omission: '...' }); currentSpinner++; } else { isLastUpdate = false; } // 是否带颜色 _msg = options.color ? exports.COLORS[type](_msg) : _msg; if (options.timestamp) { return `${chalk_1.default.dim(new Date().toLocaleTimeString())} ${tag} ${_msg}`; } else { return `${tag} ${_msg}`; } }; if (options.error) { loggedErrors.add(options.error); } if (type === lastType && msg === lastMsg && !options.update) { sameCount++; clear(); console[method](format(), chalk_1.default.yellow(`(x${sameCount + 1})`)); } else { sameCount = 0; lastMsg = msg; lastType = type; if (options.clear) { clear(); } else if (options.update) { clearLine(); } console[method](format()); } // 输出 debug 错误信息 if (options.error) outputDebug(options.error); } } function mergeOptions(originOpts, newOpts) { return { ...(originOpts || {}), ...(newOpts || {}) }; } const logger = { hasWarned: false, hasErrored: false, options: {}, init, createLoading(msg, opts) { let interval; const loadingLogger = this.withOptions(mergeOptions(opts, { update: true })); let message = msg; return { update(msg) { message = msg; return this; }, start(msg) { if (msg) message = msg; // 先输出一次正常的 info loadingLogger.info(message); this.stop(); interval = setInterval(() => loadingLogger.info(message), 80); return this; }, stop() { if (interval) clearInterval(interval); return this; }, success(msg, opts) { this.stop(); loadingLogger.success(msg, opts); }, fail(msg, opts) { this.stop(); loadingLogger.error(msg, opts); }, error(msg, opts) { this.stop(); loadingLogger.error(msg, opts); } }; }, withOptions(opts) { return { ...logger, options: mergeOptions(this.options, opts) }; }, info(msg, opts) { output('info', msg, mergeOptions(this.options, opts)); }, success(msg, opts) { output('success', msg, mergeOptions(this.options, opts)); }, warn(msg, opts) { logger.hasWarned = true; output('warn', msg, mergeOptions(this.options, opts)); }, warnOnce(msg, opts) { if (warnedMessages.has(msg)) return; logger.hasWarned = true; output('warn', msg, mergeOptions(this.options, opts)); warnedMessages.add(msg); }, error(msg, opts) { logger.hasWarned = true; logger.hasErrored = true; output('error', msg, mergeOptions(this.options, opts)); }, deprecate(deprecatedMsg, hint, error) { logger.hasWarned = true; output('warn', `(!) ${formatMessage(deprecatedMsg, this.options)} ${formatMessage(hint, this.options)}${error ? `\n${error.stack}` : ''}`); }, debug(msg, ...args) { if (outputDebug.enabled) { outputDebug(formatMessage(msg), ...args.map((m) => formatMessage(m, this.options))); // 标记为非更新, 避免执行 loading 时被覆盖 isLastUpdate = false; } }, table(tableOptions, type = 'info', opts) { let msg = new table_1.ConsoleCliTable({ ...tableOptions, ...{ style: { head: [COLOR_NAMES[type]], border: [COLOR_NAMES[type]], ...(tableOptions.style || {}) } } }).render(); const opt = mergeOptions(this.options, opts); // 如果未开启自动对齐, 则追加换行以保证表格打印正确 if (!opt.align) { msg = '\n' + msg; } output(type, msg, opt); }, time(label) { loggerTimes.set(label, process.hrtime.bigint()); }, timeEnd(label) { const prev = loggerTimes.get(label); if (!prev) { outputDebug(`logger.time 缺少标识 '${label}'`); return ''; } const time = process.hrtime.bigint(); const result = `耗时: ${Number(time - prev) / 1000000} ms`; loggerTimes.delete(label); logger.debug(`${label} ${result}`); return result; }, clearScreen(type) { if (thresh >= exports.LogLevels[type]) { clear(); } }, hasErrorLogged(error) { return loggedErrors.has(error); } }; return logger; } exports.createLogger = createLogger; /** * 默认 logger */ exports.logger = createLogger('info', { debugPrefix: constants_1.DEFAULT_NAME, prefix: `[${constants_1.DEFAULT_NAME}]` }).withOptions({ color: false, align: true }); //# sourceMappingURL=index.js.map