Update variables v2 state handling
This commit is contained in:
123
modules/variables/state2/guard.js
Normal file
123
modules/variables/state2/guard.js
Normal file
@@ -0,0 +1,123 @@
|
||||
import { getContext } from '../../../../../../extensions.js';
|
||||
|
||||
const LWB_RULES_V2_KEY = 'LWB_RULES_V2';
|
||||
|
||||
let rulesTable = {};
|
||||
|
||||
export function loadRulesFromMeta() {
|
||||
try {
|
||||
const meta = getContext()?.chatMetadata || {};
|
||||
rulesTable = meta[LWB_RULES_V2_KEY] || {};
|
||||
} catch {
|
||||
rulesTable = {};
|
||||
}
|
||||
}
|
||||
|
||||
export function saveRulesToMeta() {
|
||||
try {
|
||||
const meta = getContext()?.chatMetadata || {};
|
||||
meta[LWB_RULES_V2_KEY] = { ...rulesTable };
|
||||
getContext()?.saveMetadataDebounced?.();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function getRuleNode(path) {
|
||||
return rulesTable[path] || null;
|
||||
}
|
||||
|
||||
export function setRule(path, rule) {
|
||||
rulesTable[path] = { ...(rulesTable[path] || {}), ...rule };
|
||||
}
|
||||
|
||||
export function clearRule(path) {
|
||||
delete rulesTable[path];
|
||||
saveRulesToMeta();
|
||||
}
|
||||
|
||||
export function clearAllRules() {
|
||||
rulesTable = {};
|
||||
saveRulesToMeta();
|
||||
}
|
||||
|
||||
export function getParentPath(absPath) {
|
||||
const parts = String(absPath).split('.').filter(Boolean);
|
||||
if (parts.length <= 1) return '';
|
||||
return parts.slice(0, -1).join('.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证操作
|
||||
* @param {string} op - set/inc/push/pop/del
|
||||
* @param {string} absPath - 规范化路径
|
||||
* @param {*} payload - set的值 / inc的delta / push的值 / pop的值
|
||||
* @param {*} currentValue - 当前值
|
||||
*/
|
||||
export function validate(op, absPath, payload, currentValue) {
|
||||
const node = getRuleNode(absPath);
|
||||
const parentPath = getParentPath(absPath);
|
||||
const parentNode = parentPath ? getRuleNode(parentPath) : null;
|
||||
const isNewKey = currentValue === undefined;
|
||||
|
||||
// 父层 $lock:不允许新增/删除 key
|
||||
if (parentNode?.lock) {
|
||||
if (isNewKey && (op === 'set' || op === 'push')) {
|
||||
return { allow: false, reason: 'parent-locked' };
|
||||
}
|
||||
if (op === 'del') {
|
||||
return { allow: false, reason: 'parent-locked' };
|
||||
}
|
||||
}
|
||||
|
||||
// 当前 $ro:不允许改值
|
||||
if (node?.ro && (op === 'set' || op === 'inc')) {
|
||||
return { allow: false, reason: 'ro' };
|
||||
}
|
||||
|
||||
// 当前 $lock:不允许改结构
|
||||
if (node?.lock && (op === 'push' || op === 'pop' || op === 'del')) {
|
||||
return { allow: false, reason: 'lock' };
|
||||
}
|
||||
|
||||
// set 数值约束
|
||||
if (op === 'set') {
|
||||
const num = Number(payload);
|
||||
if (Number.isFinite(num) && (node?.min !== undefined || node?.max !== undefined)) {
|
||||
let v = num;
|
||||
if (node.min !== undefined) v = Math.max(v, node.min);
|
||||
if (node.max !== undefined) v = Math.min(v, node.max);
|
||||
return { allow: true, value: v };
|
||||
}
|
||||
// enum
|
||||
if (node?.enum?.length) {
|
||||
if (!node.enum.includes(String(payload ?? ''))) {
|
||||
return { allow: false, reason: 'enum' };
|
||||
}
|
||||
}
|
||||
return { allow: true, value: payload };
|
||||
}
|
||||
|
||||
// inc:返回最终值
|
||||
if (op === 'inc') {
|
||||
const delta = Number(payload);
|
||||
if (!Number.isFinite(delta)) return { allow: false, reason: 'delta-nan' };
|
||||
|
||||
const cur = Number(currentValue) || 0;
|
||||
let d = delta;
|
||||
|
||||
// step 限制
|
||||
if (node?.step !== undefined && node.step >= 0) {
|
||||
if (d > node.step) d = node.step;
|
||||
if (d < -node.step) d = -node.step;
|
||||
}
|
||||
|
||||
let next = cur + d;
|
||||
|
||||
// range 限制
|
||||
if (node?.min !== undefined) next = Math.max(next, node.min);
|
||||
if (node?.max !== undefined) next = Math.min(next, node.max);
|
||||
|
||||
return { allow: true, value: next };
|
||||
}
|
||||
|
||||
return { allow: true, value: payload };
|
||||
}
|
||||
Reference in New Issue
Block a user