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 }; }