diff --git a/packages/rule-engine/__tests__/createSync.test.ts b/packages/rule-engine/__tests__/createSync.test.ts index 367c28f6..470e7fb0 100644 --- a/packages/rule-engine/__tests__/createSync.test.ts +++ b/packages/rule-engine/__tests__/createSync.test.ts @@ -166,4 +166,59 @@ describe('@zodash/rule-engine', () => { description: true, }); }); + + it('if key not in rules, should be always true', () => { + const rules: IRuleNode[] = [ + { + type: 'Attr', + value: 'method', + children: [ + { + type: 'Value', + value: 1, + children: [ + { + type: 'Attr', + value: 'chat_id', + }, + ], + }, + ], + }, + ]; + + const runner = engine.create.sync(rules); + + expect( + runner.run({ + client: 1, + method: 1, + email: 'tobewhatwewant@gmail.com', + chat_id: '666', + is_group: false, + }), + ).toEqual({ + client: true, + method: true, + email: true, + chat_id: true, + is_group: true, + }); + + expect( + runner.run({ + client: 1, + method: 2, + email: 'tobewhatwewant@gmail.com', + chat_id: '666', + is_group: false, + }), + ).toEqual({ + client: true, + method: true, + email: true, + chat_id: false, + is_group: true, + }); + }); }); diff --git a/packages/rule-engine/src/core/create.ts b/packages/rule-engine/src/core/create.ts index 65b22c25..3eada62a 100644 --- a/packages/rule-engine/src/core/create.ts +++ b/packages/rule-engine/src/core/create.ts @@ -23,13 +23,43 @@ export function create( // real runner async function run(dataSource: Partial) { - const shows: IShowData = Object.keys(dataSource).reduce( - (all, key) => ((all[key] = false), all), - {} as any, - ); + let shows: IShowData = {} as any; + + const allRuleKeys: Record = {}; let attrNodeOfValue: IRuleAttrNode = null; + function traverse(rules: IRuleNode[]) { + for (const rule of rules) { + if (rule.type === 'Attr') { + allRuleKeys[rule.value] = true; + + if (rule.children && !!rule.children.length) { + traverse(rule.children); + } + } else if (rule.type === 'Value') { + if (rule.children && !!rule.children.length) { + traverse(rule.children); + } + } + } + } + + function initializeShows() { + traverse(rules); + + shows = Object.keys(dataSource).reduce((all, key) => { + // 所有未参与的 key 都应该是 true + if (!allRuleKeys[key]) { + all[key] = true; + } else { + all[key] = false; + } + + return all; + }, {} as any); + } + async function go(_rules: IRuleNode[]) { for (const rule of _rules) { // @1 attr show @@ -83,6 +113,7 @@ export function create( } } + initializeShows(); await go(rules); function getOnScaleTo() { diff --git a/packages/rule-engine/src/core/sync/create.ts b/packages/rule-engine/src/core/sync/create.ts index 0dd850b0..76b314d0 100644 --- a/packages/rule-engine/src/core/sync/create.ts +++ b/packages/rule-engine/src/core/sync/create.ts @@ -21,13 +21,43 @@ export function create( // real runner function run(dataSource: Partial) { - const shows: IShowData = Object.keys(dataSource).reduce( - (all, key) => ((all[key] = false), all), - {} as any, - ); + let shows: IShowData = {} as any; + + const allRuleKeys: Record = {}; let attrNodeOfValue: IRuleAttrNode = null; + function traverse(rules: IRuleNode[]) { + for (const rule of rules) { + if (rule.type === 'Attr') { + allRuleKeys[rule.value] = true; + + if (rule.children && !!rule.children.length) { + traverse(rule.children); + } + } else if (rule.type === 'Value') { + if (rule.children && !!rule.children.length) { + traverse(rule.children); + } + } + } + } + + function initializeShows() { + traverse(rules); + + shows = Object.keys(dataSource).reduce((all, key) => { + // 所有未参与的 key 都应该是 true + if (!allRuleKeys[key]) { + all[key] = true; + } else { + all[key] = false; + } + + return all; + }, {} as any); + } + function go(_rules: IRuleNode[]) { for (const rule of _rules) { // @1 attr show @@ -86,6 +116,8 @@ export function create( return node.onHitAttr || defaultOnHitAttr; } + // + initializeShows(); go(rules); return shows;