@xfe-repo/bff-transform 1.0.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/README.md +3 -0
- package/dist/chunk-G2JFFY2W.mjs +103 -0
- package/dist/chunk-MWZOUQAS.mjs +51 -0
- package/dist/chunk-NZ6LDQJI.mjs +564 -0
- package/dist/chunk-O7SEPPUS.mjs +23 -0
- package/dist/chunk-Q7G5RLD4.mjs +9 -0
- package/dist/chunk-V62BSXTW.mjs +28 -0
- package/dist/chunk-XUGPHFIH.mjs +49 -0
- package/dist/chunk-YP5H6IG4.mjs +130 -0
- package/dist/index.d.mts +79 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +1042 -0
- package/dist/index.mjs +147 -0
- package/dist/transform.decorators.d.mts +13 -0
- package/dist/transform.decorators.d.ts +13 -0
- package/dist/transform.decorators.js +50 -0
- package/dist/transform.decorators.mjs +9 -0
- package/dist/transform.interceptor.d.mts +16 -0
- package/dist/transform.interceptor.d.ts +16 -0
- package/dist/transform.interceptor.js +289 -0
- package/dist/transform.interceptor.mjs +10 -0
- package/dist/transform.iplugin.d.mts +22 -0
- package/dist/transform.iplugin.d.ts +22 -0
- package/dist/transform.iplugin.js +72 -0
- package/dist/transform.iplugin.mjs +9 -0
- package/dist/transform.metadata-storage.d.mts +9 -0
- package/dist/transform.metadata-storage.d.ts +9 -0
- package/dist/transform.metadata-storage.js +55 -0
- package/dist/transform.metadata-storage.mjs +7 -0
- package/dist/transform.module.d.mts +14 -0
- package/dist/transform.module.d.ts +14 -0
- package/dist/transform.module.js +887 -0
- package/dist/transform.module.mjs +12 -0
- package/dist/transform.plugin.manager.d.mts +21 -0
- package/dist/transform.plugin.manager.d.ts +21 -0
- package/dist/transform.plugin.manager.js +247 -0
- package/dist/transform.plugin.manager.mjs +9 -0
- package/dist/traverse.utils.d.mts +15 -0
- package/dist/traverse.utils.d.ts +15 -0
- package/dist/traverse.utils.js +124 -0
- package/dist/traverse.utils.mjs +7 -0
- package/package.json +50 -0
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
32
|
+
|
|
33
|
+
// src/transform.module.ts
|
|
34
|
+
var transform_module_exports = {};
|
|
35
|
+
__export(transform_module_exports, {
|
|
36
|
+
TransformModule: () => TransformModule
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(transform_module_exports);
|
|
39
|
+
var import_common5 = require("@nestjs/common");
|
|
40
|
+
var import_core3 = require("@nestjs/core");
|
|
41
|
+
|
|
42
|
+
// src/privacy/privacy.plugin.ts
|
|
43
|
+
var import_common = require("@nestjs/common");
|
|
44
|
+
|
|
45
|
+
// src/transform.iplugin.ts
|
|
46
|
+
var INJECT_TRANSFORM_PLUGINS = "INJECT_TRANSFORM_PLUGINS";
|
|
47
|
+
var _ITransformPlugin = class _ITransformPlugin {
|
|
48
|
+
/**
|
|
49
|
+
* 初始化插件
|
|
50
|
+
* 该方法会在插件被注册时调用
|
|
51
|
+
* 可以用于插件的初始化逻辑,例如加载配置、注册事件等
|
|
52
|
+
* 如果插件不需要初始化逻辑,可以不实现该方法
|
|
53
|
+
* @param request
|
|
54
|
+
*/
|
|
55
|
+
initialize(_request) {
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 执行前的钩子函数
|
|
59
|
+
* @returns {boolean} 返回 true 表示需要执行该插件,false 则不执行
|
|
60
|
+
* 这个方法可以用于判断插件是否需要在当前数据上执行操作
|
|
61
|
+
* 例如:可以根据插件的配置选项或数据状态来决定是否执行
|
|
62
|
+
* 如果返回 false,则该插件在当前数据上不执行任何操作
|
|
63
|
+
* 如果返回 true,则会执行 execute 方法
|
|
64
|
+
*/
|
|
65
|
+
executeBefore(_request) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 执行后的钩子函数
|
|
70
|
+
* 这个方法会在所有数据处理完成后被调用
|
|
71
|
+
* 可以用于清理资源或执行一些收尾工作
|
|
72
|
+
*/
|
|
73
|
+
executeAfter(_request) {
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
__name(_ITransformPlugin, "ITransformPlugin");
|
|
77
|
+
/**
|
|
78
|
+
* 插件的名称
|
|
79
|
+
* 用于标识插件,避免重复注册
|
|
80
|
+
* 每个插件必须有唯一的名称
|
|
81
|
+
*/
|
|
82
|
+
__publicField(_ITransformPlugin, "pluginName");
|
|
83
|
+
var ITransformPlugin = _ITransformPlugin;
|
|
84
|
+
|
|
85
|
+
// src/privacy/desensitize.tool.ts
|
|
86
|
+
var desensitizeMobile = /* @__PURE__ */ __name((mobile) => {
|
|
87
|
+
if (!mobile) return "";
|
|
88
|
+
return String(mobile).replace(/(\d{3})\d*(\d{4})/, "$1****$2");
|
|
89
|
+
}, "desensitizeMobile");
|
|
90
|
+
var desensitizeName = /* @__PURE__ */ __name((name = "", format = "firstAndLast") => {
|
|
91
|
+
const str = String(name || "").trim();
|
|
92
|
+
const len = str.length;
|
|
93
|
+
if (format === "first") {
|
|
94
|
+
return str.replace(/(?<=.)./g, "*");
|
|
95
|
+
}
|
|
96
|
+
if (format === "all") {
|
|
97
|
+
return "*";
|
|
98
|
+
}
|
|
99
|
+
if (format === "firstAndLast") {
|
|
100
|
+
if (len < 3) return str;
|
|
101
|
+
return `${str[0] || ""}${"*".repeat(len - 2)}${str[len - 1] || ""}`;
|
|
102
|
+
}
|
|
103
|
+
if (format === "pre2AndLast") {
|
|
104
|
+
if (len < 4) return str;
|
|
105
|
+
return `${str.slice(0, 2) || ""}${"*".repeat(len - 3)}${str[len - 1] || ""}`;
|
|
106
|
+
}
|
|
107
|
+
if (format === "maxFourLetter") {
|
|
108
|
+
if (len < 3) return `${str[0] || ""}*`;
|
|
109
|
+
return str.replace(/^(.).+(.)$/g, "$1**$2");
|
|
110
|
+
}
|
|
111
|
+
return str;
|
|
112
|
+
}, "desensitizeName");
|
|
113
|
+
var desensitizeEnterpriseName = /* @__PURE__ */ __name((str) => {
|
|
114
|
+
str = String(str || "").trim();
|
|
115
|
+
const len = str?.length;
|
|
116
|
+
if (!str || len < 3) return str;
|
|
117
|
+
return `${str.substring(0, 2)}${"*".repeat(len - 3)}${str[len - 1] || ""}`;
|
|
118
|
+
}, "desensitizeEnterpriseName");
|
|
119
|
+
var desensitizeEnterpriseNo = /* @__PURE__ */ __name((str) => {
|
|
120
|
+
if (!str) return str;
|
|
121
|
+
return str.replace(/SAAS\d+(?=\d{4})/, "SAAS****");
|
|
122
|
+
}, "desensitizeEnterpriseNo");
|
|
123
|
+
var desensitizeAddress = /* @__PURE__ */ __name((str = "", maskAll = false) => {
|
|
124
|
+
if (!str) return str;
|
|
125
|
+
if (maskAll) {
|
|
126
|
+
return "*".repeat(str.length);
|
|
127
|
+
}
|
|
128
|
+
return str.replace(/\d+(?=[室|号|楼])/g, "**");
|
|
129
|
+
}, "desensitizeAddress");
|
|
130
|
+
var desensitizePrice = /* @__PURE__ */ __name((len = 3, showUnit) => {
|
|
131
|
+
return `${showUnit ? "\xA5" : ""} ${"*".repeat(len)}`;
|
|
132
|
+
}, "desensitizePrice");
|
|
133
|
+
var desensitizeAmount = /* @__PURE__ */ __name((_value, options) => {
|
|
134
|
+
const { length = 3, showUnit = false } = options || {};
|
|
135
|
+
return `${showUnit ? "\xA5" : ""} ${"*".repeat(length)}`;
|
|
136
|
+
}, "desensitizeAmount");
|
|
137
|
+
var desensitizeNameAll = /* @__PURE__ */ __name((name = "") => {
|
|
138
|
+
return desensitizeName(name, "all");
|
|
139
|
+
}, "desensitizeNameAll");
|
|
140
|
+
var desensitizeUtil = {
|
|
141
|
+
mobile: desensitizeMobile,
|
|
142
|
+
name: desensitizeName,
|
|
143
|
+
enterpriseName: desensitizeEnterpriseName,
|
|
144
|
+
enterpriseNo: desensitizeEnterpriseNo,
|
|
145
|
+
address: desensitizeAddress,
|
|
146
|
+
price: desensitizePrice,
|
|
147
|
+
/** 和 price / desensitizeAmount 调用执行结果一致,但方法封装参数不一致 */
|
|
148
|
+
amount: desensitizeAmount,
|
|
149
|
+
nameAll: desensitizeNameAll
|
|
150
|
+
};
|
|
151
|
+
var desensitize_tool_default = desensitizeUtil;
|
|
152
|
+
|
|
153
|
+
// src/privacy/apply/desensitize.ts
|
|
154
|
+
function applyDesensitize(data, fieldName, originalValue, options, userPermission) {
|
|
155
|
+
const { permissionCode, method, params } = options;
|
|
156
|
+
if (originalValue == null) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (permissionCode && userPermission?.includes(permissionCode)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const desensitizeFn = desensitize_tool_default[method];
|
|
164
|
+
data[fieldName] = desensitizeFn(originalValue, params);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error("\u8131\u654F\u5931\u8D25:", error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
__name(applyDesensitize, "applyDesensitize");
|
|
170
|
+
|
|
171
|
+
// src/privacy/utils.ts
|
|
172
|
+
var ENCRYPTION_KEY = "Ff3UCEPfizZmCjke1Xfi";
|
|
173
|
+
function encryptValue(value) {
|
|
174
|
+
try {
|
|
175
|
+
const stringValue = String(value || "");
|
|
176
|
+
const key = Buffer.from(ENCRYPTION_KEY);
|
|
177
|
+
const data = Buffer.from(stringValue);
|
|
178
|
+
const result = Buffer.alloc(data.length);
|
|
179
|
+
for (let i = 0; i < data.length; i++) {
|
|
180
|
+
result[i] = data[i] ^ key[i % key.length];
|
|
181
|
+
}
|
|
182
|
+
return result.toString("base64");
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.error("\u52A0\u5BC6\u5931\u8D25:", error);
|
|
185
|
+
return `error:${Buffer.from(String(value || "")).toString("base64")}`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
__name(encryptValue, "encryptValue");
|
|
189
|
+
|
|
190
|
+
// src/privacy/apply/encryption.ts
|
|
191
|
+
function applyEncryption(data, fieldName, originalValue, options, userPermission) {
|
|
192
|
+
const { permissionCode } = options;
|
|
193
|
+
data[fieldName] = null;
|
|
194
|
+
const encryptedFieldName = `${fieldName}Encrypted`;
|
|
195
|
+
data[encryptedFieldName] = null;
|
|
196
|
+
const hasPermission = userPermission?.includes(permissionCode);
|
|
197
|
+
if (hasPermission && originalValue != null) {
|
|
198
|
+
try {
|
|
199
|
+
const stringValue = String(originalValue);
|
|
200
|
+
const encryptedValue = encryptValue(stringValue);
|
|
201
|
+
data[encryptedFieldName] = encryptedValue;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error("\u52A0\u5BC6\u5931\u8D25:", error);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
__name(applyEncryption, "applyEncryption");
|
|
208
|
+
|
|
209
|
+
// src/privacy/apply/isPermitted.ts
|
|
210
|
+
function applyIsPermitted(data, fieldName, options, userPermission) {
|
|
211
|
+
const { permissionCode, condition = /* @__PURE__ */ __name((_data) => true, "condition") } = options;
|
|
212
|
+
const hasRequiredPermission = !permissionCode || (userPermission?.includes(permissionCode) ?? false);
|
|
213
|
+
data[fieldName] = hasRequiredPermission && condition(data);
|
|
214
|
+
}
|
|
215
|
+
__name(applyIsPermitted, "applyIsPermitted");
|
|
216
|
+
|
|
217
|
+
// src/privacy/privacy.metadata-storage.ts
|
|
218
|
+
var import_class_transformer = require("class-transformer");
|
|
219
|
+
|
|
220
|
+
// src/transform.metadata-storage.ts
|
|
221
|
+
var classTransformer = __toESM(require("class-transformer/cjs/storage"));
|
|
222
|
+
var defaultMetadataStorage2 = classTransformer.defaultMetadataStorage;
|
|
223
|
+
var _TransformMetadataStorage = class _TransformMetadataStorage {
|
|
224
|
+
constructor() {
|
|
225
|
+
/** 继承原实例数据 */
|
|
226
|
+
__publicField(this, "metadataStorage", defaultMetadataStorage2);
|
|
227
|
+
}
|
|
228
|
+
getMetadataStorage() {
|
|
229
|
+
return this.metadataStorage;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
__name(_TransformMetadataStorage, "TransformMetadataStorage");
|
|
233
|
+
var TransformMetadataStorage = _TransformMetadataStorage;
|
|
234
|
+
|
|
235
|
+
// src/privacy/privacy.metadata-storage.ts
|
|
236
|
+
var PrivacyTransformEnum = /* @__PURE__ */ function(PrivacyTransformEnum2) {
|
|
237
|
+
PrivacyTransformEnum2["PrivacyEncrypt"] = "PrivacyEncrypt";
|
|
238
|
+
PrivacyTransformEnum2["PrivacyDesensitize"] = "PrivacyDesensitize";
|
|
239
|
+
PrivacyTransformEnum2["PrivacyIsPermitted"] = "PrivacyIsPermitted";
|
|
240
|
+
return PrivacyTransformEnum2;
|
|
241
|
+
}({});
|
|
242
|
+
var _a;
|
|
243
|
+
var PrivacyTransformMetadataStorage = (_a = class extends TransformMetadataStorage {
|
|
244
|
+
/**
|
|
245
|
+
* 添加隐私协议转换元数据
|
|
246
|
+
* @param metadata 隐私协议转换元数据
|
|
247
|
+
*/
|
|
248
|
+
addPrivacyMetadata(metadata) {
|
|
249
|
+
this.getMetadataStorage().addTransformMetadata(metadata);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* 查找隐私协议转换元数据
|
|
253
|
+
* @param target
|
|
254
|
+
* @param propertyName
|
|
255
|
+
* @param transformationType
|
|
256
|
+
* @returns
|
|
257
|
+
*/
|
|
258
|
+
findPrivacyMetadata(target, propertyName, transformName) {
|
|
259
|
+
const unionQueryMetadatas = this.getMetadataStorage().findTransformMetadatas(target, propertyName, import_class_transformer.TransformationType.PLAIN_TO_CLASS);
|
|
260
|
+
return unionQueryMetadatas.find((meta) => meta.options?.transformName === transformName);
|
|
261
|
+
}
|
|
262
|
+
}, __name(_a, "PrivacyTransformMetadataStorage"), _a);
|
|
263
|
+
var privacyMetadataStorage = new PrivacyTransformMetadataStorage();
|
|
264
|
+
|
|
265
|
+
// src/privacy/privacy.plugin.ts
|
|
266
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
267
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
268
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
269
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
270
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
271
|
+
}
|
|
272
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
273
|
+
var _PrivacyPlugin = class _PrivacyPlugin extends ITransformPlugin {
|
|
274
|
+
execute(request, { parent, key, value }) {
|
|
275
|
+
const userPermission = request.user?.permission || [];
|
|
276
|
+
this.collectAndExcuteFields(parent, key, value, userPermission);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* 处理对象的隐私字段
|
|
280
|
+
* @param data 待处理的对象数据
|
|
281
|
+
* @param privacyFields 隐私字段元数据
|
|
282
|
+
* @param userPermission 当前用户信息
|
|
283
|
+
*/
|
|
284
|
+
collectAndExcuteFields(data, key, value, userPermission) {
|
|
285
|
+
if (typeof key !== "string") return;
|
|
286
|
+
const targetClass = data?.constructor;
|
|
287
|
+
if (!targetClass) return;
|
|
288
|
+
const originalValue = value;
|
|
289
|
+
const encryptOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyEncrypt)?.options;
|
|
290
|
+
if (encryptOptions) {
|
|
291
|
+
applyEncryption(data, key, originalValue, encryptOptions, userPermission);
|
|
292
|
+
}
|
|
293
|
+
const desensitizeOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyDesensitize)?.options;
|
|
294
|
+
if (desensitizeOptions) {
|
|
295
|
+
applyDesensitize(data, key, originalValue, desensitizeOptions, userPermission);
|
|
296
|
+
}
|
|
297
|
+
const isPermittedOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyIsPermitted)?.options;
|
|
298
|
+
if (isPermittedOptions) {
|
|
299
|
+
applyIsPermitted(data, key, isPermittedOptions, userPermission);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
__name(_PrivacyPlugin, "PrivacyPlugin");
|
|
304
|
+
__publicField(_PrivacyPlugin, "pluginName", _PrivacyPlugin.name);
|
|
305
|
+
var PrivacyPlugin = _PrivacyPlugin;
|
|
306
|
+
PrivacyPlugin = _ts_decorate([
|
|
307
|
+
(0, import_common.Injectable)()
|
|
308
|
+
], PrivacyPlugin);
|
|
309
|
+
|
|
310
|
+
// src/transform.interceptor.ts
|
|
311
|
+
var import_common3 = require("@nestjs/common");
|
|
312
|
+
var import_operators = require("rxjs/operators");
|
|
313
|
+
|
|
314
|
+
// src/transform.plugin.manager.ts
|
|
315
|
+
var import_bff_core = require("@xfe-repo/bff-core");
|
|
316
|
+
var import_common2 = require("@nestjs/common");
|
|
317
|
+
var import_core = require("@nestjs/core");
|
|
318
|
+
|
|
319
|
+
// src/traverse.utils.ts
|
|
320
|
+
function traverse(obj, callback, options = {}) {
|
|
321
|
+
const { maxDepth = Infinity, detectCircular = false, method = "iterative" } = options;
|
|
322
|
+
if (method === "recursive") {
|
|
323
|
+
recursiveTraverse(obj, callback, maxDepth, detectCircular);
|
|
324
|
+
} else {
|
|
325
|
+
iterativeTraverse(obj, callback, maxDepth, detectCircular);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
__name(traverse, "traverse");
|
|
329
|
+
function recursiveTraverse(current, callback, maxDepth, detectCircular, path = [], parent = null, seen = /* @__PURE__ */ new WeakSet()) {
|
|
330
|
+
if (path.length > maxDepth) return;
|
|
331
|
+
const key = path.length > 0 ? path[path.length - 1] : null;
|
|
332
|
+
callback({
|
|
333
|
+
value: current,
|
|
334
|
+
key,
|
|
335
|
+
path,
|
|
336
|
+
parent
|
|
337
|
+
});
|
|
338
|
+
if (detectCircular && typeof current === "object" && current !== null) {
|
|
339
|
+
if (seen.has(current)) return;
|
|
340
|
+
seen.add(current);
|
|
341
|
+
}
|
|
342
|
+
if (current !== null && typeof current === "object" && path.length < maxDepth) {
|
|
343
|
+
if (Array.isArray(current)) {
|
|
344
|
+
for (let i = 0; i < current.length; i++) {
|
|
345
|
+
recursiveTraverse(current[i], callback, maxDepth, detectCircular, [
|
|
346
|
+
...path,
|
|
347
|
+
i
|
|
348
|
+
], current, seen);
|
|
349
|
+
}
|
|
350
|
+
} else {
|
|
351
|
+
for (const [k, v] of Object.entries(current)) {
|
|
352
|
+
recursiveTraverse(v, callback, maxDepth, detectCircular, [
|
|
353
|
+
...path,
|
|
354
|
+
k
|
|
355
|
+
], current, seen);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
__name(recursiveTraverse, "recursiveTraverse");
|
|
361
|
+
function iterativeTraverse(root, callback, maxDepth, detectCircular) {
|
|
362
|
+
const stack = [
|
|
363
|
+
{
|
|
364
|
+
value: root,
|
|
365
|
+
path: [],
|
|
366
|
+
parent: null
|
|
367
|
+
}
|
|
368
|
+
];
|
|
369
|
+
const seen = detectCircular ? /* @__PURE__ */ new WeakSet() : null;
|
|
370
|
+
while (stack.length > 0) {
|
|
371
|
+
const { value, path, parent } = stack.pop();
|
|
372
|
+
if (path.length > maxDepth) continue;
|
|
373
|
+
const key = path.length > 0 ? path[path.length - 1] : null;
|
|
374
|
+
callback({
|
|
375
|
+
value,
|
|
376
|
+
key,
|
|
377
|
+
path,
|
|
378
|
+
parent
|
|
379
|
+
});
|
|
380
|
+
if (value !== null && typeof value === "object" && path.length < maxDepth) {
|
|
381
|
+
if (detectCircular) {
|
|
382
|
+
if (seen.has(value)) continue;
|
|
383
|
+
seen.add(value);
|
|
384
|
+
}
|
|
385
|
+
if (Array.isArray(value)) {
|
|
386
|
+
for (let i = value.length - 1; i >= 0; i--) {
|
|
387
|
+
stack.push({
|
|
388
|
+
value: value[i],
|
|
389
|
+
path: [
|
|
390
|
+
...path,
|
|
391
|
+
i
|
|
392
|
+
],
|
|
393
|
+
parent: value
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
} else {
|
|
397
|
+
const keys = Object.keys(value);
|
|
398
|
+
for (let i = keys.length - 1; i >= 0; i--) {
|
|
399
|
+
const k = keys[i];
|
|
400
|
+
stack.push({
|
|
401
|
+
value: value[k],
|
|
402
|
+
path: [
|
|
403
|
+
...path,
|
|
404
|
+
k
|
|
405
|
+
],
|
|
406
|
+
parent: value
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
__name(iterativeTraverse, "iterativeTraverse");
|
|
414
|
+
|
|
415
|
+
// src/transform.plugin.manager.ts
|
|
416
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
417
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
418
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
419
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
420
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
421
|
+
}
|
|
422
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
423
|
+
function _ts_metadata(k, v) {
|
|
424
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
425
|
+
}
|
|
426
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
427
|
+
function _ts_param(paramIndex, decorator) {
|
|
428
|
+
return function(target, key) {
|
|
429
|
+
decorator(target, key, paramIndex);
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
__name(_ts_param, "_ts_param");
|
|
433
|
+
var _TransformPluginManager = class _TransformPluginManager {
|
|
434
|
+
constructor(ctx, moduleRef, plugins) {
|
|
435
|
+
__publicField(this, "ctx");
|
|
436
|
+
__publicField(this, "moduleRef");
|
|
437
|
+
__publicField(this, "logger", new import_common2.Logger(_TransformPluginManager.name));
|
|
438
|
+
__publicField(this, "plugins", []);
|
|
439
|
+
this.ctx = ctx;
|
|
440
|
+
this.moduleRef = moduleRef;
|
|
441
|
+
this.registerAsyncPlugins(plugins);
|
|
442
|
+
}
|
|
443
|
+
async registerAsyncPlugins(plugins) {
|
|
444
|
+
const uniquePlugins = /* @__PURE__ */ new Map();
|
|
445
|
+
for (const plugin of plugins) {
|
|
446
|
+
if (!plugin.pluginName) {
|
|
447
|
+
this.logger.error(`${plugin.name} \u7F3A\u5C11\u63D2\u4EF6\u540D\u79F0 static readonly pluginName \u5C5E\u6027, \u8BF7\u786E\u4FDD\u6BCF\u4E2A\u63D2\u4EF6\u90FD\u6709\u552F\u4E00\u7684\u540D\u79F0\u3002`);
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (!uniquePlugins.has(plugin.pluginName)) {
|
|
451
|
+
const pluginInstance = await this.moduleRef.create(plugin);
|
|
452
|
+
uniquePlugins.set(plugin.pluginName, pluginInstance);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
this.plugins = Array.from(uniquePlugins.values());
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* 主入口方法,处理请求数据
|
|
459
|
+
* @param data 实例化的数据对象
|
|
460
|
+
* @param request 请求对象, 非必传,如果没有传入,则从请求上下文中获取
|
|
461
|
+
*/
|
|
462
|
+
async main(data) {
|
|
463
|
+
const request = this.ctx.req;
|
|
464
|
+
request.data = data;
|
|
465
|
+
this.initialize(request);
|
|
466
|
+
const excutePlugins = await this.executeBefore(request);
|
|
467
|
+
this.execute(request, excutePlugins);
|
|
468
|
+
await this.executeAfter(request, excutePlugins);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* 初始化插件
|
|
472
|
+
* 可以用于插件的初始化逻辑,例如加载配置、注册事件等
|
|
473
|
+
* 如果插件不需要初始化逻辑,可以不实现该方法
|
|
474
|
+
* @param request 请求对象
|
|
475
|
+
*/
|
|
476
|
+
initialize(request) {
|
|
477
|
+
this.plugins.forEach((plugin) => plugin.initialize?.(request));
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* 执行插件的 before 钩子函数
|
|
481
|
+
* 该方法会返回需要执行的插件列表
|
|
482
|
+
* 如果插件的 executeBefore 返回 false,则不执行该插件
|
|
483
|
+
* @param request 请求对象
|
|
484
|
+
*/
|
|
485
|
+
async executeBefore(request) {
|
|
486
|
+
const beforeResList = await Promise.all(this.plugins.map((plugin) => plugin.executeBefore?.(request)));
|
|
487
|
+
return this.plugins.filter((_, index) => beforeResList[index]);
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* 执行插件的主要逻辑
|
|
491
|
+
* 该方法会在数据遍历过程中被调用
|
|
492
|
+
* 这个方法是插件的核心逻辑,用于处理数据的每个字段
|
|
493
|
+
* 此方法只调用一次递归遍历函数, 优化多个插件时的遍历性能
|
|
494
|
+
* @param request 请求对
|
|
495
|
+
* @param excutePlugins 需要执行的插件列表
|
|
496
|
+
*/
|
|
497
|
+
execute(request, excutePlugins) {
|
|
498
|
+
traverse(request.data, (traverseFnOptions) => {
|
|
499
|
+
excutePlugins.forEach((plugin) => {
|
|
500
|
+
plugin.execute(request, traverseFnOptions);
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* 执行插件的 after 钩子函数
|
|
506
|
+
* 这个方法会在所有数据处理完成后被调用
|
|
507
|
+
* 可以用于清理资源或执行一些收尾工作
|
|
508
|
+
* @param request 请求对象
|
|
509
|
+
* @param excutePlugins 需要执行的插件列表
|
|
510
|
+
*/
|
|
511
|
+
async executeAfter(request, excutePlugins) {
|
|
512
|
+
await Promise.all(excutePlugins.map((plugin) => plugin.executeAfter?.(request)));
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
__name(_TransformPluginManager, "TransformPluginManager");
|
|
516
|
+
var TransformPluginManager = _TransformPluginManager;
|
|
517
|
+
TransformPluginManager = _ts_decorate2([
|
|
518
|
+
(0, import_common2.Injectable)(),
|
|
519
|
+
_ts_param(2, (0, import_common2.Inject)(INJECT_TRANSFORM_PLUGINS)),
|
|
520
|
+
_ts_metadata("design:type", Function),
|
|
521
|
+
_ts_metadata("design:paramtypes", [
|
|
522
|
+
typeof import_bff_core.CtxService === "undefined" ? Object : import_bff_core.CtxService,
|
|
523
|
+
typeof import_core.ModuleRef === "undefined" ? Object : import_core.ModuleRef,
|
|
524
|
+
Array
|
|
525
|
+
])
|
|
526
|
+
], TransformPluginManager);
|
|
527
|
+
|
|
528
|
+
// src/transform.interceptor.ts
|
|
529
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
530
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
531
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
532
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
533
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
534
|
+
}
|
|
535
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
536
|
+
function _ts_metadata2(k, v) {
|
|
537
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
538
|
+
}
|
|
539
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
540
|
+
var _TransformInterceptor = class _TransformInterceptor {
|
|
541
|
+
constructor(transformPluginManager) {
|
|
542
|
+
__publicField(this, "transformPluginManager");
|
|
543
|
+
__publicField(this, "logger", new import_common3.Logger(_TransformInterceptor.name));
|
|
544
|
+
this.transformPluginManager = transformPluginManager;
|
|
545
|
+
}
|
|
546
|
+
intercept(_context, next) {
|
|
547
|
+
return next.handle().pipe((0, import_operators.mergeMap)(async (data) => {
|
|
548
|
+
if (!data) return data;
|
|
549
|
+
await this.transformPluginManager.main(data).catch((error) => {
|
|
550
|
+
this.logger.error("PluginManager execute failed:", error);
|
|
551
|
+
});
|
|
552
|
+
return data;
|
|
553
|
+
}));
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
__name(_TransformInterceptor, "TransformInterceptor");
|
|
557
|
+
var TransformInterceptor = _TransformInterceptor;
|
|
558
|
+
TransformInterceptor = _ts_decorate3([
|
|
559
|
+
(0, import_common3.Injectable)(),
|
|
560
|
+
_ts_metadata2("design:type", Function),
|
|
561
|
+
_ts_metadata2("design:paramtypes", [
|
|
562
|
+
typeof TransformPluginManager === "undefined" ? Object : TransformPluginManager
|
|
563
|
+
])
|
|
564
|
+
], TransformInterceptor);
|
|
565
|
+
|
|
566
|
+
// src/unionQuery/unionQuery.plugin.ts
|
|
567
|
+
var import_common4 = require("@nestjs/common");
|
|
568
|
+
var import_core2 = require("@nestjs/core");
|
|
569
|
+
var import_bff_cache2 = require("@xfe-repo/bff-cache");
|
|
570
|
+
|
|
571
|
+
// src/unionQuery/tasks/collectTasks.ts
|
|
572
|
+
var import_qs = __toESM(require("qs"));
|
|
573
|
+
|
|
574
|
+
// src/unionQuery/unionquery.metadata-storage.ts
|
|
575
|
+
var import_class_transformer2 = require("class-transformer");
|
|
576
|
+
var _a2;
|
|
577
|
+
var UnionQueryTransformMetadataStorage = (_a2 = class extends TransformMetadataStorage {
|
|
578
|
+
/**
|
|
579
|
+
* 添加联合查询转换元数据
|
|
580
|
+
* @param metadata 联合查询转换元数据
|
|
581
|
+
*/
|
|
582
|
+
addUnionQueryMetadata(metadata) {
|
|
583
|
+
const options = {
|
|
584
|
+
...metadata.options,
|
|
585
|
+
toClassOnly: true
|
|
586
|
+
};
|
|
587
|
+
this.getMetadataStorage().addTransformMetadata({
|
|
588
|
+
...metadata,
|
|
589
|
+
options
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* 查找联合查询转换元数据
|
|
594
|
+
* @param target
|
|
595
|
+
* @param propertyName
|
|
596
|
+
* @param transformationType
|
|
597
|
+
* @returns
|
|
598
|
+
*/
|
|
599
|
+
findUnionQueryMetadata(target, propertyName) {
|
|
600
|
+
const unionQueryMetadatas = this.getMetadataStorage().findTransformMetadatas(target, propertyName, import_class_transformer2.TransformationType.PLAIN_TO_CLASS);
|
|
601
|
+
return unionQueryMetadatas.find((meta) => meta.options?.transformName === "UnionQuery");
|
|
602
|
+
}
|
|
603
|
+
}, __name(_a2, "UnionQueryTransformMetadataStorage"), _a2);
|
|
604
|
+
var unionQueryMetadataStorage = new UnionQueryTransformMetadataStorage();
|
|
605
|
+
|
|
606
|
+
// src/unionQuery/tasks/utils.ts
|
|
607
|
+
var import_constants = require("@nestjs/common/constants");
|
|
608
|
+
function isNullOrUndefined(x) {
|
|
609
|
+
return x === null || x === void 0;
|
|
610
|
+
}
|
|
611
|
+
__name(isNullOrUndefined, "isNullOrUndefined");
|
|
612
|
+
function getServiceName(service) {
|
|
613
|
+
if (typeof service === "function") return service.name;
|
|
614
|
+
if (typeof service === "object" && service !== null && "provide" in service) {
|
|
615
|
+
const token = service.provide;
|
|
616
|
+
if (typeof token === "string" || typeof token === "symbol") return token.toString();
|
|
617
|
+
if (typeof token === "function") return token.name;
|
|
618
|
+
}
|
|
619
|
+
return "\u672A\u77E5\u670D\u52A1";
|
|
620
|
+
}
|
|
621
|
+
__name(getServiceName, "getServiceName");
|
|
622
|
+
function getServiceToken(service) {
|
|
623
|
+
if (typeof service === "function") return service;
|
|
624
|
+
if (typeof service === "object" && service !== null && "provide" in service) return service.provide;
|
|
625
|
+
throw new Error(`\u65E0\u6548\u7684\u670D\u52A1\u914D\u7F6E: ${JSON.stringify(service)}`);
|
|
626
|
+
}
|
|
627
|
+
__name(getServiceToken, "getServiceToken");
|
|
628
|
+
var getServiceInstance = /* @__PURE__ */ __name((service, moduleRef) => {
|
|
629
|
+
const serviceName = getServiceName(service);
|
|
630
|
+
try {
|
|
631
|
+
const token = getServiceToken(service);
|
|
632
|
+
const instance = moduleRef.get(token, {
|
|
633
|
+
strict: false
|
|
634
|
+
});
|
|
635
|
+
if (!instance) {
|
|
636
|
+
throw new Error(`\u672A\u627E\u5230\u670D\u52A1 ${serviceName}\uFF0C\u8BF7\u68C0\u67E5 Provider \u914D\u7F6E\u3002`);
|
|
637
|
+
}
|
|
638
|
+
return instance;
|
|
639
|
+
} catch (error) {
|
|
640
|
+
throw new Error(`\u83B7\u53D6\u670D\u52A1\u5B9E\u4F8B ${serviceName} \u51FA\u9519: ${error instanceof Error ? error.message : String(error)}${error instanceof Error ? error.stack : ""}`);
|
|
641
|
+
}
|
|
642
|
+
}, "getServiceInstance");
|
|
643
|
+
|
|
644
|
+
// src/unionQuery/tasks/collectTasks.ts
|
|
645
|
+
var TTL = 10 * 60 * 1e3;
|
|
646
|
+
function collectTasks(data, propertyKey, _value, options) {
|
|
647
|
+
const { tasks, logger } = options;
|
|
648
|
+
if (typeof propertyKey !== "string") return;
|
|
649
|
+
const targetClass = data?.constructor;
|
|
650
|
+
if (!targetClass) return;
|
|
651
|
+
const UnionQueryOptions = unionQueryMetadataStorage.findUnionQueryMetadata(targetClass, propertyKey)?.options;
|
|
652
|
+
if (UnionQueryOptions) {
|
|
653
|
+
const { service, methodFn, inFn, cacheFn, ttl = TTL } = UnionQueryOptions;
|
|
654
|
+
let extractedObject;
|
|
655
|
+
try {
|
|
656
|
+
extractedObject = inFn?.(data) || {};
|
|
657
|
+
} catch (e) {
|
|
658
|
+
logger(`\u6267\u884C inFn \u51FA\u9519 (${targetClass.name}.${propertyKey}): ${e.message}, ${e.stack}`);
|
|
659
|
+
}
|
|
660
|
+
const methodName = String(methodFn).split(".")[1];
|
|
661
|
+
const taskKey = `${getServiceName(service)}:${String(methodFn)}`;
|
|
662
|
+
let task = tasks.get(taskKey);
|
|
663
|
+
if (!task) {
|
|
664
|
+
task = {
|
|
665
|
+
taskKey,
|
|
666
|
+
targetName: targetClass.name,
|
|
667
|
+
service,
|
|
668
|
+
methodFn,
|
|
669
|
+
methodName,
|
|
670
|
+
ttl,
|
|
671
|
+
paramAggregators: {},
|
|
672
|
+
cacheKeyList: [],
|
|
673
|
+
contexts: []
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
const context = {
|
|
677
|
+
context: data,
|
|
678
|
+
propertyKey,
|
|
679
|
+
options: UnionQueryOptions
|
|
680
|
+
};
|
|
681
|
+
if (cacheFn) {
|
|
682
|
+
const cacheKey = `${task.taskKey}:${import_qs.default.stringify(extractedObject)}`;
|
|
683
|
+
if (!task.cacheKeyList.includes(cacheKey)) {
|
|
684
|
+
task.cacheKeyList.push(cacheKey);
|
|
685
|
+
}
|
|
686
|
+
context.cacheKey = cacheKey;
|
|
687
|
+
}
|
|
688
|
+
for (const [extractedKey, extractedValue] of Object.entries(extractedObject)) {
|
|
689
|
+
if (!task.paramAggregators[extractedKey]) {
|
|
690
|
+
task.paramAggregators[extractedKey] = [];
|
|
691
|
+
}
|
|
692
|
+
if (!isNullOrUndefined(extractedValue) && !task.paramAggregators[extractedKey].includes(extractedValue)) {
|
|
693
|
+
task.paramAggregators[extractedKey].push(extractedValue);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
task.contexts.push(context);
|
|
697
|
+
tasks.set(taskKey, task);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
__name(collectTasks, "collectTasks");
|
|
701
|
+
|
|
702
|
+
// src/unionQuery/tasks/executeTask.ts
|
|
703
|
+
var import_bff_cache = require("@xfe-repo/bff-cache");
|
|
704
|
+
var import_qs2 = __toESM(require("qs"));
|
|
705
|
+
async function executeTask(task, options) {
|
|
706
|
+
const { moduleRef, cacheManagerService, logger } = options;
|
|
707
|
+
const serviceName = getServiceName(task.service);
|
|
708
|
+
const methodName = task.methodName;
|
|
709
|
+
const loggerPrifixed = `\u3010Vo: ${task.targetName}, key: ${task.taskKey}, params: ${JSON.stringify(task.paramAggregators)}}\u3011`;
|
|
710
|
+
const cacheResultList = await cacheManagerService.mget(import_bff_cache.CachePrefix.UnionQuery, task.cacheKeyList);
|
|
711
|
+
const cacheResultDic = {};
|
|
712
|
+
cacheResultList.forEach((result, index) => {
|
|
713
|
+
if (result) {
|
|
714
|
+
const cacheKey = task.cacheKeyList[index];
|
|
715
|
+
cacheResultDic[cacheKey] = result;
|
|
716
|
+
const inFnParamsFromCacheKey = import_qs2.default.parse(cacheKey.split(":")[2]);
|
|
717
|
+
for (const paramsKey in inFnParamsFromCacheKey) {
|
|
718
|
+
const paramsValue = inFnParamsFromCacheKey[paramsKey];
|
|
719
|
+
task.paramAggregators[paramsKey] = task.paramAggregators[paramsKey].filter((param) => param !== paramsValue);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
const aggregatedParams = {};
|
|
724
|
+
for (const inField in task.paramAggregators) {
|
|
725
|
+
aggregatedParams[inField] = task.paramAggregators[inField].join(",");
|
|
726
|
+
}
|
|
727
|
+
try {
|
|
728
|
+
let unionResult = {};
|
|
729
|
+
const hasCacheResult = Object.keys(cacheResultDic).length > 0;
|
|
730
|
+
const hasAggregatedParams = Object.values(aggregatedParams).filter(Boolean).length > 0;
|
|
731
|
+
const shouldCallService = !hasCacheResult || hasAggregatedParams;
|
|
732
|
+
if (shouldCallService) {
|
|
733
|
+
const serviceInstance = getServiceInstance(task.service, moduleRef);
|
|
734
|
+
if (!serviceInstance) return;
|
|
735
|
+
const serviceMethod = task.methodFn(serviceInstance);
|
|
736
|
+
unionResult = await serviceMethod.call(serviceInstance, aggregatedParams);
|
|
737
|
+
logger(`${loggerPrifixed}\u6267\u884C\u67E5\u8BE2: ${serviceName}.${serviceMethod.name}(${JSON.stringify(aggregatedParams)})`, "Access");
|
|
738
|
+
} else {
|
|
739
|
+
logger(`${loggerPrifixed}\u4ECE\u7F13\u5B58\u83B7\u53D6\u6570\u636E\uFF0C\u5DF2\u8DF3\u8FC7\u67E5\u8BE2\u3002`, "Access");
|
|
740
|
+
}
|
|
741
|
+
const setCacheKeyList = [];
|
|
742
|
+
task.contexts.forEach((contextItem) => {
|
|
743
|
+
const { options: options2, context, propertyKey, cacheKey } = contextItem;
|
|
744
|
+
try {
|
|
745
|
+
const { cacheFn, outFn } = options2;
|
|
746
|
+
if (cacheFn && cacheKey) {
|
|
747
|
+
const cacheResult = cacheResultDic[cacheKey];
|
|
748
|
+
if (cacheResult) {
|
|
749
|
+
context[propertyKey] = outFn(cacheResult, context);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const cachedValue = cacheFn(unionResult, context) || {};
|
|
753
|
+
const newValue = outFn(cachedValue, context);
|
|
754
|
+
context[propertyKey] = newValue;
|
|
755
|
+
if (!setCacheKeyList.find((item) => item.key === cacheKey)) {
|
|
756
|
+
setCacheKeyList.push({
|
|
757
|
+
key: cacheKey,
|
|
758
|
+
value: cachedValue
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
const newValue = outFn(unionResult, context);
|
|
763
|
+
context[propertyKey] = newValue;
|
|
764
|
+
}
|
|
765
|
+
} catch (e) {
|
|
766
|
+
logger(`${loggerPrifixed}\u6267\u884C ${String(propertyKey)}.outFn \u51FA\u9519: ${e.message} ${e.stack}`);
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
if (setCacheKeyList.length > 0) {
|
|
770
|
+
cacheManagerService.mset(import_bff_cache.CachePrefix.UnionQuery, setCacheKeyList, task.ttl);
|
|
771
|
+
}
|
|
772
|
+
} catch (error) {
|
|
773
|
+
logger(`${loggerPrifixed}\u6267\u884C ${serviceName}#${methodName}(${JSON.stringify(aggregatedParams)}) \u5931\u8D25: ${error instanceof Error ? error.message : String(error)} ${error instanceof Error ? error.stack : ""}`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
__name(executeTask, "executeTask");
|
|
777
|
+
|
|
778
|
+
// src/unionQuery/unionQuery.plugin.ts
|
|
779
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
780
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
781
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
782
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
783
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
784
|
+
}
|
|
785
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
786
|
+
function _ts_metadata3(k, v) {
|
|
787
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
788
|
+
}
|
|
789
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
790
|
+
var _UnionQueryPlugin = class _UnionQueryPlugin extends ITransformPlugin {
|
|
791
|
+
constructor(moduleRef, cacheManagerService) {
|
|
792
|
+
super();
|
|
793
|
+
__publicField(this, "moduleRef");
|
|
794
|
+
__publicField(this, "cacheManagerService");
|
|
795
|
+
__publicField(this, "logger", new import_common4.Logger(_UnionQueryPlugin.name));
|
|
796
|
+
__publicField(this, "emitLogger", /* @__PURE__ */ __name((message, type = "Error") => {
|
|
797
|
+
this.logger.log(`${type}: ${message}`);
|
|
798
|
+
}, "emitLogger"));
|
|
799
|
+
this.moduleRef = moduleRef, this.cacheManagerService = cacheManagerService;
|
|
800
|
+
}
|
|
801
|
+
initialize(request) {
|
|
802
|
+
if (!request._union_query_tasks) {
|
|
803
|
+
request._union_query_tasks = /* @__PURE__ */ new Map();
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
execute(request, { parent, key, value }) {
|
|
807
|
+
collectTasks(parent, key, value, {
|
|
808
|
+
tasks: request._union_query_tasks,
|
|
809
|
+
logger: this.emitLogger
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
async executeAfter(request) {
|
|
813
|
+
const { _union_query_tasks: tasks } = request;
|
|
814
|
+
if (tasks.size === 0) return;
|
|
815
|
+
const excuteTaskOptions = {
|
|
816
|
+
moduleRef: this.moduleRef,
|
|
817
|
+
cacheManagerService: this.cacheManagerService,
|
|
818
|
+
logger: this.emitLogger
|
|
819
|
+
};
|
|
820
|
+
await Promise.all(Array.from(tasks.values()).map((task) => executeTask(task, excuteTaskOptions)));
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
__name(_UnionQueryPlugin, "UnionQueryPlugin");
|
|
824
|
+
__publicField(_UnionQueryPlugin, "pluginName", _UnionQueryPlugin.name);
|
|
825
|
+
var UnionQueryPlugin = _UnionQueryPlugin;
|
|
826
|
+
UnionQueryPlugin = _ts_decorate4([
|
|
827
|
+
(0, import_common4.Injectable)(),
|
|
828
|
+
_ts_metadata3("design:type", Function),
|
|
829
|
+
_ts_metadata3("design:paramtypes", [
|
|
830
|
+
typeof import_core2.ModuleRef === "undefined" ? Object : import_core2.ModuleRef,
|
|
831
|
+
typeof import_bff_cache2.CacheManagerService === "undefined" ? Object : import_bff_cache2.CacheManagerService
|
|
832
|
+
])
|
|
833
|
+
], UnionQueryPlugin);
|
|
834
|
+
|
|
835
|
+
// src/transform.module.ts
|
|
836
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
837
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
838
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
839
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
840
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
841
|
+
}
|
|
842
|
+
__name(_ts_decorate5, "_ts_decorate");
|
|
843
|
+
var _TransformModule = class _TransformModule {
|
|
844
|
+
/* 注册插件
|
|
845
|
+
* @param global 是否全局模块,默认值为 false
|
|
846
|
+
* @param plugins 扩展插件列表
|
|
847
|
+
* @returns {DynamicModule} 动态模块
|
|
848
|
+
*/
|
|
849
|
+
static register(options = {}) {
|
|
850
|
+
const corePlugins = [
|
|
851
|
+
UnionQueryPlugin,
|
|
852
|
+
PrivacyPlugin
|
|
853
|
+
];
|
|
854
|
+
return {
|
|
855
|
+
global: options.global,
|
|
856
|
+
module: _TransformModule,
|
|
857
|
+
providers: [
|
|
858
|
+
{
|
|
859
|
+
provide: INJECT_TRANSFORM_PLUGINS,
|
|
860
|
+
// 将核心插件和自定义插件合并
|
|
861
|
+
// 此处注意约定注册顺序为: 自定义插件早于内置插件, 如果有同名插件, 可以保证自定义插件可以覆盖内置插件
|
|
862
|
+
useValue: options.plugins ? [
|
|
863
|
+
...options.plugins,
|
|
864
|
+
...corePlugins
|
|
865
|
+
] : corePlugins
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
__name(_TransformModule, "TransformModule");
|
|
872
|
+
var TransformModule = _TransformModule;
|
|
873
|
+
TransformModule = _ts_decorate5([
|
|
874
|
+
(0, import_common5.Module)({
|
|
875
|
+
providers: [
|
|
876
|
+
TransformPluginManager,
|
|
877
|
+
{
|
|
878
|
+
provide: import_core3.APP_INTERCEPTOR,
|
|
879
|
+
useClass: TransformInterceptor
|
|
880
|
+
}
|
|
881
|
+
]
|
|
882
|
+
})
|
|
883
|
+
], TransformModule);
|
|
884
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
885
|
+
0 && (module.exports = {
|
|
886
|
+
TransformModule
|
|
887
|
+
});
|