From ef049c9167ccaf9189d3a5bee091dfbf92733808 Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 12 Apr 2024 16:16:03 +0200 Subject: [PATCH 1/6] fix(core): support length on anything that has a length Previously it was only supported on arrays --- rita-core/src/Assertions.ts | 8 +++++--- rita-core/src/logicElements/Macro.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/rita-core/src/Assertions.ts b/rita-core/src/Assertions.ts index 0607d89..5a48580 100644 --- a/rita-core/src/Assertions.ts +++ b/rita-core/src/Assertions.ts @@ -29,8 +29,10 @@ export function assertDuration(value: any): asserts value is Duration { } } -export function assertArray(value: any): asserts value is Array { - if (!Array.isArray(value)) { - throw new TypeError(); +export function hasLength( + value: any +): asserts value is Record & { length: number } { + if (!('length' in value)) { + throw new TypeError('Value does not have a length property'); } } diff --git a/rita-core/src/logicElements/Macro.ts b/rita-core/src/logicElements/Macro.ts index 600bb8c..c6bea46 100644 --- a/rita-core/src/logicElements/Macro.ts +++ b/rita-core/src/logicElements/Macro.ts @@ -1,6 +1,6 @@ import { Formula, FormulaResults } from './Formula'; import { Atom } from './Atom'; -import { assertArray } from '../Assertions'; +import { hasLength } from '../Assertions'; export class Macro extends Formula { /** Indicates the type of this atom **/ @@ -21,7 +21,7 @@ export class Macro extends Formula { return new Date(); case 'length': const ar = await this.array?.evaluate(data); - assertArray(ar); + hasLength(ar); return ar.length; } } From 8267485dfe3baab324f98d0cd0e7bd6e53131dc6 Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 12 Apr 2024 16:17:07 +0200 Subject: [PATCH 2/6] chore: changes --- .../@educorvi/rita/develop_2024-04-12-14-16.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@educorvi/rita/develop_2024-04-12-14-16.json diff --git a/common/changes/@educorvi/rita/develop_2024-04-12-14-16.json b/common/changes/@educorvi/rita/develop_2024-04-12-14-16.json new file mode 100644 index 0000000..125751e --- /dev/null +++ b/common/changes/@educorvi/rita/develop_2024-04-12-14-16.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@educorvi/rita", + "comment": "support length on anything that has a length, not just arrays", + "type": "patch" + } + ], + "packageName": "@educorvi/rita" +} \ No newline at end of file From 35c89efd9d209cef98fa8e6841dcb0021d90e49a Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 21 Jun 2024 15:04:15 +0200 Subject: [PATCH 3/6] fix(core): fixes TypeError when evaluating macro('length', string) fixes #29 --- rita-core/src/Assertions.ts | 2 +- .../test/implementationTests/macro.test.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/rita-core/src/Assertions.ts b/rita-core/src/Assertions.ts index 5a48580..12b9321 100644 --- a/rita-core/src/Assertions.ts +++ b/rita-core/src/Assertions.ts @@ -32,7 +32,7 @@ export function assertDuration(value: any): asserts value is Duration { export function hasLength( value: any ): asserts value is Record & { length: number } { - if (!('length' in value)) { + if (!value.hasOwnProperty('length')) { throw new TypeError('Value does not have a length property'); } } diff --git a/rita-core/test/implementationTests/macro.test.ts b/rita-core/test/implementationTests/macro.test.ts index 6d767de..c4128ab 100644 --- a/rita-core/test/implementationTests/macro.test.ts +++ b/rita-core/test/implementationTests/macro.test.ts @@ -39,6 +39,27 @@ it("Expect 'length' to be correct", () => { ).resolves.toEqual(l); }); +it("Test 'length' for string", () => { + const m = p.parseMacro({ + type: 'macro', + macro: { + type: 'length', + array: { + type: 'atom', + path: 'data', + }, + }, + }); + const l = Math.round(Math.random() * 10 + 1); + const string = new Array(l + 1).join('e'); + + expect( + m.evaluate({ + data: string, + }) + ).resolves.toEqual(l); +}); + it('Example Ruleset is true', async () => { const rs = p.parseRuleSet(macroRuleset); expect((await evaluateAll(rs, exampleData)).result).toBe(true); From 3944ac06dc05975e809e0fead9d6f07231e862e6 Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 21 Jun 2024 15:25:02 +0200 Subject: [PATCH 4/6] =?UTF-8?q?feat(core):=20add=20=C2=B4allowDifferentTyp?= =?UTF-8?q?es=C2=B4=20option=20to=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rita-core/src/schema/comparison.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rita-core/src/schema/comparison.json b/rita-core/src/schema/comparison.json index eda18b5..5d905e8 100644 --- a/rita-core/src/schema/comparison.json +++ b/rita-core/src/schema/comparison.json @@ -25,6 +25,11 @@ "type": "boolean", "default": false }, + "allowDifferentTypes": { + "description": "Indicates if different types are allowed inside a comparison. This follows the JavaScript rules for comparison (´===´ is used for ´equals´).", + "type": "boolean", + "default": false + }, "arguments": { "type": "array", "minItems": 2, From fad8f30d4b4e896ebdb92ebdc8b27a0aef8af29b Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 21 Jun 2024 15:38:37 +0200 Subject: [PATCH 5/6] =?UTF-8?q?feat(core):=20add=20=C2=B4allowDifferentTyp?= =?UTF-8?q?es=C2=B4=20option=20to=20implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rita-core/src/Parser.ts | 9 +++---- rita-core/src/logicElements/Comparison.ts | 18 ++++++++++---- .../implementationTests/comparison.test.ts | 24 ++++++++++++------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/rita-core/src/Parser.ts b/rita-core/src/Parser.ts index 5b3c177..69382c6 100644 --- a/rita-core/src/Parser.ts +++ b/rita-core/src/Parser.ts @@ -186,11 +186,7 @@ export default class Parser { throw new UsageError('Invalid Date: ' + parameter); } } else { - if (typeof parameter === 'number') { - params.push(parameter); - } else { - params.push(parameter); - } + params.push(parameter); } } return params; @@ -207,7 +203,8 @@ export default class Parser { jsonRuleset['dates'] ), jsonRuleset['operation'], - jsonRuleset['dates'] + jsonRuleset['dates'], + jsonRuleset['allowDifferentTypes'] ); } diff --git a/rita-core/src/logicElements/Comparison.ts b/rita-core/src/logicElements/Comparison.ts index eaaa9d1..893abac 100644 --- a/rita-core/src/logicElements/Comparison.ts +++ b/rita-core/src/logicElements/Comparison.ts @@ -33,21 +33,29 @@ export class Comparison extends Formula { */ public dates: boolean; + /** + * Indicates if different types are allowed inside a comparison + */ + public allowDifferentTypes: boolean; + /** * @constructor * @param formulaArguments The arguments * @param operation Type of the comparison * @param dates Indicates if dates are compared + * @param allowDifferentTypes Indicates if different types are allowed inside a comparison */ constructor( formulaArguments: Array, operation: comparisons, - dates: boolean = false + dates: boolean = false, + allowDifferentTypes: boolean = false ) { super(); this.arguments = formulaArguments; this.operation = operation; this.dates = dates; + this.allowDifferentTypes = allowDifferentTypes; } toJsonReady(): Record { @@ -74,9 +82,11 @@ export class Comparison extends Formula { if (p1 === undefined || p2 === undefined) return false; if (typeof p1 !== typeof p2) { - throw new UsageError( - 'Elements in comparison must have the same type' - ); + if (!this.allowDifferentTypes) { + throw new UsageError( + 'Elements in comparison must have the same type' + ); + } } if (p1 instanceof Date) p1 = p1.getTime(); diff --git a/rita-core/test/implementationTests/comparison.test.ts b/rita-core/test/implementationTests/comparison.test.ts index 82250c4..6561a7f 100644 --- a/rita-core/test/implementationTests/comparison.test.ts +++ b/rita-core/test/implementationTests/comparison.test.ts @@ -1,10 +1,4 @@ -import { - Comparison, - comparisons, - evaluateAll, - Parser, - UsageError, -} from '../../src'; +import { evaluateAll, Parser, UsageError } from '../../src'; // @ts-ignore import { exampleData, ruleTemplate } from '../assets/exampleData'; // @ts-ignore @@ -116,7 +110,11 @@ it('run math example', async () => { }); it('error on different type', async () => { - const c = new Comparison([2, 'Test'], comparisons.equal); + const c = p.parseComparison({ + type: 'comparison', + operation: 'smaller', + arguments: [2, '2'], + }); try { await c.evaluate({}); expect(true).toBe(false); @@ -124,3 +122,13 @@ it('error on different type', async () => { expect(e).toBeInstanceOf(UsageError); } }); + +it('compare number with string', async () => { + const c = p.parseComparison({ + type: 'comparison', + operation: 'equal', + allowDifferentTypes: true, + arguments: [2, '2'], + }); + expect(await c.evaluate({})).toBe(false); +}); From 989079db71620ccaddd1b4214041e4d56d1c49b3 Mon Sep 17 00:00:00 2001 From: Julian Pollinger Date: Fri, 21 Jun 2024 15:39:47 +0200 Subject: [PATCH 6/6] chore: changes --- ...n_of_differtent_type-YT-JSO-2_2024-06-21-13-39.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@educorvi/rita/fix-allow_comparison_of_differtent_type-YT-JSO-2_2024-06-21-13-39.json diff --git a/common/changes/@educorvi/rita/fix-allow_comparison_of_differtent_type-YT-JSO-2_2024-06-21-13-39.json b/common/changes/@educorvi/rita/fix-allow_comparison_of_differtent_type-YT-JSO-2_2024-06-21-13-39.json new file mode 100644 index 0000000..160d3ce --- /dev/null +++ b/common/changes/@educorvi/rita/fix-allow_comparison_of_differtent_type-YT-JSO-2_2024-06-21-13-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@educorvi/rita", + "comment": "add ´allowDifferentTypes´ option to comparisons", + "type": "minor" + } + ], + "packageName": "@educorvi/rita" +} \ No newline at end of file