@wiajs/core 1.2.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs +125 -160
- package/dist/core.js +124 -158
- package/dist/core.min.js +3 -9
- package/dist/core.mjs +125 -160
- package/dist/jsx-runtime.js +1 -1
- package/package.json +1 -1
- package/util/log.d.ts +113 -0
- package/util/log.js +189 -0
- package/util/tool.js +94 -81
package/dist/core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* wia core
|
|
2
|
+
* wia core v2.1.0
|
|
3
3
|
* (c) 2015-2026 Sibyl Yu and contributors
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -2073,227 +2073,193 @@ class Event {
|
|
|
2073
2073
|
}
|
|
2074
2074
|
}
|
|
2075
2075
|
|
|
2076
|
-
/*!
|
|
2077
|
-
* wia util v3.4.25
|
|
2078
|
-
* (c) 2018-2024 Yan (Sibyl) Yu and Yuxi (Evan) You and wia/vue contributors
|
|
2079
|
-
* Released under the MIT License.
|
|
2080
|
-
*/
|
|
2081
2076
|
/**
|
|
2082
|
-
*
|
|
2083
|
-
*
|
|
2077
|
+
* @typedef {Object} LogOptions
|
|
2078
|
+
* @property {string} m - 模块名称
|
|
2079
|
+
*/
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* @typedef {((...args: any[]) => void) & { debug: (...args: any[])=>void, info: (...args: any[])=>void, warn: (...args: any[])=>void, error: (...args: any[])=>void, err: (...args: any[])=>void }} ScopedLogger
|
|
2084
2083
|
*/
|
|
2085
2084
|
|
|
2086
|
-
|
|
2087
2085
|
/**
|
|
2088
|
-
*
|
|
2089
|
-
|
|
2090
|
-
|
|
2086
|
+
* @typedef {((...args: any[]) => void) & { log: (...args: any[])=>void, debug: (...args: any[])=>void, info: (...args: any[])=>void, warn: (...args: any[])=>void, error: (...args: any[])=>void, err: (...args: any[])=>void, fn: (name: string) => ScopedLogger }} LoggerFn
|
|
2087
|
+
*/
|
|
2088
|
+
|
|
2089
|
+
// 1. 安全地获取开发环境状态(兼容打包工具、浏览器和 Node.js)
|
|
2090
|
+
// 如果 Rspack 注入了 __DEV__,就用注入的值;如果是在 Node.js 下,就回退读取 "production"
|
|
2091
|
+
const isDev = typeof __DEV__ !== 'undefined' ? __DEV__ : "production" !== 'production';
|
|
2092
|
+
|
|
2093
|
+
/**
|
|
2094
|
+
* 前端日志输出,封装 console 日志,简化代码
|
|
2095
|
+
* 自动识别并重排提示符与对象,保持前后端一致性
|
|
2091
2096
|
*/
|
|
2092
2097
|
class Log {
|
|
2093
|
-
/** @type {string}
|
|
2098
|
+
/** @type {string} 模块名称 */
|
|
2094
2099
|
m = ''
|
|
2095
2100
|
|
|
2096
|
-
/** @type {string}
|
|
2097
|
-
|
|
2101
|
+
/** @type {string} 函数名称 */
|
|
2102
|
+
fnName = ''
|
|
2098
2103
|
|
|
2099
2104
|
/**
|
|
2100
|
-
* @param {string} m 模块
|
|
2105
|
+
* @param {string} [m=''] 模块
|
|
2106
|
+
* @param {string} [fnName=''] 函数
|
|
2101
2107
|
*/
|
|
2102
|
-
constructor(m) {
|
|
2108
|
+
constructor(m = '', fnName = '') {
|
|
2103
2109
|
this.m = m;
|
|
2110
|
+
this.fnName = fnName;
|
|
2104
2111
|
}
|
|
2105
2112
|
|
|
2106
2113
|
/**
|
|
2107
|
-
*
|
|
2108
|
-
*
|
|
2109
|
-
* @param {
|
|
2110
|
-
* @returns {
|
|
2114
|
+
* 格式化参数:提取提示符,构建前缀,将对象后置
|
|
2115
|
+
* 格式要求:[模块名称:函数名称]提示符: {对象}
|
|
2116
|
+
* @param {any[]} args
|
|
2117
|
+
* @returns {any[]} 返回处理后传递给 console 的参数数组
|
|
2111
2118
|
*/
|
|
2112
|
-
|
|
2119
|
+
formatArgs(args) {
|
|
2113
2120
|
let R = '';
|
|
2121
|
+
const _ = this;
|
|
2114
2122
|
try {
|
|
2115
|
-
const
|
|
2116
|
-
const
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
if (typeof last === 'object') {
|
|
2123
|
-
;({ desc, fn } = last);
|
|
2124
|
-
} else if (typeof last === 'string') desc = last;
|
|
2125
|
-
if (desc || fn) {
|
|
2126
|
-
fn = fn || _.fn;
|
|
2127
|
-
_.fn = fn;
|
|
2128
|
-
args.pop();
|
|
2129
|
-
}
|
|
2123
|
+
const msgs = [];
|
|
2124
|
+
const objs = [];
|
|
2125
|
+
|
|
2126
|
+
// 1. 将字符串(提示符)和非字符串(对象/数值等)分开
|
|
2127
|
+
for (const arg of args) {
|
|
2128
|
+
if (typeof arg === 'string') msgs.push(arg);
|
|
2129
|
+
else objs.push(arg);
|
|
2130
2130
|
}
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2131
|
+
|
|
2132
|
+
let prefix = '';
|
|
2133
|
+
|
|
2134
|
+
// 2. 添加模块与函数前缀
|
|
2135
|
+
if (_.m) prefix = `[${_.m}${_.fnName ? ':' + _.fnName : ''}]`;
|
|
2136
|
+
else if (_.fnName) prefix = `[:${_.fnName}]`;
|
|
2137
|
+
|
|
2138
|
+
// 3. 拼接提示符
|
|
2139
|
+
const msg = msgs.join(' ');
|
|
2140
|
+
if (msg) prefix += msg;
|
|
2141
|
+
|
|
2142
|
+
R = [];
|
|
2143
|
+
if (prefix) R.push(prefix);
|
|
2144
|
+
R.push(...objs);
|
|
2134
2145
|
} catch (e) {
|
|
2135
|
-
console.error(`
|
|
2146
|
+
console.error(`formatArgs exp:${e.message}`);
|
|
2136
2147
|
}
|
|
2137
2148
|
|
|
2138
2149
|
return R
|
|
2139
2150
|
}
|
|
2140
2151
|
|
|
2141
|
-
/** @param {...any} args
|
|
2152
|
+
/** @param {...any} args */
|
|
2142
2153
|
log(...args) {
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
// clear fn
|
|
2146
|
-
if (args.length === 1 && typeof last === 'object' && last.fn) _.fn = '';
|
|
2147
|
-
else {
|
|
2148
|
-
const desc = _.getDesc(args);
|
|
2149
|
-
console.log(desc, ...args);
|
|
2150
|
-
}
|
|
2154
|
+
// 生产环境安全剔除 (需 Rspack DefinePlugin 注入 __DEV__)
|
|
2155
|
+
if (isDev) console.log(...this.formatArgs(args));
|
|
2151
2156
|
}
|
|
2152
2157
|
|
|
2153
|
-
/** @param {...any} args
|
|
2158
|
+
/** @param {...any} args */
|
|
2154
2159
|
debug(...args) {
|
|
2155
|
-
|
|
2156
|
-
const desc = _.getDesc(args);
|
|
2157
|
-
if (desc) console.log(desc, ...args);
|
|
2158
|
-
else console.log(...args);
|
|
2160
|
+
if (isDev) console.debug(...this.formatArgs(args));
|
|
2159
2161
|
}
|
|
2160
2162
|
|
|
2161
|
-
/** @param {...any} args
|
|
2163
|
+
/** @param {...any} args */
|
|
2162
2164
|
info(...args) {
|
|
2163
|
-
|
|
2164
|
-
const desc = _.getDesc(args);
|
|
2165
|
-
if (desc) console.info(desc, ...args);
|
|
2166
|
-
else console.log(...args);
|
|
2165
|
+
if (isDev) console.info(...this.formatArgs(args));
|
|
2167
2166
|
}
|
|
2168
2167
|
|
|
2169
|
-
/** @param {...any} args
|
|
2168
|
+
/** @param {...any} args */
|
|
2170
2169
|
warn(...args) {
|
|
2171
|
-
|
|
2172
|
-
const { desc, arg } = _.getDesc(args);
|
|
2173
|
-
if (desc) console.warn(desc, ...arg);
|
|
2174
|
-
else console.log(...args);
|
|
2170
|
+
if (isDev) console.warn(...this.formatArgs(args));
|
|
2175
2171
|
}
|
|
2176
2172
|
|
|
2177
|
-
/** @param {...any} args
|
|
2173
|
+
/** @param {...any} args */
|
|
2178
2174
|
trace(...args) {
|
|
2179
|
-
|
|
2180
|
-
const { desc, arg } = _.getDesc(args);
|
|
2181
|
-
if (desc) console.trace(desc, ...arg);
|
|
2182
|
-
else console.trace(...args);
|
|
2175
|
+
if (isDev) console.trace(...this.formatArgs(args));
|
|
2183
2176
|
}
|
|
2184
2177
|
|
|
2185
|
-
/**
|
|
2178
|
+
/** * error 会在生产环境保留
|
|
2179
|
+
* @param {...any} args
|
|
2180
|
+
*/
|
|
2186
2181
|
error(...args) {
|
|
2187
|
-
|
|
2188
|
-
const desc = _.getDesc(args);
|
|
2189
|
-
if (desc) console.error(desc, ...args);
|
|
2190
|
-
else console.log(...args);
|
|
2182
|
+
console.error(...this.formatArgs(args));
|
|
2191
2183
|
}
|
|
2192
2184
|
|
|
2193
2185
|
/**
|
|
2194
|
-
* 用于 catch(e) log.err(e)
|
|
2195
|
-
*
|
|
2186
|
+
* 用于 catch(e) log.err(e) 或 log.err("提示符", e) 或 log.err(e, "提示符")
|
|
2187
|
+
* 自动对齐前缀 [模块:函数] 提示符: Error对象,并保留堆栈
|
|
2188
|
+
* @param {...any} args
|
|
2189
|
+
*/
|
|
2196
2190
|
err(...args) {
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
)
|
|
2203
|
-
args[0] = { exp: args[0].message };
|
|
2204
|
-
_.error(...args);
|
|
2191
|
+
// 生产环境安全输出,不会被 Tree-shaking 摇掉
|
|
2192
|
+
// formatArgs 会自动分离字符串与 Error 对象,并补全冒号
|
|
2193
|
+
const formattedArgs = this.formatArgs(args);
|
|
2194
|
+
|
|
2195
|
+
// 原生打印,保持 stack trace 可点击跳转!
|
|
2196
|
+
console.error(...formattedArgs);
|
|
2205
2197
|
}
|
|
2206
|
-
}
|
|
2207
2198
|
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2199
|
+
/**
|
|
2200
|
+
* 派生函数级别日志实例 (完美对齐后端 log.fn)
|
|
2201
|
+
* @param {string} name 函数名称
|
|
2202
|
+
* @returns {ScopedLogger}
|
|
2203
|
+
*/
|
|
2204
|
+
fn(name) {
|
|
2205
|
+
const scopedLog = new Log(this.m, name);
|
|
2206
|
+
|
|
2207
|
+
/** @type {any} */
|
|
2208
|
+
const R = (...args) => scopedLog.log(...args);
|
|
2209
|
+
|
|
2210
|
+
R.debug = scopedLog.debug.bind(scopedLog);
|
|
2211
|
+
R.info = scopedLog.info.bind(scopedLog);
|
|
2212
|
+
R.warn = scopedLog.warn.bind(scopedLog);
|
|
2213
|
+
R.trace = scopedLog.trace.bind(scopedLog);
|
|
2214
|
+
R.error = scopedLog.error.bind(scopedLog);
|
|
2215
|
+
R.err = scopedLog.err.bind(scopedLog);
|
|
2216
|
+
|
|
2217
|
+
return /** @type {ScopedLogger} */ (R)
|
|
2214
2218
|
}
|
|
2215
|
-
return desc
|
|
2216
2219
|
}
|
|
2217
2220
|
|
|
2221
|
+
// 实例化唯一的全局日志单例
|
|
2222
|
+
const _log = new Log();
|
|
2223
|
+
|
|
2218
2224
|
/**
|
|
2219
2225
|
* 标准日志输出或构建模块日志类实例,用于模块中带[m:xxx]标记日志输出
|
|
2220
|
-
*
|
|
2226
|
+
* 传入 { m: '模块名' } 构建实例,或直接传入参数输出全局日志
|
|
2221
2227
|
* @param {...any} args - params
|
|
2222
2228
|
* returns {*}
|
|
2223
2229
|
*/
|
|
2224
2230
|
function log(...args) {
|
|
2225
2231
|
const last = args.at(-1);
|
|
2226
2232
|
|
|
2227
|
-
//
|
|
2228
|
-
if (args.length
|
|
2229
|
-
const
|
|
2230
|
-
desc ? console.log(desc, ...args) : console.log(...args);
|
|
2231
|
-
return
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
|
-
// 唯一 m 属性,则构造新的 log 实例,这种写法,能被jsDoc识别子属性
|
|
2235
|
-
const lg = new Log(last?.m);
|
|
2236
|
-
/** @param {*} args2 */
|
|
2237
|
-
const R = (...args2) => lg.log(...args2);
|
|
2238
|
-
R.debug = lg.debug.bind(lg);
|
|
2239
|
-
R.info = lg.info.bind(lg);
|
|
2240
|
-
R.warn = lg.warn.bind(lg);
|
|
2241
|
-
R.info = lg.info.bind(lg);
|
|
2242
|
-
R.trace = lg.trace.bind(lg);
|
|
2243
|
-
R.error = lg.error.bind(lg);
|
|
2244
|
-
R.err = lg.err.bind(lg);
|
|
2245
|
-
|
|
2246
|
-
return R
|
|
2247
|
-
}
|
|
2233
|
+
// 1. 如果只有一个参数且带 m 属性,说明是构造 Logger 实例 (如: const log = Log({m: 'User'}))
|
|
2234
|
+
if (args.length === 1 && typeof last === 'object' && last !== null && 'm' in last) {
|
|
2235
|
+
const lg = new Log(last.m);
|
|
2248
2236
|
|
|
2249
|
-
/**
|
|
2250
|
-
|
|
2251
|
-
* @param {...any} args - params */
|
|
2252
|
-
log.err = (...args) => {
|
|
2253
|
-
const desc = getDesc(args);
|
|
2254
|
-
const first = args?.[0];
|
|
2255
|
-
if (
|
|
2256
|
-
first instanceof Error ||
|
|
2257
|
-
(first && first.message && first.cause && first.stack)
|
|
2258
|
-
)
|
|
2259
|
-
args[0] = { exp: args[0].message };
|
|
2260
|
-
desc ? console.error(desc, ...args) : console.error(...args);
|
|
2261
|
-
};
|
|
2237
|
+
/** @type {any} */
|
|
2238
|
+
const R = (...args2) => lg.log(...args2);
|
|
2262
2239
|
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
* @param {...any} args - params */
|
|
2272
|
-
log.warn = (...args) => {
|
|
2273
|
-
const desc = getDesc(args);
|
|
2274
|
-
desc ? console.warn(desc, ...args) : console.warn(...args);
|
|
2275
|
-
};
|
|
2240
|
+
R.log = lg.log.bind(lg);
|
|
2241
|
+
R.debug = lg.debug.bind(lg);
|
|
2242
|
+
R.info = lg.info.bind(lg);
|
|
2243
|
+
R.warn = lg.warn.bind(lg);
|
|
2244
|
+
R.trace = lg.trace.bind(lg);
|
|
2245
|
+
R.error = lg.error.bind(lg);
|
|
2246
|
+
R.err = lg.err.bind(lg);
|
|
2247
|
+
R.fn = lg.fn.bind(lg); // 暴露派生函数作用域方法
|
|
2276
2248
|
|
|
2277
|
-
/**
|
|
2278
|
-
|
|
2279
|
-
log.info = (...args) => {
|
|
2280
|
-
const desc = getDesc(args);
|
|
2281
|
-
desc ? console.info(desc, ...args) : console.info(...args);
|
|
2282
|
-
};
|
|
2249
|
+
return /** @type {LoggerFn} */ (R)
|
|
2250
|
+
}
|
|
2283
2251
|
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
const desc = getDesc(args);
|
|
2288
|
-
desc ? console.log(desc, ...args) : console.log(...args);
|
|
2289
|
-
};
|
|
2252
|
+
// 2. 否则作为全局普通日志直接输出
|
|
2253
|
+
_log.log(...args);
|
|
2254
|
+
}
|
|
2290
2255
|
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
log.
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2256
|
+
// 绑定全局快捷方法,方便直接调用 log.err(e) 等
|
|
2257
|
+
log.err = _log.err.bind(_log);
|
|
2258
|
+
log.error = _log.error.bind(_log);
|
|
2259
|
+
log.warn = _log.warn.bind(_log);
|
|
2260
|
+
log.info = _log.info.bind(_log);
|
|
2261
|
+
log.debug = _log.debug.bind(_log);
|
|
2262
|
+
log.trace = _log.trace.bind(_log);
|
|
2297
2263
|
|
|
2298
2264
|
/**
|
|
2299
2265
|
* 所有页面从该类继承,并必须实现 load 事件!
|
|
@@ -2323,7 +2289,6 @@ log.trace = (...args) => {
|
|
|
2323
2289
|
*
|
|
2324
2290
|
*/
|
|
2325
2291
|
|
|
2326
|
-
|
|
2327
2292
|
class Page extends Event {
|
|
2328
2293
|
constructor(app, name, title, style) {
|
|
2329
2294
|
super(null, [app]);
|
package/dist/jsx-runtime.js
CHANGED
package/package.json
CHANGED
package/util/log.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块日志选项
|
|
3
|
+
*/
|
|
4
|
+
export interface LogOptions {
|
|
5
|
+
/** 模块名称 */
|
|
6
|
+
m: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 派生函数级别的日志实例(支持直接作为函数调用,或调用内部方法)
|
|
11
|
+
*/
|
|
12
|
+
export interface ScopedLogger {
|
|
13
|
+
(...args: any[]): void
|
|
14
|
+
debug(...args: any[]): void
|
|
15
|
+
info(...args: any[]): void
|
|
16
|
+
warn(...args: any[]): void
|
|
17
|
+
error(...args: any[]): void
|
|
18
|
+
err(...args: any[]): void
|
|
19
|
+
trace(...args: any[]): void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 模块级别的日志实例(带有派生子函数 .fn 的能力)
|
|
24
|
+
*/
|
|
25
|
+
export interface LoggerFn {
|
|
26
|
+
(...args: any[]): void
|
|
27
|
+
log(...args: any[]): void
|
|
28
|
+
debug(...args: any[]): void
|
|
29
|
+
info(...args: any[]): void
|
|
30
|
+
warn(...args: any[]): void
|
|
31
|
+
error(...args: any[]): void
|
|
32
|
+
err(...args: any[]): void
|
|
33
|
+
trace(...args: any[]): void
|
|
34
|
+
/**
|
|
35
|
+
* 派生函数级别日志实例 (完美对齐后端 log.fn)
|
|
36
|
+
* @param name 函数名称
|
|
37
|
+
*/
|
|
38
|
+
fn(name: string): ScopedLogger
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 前端日志输出核心类
|
|
43
|
+
* 自动识别并重排提示符与对象,保持前后端一致性
|
|
44
|
+
*/
|
|
45
|
+
export class Log {
|
|
46
|
+
/** 模块名称 */
|
|
47
|
+
m: string
|
|
48
|
+
/** 函数名称 */
|
|
49
|
+
fnName: string
|
|
50
|
+
|
|
51
|
+
constructor(m?: string, fnName?: string)
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 格式化参数:提取提示符,构建前缀,将对象后置
|
|
55
|
+
* 格式要求:[模块名称:函数名称]提示符: {对象}
|
|
56
|
+
* @param args
|
|
57
|
+
* @returns 返回处理后传递给 console 的参数数组
|
|
58
|
+
*/
|
|
59
|
+
formatArgs(args: any[]): any[]
|
|
60
|
+
|
|
61
|
+
log(...args: any[]): void
|
|
62
|
+
debug(...args: any[]): void
|
|
63
|
+
info(...args: any[]): void
|
|
64
|
+
warn(...args: any[]): void
|
|
65
|
+
trace(...args: any[]): void
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* error 会在生产环境保留
|
|
69
|
+
*/
|
|
70
|
+
error(...args: any[]): void
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 用于 catch(e) log.err(e) 或 log.err("提示符", e) 或 log.err(e, "提示符")
|
|
74
|
+
* 自动对齐前缀 [模块:函数] 提示符: Error对象,并保留堆栈
|
|
75
|
+
*/
|
|
76
|
+
err(...args: any[]): void
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 派生函数级别日志实例
|
|
80
|
+
* @param name 函数名称
|
|
81
|
+
*/
|
|
82
|
+
fn(name: string): ScopedLogger
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 全局的 log 实例接口
|
|
87
|
+
* 实现了函数重载,支持构造日志模块对象,或是直接调用
|
|
88
|
+
*/
|
|
89
|
+
export interface GlobalLogger {
|
|
90
|
+
/**
|
|
91
|
+
* 构建模块日志类实例
|
|
92
|
+
* @example const uploaderLog = log({ m: 'uploader' })
|
|
93
|
+
*/
|
|
94
|
+
(opt: LogOptions): LoggerFn
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 标准日志输出 (无模块前缀)
|
|
98
|
+
* @example log('普通提示', { data: 1 })
|
|
99
|
+
*/
|
|
100
|
+
(...args: any[]): void
|
|
101
|
+
|
|
102
|
+
err(...args: any[]): void
|
|
103
|
+
error(...args: any[]): void
|
|
104
|
+
warn(...args: any[]): void
|
|
105
|
+
info(...args: any[]): void
|
|
106
|
+
debug(...args: any[]): void
|
|
107
|
+
trace(...args: any[]): void
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 标准日志输出或构建模块日志类实例
|
|
112
|
+
*/
|
|
113
|
+
export const log: GlobalLogger
|
package/util/log.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} LogOptions
|
|
3
|
+
* @property {string} m - 模块名称
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {((...args: any[]) => void) & { debug: (...args: any[])=>void, info: (...args: any[])=>void, warn: (...args: any[])=>void, error: (...args: any[])=>void, err: (...args: any[])=>void }} ScopedLogger
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {((...args: any[]) => void) & { log: (...args: any[])=>void, debug: (...args: any[])=>void, info: (...args: any[])=>void, warn: (...args: any[])=>void, error: (...args: any[])=>void, err: (...args: any[])=>void, fn: (name: string) => ScopedLogger }} LoggerFn
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// 1. 安全地获取开发环境状态(兼容打包工具、浏览器和 Node.js)
|
|
15
|
+
// 如果 Rspack 注入了 __DEV__,就用注入的值;如果是在 Node.js 下,就回退读取 process.env.NODE_ENV
|
|
16
|
+
const isDev = typeof __DEV__ !== 'undefined' ? __DEV__ : process.env.NODE_ENV !== 'production'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 前端日志输出,封装 console 日志,简化代码
|
|
20
|
+
* 自动识别并重排提示符与对象,保持前后端一致性
|
|
21
|
+
*/
|
|
22
|
+
class Log {
|
|
23
|
+
/** @type {string} 模块名称 */
|
|
24
|
+
m = ''
|
|
25
|
+
|
|
26
|
+
/** @type {string} 函数名称 */
|
|
27
|
+
fnName = ''
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} [m=''] 模块
|
|
31
|
+
* @param {string} [fnName=''] 函数
|
|
32
|
+
*/
|
|
33
|
+
constructor(m = '', fnName = '') {
|
|
34
|
+
this.m = m
|
|
35
|
+
this.fnName = fnName
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 格式化参数:提取提示符,构建前缀,将对象后置
|
|
40
|
+
* 格式要求:[模块名称:函数名称]提示符: {对象}
|
|
41
|
+
* @param {any[]} args
|
|
42
|
+
* @returns {any[]} 返回处理后传递给 console 的参数数组
|
|
43
|
+
*/
|
|
44
|
+
formatArgs(args) {
|
|
45
|
+
let R = ''
|
|
46
|
+
const _ = this
|
|
47
|
+
try {
|
|
48
|
+
const msgs = []
|
|
49
|
+
const objs = []
|
|
50
|
+
|
|
51
|
+
// 1. 将字符串(提示符)和非字符串(对象/数值等)分开
|
|
52
|
+
for (const arg of args) {
|
|
53
|
+
if (typeof arg === 'string') msgs.push(arg)
|
|
54
|
+
else objs.push(arg)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let prefix = ''
|
|
58
|
+
|
|
59
|
+
// 2. 添加模块与函数前缀
|
|
60
|
+
if (_.m) prefix = `[${_.m}${_.fnName ? ':' + _.fnName : ''}]`
|
|
61
|
+
else if (_.fnName) prefix = `[:${_.fnName}]`
|
|
62
|
+
|
|
63
|
+
// 3. 拼接提示符
|
|
64
|
+
const msg = msgs.join(' ')
|
|
65
|
+
if (msg) prefix += msg
|
|
66
|
+
|
|
67
|
+
R = []
|
|
68
|
+
if (prefix) R.push(prefix)
|
|
69
|
+
R.push(...objs)
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error(`formatArgs exp:${e.message}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return R
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** @param {...any} args */
|
|
78
|
+
log(...args) {
|
|
79
|
+
// 生产环境安全剔除 (需 Rspack DefinePlugin 注入 __DEV__)
|
|
80
|
+
if (isDev) console.log(...this.formatArgs(args))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** @param {...any} args */
|
|
84
|
+
debug(...args) {
|
|
85
|
+
if (isDev) console.debug(...this.formatArgs(args))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** @param {...any} args */
|
|
89
|
+
info(...args) {
|
|
90
|
+
if (isDev) console.info(...this.formatArgs(args))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** @param {...any} args */
|
|
94
|
+
warn(...args) {
|
|
95
|
+
if (isDev) console.warn(...this.formatArgs(args))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** @param {...any} args */
|
|
99
|
+
trace(...args) {
|
|
100
|
+
if (isDev) console.trace(...this.formatArgs(args))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** * error 会在生产环境保留
|
|
104
|
+
* @param {...any} args
|
|
105
|
+
*/
|
|
106
|
+
error(...args) {
|
|
107
|
+
console.error(...this.formatArgs(args))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 用于 catch(e) log.err(e) 或 log.err("提示符", e) 或 log.err(e, "提示符")
|
|
112
|
+
* 自动对齐前缀 [模块:函数] 提示符: Error对象,并保留堆栈
|
|
113
|
+
* @param {...any} args
|
|
114
|
+
*/
|
|
115
|
+
err(...args) {
|
|
116
|
+
// 生产环境安全输出,不会被 Tree-shaking 摇掉
|
|
117
|
+
// formatArgs 会自动分离字符串与 Error 对象,并补全冒号
|
|
118
|
+
const formattedArgs = this.formatArgs(args)
|
|
119
|
+
|
|
120
|
+
// 原生打印,保持 stack trace 可点击跳转!
|
|
121
|
+
console.error(...formattedArgs)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 派生函数级别日志实例 (完美对齐后端 log.fn)
|
|
126
|
+
* @param {string} name 函数名称
|
|
127
|
+
* @returns {ScopedLogger}
|
|
128
|
+
*/
|
|
129
|
+
fn(name) {
|
|
130
|
+
const scopedLog = new Log(this.m, name)
|
|
131
|
+
|
|
132
|
+
/** @type {any} */
|
|
133
|
+
const R = (...args) => scopedLog.log(...args)
|
|
134
|
+
|
|
135
|
+
R.debug = scopedLog.debug.bind(scopedLog)
|
|
136
|
+
R.info = scopedLog.info.bind(scopedLog)
|
|
137
|
+
R.warn = scopedLog.warn.bind(scopedLog)
|
|
138
|
+
R.trace = scopedLog.trace.bind(scopedLog)
|
|
139
|
+
R.error = scopedLog.error.bind(scopedLog)
|
|
140
|
+
R.err = scopedLog.err.bind(scopedLog)
|
|
141
|
+
|
|
142
|
+
return /** @type {ScopedLogger} */ (R)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 实例化唯一的全局日志单例
|
|
147
|
+
const _log = new Log()
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 标准日志输出或构建模块日志类实例,用于模块中带[m:xxx]标记日志输出
|
|
151
|
+
* 传入 { m: '模块名' } 构建实例,或直接传入参数输出全局日志
|
|
152
|
+
* @param {...any} args - params
|
|
153
|
+
* returns {*}
|
|
154
|
+
*/
|
|
155
|
+
function log(...args) {
|
|
156
|
+
const last = args.at(-1)
|
|
157
|
+
|
|
158
|
+
// 1. 如果只有一个参数且带 m 属性,说明是构造 Logger 实例 (如: const log = Log({m: 'User'}))
|
|
159
|
+
if (args.length === 1 && typeof last === 'object' && last !== null && 'm' in last) {
|
|
160
|
+
const lg = new Log(last.m)
|
|
161
|
+
|
|
162
|
+
/** @type {any} */
|
|
163
|
+
const R = (...args2) => lg.log(...args2)
|
|
164
|
+
|
|
165
|
+
R.log = lg.log.bind(lg)
|
|
166
|
+
R.debug = lg.debug.bind(lg)
|
|
167
|
+
R.info = lg.info.bind(lg)
|
|
168
|
+
R.warn = lg.warn.bind(lg)
|
|
169
|
+
R.trace = lg.trace.bind(lg)
|
|
170
|
+
R.error = lg.error.bind(lg)
|
|
171
|
+
R.err = lg.err.bind(lg)
|
|
172
|
+
R.fn = lg.fn.bind(lg) // 暴露派生函数作用域方法
|
|
173
|
+
|
|
174
|
+
return /** @type {LoggerFn} */ (R)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 2. 否则作为全局普通日志直接输出
|
|
178
|
+
_log.log(...args)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 绑定全局快捷方法,方便直接调用 log.err(e) 等
|
|
182
|
+
log.err = _log.err.bind(_log)
|
|
183
|
+
log.error = _log.error.bind(_log)
|
|
184
|
+
log.warn = _log.warn.bind(_log)
|
|
185
|
+
log.info = _log.info.bind(_log)
|
|
186
|
+
log.debug = _log.debug.bind(_log)
|
|
187
|
+
log.trace = _log.trace.bind(_log)
|
|
188
|
+
|
|
189
|
+
export {log, Log}
|