@pisell/pisellos 2.1.59 → 2.1.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.js +1 -0
- package/dist/model/strategy/adapter/index.d.ts +3 -0
- package/dist/model/strategy/adapter/index.js +4 -0
- package/dist/model/strategy/adapter/type.d.ts +28 -0
- package/dist/model/strategy/adapter/type.js +1 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +496 -0
- package/dist/model/strategy/adapter/walletPass/example.d.ts +4 -0
- package/dist/model/strategy/adapter/walletPass/example.js +258 -0
- package/dist/model/strategy/adapter/walletPass/index.d.ts +32 -0
- package/dist/model/strategy/adapter/walletPass/index.js +182 -0
- package/dist/model/strategy/adapter/walletPass/locales.d.ts +1 -0
- package/dist/model/strategy/adapter/walletPass/locales.js +23 -0
- package/dist/model/strategy/adapter/walletPass/type.d.ts +163 -0
- package/dist/model/strategy/adapter/walletPass/type.js +1 -0
- package/dist/model/strategy/adapter/walletPass/utils.d.ts +50 -0
- package/dist/model/strategy/adapter/walletPass/utils.js +965 -0
- package/dist/model/strategy/index.d.ts +94 -0
- package/dist/model/strategy/index.js +551 -0
- package/dist/model/strategy/strategy-example.d.ts +5 -0
- package/dist/model/strategy/strategy-example.js +331 -0
- package/dist/model/strategy/type.d.ts +228 -0
- package/dist/model/strategy/type.js +94 -0
- package/dist/modules/Cart/types.d.ts +2 -0
- package/dist/modules/Cart/utils/cartProduct.js +11 -0
- package/dist/modules/Discount/types.d.ts +15 -0
- package/dist/modules/Payment/index.d.ts +2 -1
- package/dist/modules/Payment/index.js +10 -7
- package/dist/modules/Payment/utils.js +3 -0
- package/dist/modules/Payment/walletpass.d.ts +23 -0
- package/dist/modules/Payment/walletpass.js +191 -95
- package/dist/modules/Rules/index.d.ts +8 -3
- package/dist/modules/Rules/index.js +152 -26
- package/dist/modules/Rules/types.d.ts +1 -0
- package/dist/modules/Summary/types.d.ts +2 -0
- package/dist/modules/Summary/utils.d.ts +6 -0
- package/dist/modules/Summary/utils.js +21 -0
- package/dist/plugins/window.d.ts +2 -0
- package/dist/solution/BookingByStep/index.d.ts +2 -1
- package/dist/solution/Checkout/index.js +2 -0
- package/dist/solution/ShopDiscount/index.d.ts +1 -0
- package/dist/solution/ShopDiscount/index.js +11 -1
- package/dist/solution/ShopDiscount/types.d.ts +1 -0
- package/dist/solution/ShopDiscount/utils.js +26 -11
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/model/index.d.ts +1 -0
- package/lib/model/index.js +23 -0
- package/lib/model/strategy/adapter/index.d.ts +3 -0
- package/lib/model/strategy/adapter/index.js +45 -0
- package/lib/model/strategy/adapter/type.d.ts +28 -0
- package/lib/model/strategy/adapter/type.js +17 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +420 -0
- package/lib/model/strategy/adapter/walletPass/example.d.ts +4 -0
- package/lib/model/strategy/adapter/walletPass/example.js +207 -0
- package/lib/model/strategy/adapter/walletPass/index.d.ts +32 -0
- package/lib/model/strategy/adapter/walletPass/index.js +142 -0
- package/lib/model/strategy/adapter/walletPass/locales.d.ts +1 -0
- package/lib/model/strategy/adapter/walletPass/locales.js +51 -0
- package/lib/model/strategy/adapter/walletPass/type.d.ts +163 -0
- package/lib/model/strategy/adapter/walletPass/type.js +17 -0
- package/lib/model/strategy/adapter/walletPass/utils.d.ts +50 -0
- package/lib/model/strategy/adapter/walletPass/utils.js +660 -0
- package/lib/model/strategy/index.d.ts +94 -0
- package/lib/model/strategy/index.js +413 -0
- package/lib/model/strategy/strategy-example.d.ts +5 -0
- package/lib/model/strategy/strategy-example.js +318 -0
- package/lib/model/strategy/type.d.ts +228 -0
- package/lib/model/strategy/type.js +44 -0
- package/lib/modules/Cart/types.d.ts +2 -0
- package/lib/modules/Cart/utils/cartProduct.js +9 -0
- package/lib/modules/Discount/types.d.ts +15 -0
- package/lib/modules/Payment/index.d.ts +2 -1
- package/lib/modules/Payment/index.js +1 -0
- package/lib/modules/Payment/utils.js +3 -0
- package/lib/modules/Payment/walletpass.d.ts +23 -0
- package/lib/modules/Payment/walletpass.js +94 -17
- package/lib/modules/Rules/index.d.ts +8 -3
- package/lib/modules/Rules/index.js +370 -192
- package/lib/modules/Rules/types.d.ts +1 -0
- package/lib/modules/Summary/types.d.ts +2 -0
- package/lib/modules/Summary/utils.d.ts +6 -0
- package/lib/modules/Summary/utils.js +15 -0
- package/lib/plugins/window.d.ts +2 -0
- package/lib/solution/BookingByStep/index.d.ts +2 -1
- package/lib/solution/Checkout/index.js +2 -0
- package/lib/solution/ShopDiscount/index.d.ts +1 -0
- package/lib/solution/ShopDiscount/index.js +6 -0
- package/lib/solution/ShopDiscount/types.d.ts +1 -0
- package/lib/solution/ShopDiscount/utils.js +10 -6
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { StrategyConfig, RuntimeContext, EvaluationResult, EngineOptions, OperatorHandler } from './type';
|
|
2
|
+
/**
|
|
3
|
+
* 策略模型 - 核心实现
|
|
4
|
+
*
|
|
5
|
+
* 完全业务无关的通用策略引擎
|
|
6
|
+
* 支持条件评估、动作匹配、结果返回
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* 策略引擎
|
|
10
|
+
*
|
|
11
|
+
* 核心职责:
|
|
12
|
+
* 1. 递归评估条件组
|
|
13
|
+
* 2. 收集满足条件的 actionIds
|
|
14
|
+
* 3. 根据 actionIds 获取 ActionEffect 对象
|
|
15
|
+
* 4. 按 priority 排序返回
|
|
16
|
+
*/
|
|
17
|
+
export declare class StrategyEngine {
|
|
18
|
+
private options;
|
|
19
|
+
private operatorHandlers;
|
|
20
|
+
constructor(options?: EngineOptions);
|
|
21
|
+
/**
|
|
22
|
+
* 评估策略
|
|
23
|
+
*/
|
|
24
|
+
evaluate(config: StrategyConfig, context: RuntimeContext): EvaluationResult;
|
|
25
|
+
/**
|
|
26
|
+
* 递归评估条件组
|
|
27
|
+
*
|
|
28
|
+
* @param group 条件组
|
|
29
|
+
* @param context 运行时上下文
|
|
30
|
+
* @returns 评估结果对象,包含条件是否满足和收集到的 actionIds
|
|
31
|
+
*/
|
|
32
|
+
private evaluateConditionGroup;
|
|
33
|
+
/**
|
|
34
|
+
* 评估条件组的逻辑运算
|
|
35
|
+
*/
|
|
36
|
+
private evaluateGroupLogic;
|
|
37
|
+
/**
|
|
38
|
+
* 评估单个规则
|
|
39
|
+
*/
|
|
40
|
+
private evaluateRule;
|
|
41
|
+
/**
|
|
42
|
+
* 评估代码模式条件
|
|
43
|
+
*/
|
|
44
|
+
private evaluateCodeCondition;
|
|
45
|
+
/**
|
|
46
|
+
* 评估运算符模式条件
|
|
47
|
+
*/
|
|
48
|
+
private evaluateOperatorCondition;
|
|
49
|
+
/**
|
|
50
|
+
* 获取字段值
|
|
51
|
+
*/
|
|
52
|
+
private getFieldValue;
|
|
53
|
+
/**
|
|
54
|
+
* 评估内置运算符
|
|
55
|
+
*/
|
|
56
|
+
private evaluateBuiltInOperator;
|
|
57
|
+
/**
|
|
58
|
+
* 根据 actionIds 获取 ActionEffect 对象
|
|
59
|
+
*/
|
|
60
|
+
private getActionsByIds;
|
|
61
|
+
/**
|
|
62
|
+
* 按 priority 排序(降序)
|
|
63
|
+
*/
|
|
64
|
+
private sortActionsByPriority;
|
|
65
|
+
/**
|
|
66
|
+
* 判断是否为条件组
|
|
67
|
+
*/
|
|
68
|
+
private isConditionGroup;
|
|
69
|
+
/**
|
|
70
|
+
* 验证配置
|
|
71
|
+
*/
|
|
72
|
+
private validateConfig;
|
|
73
|
+
/**
|
|
74
|
+
* 初始化内置运算符处理器
|
|
75
|
+
*/
|
|
76
|
+
private initializeBuiltInOperators;
|
|
77
|
+
/**
|
|
78
|
+
* 注册自定义运算符
|
|
79
|
+
*/
|
|
80
|
+
registerOperator(operator: string, handler: OperatorHandler): void;
|
|
81
|
+
/**
|
|
82
|
+
* 获取调试信息
|
|
83
|
+
*/
|
|
84
|
+
getDebugInfo(): Record<string, any>;
|
|
85
|
+
}
|
|
86
|
+
export * from './adapter';
|
|
87
|
+
/**
|
|
88
|
+
* 创建策略引擎实例
|
|
89
|
+
*/
|
|
90
|
+
export declare function createStrategyEngine(options?: EngineOptions): StrategyEngine;
|
|
91
|
+
/**
|
|
92
|
+
* 快速评估(使用默认引擎配置)
|
|
93
|
+
*/
|
|
94
|
+
export declare function evaluate(config: StrategyConfig, context: RuntimeContext): EvaluationResult;
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/model/strategy/index.ts
|
|
21
|
+
var strategy_exports = {};
|
|
22
|
+
__export(strategy_exports, {
|
|
23
|
+
StrategyEngine: () => StrategyEngine,
|
|
24
|
+
createStrategyEngine: () => createStrategyEngine,
|
|
25
|
+
evaluate: () => evaluate
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(strategy_exports);
|
|
28
|
+
var import_type = require("./type");
|
|
29
|
+
__reExport(strategy_exports, require("./adapter"), module.exports);
|
|
30
|
+
var StrategyEngine = class {
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
this.options = {
|
|
33
|
+
debug: options.debug ?? false,
|
|
34
|
+
enableTrace: options.enableTrace ?? false,
|
|
35
|
+
operatorHandlers: options.operatorHandlers ?? {},
|
|
36
|
+
errorHandler: options.errorHandler ?? ((error) => console.error(error))
|
|
37
|
+
};
|
|
38
|
+
this.operatorHandlers = new Map(
|
|
39
|
+
Object.entries(this.options.operatorHandlers)
|
|
40
|
+
);
|
|
41
|
+
this.initializeBuiltInOperators();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 评估策略
|
|
45
|
+
*/
|
|
46
|
+
evaluate(config, context) {
|
|
47
|
+
var _a;
|
|
48
|
+
const startTime = Date.now();
|
|
49
|
+
const trace = {
|
|
50
|
+
steps: [],
|
|
51
|
+
duration: 0,
|
|
52
|
+
errors: []
|
|
53
|
+
};
|
|
54
|
+
try {
|
|
55
|
+
this.validateConfig(config);
|
|
56
|
+
if (this.options.enableTrace) {
|
|
57
|
+
trace.steps.push({
|
|
58
|
+
step: "validate_config",
|
|
59
|
+
status: "success",
|
|
60
|
+
duration: Date.now() - startTime
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const evaluateStart = Date.now();
|
|
64
|
+
const evaluationResult = this.evaluateConditionGroup(
|
|
65
|
+
config.conditions,
|
|
66
|
+
context
|
|
67
|
+
);
|
|
68
|
+
if (this.options.enableTrace) {
|
|
69
|
+
trace.steps.push({
|
|
70
|
+
step: "evaluate_conditions",
|
|
71
|
+
status: "success",
|
|
72
|
+
duration: Date.now() - evaluateStart,
|
|
73
|
+
details: {
|
|
74
|
+
satisfied: evaluationResult.satisfied,
|
|
75
|
+
collectedActionIds: evaluationResult.actionIds
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const actionStart = Date.now();
|
|
80
|
+
const matchedActions = this.getActionsByIds(
|
|
81
|
+
evaluationResult.actionIds,
|
|
82
|
+
config.actions
|
|
83
|
+
);
|
|
84
|
+
if (this.options.enableTrace) {
|
|
85
|
+
trace.steps.push({
|
|
86
|
+
step: "get_actions",
|
|
87
|
+
status: "success",
|
|
88
|
+
duration: Date.now() - actionStart,
|
|
89
|
+
details: { matchedCount: matchedActions.length }
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const sortStart = Date.now();
|
|
93
|
+
const sortedActions = this.sortActionsByPriority(matchedActions);
|
|
94
|
+
if (this.options.enableTrace) {
|
|
95
|
+
trace.steps.push({
|
|
96
|
+
step: "sort_actions",
|
|
97
|
+
status: "success",
|
|
98
|
+
duration: Date.now() - sortStart
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const applicable = evaluationResult.satisfied;
|
|
102
|
+
const result = {
|
|
103
|
+
success: true,
|
|
104
|
+
applicable,
|
|
105
|
+
code: applicable ? import_type.SUCCESS_CODES.SUCCESS : import_type.NOT_APPLICABLE_CODES.CONDITION_NOT_MET,
|
|
106
|
+
message: applicable ? "Strategy is applicable" : "Conditions not met",
|
|
107
|
+
matched: {
|
|
108
|
+
conditions: applicable,
|
|
109
|
+
actionIds: evaluationResult.actionIds,
|
|
110
|
+
details: {}
|
|
111
|
+
},
|
|
112
|
+
matchedActions: sortedActions,
|
|
113
|
+
outputs: {},
|
|
114
|
+
config
|
|
115
|
+
};
|
|
116
|
+
trace.duration = Date.now() - startTime;
|
|
117
|
+
if (this.options.enableTrace) {
|
|
118
|
+
result.trace = trace;
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
123
|
+
if (this.options.enableTrace) {
|
|
124
|
+
(_a = trace.errors) == null ? void 0 : _a.push({
|
|
125
|
+
step: "evaluation",
|
|
126
|
+
error: errorMessage,
|
|
127
|
+
timestamp: Date.now()
|
|
128
|
+
});
|
|
129
|
+
trace.duration = Date.now() - startTime;
|
|
130
|
+
}
|
|
131
|
+
this.options.errorHandler(error, context);
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
applicable: false,
|
|
135
|
+
code: import_type.ERROR_CODES.EVALUATION_ERROR,
|
|
136
|
+
message: errorMessage,
|
|
137
|
+
matched: {
|
|
138
|
+
conditions: false,
|
|
139
|
+
actionIds: [],
|
|
140
|
+
details: {}
|
|
141
|
+
},
|
|
142
|
+
matchedActions: [],
|
|
143
|
+
outputs: {},
|
|
144
|
+
trace: this.options.enableTrace ? trace : void 0,
|
|
145
|
+
config
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 递归评估条件组
|
|
151
|
+
*
|
|
152
|
+
* @param group 条件组
|
|
153
|
+
* @param context 运行时上下文
|
|
154
|
+
* @returns 评估结果对象,包含条件是否满足和收集到的 actionIds
|
|
155
|
+
*/
|
|
156
|
+
evaluateConditionGroup(group, context) {
|
|
157
|
+
const collectedActionIds = [];
|
|
158
|
+
const isCurrentLayerSatisfied = this.evaluateGroupLogic(group, context);
|
|
159
|
+
if (isCurrentLayerSatisfied) {
|
|
160
|
+
collectedActionIds.push(...group.actionIds);
|
|
161
|
+
for (const rule of group.rules) {
|
|
162
|
+
if (this.isConditionGroup(rule)) {
|
|
163
|
+
const nestedResult = this.evaluateConditionGroup(rule, context);
|
|
164
|
+
collectedActionIds.push(...nestedResult.actionIds);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
satisfied: isCurrentLayerSatisfied,
|
|
170
|
+
actionIds: collectedActionIds
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 评估条件组的逻辑运算
|
|
175
|
+
*/
|
|
176
|
+
evaluateGroupLogic(group, context) {
|
|
177
|
+
const { operator, rules } = group;
|
|
178
|
+
switch (operator) {
|
|
179
|
+
case "and":
|
|
180
|
+
return rules.every((rule) => this.evaluateRule(rule, context));
|
|
181
|
+
case "or":
|
|
182
|
+
return rules.some((rule) => this.evaluateRule(rule, context));
|
|
183
|
+
case "not":
|
|
184
|
+
if (rules.length === 0)
|
|
185
|
+
return false;
|
|
186
|
+
return !this.evaluateRule(rules[0], context);
|
|
187
|
+
default:
|
|
188
|
+
throw new Error(`Unknown operator: ${operator}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* 评估单个规则
|
|
193
|
+
*/
|
|
194
|
+
evaluateRule(rule, context) {
|
|
195
|
+
if (this.isConditionGroup(rule)) {
|
|
196
|
+
return this.evaluateGroupLogic(rule, context);
|
|
197
|
+
}
|
|
198
|
+
const conditionRule = rule;
|
|
199
|
+
if (conditionRule.type === "code" && conditionRule.code) {
|
|
200
|
+
return this.evaluateCodeCondition(conditionRule.code, context);
|
|
201
|
+
}
|
|
202
|
+
return this.evaluateOperatorCondition(conditionRule, context);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* 评估代码模式条件
|
|
206
|
+
*/
|
|
207
|
+
evaluateCodeCondition(code, context) {
|
|
208
|
+
try {
|
|
209
|
+
const { entities, attributes, metadata } = context;
|
|
210
|
+
const evalFunc = new Function(
|
|
211
|
+
"entities",
|
|
212
|
+
"attributes",
|
|
213
|
+
"metadata",
|
|
214
|
+
`return (${code})`
|
|
215
|
+
);
|
|
216
|
+
const result = evalFunc(entities, attributes, metadata);
|
|
217
|
+
return Boolean(result);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (this.options.debug) {
|
|
220
|
+
console.error("Code evaluation error:", error);
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* 评估运算符模式条件
|
|
227
|
+
*/
|
|
228
|
+
evaluateOperatorCondition(rule, context) {
|
|
229
|
+
const { field, operator, value } = rule;
|
|
230
|
+
if (!field || !operator) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
const fieldValue = this.getFieldValue(field, context);
|
|
234
|
+
const handler = this.operatorHandlers.get(operator);
|
|
235
|
+
if (handler) {
|
|
236
|
+
return handler(fieldValue, value, rule);
|
|
237
|
+
}
|
|
238
|
+
return this.evaluateBuiltInOperator(fieldValue, operator, value);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* 获取字段值
|
|
242
|
+
*/
|
|
243
|
+
getFieldValue(field, context) {
|
|
244
|
+
const path = field.split(".");
|
|
245
|
+
let value = context.attributes;
|
|
246
|
+
for (const key of path) {
|
|
247
|
+
if (value && typeof value === "object" && key in value) {
|
|
248
|
+
value = value[key];
|
|
249
|
+
} else {
|
|
250
|
+
return void 0;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return value;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* 评估内置运算符
|
|
257
|
+
*/
|
|
258
|
+
evaluateBuiltInOperator(fieldValue, operator, compareValue) {
|
|
259
|
+
switch (operator) {
|
|
260
|
+
case "=":
|
|
261
|
+
case "==":
|
|
262
|
+
return fieldValue == compareValue;
|
|
263
|
+
case "!=":
|
|
264
|
+
return fieldValue != compareValue;
|
|
265
|
+
case ">":
|
|
266
|
+
return fieldValue > compareValue;
|
|
267
|
+
case ">=":
|
|
268
|
+
return fieldValue >= compareValue;
|
|
269
|
+
case "<":
|
|
270
|
+
return fieldValue < compareValue;
|
|
271
|
+
case "<=":
|
|
272
|
+
return fieldValue <= compareValue;
|
|
273
|
+
case "in":
|
|
274
|
+
return Array.isArray(compareValue) && compareValue.includes(fieldValue);
|
|
275
|
+
case "not_in":
|
|
276
|
+
return Array.isArray(compareValue) && !compareValue.includes(fieldValue);
|
|
277
|
+
case "contains":
|
|
278
|
+
if (Array.isArray(fieldValue)) {
|
|
279
|
+
return fieldValue.includes(compareValue);
|
|
280
|
+
}
|
|
281
|
+
if (typeof fieldValue === "string") {
|
|
282
|
+
return fieldValue.includes(compareValue);
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
case "not_contains":
|
|
286
|
+
if (Array.isArray(fieldValue)) {
|
|
287
|
+
return !fieldValue.includes(compareValue);
|
|
288
|
+
}
|
|
289
|
+
if (typeof fieldValue === "string") {
|
|
290
|
+
return !fieldValue.includes(compareValue);
|
|
291
|
+
}
|
|
292
|
+
return true;
|
|
293
|
+
case "starts_with":
|
|
294
|
+
return typeof fieldValue === "string" && fieldValue.startsWith(compareValue);
|
|
295
|
+
case "ends_with":
|
|
296
|
+
return typeof fieldValue === "string" && fieldValue.endsWith(compareValue);
|
|
297
|
+
case "regex":
|
|
298
|
+
return typeof fieldValue === "string" && new RegExp(compareValue).test(fieldValue);
|
|
299
|
+
case "between":
|
|
300
|
+
if (!Array.isArray(compareValue) || compareValue.length !== 2)
|
|
301
|
+
return false;
|
|
302
|
+
return fieldValue >= compareValue[0] && fieldValue <= compareValue[1];
|
|
303
|
+
case "is_null":
|
|
304
|
+
return fieldValue === null || fieldValue === void 0;
|
|
305
|
+
case "is_not_null":
|
|
306
|
+
return fieldValue !== null && fieldValue !== void 0;
|
|
307
|
+
case "is_empty":
|
|
308
|
+
if (Array.isArray(fieldValue))
|
|
309
|
+
return fieldValue.length === 0;
|
|
310
|
+
if (typeof fieldValue === "string")
|
|
311
|
+
return fieldValue.length === 0;
|
|
312
|
+
if (typeof fieldValue === "object")
|
|
313
|
+
return Object.keys(fieldValue).length === 0;
|
|
314
|
+
return !fieldValue;
|
|
315
|
+
case "is_not_empty":
|
|
316
|
+
if (Array.isArray(fieldValue))
|
|
317
|
+
return fieldValue.length > 0;
|
|
318
|
+
if (typeof fieldValue === "string")
|
|
319
|
+
return fieldValue.length > 0;
|
|
320
|
+
if (typeof fieldValue === "object")
|
|
321
|
+
return Object.keys(fieldValue).length > 0;
|
|
322
|
+
return Boolean(fieldValue);
|
|
323
|
+
default:
|
|
324
|
+
throw new Error(`Unsupported operator: ${operator}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 根据 actionIds 获取 ActionEffect 对象
|
|
329
|
+
*/
|
|
330
|
+
getActionsByIds(actionIds, actions) {
|
|
331
|
+
const matchedActions = [];
|
|
332
|
+
const actionMap = new Map(actions.map((action) => [action.id, action]));
|
|
333
|
+
for (const id of actionIds) {
|
|
334
|
+
const action = actionMap.get(id);
|
|
335
|
+
if (action) {
|
|
336
|
+
matchedActions.push(action);
|
|
337
|
+
} else {
|
|
338
|
+
if (this.options.debug) {
|
|
339
|
+
console.warn(`Action with id "${id}" not found in actions array`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return matchedActions;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* 按 priority 排序(降序)
|
|
347
|
+
*/
|
|
348
|
+
sortActionsByPriority(actions) {
|
|
349
|
+
return [...actions].sort((a, b) => {
|
|
350
|
+
const priorityA = a.priority ?? 0;
|
|
351
|
+
const priorityB = b.priority ?? 0;
|
|
352
|
+
return priorityB - priorityA;
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* 判断是否为条件组
|
|
357
|
+
*/
|
|
358
|
+
isConditionGroup(rule) {
|
|
359
|
+
return "operator" in rule && "rules" in rule && Array.isArray(rule.rules);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* 验证配置
|
|
363
|
+
*/
|
|
364
|
+
validateConfig(config) {
|
|
365
|
+
if (!config) {
|
|
366
|
+
throw new Error("Strategy config is required");
|
|
367
|
+
}
|
|
368
|
+
if (!config.metadata || !config.metadata.id) {
|
|
369
|
+
throw new Error("Strategy metadata.id is required");
|
|
370
|
+
}
|
|
371
|
+
if (!config.conditions) {
|
|
372
|
+
throw new Error("Strategy conditions is required");
|
|
373
|
+
}
|
|
374
|
+
if (!Array.isArray(config.actions)) {
|
|
375
|
+
throw new Error("Strategy actions must be an array");
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 初始化内置运算符处理器
|
|
380
|
+
*/
|
|
381
|
+
initializeBuiltInOperators() {
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* 注册自定义运算符
|
|
385
|
+
*/
|
|
386
|
+
registerOperator(operator, handler) {
|
|
387
|
+
this.operatorHandlers.set(operator, handler);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* 获取调试信息
|
|
391
|
+
*/
|
|
392
|
+
getDebugInfo() {
|
|
393
|
+
return {
|
|
394
|
+
debug: this.options.debug,
|
|
395
|
+
enableTrace: this.options.enableTrace,
|
|
396
|
+
registeredOperators: Array.from(this.operatorHandlers.keys())
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
function createStrategyEngine(options) {
|
|
401
|
+
return new StrategyEngine(options);
|
|
402
|
+
}
|
|
403
|
+
function evaluate(config, context) {
|
|
404
|
+
const engine = new StrategyEngine();
|
|
405
|
+
return engine.evaluate(config, context);
|
|
406
|
+
}
|
|
407
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
408
|
+
0 && (module.exports = {
|
|
409
|
+
StrategyEngine,
|
|
410
|
+
createStrategyEngine,
|
|
411
|
+
evaluate,
|
|
412
|
+
...require("./adapter")
|
|
413
|
+
});
|