@pangza/log 0.0.0-stage → 1.0.1
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/README.md +2 -2
- package/dist/decorators.d.ts +7 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +14 -0
- package/dist/decorators.js.map +1 -0
- package/dist/flag.d.ts +2 -0
- package/dist/flag.d.ts.map +1 -0
- package/dist/flag.js +6 -0
- package/dist/flag.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/ip.d.ts +23 -0
- package/dist/ip.d.ts.map +1 -0
- package/dist/ip.js +138 -0
- package/dist/ip.js.map +1 -0
- package/dist/recorder.d.ts +26 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +150 -0
- package/dist/recorder.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +26 -0
- package/dist/types.js.map +1 -0
- package/package.json +36 -4
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pangza/log
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
操作审计日志
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,eAAoB,GAAG,eAAe,CAQ3E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogDecorator = LogDecorator;
|
|
4
|
+
const metadata_1 = require("@pangza/core/Application/metadata");
|
|
5
|
+
/**
|
|
6
|
+
* 方法装饰器:为接口声明操作日志。
|
|
7
|
+
* 推荐从 `@pangza/core/Application` 导入同名装饰器。
|
|
8
|
+
*/
|
|
9
|
+
function LogDecorator(options = {}) {
|
|
10
|
+
return (target, propertyKey) => {
|
|
11
|
+
(0, metadata_1.mergeMethodLog)(target.constructor, String(propertyKey), options);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":";;AAOA,oCAQC;AAfD,gEAAmE;AAGnE;;;GAGG;AACH,SAAgB,YAAY,CAAC,UAA2B,EAAE;IACxD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,IAAA,yBAAc,EACX,MAAiB,CAAC,WAAW,EAC9B,MAAM,CAAC,WAAW,CAAC,EACnB,OAAO,CACR,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/flag.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.d.ts","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/flag.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LOG_MIDDLEWARE_FLAG = void 0;
|
|
4
|
+
var moduleFlags_1 = require("@pangza/core/moduleFlags");
|
|
5
|
+
Object.defineProperty(exports, "LOG_MIDDLEWARE_FLAG", { enumerable: true, get: function () { return moduleFlags_1.LOG_MIDDLEWARE_FLAG; } });
|
|
6
|
+
//# sourceMappingURL=flag.js.map
|
package/dist/flag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":";;;AAAA,wDAA+D;AAAtD,kHAAA,mBAAmB,OAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
import type { LogModuleOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Log 模块工厂(对齐 Auth)。
|
|
5
|
+
* 通过 Application.registry(Log()) 注册后,
|
|
6
|
+
* 路由 option.log / @Log 才会真正落库。
|
|
7
|
+
*/
|
|
8
|
+
export default function Log(options?: LogModuleOptions): (_req: Request, _res: Response, next: NextFunction) => void;
|
|
9
|
+
export { LOG_MIDDLEWARE_FLAG } from "./flag";
|
|
10
|
+
export { configureLog, recordOperationLog, isLogRegistered, getLogOptions, } from "./recorder";
|
|
11
|
+
export { getClientIp, resolveIpAddress, normalizeIp, isInternalIp, } from "./ip";
|
|
12
|
+
export { BusinessType, OperType } from "./types";
|
|
13
|
+
export type { LogModuleOptions, LogRecordOption, BusinessTypeValue, OperTypeValue, OperationLogRecord, } from "./types";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,OAAO,GAAE,gBAAqB,UAG9B,OAAO,QAAQ,QAAQ,QAAQ,YAAY,UAUtE;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,GACb,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperType = exports.BusinessType = exports.isInternalIp = exports.normalizeIp = exports.resolveIpAddress = exports.getClientIp = exports.getLogOptions = exports.isLogRegistered = exports.recordOperationLog = exports.configureLog = exports.LOG_MIDDLEWARE_FLAG = void 0;
|
|
4
|
+
exports.default = Log;
|
|
5
|
+
const recorder_1 = require("./recorder");
|
|
6
|
+
const flag_1 = require("./flag");
|
|
7
|
+
/**
|
|
8
|
+
* Log 模块工厂(对齐 Auth)。
|
|
9
|
+
* 通过 Application.registry(Log()) 注册后,
|
|
10
|
+
* 路由 option.log / @Log 才会真正落库。
|
|
11
|
+
*/
|
|
12
|
+
function Log(options = {}) {
|
|
13
|
+
(0, recorder_1.configureLog)(options);
|
|
14
|
+
const middleware = (_req, _res, next) => {
|
|
15
|
+
next();
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(middleware, flag_1.LOG_MIDDLEWARE_FLAG, {
|
|
18
|
+
value: true,
|
|
19
|
+
enumerable: false,
|
|
20
|
+
});
|
|
21
|
+
return middleware;
|
|
22
|
+
}
|
|
23
|
+
var flag_2 = require("./flag");
|
|
24
|
+
Object.defineProperty(exports, "LOG_MIDDLEWARE_FLAG", { enumerable: true, get: function () { return flag_2.LOG_MIDDLEWARE_FLAG; } });
|
|
25
|
+
var recorder_2 = require("./recorder");
|
|
26
|
+
Object.defineProperty(exports, "configureLog", { enumerable: true, get: function () { return recorder_2.configureLog; } });
|
|
27
|
+
Object.defineProperty(exports, "recordOperationLog", { enumerable: true, get: function () { return recorder_2.recordOperationLog; } });
|
|
28
|
+
Object.defineProperty(exports, "isLogRegistered", { enumerable: true, get: function () { return recorder_2.isLogRegistered; } });
|
|
29
|
+
Object.defineProperty(exports, "getLogOptions", { enumerable: true, get: function () { return recorder_2.getLogOptions; } });
|
|
30
|
+
var ip_1 = require("./ip");
|
|
31
|
+
Object.defineProperty(exports, "getClientIp", { enumerable: true, get: function () { return ip_1.getClientIp; } });
|
|
32
|
+
Object.defineProperty(exports, "resolveIpAddress", { enumerable: true, get: function () { return ip_1.resolveIpAddress; } });
|
|
33
|
+
Object.defineProperty(exports, "normalizeIp", { enumerable: true, get: function () { return ip_1.normalizeIp; } });
|
|
34
|
+
Object.defineProperty(exports, "isInternalIp", { enumerable: true, get: function () { return ip_1.isInternalIp; } });
|
|
35
|
+
var types_1 = require("./types");
|
|
36
|
+
Object.defineProperty(exports, "BusinessType", { enumerable: true, get: function () { return types_1.BusinessType; } });
|
|
37
|
+
Object.defineProperty(exports, "OperType", { enumerable: true, get: function () { return types_1.OperType; } });
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAUA,sBAaC;AAtBD,yCAA0C;AAC1C,iCAA6C;AAG7C;;;;GAIG;AACH,SAAwB,GAAG,CAAC,UAA4B,EAAE;IACxD,IAAA,uBAAY,EAAC,OAAO,CAAC,CAAC;IAEtB,MAAM,UAAU,GAAG,CAAC,IAAa,EAAE,IAAc,EAAE,IAAkB,EAAE,EAAE;QACvE,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;IAEF,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,0BAAmB,EAAE;QACrD,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,KAAK;KAClB,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,+BAA6C;AAApC,2GAAA,mBAAmB,OAAA;AAC5B,uCAKoB;AAJlB,wGAAA,YAAY,OAAA;AACZ,8GAAA,kBAAkB,OAAA;AAClB,2GAAA,eAAe,OAAA;AACf,yGAAA,aAAa,OAAA;AAEf,2BAKc;AAJZ,iGAAA,WAAW,OAAA;AACX,sGAAA,gBAAgB,OAAA;AAChB,iGAAA,WAAW,OAAA;AACX,kGAAA,YAAY,OAAA;AAEd,iCAAiD;AAAxC,qGAAA,YAAY,OAAA;AAAE,iGAAA,QAAQ,OAAA"}
|
package/dist/ip.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Request } from "express";
|
|
2
|
+
/** 是否内网 / 本机 */
|
|
3
|
+
export declare function isInternalIp(ip: string): boolean;
|
|
4
|
+
/** 规范化:去掉 IPv6 映射前缀、方括号 */
|
|
5
|
+
export declare function normalizeIp(ip: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* 从请求解析客户端 IP。
|
|
8
|
+
* - `server.trustProxy: false`(默认):只用直连 socket / Express req.ip,忽略转发头,防伪造绕过限流。
|
|
9
|
+
* - `server.trustProxy: true`:优先读 X-Forwarded-For / X-Real-IP 等(须前面有可信反代)。
|
|
10
|
+
* @param options.trustProxy 覆盖全局配置(测试用)
|
|
11
|
+
*/
|
|
12
|
+
export declare function getClientIp(req: Request, options?: {
|
|
13
|
+
trustProxy?: boolean;
|
|
14
|
+
}): string;
|
|
15
|
+
export interface IpRegionResult {
|
|
16
|
+
country?: string;
|
|
17
|
+
province?: string;
|
|
18
|
+
city?: string;
|
|
19
|
+
isp?: string;
|
|
20
|
+
}
|
|
21
|
+
/** 离线解析 IP 归属地(内网返回「内网IP」) */
|
|
22
|
+
export declare function resolveIpAddress(ip: string): string;
|
|
23
|
+
//# sourceMappingURL=ip.d.ts.map
|
package/dist/ip.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip.d.ts","sourceRoot":"","sources":["../src/ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAiBvC,gBAAgB;AAChB,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAahD;AAED,2BAA2B;AAC3B,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAe9C;AA6BD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,MAAM,CAeR;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAqBnD"}
|
package/dist/ip.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isInternalIp = isInternalIp;
|
|
7
|
+
exports.normalizeIp = normalizeIp;
|
|
8
|
+
exports.getClientIp = getClientIp;
|
|
9
|
+
exports.resolveIpAddress = resolveIpAddress;
|
|
10
|
+
const ip2region_1 = __importDefault(require("ip2region"));
|
|
11
|
+
const config_1 = require("@pangza/core/config");
|
|
12
|
+
const Logger_1 = require("@pangza/core/Logger");
|
|
13
|
+
const log = (0, Logger_1.getLogger)("OperLog.IP");
|
|
14
|
+
let searcher = null;
|
|
15
|
+
function getSearcher() {
|
|
16
|
+
if (!searcher) {
|
|
17
|
+
// 包内自带库;关闭 IPv6 降低内存
|
|
18
|
+
searcher = new ip2region_1.default({ disableIpv6: true });
|
|
19
|
+
}
|
|
20
|
+
return searcher;
|
|
21
|
+
}
|
|
22
|
+
/** 是否内网 / 本机 */
|
|
23
|
+
function isInternalIp(ip) {
|
|
24
|
+
const v = normalizeIp(ip);
|
|
25
|
+
if (!v)
|
|
26
|
+
return true;
|
|
27
|
+
if (v === "127.0.0.1" || v === "localhost" || v === "0.0.0.0")
|
|
28
|
+
return true;
|
|
29
|
+
if (v.startsWith("10."))
|
|
30
|
+
return true;
|
|
31
|
+
if (v.startsWith("192.168."))
|
|
32
|
+
return true;
|
|
33
|
+
if (v.startsWith("169.254."))
|
|
34
|
+
return true;
|
|
35
|
+
const m = v.match(/^172\.(\d+)\./);
|
|
36
|
+
if (m) {
|
|
37
|
+
const n = Number(m[1]);
|
|
38
|
+
if (n >= 16 && n <= 31)
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
/** 规范化:去掉 IPv6 映射前缀、方括号 */
|
|
44
|
+
function normalizeIp(ip) {
|
|
45
|
+
let v = String(ip || "").trim();
|
|
46
|
+
if (!v)
|
|
47
|
+
return "";
|
|
48
|
+
if (v.startsWith("[") && v.endsWith("]")) {
|
|
49
|
+
v = v.slice(1, -1);
|
|
50
|
+
}
|
|
51
|
+
if (v.startsWith("::ffff:")) {
|
|
52
|
+
v = v.slice(7);
|
|
53
|
+
}
|
|
54
|
+
if (v === "::1")
|
|
55
|
+
return "127.0.0.1";
|
|
56
|
+
// 去掉端口(极少见)
|
|
57
|
+
if (/^\d+\.\d+\.\d+\.\d+:\d+$/.test(v)) {
|
|
58
|
+
v = v.split(":")[0];
|
|
59
|
+
}
|
|
60
|
+
return v;
|
|
61
|
+
}
|
|
62
|
+
function pickFromHeader(raw) {
|
|
63
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
64
|
+
// x-forwarded-for: client, proxy1, proxy2 — 取最左侧客户端
|
|
65
|
+
const first = raw.split(",")[0].trim();
|
|
66
|
+
return normalizeIp(first);
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(raw) && raw.length > 0) {
|
|
69
|
+
return normalizeIp(String(raw[0]));
|
|
70
|
+
}
|
|
71
|
+
return "";
|
|
72
|
+
}
|
|
73
|
+
function socketIp(req) {
|
|
74
|
+
const candidates = [
|
|
75
|
+
req.ip,
|
|
76
|
+
req.socket?.remoteAddress,
|
|
77
|
+
req.connection?.remoteAddress,
|
|
78
|
+
];
|
|
79
|
+
for (const raw of candidates) {
|
|
80
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
81
|
+
const ip = normalizeIp(raw);
|
|
82
|
+
if (ip)
|
|
83
|
+
return ip;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 从请求解析客户端 IP。
|
|
90
|
+
* - `server.trustProxy: false`(默认):只用直连 socket / Express req.ip,忽略转发头,防伪造绕过限流。
|
|
91
|
+
* - `server.trustProxy: true`:优先读 X-Forwarded-For / X-Real-IP 等(须前面有可信反代)。
|
|
92
|
+
* @param options.trustProxy 覆盖全局配置(测试用)
|
|
93
|
+
*/
|
|
94
|
+
function getClientIp(req, options) {
|
|
95
|
+
const useProxy = options?.trustProxy ?? config_1.trustProxy;
|
|
96
|
+
if (useProxy) {
|
|
97
|
+
const forwarded = [
|
|
98
|
+
req.headers["x-forwarded-for"],
|
|
99
|
+
req.headers["x-real-ip"],
|
|
100
|
+
req.headers["cf-connecting-ip"],
|
|
101
|
+
req.headers["x-client-ip"],
|
|
102
|
+
];
|
|
103
|
+
for (const raw of forwarded) {
|
|
104
|
+
const ip = pickFromHeader(raw);
|
|
105
|
+
if (ip)
|
|
106
|
+
return ip;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return socketIp(req);
|
|
110
|
+
}
|
|
111
|
+
/** 离线解析 IP 归属地(内网返回「内网IP」) */
|
|
112
|
+
function resolveIpAddress(ip) {
|
|
113
|
+
const v = normalizeIp(ip);
|
|
114
|
+
if (!v)
|
|
115
|
+
return "";
|
|
116
|
+
if (isInternalIp(v))
|
|
117
|
+
return "内网IP";
|
|
118
|
+
try {
|
|
119
|
+
const res = getSearcher().search(v);
|
|
120
|
+
if (!res)
|
|
121
|
+
return "未知";
|
|
122
|
+
const parts = [res.country, res.province, res.city, res.isp]
|
|
123
|
+
.map((s) => String(s || "").trim())
|
|
124
|
+
.filter((s) => s && s !== "0");
|
|
125
|
+
// 去重:省市区可能重复
|
|
126
|
+
const uniq = [];
|
|
127
|
+
for (const p of parts) {
|
|
128
|
+
if (!uniq.includes(p))
|
|
129
|
+
uniq.push(p);
|
|
130
|
+
}
|
|
131
|
+
return uniq.join(" ") || "未知";
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
log.warn({ err: e, ip: v }, "IP 归属地解析失败");
|
|
135
|
+
return "未知";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=ip.js.map
|
package/dist/ip.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip.js","sourceRoot":"","sources":["../src/ip.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Request } from "express";
|
|
2
|
+
import type { LogModuleOptions, LogRecordOption } from "./types";
|
|
3
|
+
export declare function configureLog(options?: LogModuleOptions): void;
|
|
4
|
+
export declare function isLogRegistered(): boolean;
|
|
5
|
+
export declare function getLogOptions(): Required<Pick<LogModuleOptions, "enabled" | "silent">> & LogModuleOptions;
|
|
6
|
+
export interface RecordLogContext {
|
|
7
|
+
req: Request;
|
|
8
|
+
option: LogRecordOption;
|
|
9
|
+
result?: unknown;
|
|
10
|
+
error?: unknown;
|
|
11
|
+
statusCode: number | string;
|
|
12
|
+
startTime: number;
|
|
13
|
+
controllerName?: string;
|
|
14
|
+
/**
|
|
15
|
+
* 请求结束前同步抓取的客户端 IP(避免 setImmediate 后 socket 已释放导致为空)。
|
|
16
|
+
* 不传则回退从 req 再解析一次。
|
|
17
|
+
*/
|
|
18
|
+
clientIp?: string;
|
|
19
|
+
userAgent?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 异步写入操作日志(失败不影响业务)。
|
|
23
|
+
* 持久化由 Log({ writer }) 注入,framework 不依赖 business Service。
|
|
24
|
+
*/
|
|
25
|
+
export declare function recordOperationLog(ctx: RecordLogContext): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIvC,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAEhB,MAAM,SAAS,CAAC;AAsBjB,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAWjE;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,aAAa,8EAE5B;AAkCD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E7E"}
|
package/dist/recorder.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureLog = configureLog;
|
|
4
|
+
exports.isLogRegistered = isLogRegistered;
|
|
5
|
+
exports.getLogOptions = getLogOptions;
|
|
6
|
+
exports.recordOperationLog = recordOperationLog;
|
|
7
|
+
const auth_1 = require("@pangza/auth");
|
|
8
|
+
const Logger_1 = require("@pangza/core/Logger");
|
|
9
|
+
const ip_1 = require("./ip");
|
|
10
|
+
const types_1 = require("./types");
|
|
11
|
+
const log = (0, Logger_1.getLogger)("OperLog");
|
|
12
|
+
const DEFAULT_EXCLUDE = [
|
|
13
|
+
"password",
|
|
14
|
+
"oldPassword",
|
|
15
|
+
"newPassword",
|
|
16
|
+
"confirmPassword",
|
|
17
|
+
"attachments",
|
|
18
|
+
];
|
|
19
|
+
let moduleOptions = {
|
|
20
|
+
enabled: true,
|
|
21
|
+
silent: false,
|
|
22
|
+
excludeParamNames: [],
|
|
23
|
+
};
|
|
24
|
+
let logRegistered = false;
|
|
25
|
+
function configureLog(options = {}) {
|
|
26
|
+
moduleOptions = {
|
|
27
|
+
...moduleOptions,
|
|
28
|
+
...options,
|
|
29
|
+
enabled: options.enabled ?? moduleOptions.enabled,
|
|
30
|
+
silent: options.silent ?? moduleOptions.silent,
|
|
31
|
+
excludeParamNames: options.excludeParamNames ?? moduleOptions.excludeParamNames,
|
|
32
|
+
writer: options.writer ?? moduleOptions.writer,
|
|
33
|
+
};
|
|
34
|
+
logRegistered = true;
|
|
35
|
+
}
|
|
36
|
+
function isLogRegistered() {
|
|
37
|
+
return logRegistered;
|
|
38
|
+
}
|
|
39
|
+
function getLogOptions() {
|
|
40
|
+
return moduleOptions;
|
|
41
|
+
}
|
|
42
|
+
function shouldRecord(option) {
|
|
43
|
+
if (!logRegistered || !moduleOptions.enabled)
|
|
44
|
+
return false;
|
|
45
|
+
if (!option || option.ignore)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
function omitSensitive(value, exclude) {
|
|
50
|
+
if (value == null)
|
|
51
|
+
return value;
|
|
52
|
+
if (Array.isArray(value)) {
|
|
53
|
+
return value.map((item) => omitSensitive(item, exclude));
|
|
54
|
+
}
|
|
55
|
+
if (typeof value === "object") {
|
|
56
|
+
const obj = value;
|
|
57
|
+
const next = {};
|
|
58
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
59
|
+
if (exclude.includes(k))
|
|
60
|
+
continue;
|
|
61
|
+
next[k] = omitSensitive(v, exclude);
|
|
62
|
+
}
|
|
63
|
+
return next;
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function safeJson(value, exclude, max = 2000) {
|
|
68
|
+
try {
|
|
69
|
+
const text = JSON.stringify(omitSensitive(value, exclude) ?? null);
|
|
70
|
+
return text.length > max ? text.slice(0, max) : text;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return "";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 异步写入操作日志(失败不影响业务)。
|
|
78
|
+
* 持久化由 Log({ writer }) 注入,framework 不依赖 business Service。
|
|
79
|
+
*/
|
|
80
|
+
async function recordOperationLog(ctx) {
|
|
81
|
+
if (!shouldRecord(ctx.option))
|
|
82
|
+
return;
|
|
83
|
+
const writer = moduleOptions.writer;
|
|
84
|
+
if (!writer) {
|
|
85
|
+
// 未注入 writer(如删除 business)时静默跳过,便于纯净启动
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const exclude = [
|
|
90
|
+
...DEFAULT_EXCLUDE,
|
|
91
|
+
...(moduleOptions.excludeParamNames ?? []),
|
|
92
|
+
...(ctx.option.excludeParamNames ?? []),
|
|
93
|
+
];
|
|
94
|
+
let username = "";
|
|
95
|
+
let avatar = "";
|
|
96
|
+
try {
|
|
97
|
+
const session = await auth_1.AuthUtil.getSession();
|
|
98
|
+
if (session) {
|
|
99
|
+
username = session.username || String(session.loginId ?? "");
|
|
100
|
+
avatar = session.avatar || "";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// ignore
|
|
105
|
+
}
|
|
106
|
+
const params = ctx.req.method === "GET"
|
|
107
|
+
? safeJson(ctx.req.query, exclude)
|
|
108
|
+
: safeJson(ctx.req.body, exclude);
|
|
109
|
+
let errorMessage = "";
|
|
110
|
+
if (ctx.error) {
|
|
111
|
+
errorMessage =
|
|
112
|
+
ctx.error instanceof Error
|
|
113
|
+
? ctx.error.message || ctx.error.name
|
|
114
|
+
: String(ctx.error);
|
|
115
|
+
if (errorMessage.length > 2000)
|
|
116
|
+
errorMessage = errorMessage.slice(0, 2000);
|
|
117
|
+
}
|
|
118
|
+
const ip = ctx.clientIp || (0, ip_1.getClientIp)(ctx.req);
|
|
119
|
+
const address = (0, ip_1.resolveIpAddress)(ip);
|
|
120
|
+
const userAgent = (ctx.userAgent ??
|
|
121
|
+
String(ctx.req.headers["user-agent"] || "")).slice(0, 255);
|
|
122
|
+
const row = {
|
|
123
|
+
title: ctx.option.title || "",
|
|
124
|
+
username,
|
|
125
|
+
avatar,
|
|
126
|
+
business: String(ctx.option.business ?? types_1.BusinessType.OTHER),
|
|
127
|
+
oper: String(ctx.option.oper ?? types_1.OperType.PC),
|
|
128
|
+
params,
|
|
129
|
+
response: safeJson(ctx.result, exclude),
|
|
130
|
+
methodName: ctx.req.method,
|
|
131
|
+
controllerName: ctx.controllerName || "",
|
|
132
|
+
status: String(ctx.statusCode),
|
|
133
|
+
timeLong: Math.max(0, Date.now() - ctx.startTime),
|
|
134
|
+
ip,
|
|
135
|
+
address,
|
|
136
|
+
userAgent,
|
|
137
|
+
url: String(ctx.req.originalUrl || ctx.req.url || "").slice(0, 255),
|
|
138
|
+
errorMessage,
|
|
139
|
+
deleteFlag: 0,
|
|
140
|
+
createTime: new Date(),
|
|
141
|
+
};
|
|
142
|
+
await writer(row);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
if (!moduleOptions.silent) {
|
|
146
|
+
log.error({ err: e }, "记录操作日志失败");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":";;AA8BA,oCAWC;AAED,0CAEC;AAED,sCAEC;AAsDD,gDA4EC;AAlLD,uCAAwC;AACxC,gDAAgD;AAChD,6BAAqD;AAMrD,mCAAiD;AAEjD,MAAM,GAAG,GAAG,IAAA,kBAAS,EAAC,SAAS,CAAC,CAAC;AAEjC,MAAM,eAAe,GAAG;IACtB,UAAU;IACV,aAAa;IACb,aAAa;IACb,iBAAiB;IACjB,aAAa;CACd,CAAC;AAEF,IAAI,aAAa,GACI;IACnB,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,KAAK;IACb,iBAAiB,EAAE,EAAE;CACtB,CAAC;AAEF,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,SAAgB,YAAY,CAAC,UAA4B,EAAE;IACzD,aAAa,GAAG;QACd,GAAG,aAAa;QAChB,GAAG,OAAO;QACV,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO;QACjD,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM;QAC9C,iBAAiB,EACf,OAAO,CAAC,iBAAiB,IAAI,aAAa,CAAC,iBAAiB;QAC9D,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM;KAC/C,CAAC;IACF,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC;AAED,SAAgB,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAgB,aAAa;IAC3B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,YAAY,CAAC,MAAwB;IAC5C,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAAc,EAAE,OAAiB;IACtD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,SAAS;YAClC,IAAI,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc,EAAE,OAAiB,EAAE,GAAG,GAAG,IAAI;IAC7D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAkBD;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CAAC,GAAqB;IAC5D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO;IAEtC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,uCAAuC;QACvC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG;YACd,GAAG,eAAe;YAClB,GAAG,CAAC,aAAa,CAAC,iBAAiB,IAAI,EAAE,CAAC;YAC1C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC;SACxC,CAAC;QAEF,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,eAAQ,CAAC,UAAU,EAAE,CAAC;YAC5C,IAAI,OAAO,EAAE,CAAC;gBACZ,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;gBAC7D,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;YAChC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GACV,GAAG,CAAC,GAAG,CAAC,MAAM,KAAK,KAAK;YACtB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC;YAClC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEtC,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,YAAY;gBACV,GAAG,CAAC,KAAK,YAAY,KAAK;oBACxB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI;oBACrC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,IAAI,YAAY,CAAC,MAAM,GAAG,IAAI;gBAAE,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,EAAE,GAAG,GAAG,CAAC,QAAQ,IAAI,IAAA,gBAAW,EAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,IAAA,qBAAgB,EAAC,EAAE,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,CAChB,GAAG,CAAC,SAAS;YACb,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAC5C,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAEhB,MAAM,GAAG,GAAuB;YAC9B,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC7B,QAAQ;YACR,MAAM;YACN,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,oBAAY,CAAC,KAAK,CAAC;YAC3D,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,gBAAQ,CAAC,EAAE,CAAC;YAC5C,MAAM;YACN,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;YACvC,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM;YAC1B,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,EAAE;YACxC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;YAC9B,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC;YACjD,EAAE;YACF,OAAO;YACP,SAAS;YACT,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YACnE,YAAY;YACZ,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,IAAI,IAAI,EAAE;SACvB,CAAC;QAEF,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 业务类型(入库为字符串序数)
|
|
3
|
+
* CREATE=0 … LOGIN=8 … OTHER=9
|
|
4
|
+
*/
|
|
5
|
+
export declare const BusinessType: {
|
|
6
|
+
readonly CREATE: 0;
|
|
7
|
+
readonly UPDATE: 1;
|
|
8
|
+
readonly DELETE: 2;
|
|
9
|
+
readonly READ: 3;
|
|
10
|
+
readonly LIST: 4;
|
|
11
|
+
readonly UPLOAD: 5;
|
|
12
|
+
readonly EXPORT: 6;
|
|
13
|
+
readonly IMPORT: 7;
|
|
14
|
+
readonly LOGIN: 8;
|
|
15
|
+
readonly OTHER: 9;
|
|
16
|
+
};
|
|
17
|
+
export type BusinessTypeValue = (typeof BusinessType)[keyof typeof BusinessType];
|
|
18
|
+
/** 操作端 */
|
|
19
|
+
export declare const OperType: {
|
|
20
|
+
readonly MOBILE: 0;
|
|
21
|
+
readonly PC: 1;
|
|
22
|
+
readonly OTHER: 2;
|
|
23
|
+
};
|
|
24
|
+
export type OperTypeValue = (typeof OperType)[keyof typeof OperType];
|
|
25
|
+
/** 路由 / 装饰器上的日志配置 */
|
|
26
|
+
export interface LogRecordOption {
|
|
27
|
+
/** 操作标题 */
|
|
28
|
+
title?: string;
|
|
29
|
+
/** 业务类型序数,默认 OTHER */
|
|
30
|
+
business?: BusinessTypeValue | number;
|
|
31
|
+
/** 操作端序数,默认 PC */
|
|
32
|
+
oper?: OperTypeValue | number;
|
|
33
|
+
/** 额外排除的参数名(密码等默认已排除) */
|
|
34
|
+
excludeParamNames?: string[];
|
|
35
|
+
/** 为 true 时本接口不记日志 */
|
|
36
|
+
ignore?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Log() 工厂全局配置 */
|
|
39
|
+
export interface LogModuleOptions {
|
|
40
|
+
/** 是否启用(默认 true) */
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
/** 默认排除字段 */
|
|
43
|
+
excludeParamNames?: string[];
|
|
44
|
+
/** 异步写入失败是否打印 */
|
|
45
|
+
silent?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* 业务侧注入的落库实现(framework 不依赖具体 Service)。
|
|
48
|
+
* 未配置时只组装日志字段,不写库。
|
|
49
|
+
*/
|
|
50
|
+
writer?: (row: OperationLogRecord) => void | Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/** 操作日志落库行(由 framework 组装,business 负责持久化) */
|
|
53
|
+
export interface OperationLogRecord {
|
|
54
|
+
title: string;
|
|
55
|
+
username: string;
|
|
56
|
+
avatar: string;
|
|
57
|
+
business: string;
|
|
58
|
+
oper: string;
|
|
59
|
+
params: string;
|
|
60
|
+
response: string;
|
|
61
|
+
methodName: string;
|
|
62
|
+
controllerName: string;
|
|
63
|
+
status: string;
|
|
64
|
+
timeLong: number;
|
|
65
|
+
ip: string;
|
|
66
|
+
address: string;
|
|
67
|
+
userAgent: string;
|
|
68
|
+
url: string;
|
|
69
|
+
errorMessage: string;
|
|
70
|
+
deleteFlag: number;
|
|
71
|
+
createTime: Date;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAEjF,UAAU;AACV,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAErE,qBAAqB;AACrB,MAAM,WAAW,eAAe;IAC9B,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,QAAQ,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACtC,kBAAkB;IAClB,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAC9B,yBAAyB;IACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,sBAAsB;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,mBAAmB;AACnB,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa;IACb,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,6CAA6C;AAC7C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OperType = exports.BusinessType = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 业务类型(入库为字符串序数)
|
|
6
|
+
* CREATE=0 … LOGIN=8 … OTHER=9
|
|
7
|
+
*/
|
|
8
|
+
exports.BusinessType = {
|
|
9
|
+
CREATE: 0,
|
|
10
|
+
UPDATE: 1,
|
|
11
|
+
DELETE: 2,
|
|
12
|
+
READ: 3,
|
|
13
|
+
LIST: 4,
|
|
14
|
+
UPLOAD: 5,
|
|
15
|
+
EXPORT: 6,
|
|
16
|
+
IMPORT: 7,
|
|
17
|
+
LOGIN: 8,
|
|
18
|
+
OTHER: 9,
|
|
19
|
+
};
|
|
20
|
+
/** 操作端 */
|
|
21
|
+
exports.OperType = {
|
|
22
|
+
MOBILE: 0,
|
|
23
|
+
PC: 1,
|
|
24
|
+
OTHER: 2,
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,YAAY,GAAG;IAC1B,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACA,CAAC;AAIX,UAAU;AACG,QAAA,QAAQ,GAAG;IACtB,MAAM,EAAE,CAAC;IACT,EAAE,EAAE,CAAC;IACL,KAAK,EAAE,CAAC;CACA,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pangza/log",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "操作审计日志",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json",
|
|
14
|
+
"./*": {
|
|
15
|
+
"types": "./dist/*.d.ts",
|
|
16
|
+
"require": "./dist/*.js",
|
|
17
|
+
"default": "./dist/*.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.json",
|
|
26
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@pangza/core": "^1.0.1",
|
|
30
|
+
"ip2region": "^2.3.0"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18"
|
|
37
|
+
}
|
|
38
|
+
}
|