takin
Version:
Front end engineering base toolchain and scaffold
417 lines • 14.9 kB
JavaScript
;
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