@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,564 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransformInterceptor
|
|
3
|
+
} from "./chunk-MWZOUQAS.mjs";
|
|
4
|
+
import {
|
|
5
|
+
TransformMetadataStorage
|
|
6
|
+
} from "./chunk-O7SEPPUS.mjs";
|
|
7
|
+
import {
|
|
8
|
+
TransformPluginManager
|
|
9
|
+
} from "./chunk-YP5H6IG4.mjs";
|
|
10
|
+
import {
|
|
11
|
+
INJECT_TRANSFORM_PLUGINS,
|
|
12
|
+
ITransformPlugin
|
|
13
|
+
} from "./chunk-XUGPHFIH.mjs";
|
|
14
|
+
import {
|
|
15
|
+
__name,
|
|
16
|
+
__publicField
|
|
17
|
+
} from "./chunk-Q7G5RLD4.mjs";
|
|
18
|
+
|
|
19
|
+
// src/transform.module.ts
|
|
20
|
+
import { Module } from "@nestjs/common";
|
|
21
|
+
import { APP_INTERCEPTOR } from "@nestjs/core";
|
|
22
|
+
|
|
23
|
+
// src/privacy/privacy.plugin.ts
|
|
24
|
+
import { Injectable } from "@nestjs/common";
|
|
25
|
+
|
|
26
|
+
// src/privacy/desensitize.tool.ts
|
|
27
|
+
var desensitizeMobile = /* @__PURE__ */ __name((mobile) => {
|
|
28
|
+
if (!mobile) return "";
|
|
29
|
+
return String(mobile).replace(/(\d{3})\d*(\d{4})/, "$1****$2");
|
|
30
|
+
}, "desensitizeMobile");
|
|
31
|
+
var desensitizeName = /* @__PURE__ */ __name((name = "", format = "firstAndLast") => {
|
|
32
|
+
const str = String(name || "").trim();
|
|
33
|
+
const len = str.length;
|
|
34
|
+
if (format === "first") {
|
|
35
|
+
return str.replace(/(?<=.)./g, "*");
|
|
36
|
+
}
|
|
37
|
+
if (format === "all") {
|
|
38
|
+
return "*";
|
|
39
|
+
}
|
|
40
|
+
if (format === "firstAndLast") {
|
|
41
|
+
if (len < 3) return str;
|
|
42
|
+
return `${str[0] || ""}${"*".repeat(len - 2)}${str[len - 1] || ""}`;
|
|
43
|
+
}
|
|
44
|
+
if (format === "pre2AndLast") {
|
|
45
|
+
if (len < 4) return str;
|
|
46
|
+
return `${str.slice(0, 2) || ""}${"*".repeat(len - 3)}${str[len - 1] || ""}`;
|
|
47
|
+
}
|
|
48
|
+
if (format === "maxFourLetter") {
|
|
49
|
+
if (len < 3) return `${str[0] || ""}*`;
|
|
50
|
+
return str.replace(/^(.).+(.)$/g, "$1**$2");
|
|
51
|
+
}
|
|
52
|
+
return str;
|
|
53
|
+
}, "desensitizeName");
|
|
54
|
+
var desensitizeEnterpriseName = /* @__PURE__ */ __name((str) => {
|
|
55
|
+
str = String(str || "").trim();
|
|
56
|
+
const len = str?.length;
|
|
57
|
+
if (!str || len < 3) return str;
|
|
58
|
+
return `${str.substring(0, 2)}${"*".repeat(len - 3)}${str[len - 1] || ""}`;
|
|
59
|
+
}, "desensitizeEnterpriseName");
|
|
60
|
+
var desensitizeEnterpriseNo = /* @__PURE__ */ __name((str) => {
|
|
61
|
+
if (!str) return str;
|
|
62
|
+
return str.replace(/SAAS\d+(?=\d{4})/, "SAAS****");
|
|
63
|
+
}, "desensitizeEnterpriseNo");
|
|
64
|
+
var desensitizeAddress = /* @__PURE__ */ __name((str = "", maskAll = false) => {
|
|
65
|
+
if (!str) return str;
|
|
66
|
+
if (maskAll) {
|
|
67
|
+
return "*".repeat(str.length);
|
|
68
|
+
}
|
|
69
|
+
return str.replace(/\d+(?=[室|号|楼])/g, "**");
|
|
70
|
+
}, "desensitizeAddress");
|
|
71
|
+
var desensitizePrice = /* @__PURE__ */ __name((len = 3, showUnit) => {
|
|
72
|
+
return `${showUnit ? "\xA5" : ""} ${"*".repeat(len)}`;
|
|
73
|
+
}, "desensitizePrice");
|
|
74
|
+
var desensitizeAmount = /* @__PURE__ */ __name((_value, options) => {
|
|
75
|
+
const { length = 3, showUnit = false } = options || {};
|
|
76
|
+
return `${showUnit ? "\xA5" : ""} ${"*".repeat(length)}`;
|
|
77
|
+
}, "desensitizeAmount");
|
|
78
|
+
var desensitizeNameAll = /* @__PURE__ */ __name((name = "") => {
|
|
79
|
+
return desensitizeName(name, "all");
|
|
80
|
+
}, "desensitizeNameAll");
|
|
81
|
+
var desensitizeUtil = {
|
|
82
|
+
mobile: desensitizeMobile,
|
|
83
|
+
name: desensitizeName,
|
|
84
|
+
enterpriseName: desensitizeEnterpriseName,
|
|
85
|
+
enterpriseNo: desensitizeEnterpriseNo,
|
|
86
|
+
address: desensitizeAddress,
|
|
87
|
+
price: desensitizePrice,
|
|
88
|
+
/** 和 price / desensitizeAmount 调用执行结果一致,但方法封装参数不一致 */
|
|
89
|
+
amount: desensitizeAmount,
|
|
90
|
+
nameAll: desensitizeNameAll
|
|
91
|
+
};
|
|
92
|
+
var desensitize_tool_default = desensitizeUtil;
|
|
93
|
+
|
|
94
|
+
// src/privacy/apply/desensitize.ts
|
|
95
|
+
function applyDesensitize(data, fieldName, originalValue, options, userPermission) {
|
|
96
|
+
const { permissionCode, method, params } = options;
|
|
97
|
+
if (originalValue == null) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (permissionCode && userPermission?.includes(permissionCode)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const desensitizeFn = desensitize_tool_default[method];
|
|
105
|
+
data[fieldName] = desensitizeFn(originalValue, params);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("\u8131\u654F\u5931\u8D25:", error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
__name(applyDesensitize, "applyDesensitize");
|
|
111
|
+
|
|
112
|
+
// src/privacy/utils.ts
|
|
113
|
+
var ENCRYPTION_KEY = "Ff3UCEPfizZmCjke1Xfi";
|
|
114
|
+
function encryptValue(value) {
|
|
115
|
+
try {
|
|
116
|
+
const stringValue = String(value || "");
|
|
117
|
+
const key = Buffer.from(ENCRYPTION_KEY);
|
|
118
|
+
const data = Buffer.from(stringValue);
|
|
119
|
+
const result = Buffer.alloc(data.length);
|
|
120
|
+
for (let i = 0; i < data.length; i++) {
|
|
121
|
+
result[i] = data[i] ^ key[i % key.length];
|
|
122
|
+
}
|
|
123
|
+
return result.toString("base64");
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error("\u52A0\u5BC6\u5931\u8D25:", error);
|
|
126
|
+
return `error:${Buffer.from(String(value || "")).toString("base64")}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
__name(encryptValue, "encryptValue");
|
|
130
|
+
|
|
131
|
+
// src/privacy/apply/encryption.ts
|
|
132
|
+
function applyEncryption(data, fieldName, originalValue, options, userPermission) {
|
|
133
|
+
const { permissionCode } = options;
|
|
134
|
+
data[fieldName] = null;
|
|
135
|
+
const encryptedFieldName = `${fieldName}Encrypted`;
|
|
136
|
+
data[encryptedFieldName] = null;
|
|
137
|
+
const hasPermission = userPermission?.includes(permissionCode);
|
|
138
|
+
if (hasPermission && originalValue != null) {
|
|
139
|
+
try {
|
|
140
|
+
const stringValue = String(originalValue);
|
|
141
|
+
const encryptedValue = encryptValue(stringValue);
|
|
142
|
+
data[encryptedFieldName] = encryptedValue;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error("\u52A0\u5BC6\u5931\u8D25:", error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
__name(applyEncryption, "applyEncryption");
|
|
149
|
+
|
|
150
|
+
// src/privacy/apply/isPermitted.ts
|
|
151
|
+
function applyIsPermitted(data, fieldName, options, userPermission) {
|
|
152
|
+
const { permissionCode, condition = /* @__PURE__ */ __name((_data) => true, "condition") } = options;
|
|
153
|
+
const hasRequiredPermission = !permissionCode || (userPermission?.includes(permissionCode) ?? false);
|
|
154
|
+
data[fieldName] = hasRequiredPermission && condition(data);
|
|
155
|
+
}
|
|
156
|
+
__name(applyIsPermitted, "applyIsPermitted");
|
|
157
|
+
|
|
158
|
+
// src/privacy/privacy.metadata-storage.ts
|
|
159
|
+
import { TransformationType } from "class-transformer";
|
|
160
|
+
var PrivacyTransformEnum = /* @__PURE__ */ function(PrivacyTransformEnum2) {
|
|
161
|
+
PrivacyTransformEnum2["PrivacyEncrypt"] = "PrivacyEncrypt";
|
|
162
|
+
PrivacyTransformEnum2["PrivacyDesensitize"] = "PrivacyDesensitize";
|
|
163
|
+
PrivacyTransformEnum2["PrivacyIsPermitted"] = "PrivacyIsPermitted";
|
|
164
|
+
return PrivacyTransformEnum2;
|
|
165
|
+
}({});
|
|
166
|
+
var _a;
|
|
167
|
+
var PrivacyTransformMetadataStorage = (_a = class extends TransformMetadataStorage {
|
|
168
|
+
/**
|
|
169
|
+
* 添加隐私协议转换元数据
|
|
170
|
+
* @param metadata 隐私协议转换元数据
|
|
171
|
+
*/
|
|
172
|
+
addPrivacyMetadata(metadata) {
|
|
173
|
+
this.getMetadataStorage().addTransformMetadata(metadata);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 查找隐私协议转换元数据
|
|
177
|
+
* @param target
|
|
178
|
+
* @param propertyName
|
|
179
|
+
* @param transformationType
|
|
180
|
+
* @returns
|
|
181
|
+
*/
|
|
182
|
+
findPrivacyMetadata(target, propertyName, transformName) {
|
|
183
|
+
const unionQueryMetadatas = this.getMetadataStorage().findTransformMetadatas(target, propertyName, TransformationType.PLAIN_TO_CLASS);
|
|
184
|
+
return unionQueryMetadatas.find((meta) => meta.options?.transformName === transformName);
|
|
185
|
+
}
|
|
186
|
+
}, __name(_a, "PrivacyTransformMetadataStorage"), _a);
|
|
187
|
+
var privacyMetadataStorage = new PrivacyTransformMetadataStorage();
|
|
188
|
+
|
|
189
|
+
// src/privacy/privacy.plugin.ts
|
|
190
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
191
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
192
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
193
|
+
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;
|
|
194
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
195
|
+
}
|
|
196
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
197
|
+
var _PrivacyPlugin = class _PrivacyPlugin extends ITransformPlugin {
|
|
198
|
+
execute(request, { parent, key, value }) {
|
|
199
|
+
const userPermission = request.user?.permission || [];
|
|
200
|
+
this.collectAndExcuteFields(parent, key, value, userPermission);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* 处理对象的隐私字段
|
|
204
|
+
* @param data 待处理的对象数据
|
|
205
|
+
* @param privacyFields 隐私字段元数据
|
|
206
|
+
* @param userPermission 当前用户信息
|
|
207
|
+
*/
|
|
208
|
+
collectAndExcuteFields(data, key, value, userPermission) {
|
|
209
|
+
if (typeof key !== "string") return;
|
|
210
|
+
const targetClass = data?.constructor;
|
|
211
|
+
if (!targetClass) return;
|
|
212
|
+
const originalValue = value;
|
|
213
|
+
const encryptOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyEncrypt)?.options;
|
|
214
|
+
if (encryptOptions) {
|
|
215
|
+
applyEncryption(data, key, originalValue, encryptOptions, userPermission);
|
|
216
|
+
}
|
|
217
|
+
const desensitizeOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyDesensitize)?.options;
|
|
218
|
+
if (desensitizeOptions) {
|
|
219
|
+
applyDesensitize(data, key, originalValue, desensitizeOptions, userPermission);
|
|
220
|
+
}
|
|
221
|
+
const isPermittedOptions = privacyMetadataStorage.findPrivacyMetadata(targetClass, key, PrivacyTransformEnum.PrivacyIsPermitted)?.options;
|
|
222
|
+
if (isPermittedOptions) {
|
|
223
|
+
applyIsPermitted(data, key, isPermittedOptions, userPermission);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
__name(_PrivacyPlugin, "PrivacyPlugin");
|
|
228
|
+
__publicField(_PrivacyPlugin, "pluginName", _PrivacyPlugin.name);
|
|
229
|
+
var PrivacyPlugin = _PrivacyPlugin;
|
|
230
|
+
PrivacyPlugin = _ts_decorate([
|
|
231
|
+
Injectable()
|
|
232
|
+
], PrivacyPlugin);
|
|
233
|
+
|
|
234
|
+
// src/unionQuery/unionQuery.plugin.ts
|
|
235
|
+
import { Injectable as Injectable2, Logger } from "@nestjs/common";
|
|
236
|
+
import { ModuleRef } from "@nestjs/core";
|
|
237
|
+
import { CacheManagerService } from "@xfe-repo/bff-cache";
|
|
238
|
+
|
|
239
|
+
// src/unionQuery/tasks/collectTasks.ts
|
|
240
|
+
import qs from "qs";
|
|
241
|
+
|
|
242
|
+
// src/unionQuery/unionquery.metadata-storage.ts
|
|
243
|
+
import { TransformationType as TransformationType2 } from "class-transformer";
|
|
244
|
+
var UnionQueryTransformEnum = /* @__PURE__ */ function(UnionQueryTransformEnum2) {
|
|
245
|
+
UnionQueryTransformEnum2["UnionQuery"] = "UnionQuery";
|
|
246
|
+
return UnionQueryTransformEnum2;
|
|
247
|
+
}({});
|
|
248
|
+
var _a2;
|
|
249
|
+
var UnionQueryTransformMetadataStorage = (_a2 = class extends TransformMetadataStorage {
|
|
250
|
+
/**
|
|
251
|
+
* 添加联合查询转换元数据
|
|
252
|
+
* @param metadata 联合查询转换元数据
|
|
253
|
+
*/
|
|
254
|
+
addUnionQueryMetadata(metadata) {
|
|
255
|
+
const options = {
|
|
256
|
+
...metadata.options,
|
|
257
|
+
toClassOnly: true
|
|
258
|
+
};
|
|
259
|
+
this.getMetadataStorage().addTransformMetadata({
|
|
260
|
+
...metadata,
|
|
261
|
+
options
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 查找联合查询转换元数据
|
|
266
|
+
* @param target
|
|
267
|
+
* @param propertyName
|
|
268
|
+
* @param transformationType
|
|
269
|
+
* @returns
|
|
270
|
+
*/
|
|
271
|
+
findUnionQueryMetadata(target, propertyName) {
|
|
272
|
+
const unionQueryMetadatas = this.getMetadataStorage().findTransformMetadatas(target, propertyName, TransformationType2.PLAIN_TO_CLASS);
|
|
273
|
+
return unionQueryMetadatas.find((meta) => meta.options?.transformName === "UnionQuery");
|
|
274
|
+
}
|
|
275
|
+
}, __name(_a2, "UnionQueryTransformMetadataStorage"), _a2);
|
|
276
|
+
var unionQueryMetadataStorage = new UnionQueryTransformMetadataStorage();
|
|
277
|
+
|
|
278
|
+
// src/unionQuery/tasks/utils.ts
|
|
279
|
+
import { INJECTABLE_WATERMARK } from "@nestjs/common/constants";
|
|
280
|
+
function isNullOrUndefined(x) {
|
|
281
|
+
return x === null || x === void 0;
|
|
282
|
+
}
|
|
283
|
+
__name(isNullOrUndefined, "isNullOrUndefined");
|
|
284
|
+
function getServiceName(service) {
|
|
285
|
+
if (typeof service === "function") return service.name;
|
|
286
|
+
if (typeof service === "object" && service !== null && "provide" in service) {
|
|
287
|
+
const token = service.provide;
|
|
288
|
+
if (typeof token === "string" || typeof token === "symbol") return token.toString();
|
|
289
|
+
if (typeof token === "function") return token.name;
|
|
290
|
+
}
|
|
291
|
+
return "\u672A\u77E5\u670D\u52A1";
|
|
292
|
+
}
|
|
293
|
+
__name(getServiceName, "getServiceName");
|
|
294
|
+
function getServiceToken(service) {
|
|
295
|
+
if (typeof service === "function") return service;
|
|
296
|
+
if (typeof service === "object" && service !== null && "provide" in service) return service.provide;
|
|
297
|
+
throw new Error(`\u65E0\u6548\u7684\u670D\u52A1\u914D\u7F6E: ${JSON.stringify(service)}`);
|
|
298
|
+
}
|
|
299
|
+
__name(getServiceToken, "getServiceToken");
|
|
300
|
+
var getServiceInstance = /* @__PURE__ */ __name((service, moduleRef) => {
|
|
301
|
+
const serviceName = getServiceName(service);
|
|
302
|
+
try {
|
|
303
|
+
const token = getServiceToken(service);
|
|
304
|
+
const instance = moduleRef.get(token, {
|
|
305
|
+
strict: false
|
|
306
|
+
});
|
|
307
|
+
if (!instance) {
|
|
308
|
+
throw new Error(`\u672A\u627E\u5230\u670D\u52A1 ${serviceName}\uFF0C\u8BF7\u68C0\u67E5 Provider \u914D\u7F6E\u3002`);
|
|
309
|
+
}
|
|
310
|
+
return instance;
|
|
311
|
+
} catch (error) {
|
|
312
|
+
throw new Error(`\u83B7\u53D6\u670D\u52A1\u5B9E\u4F8B ${serviceName} \u51FA\u9519: ${error instanceof Error ? error.message : String(error)}${error instanceof Error ? error.stack : ""}`);
|
|
313
|
+
}
|
|
314
|
+
}, "getServiceInstance");
|
|
315
|
+
|
|
316
|
+
// src/unionQuery/tasks/collectTasks.ts
|
|
317
|
+
var TTL = 10 * 60 * 1e3;
|
|
318
|
+
function collectTasks(data, propertyKey, _value, options) {
|
|
319
|
+
const { tasks, logger } = options;
|
|
320
|
+
if (typeof propertyKey !== "string") return;
|
|
321
|
+
const targetClass = data?.constructor;
|
|
322
|
+
if (!targetClass) return;
|
|
323
|
+
const UnionQueryOptions = unionQueryMetadataStorage.findUnionQueryMetadata(targetClass, propertyKey)?.options;
|
|
324
|
+
if (UnionQueryOptions) {
|
|
325
|
+
const { service, methodFn, inFn, cacheFn, ttl = TTL } = UnionQueryOptions;
|
|
326
|
+
let extractedObject;
|
|
327
|
+
try {
|
|
328
|
+
extractedObject = inFn?.(data) || {};
|
|
329
|
+
} catch (e) {
|
|
330
|
+
logger(`\u6267\u884C inFn \u51FA\u9519 (${targetClass.name}.${propertyKey}): ${e.message}, ${e.stack}`);
|
|
331
|
+
}
|
|
332
|
+
const methodName = String(methodFn).split(".")[1];
|
|
333
|
+
const taskKey = `${getServiceName(service)}:${String(methodFn)}`;
|
|
334
|
+
let task = tasks.get(taskKey);
|
|
335
|
+
if (!task) {
|
|
336
|
+
task = {
|
|
337
|
+
taskKey,
|
|
338
|
+
targetName: targetClass.name,
|
|
339
|
+
service,
|
|
340
|
+
methodFn,
|
|
341
|
+
methodName,
|
|
342
|
+
ttl,
|
|
343
|
+
paramAggregators: {},
|
|
344
|
+
cacheKeyList: [],
|
|
345
|
+
contexts: []
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const context = {
|
|
349
|
+
context: data,
|
|
350
|
+
propertyKey,
|
|
351
|
+
options: UnionQueryOptions
|
|
352
|
+
};
|
|
353
|
+
if (cacheFn) {
|
|
354
|
+
const cacheKey = `${task.taskKey}:${qs.stringify(extractedObject)}`;
|
|
355
|
+
if (!task.cacheKeyList.includes(cacheKey)) {
|
|
356
|
+
task.cacheKeyList.push(cacheKey);
|
|
357
|
+
}
|
|
358
|
+
context.cacheKey = cacheKey;
|
|
359
|
+
}
|
|
360
|
+
for (const [extractedKey, extractedValue] of Object.entries(extractedObject)) {
|
|
361
|
+
if (!task.paramAggregators[extractedKey]) {
|
|
362
|
+
task.paramAggregators[extractedKey] = [];
|
|
363
|
+
}
|
|
364
|
+
if (!isNullOrUndefined(extractedValue) && !task.paramAggregators[extractedKey].includes(extractedValue)) {
|
|
365
|
+
task.paramAggregators[extractedKey].push(extractedValue);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
task.contexts.push(context);
|
|
369
|
+
tasks.set(taskKey, task);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
__name(collectTasks, "collectTasks");
|
|
373
|
+
|
|
374
|
+
// src/unionQuery/tasks/executeTask.ts
|
|
375
|
+
import { CachePrefix } from "@xfe-repo/bff-cache";
|
|
376
|
+
import qs2 from "qs";
|
|
377
|
+
async function executeTask(task, options) {
|
|
378
|
+
const { moduleRef, cacheManagerService, logger } = options;
|
|
379
|
+
const serviceName = getServiceName(task.service);
|
|
380
|
+
const methodName = task.methodName;
|
|
381
|
+
const loggerPrifixed = `\u3010Vo: ${task.targetName}, key: ${task.taskKey}, params: ${JSON.stringify(task.paramAggregators)}}\u3011`;
|
|
382
|
+
const cacheResultList = await cacheManagerService.mget(CachePrefix.UnionQuery, task.cacheKeyList);
|
|
383
|
+
const cacheResultDic = {};
|
|
384
|
+
cacheResultList.forEach((result, index) => {
|
|
385
|
+
if (result) {
|
|
386
|
+
const cacheKey = task.cacheKeyList[index];
|
|
387
|
+
cacheResultDic[cacheKey] = result;
|
|
388
|
+
const inFnParamsFromCacheKey = qs2.parse(cacheKey.split(":")[2]);
|
|
389
|
+
for (const paramsKey in inFnParamsFromCacheKey) {
|
|
390
|
+
const paramsValue = inFnParamsFromCacheKey[paramsKey];
|
|
391
|
+
task.paramAggregators[paramsKey] = task.paramAggregators[paramsKey].filter((param) => param !== paramsValue);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
const aggregatedParams = {};
|
|
396
|
+
for (const inField in task.paramAggregators) {
|
|
397
|
+
aggregatedParams[inField] = task.paramAggregators[inField].join(",");
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
let unionResult = {};
|
|
401
|
+
const hasCacheResult = Object.keys(cacheResultDic).length > 0;
|
|
402
|
+
const hasAggregatedParams = Object.values(aggregatedParams).filter(Boolean).length > 0;
|
|
403
|
+
const shouldCallService = !hasCacheResult || hasAggregatedParams;
|
|
404
|
+
if (shouldCallService) {
|
|
405
|
+
const serviceInstance = getServiceInstance(task.service, moduleRef);
|
|
406
|
+
if (!serviceInstance) return;
|
|
407
|
+
const serviceMethod = task.methodFn(serviceInstance);
|
|
408
|
+
unionResult = await serviceMethod.call(serviceInstance, aggregatedParams);
|
|
409
|
+
logger(`${loggerPrifixed}\u6267\u884C\u67E5\u8BE2: ${serviceName}.${serviceMethod.name}(${JSON.stringify(aggregatedParams)})`, "Access");
|
|
410
|
+
} else {
|
|
411
|
+
logger(`${loggerPrifixed}\u4ECE\u7F13\u5B58\u83B7\u53D6\u6570\u636E\uFF0C\u5DF2\u8DF3\u8FC7\u67E5\u8BE2\u3002`, "Access");
|
|
412
|
+
}
|
|
413
|
+
const setCacheKeyList = [];
|
|
414
|
+
task.contexts.forEach((contextItem) => {
|
|
415
|
+
const { options: options2, context, propertyKey, cacheKey } = contextItem;
|
|
416
|
+
try {
|
|
417
|
+
const { cacheFn, outFn } = options2;
|
|
418
|
+
if (cacheFn && cacheKey) {
|
|
419
|
+
const cacheResult = cacheResultDic[cacheKey];
|
|
420
|
+
if (cacheResult) {
|
|
421
|
+
context[propertyKey] = outFn(cacheResult, context);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const cachedValue = cacheFn(unionResult, context) || {};
|
|
425
|
+
const newValue = outFn(cachedValue, context);
|
|
426
|
+
context[propertyKey] = newValue;
|
|
427
|
+
if (!setCacheKeyList.find((item) => item.key === cacheKey)) {
|
|
428
|
+
setCacheKeyList.push({
|
|
429
|
+
key: cacheKey,
|
|
430
|
+
value: cachedValue
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
const newValue = outFn(unionResult, context);
|
|
435
|
+
context[propertyKey] = newValue;
|
|
436
|
+
}
|
|
437
|
+
} catch (e) {
|
|
438
|
+
logger(`${loggerPrifixed}\u6267\u884C ${String(propertyKey)}.outFn \u51FA\u9519: ${e.message} ${e.stack}`);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
if (setCacheKeyList.length > 0) {
|
|
442
|
+
cacheManagerService.mset(CachePrefix.UnionQuery, setCacheKeyList, task.ttl);
|
|
443
|
+
}
|
|
444
|
+
} catch (error) {
|
|
445
|
+
logger(`${loggerPrifixed}\u6267\u884C ${serviceName}#${methodName}(${JSON.stringify(aggregatedParams)}) \u5931\u8D25: ${error instanceof Error ? error.message : String(error)} ${error instanceof Error ? error.stack : ""}`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
__name(executeTask, "executeTask");
|
|
449
|
+
|
|
450
|
+
// src/unionQuery/unionQuery.plugin.ts
|
|
451
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
452
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
453
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
454
|
+
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;
|
|
455
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
456
|
+
}
|
|
457
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
458
|
+
function _ts_metadata(k, v) {
|
|
459
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
460
|
+
}
|
|
461
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
462
|
+
var _UnionQueryPlugin = class _UnionQueryPlugin extends ITransformPlugin {
|
|
463
|
+
constructor(moduleRef, cacheManagerService) {
|
|
464
|
+
super();
|
|
465
|
+
__publicField(this, "moduleRef");
|
|
466
|
+
__publicField(this, "cacheManagerService");
|
|
467
|
+
__publicField(this, "logger", new Logger(_UnionQueryPlugin.name));
|
|
468
|
+
__publicField(this, "emitLogger", /* @__PURE__ */ __name((message, type = "Error") => {
|
|
469
|
+
this.logger.log(`${type}: ${message}`);
|
|
470
|
+
}, "emitLogger"));
|
|
471
|
+
this.moduleRef = moduleRef, this.cacheManagerService = cacheManagerService;
|
|
472
|
+
}
|
|
473
|
+
initialize(request) {
|
|
474
|
+
if (!request._union_query_tasks) {
|
|
475
|
+
request._union_query_tasks = /* @__PURE__ */ new Map();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
execute(request, { parent, key, value }) {
|
|
479
|
+
collectTasks(parent, key, value, {
|
|
480
|
+
tasks: request._union_query_tasks,
|
|
481
|
+
logger: this.emitLogger
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
async executeAfter(request) {
|
|
485
|
+
const { _union_query_tasks: tasks } = request;
|
|
486
|
+
if (tasks.size === 0) return;
|
|
487
|
+
const excuteTaskOptions = {
|
|
488
|
+
moduleRef: this.moduleRef,
|
|
489
|
+
cacheManagerService: this.cacheManagerService,
|
|
490
|
+
logger: this.emitLogger
|
|
491
|
+
};
|
|
492
|
+
await Promise.all(Array.from(tasks.values()).map((task) => executeTask(task, excuteTaskOptions)));
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
__name(_UnionQueryPlugin, "UnionQueryPlugin");
|
|
496
|
+
__publicField(_UnionQueryPlugin, "pluginName", _UnionQueryPlugin.name);
|
|
497
|
+
var UnionQueryPlugin = _UnionQueryPlugin;
|
|
498
|
+
UnionQueryPlugin = _ts_decorate2([
|
|
499
|
+
Injectable2(),
|
|
500
|
+
_ts_metadata("design:type", Function),
|
|
501
|
+
_ts_metadata("design:paramtypes", [
|
|
502
|
+
typeof ModuleRef === "undefined" ? Object : ModuleRef,
|
|
503
|
+
typeof CacheManagerService === "undefined" ? Object : CacheManagerService
|
|
504
|
+
])
|
|
505
|
+
], UnionQueryPlugin);
|
|
506
|
+
|
|
507
|
+
// src/transform.module.ts
|
|
508
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
509
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
510
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
511
|
+
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;
|
|
512
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
513
|
+
}
|
|
514
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
515
|
+
var _TransformModule = class _TransformModule {
|
|
516
|
+
/* 注册插件
|
|
517
|
+
* @param global 是否全局模块,默认值为 false
|
|
518
|
+
* @param plugins 扩展插件列表
|
|
519
|
+
* @returns {DynamicModule} 动态模块
|
|
520
|
+
*/
|
|
521
|
+
static register(options = {}) {
|
|
522
|
+
const corePlugins = [
|
|
523
|
+
UnionQueryPlugin,
|
|
524
|
+
PrivacyPlugin
|
|
525
|
+
];
|
|
526
|
+
return {
|
|
527
|
+
global: options.global,
|
|
528
|
+
module: _TransformModule,
|
|
529
|
+
providers: [
|
|
530
|
+
{
|
|
531
|
+
provide: INJECT_TRANSFORM_PLUGINS,
|
|
532
|
+
// 将核心插件和自定义插件合并
|
|
533
|
+
// 此处注意约定注册顺序为: 自定义插件早于内置插件, 如果有同名插件, 可以保证自定义插件可以覆盖内置插件
|
|
534
|
+
useValue: options.plugins ? [
|
|
535
|
+
...options.plugins,
|
|
536
|
+
...corePlugins
|
|
537
|
+
] : corePlugins
|
|
538
|
+
}
|
|
539
|
+
]
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
__name(_TransformModule, "TransformModule");
|
|
544
|
+
var TransformModule = _TransformModule;
|
|
545
|
+
TransformModule = _ts_decorate3([
|
|
546
|
+
Module({
|
|
547
|
+
providers: [
|
|
548
|
+
TransformPluginManager,
|
|
549
|
+
{
|
|
550
|
+
provide: APP_INTERCEPTOR,
|
|
551
|
+
useClass: TransformInterceptor
|
|
552
|
+
}
|
|
553
|
+
]
|
|
554
|
+
})
|
|
555
|
+
], TransformModule);
|
|
556
|
+
|
|
557
|
+
export {
|
|
558
|
+
PrivacyTransformEnum,
|
|
559
|
+
privacyMetadataStorage,
|
|
560
|
+
PrivacyPlugin,
|
|
561
|
+
UnionQueryTransformEnum,
|
|
562
|
+
unionQueryMetadataStorage,
|
|
563
|
+
TransformModule
|
|
564
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name,
|
|
3
|
+
__publicField
|
|
4
|
+
} from "./chunk-Q7G5RLD4.mjs";
|
|
5
|
+
|
|
6
|
+
// src/transform.metadata-storage.ts
|
|
7
|
+
import * as classTransformer from "class-transformer/cjs/storage";
|
|
8
|
+
var defaultMetadataStorage2 = classTransformer.defaultMetadataStorage;
|
|
9
|
+
var _TransformMetadataStorage = class _TransformMetadataStorage {
|
|
10
|
+
constructor() {
|
|
11
|
+
/** 继承原实例数据 */
|
|
12
|
+
__publicField(this, "metadataStorage", defaultMetadataStorage2);
|
|
13
|
+
}
|
|
14
|
+
getMetadataStorage() {
|
|
15
|
+
return this.metadataStorage;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
__name(_TransformMetadataStorage, "TransformMetadataStorage");
|
|
19
|
+
var TransformMetadataStorage = _TransformMetadataStorage;
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
TransformMetadataStorage
|
|
23
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
__name,
|
|
8
|
+
__publicField
|
|
9
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name
|
|
3
|
+
} from "./chunk-Q7G5RLD4.mjs";
|
|
4
|
+
|
|
5
|
+
// src/transform.decorators.ts
|
|
6
|
+
import { applyDecorators } from "@nestjs/common";
|
|
7
|
+
import { Transform } from "class-transformer";
|
|
8
|
+
var TransformTyped = /* @__PURE__ */ __name((transformFn, options) => {
|
|
9
|
+
const _transformFn = /* @__PURE__ */ __name((params) => transformFn(params.obj), "_transformFn");
|
|
10
|
+
return Transform(_transformFn, {
|
|
11
|
+
toClassOnly: true,
|
|
12
|
+
...options
|
|
13
|
+
});
|
|
14
|
+
}, "TransformTyped");
|
|
15
|
+
function TransformCurrency(props) {
|
|
16
|
+
const { unit } = props;
|
|
17
|
+
return applyDecorators(Transform(({ value }) => {
|
|
18
|
+
return unit === "Fen2Yuan" ? value / 100 : value * 100;
|
|
19
|
+
}, {
|
|
20
|
+
toClassOnly: true
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
__name(TransformCurrency, "TransformCurrency");
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
TransformTyped,
|
|
27
|
+
TransformCurrency
|
|
28
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__name,
|
|
3
|
+
__publicField
|
|
4
|
+
} from "./chunk-Q7G5RLD4.mjs";
|
|
5
|
+
|
|
6
|
+
// src/transform.iplugin.ts
|
|
7
|
+
var INJECT_TRANSFORM_PLUGINS = "INJECT_TRANSFORM_PLUGINS";
|
|
8
|
+
var _ITransformPlugin = class _ITransformPlugin {
|
|
9
|
+
/**
|
|
10
|
+
* 初始化插件
|
|
11
|
+
* 该方法会在插件被注册时调用
|
|
12
|
+
* 可以用于插件的初始化逻辑,例如加载配置、注册事件等
|
|
13
|
+
* 如果插件不需要初始化逻辑,可以不实现该方法
|
|
14
|
+
* @param request
|
|
15
|
+
*/
|
|
16
|
+
initialize(_request) {
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 执行前的钩子函数
|
|
20
|
+
* @returns {boolean} 返回 true 表示需要执行该插件,false 则不执行
|
|
21
|
+
* 这个方法可以用于判断插件是否需要在当前数据上执行操作
|
|
22
|
+
* 例如:可以根据插件的配置选项或数据状态来决定是否执行
|
|
23
|
+
* 如果返回 false,则该插件在当前数据上不执行任何操作
|
|
24
|
+
* 如果返回 true,则会执行 execute 方法
|
|
25
|
+
*/
|
|
26
|
+
executeBefore(_request) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 执行后的钩子函数
|
|
31
|
+
* 这个方法会在所有数据处理完成后被调用
|
|
32
|
+
* 可以用于清理资源或执行一些收尾工作
|
|
33
|
+
*/
|
|
34
|
+
executeAfter(_request) {
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
__name(_ITransformPlugin, "ITransformPlugin");
|
|
38
|
+
/**
|
|
39
|
+
* 插件的名称
|
|
40
|
+
* 用于标识插件,避免重复注册
|
|
41
|
+
* 每个插件必须有唯一的名称
|
|
42
|
+
*/
|
|
43
|
+
__publicField(_ITransformPlugin, "pluginName");
|
|
44
|
+
var ITransformPlugin = _ITransformPlugin;
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
INJECT_TRANSFORM_PLUGINS,
|
|
48
|
+
ITransformPlugin
|
|
49
|
+
};
|