rules-machine icon indicating copy to clipboard operation
rules-machine copied to clipboard

Support functions in input context

Open justsml opened this issue 3 years ago • 6 comments

justsml avatar Sep 23 '22 21:09 justsml

This is still failing with both of the following:

import { ruleFactory } from '@elite-libs/rules-machine';

const things = [
  {
    name: "ABC"
  },
  {
    name: "DEF"
  },
  {
    name: "123"
  }
];

const thingRules = ([
  {
    if: 'isConditional(thing.name) == false', then: 'keep = false'
  },
  {
    return: "keep"
  }
]);

const filterWithRules = ruleFactory(thingRules)

function isFiltered(thing: Record<string, string>): boolean {
  const result = filterWithRules({
    thing,
    isConditional: (value:string) => value.endsWith('C'),
    keep: true
  });
  return result;
}

console.dir(things.filter(isFiltered));
import { ruleFactory } from '@elite-libs/rules-machine';

const things = [
  {
    name: "ABC"
  },
  {
    name: "DEF"
  },
  {
    name: "123"
  }
];

const thingRules = ([
  {
    if: 'isConditional(thing.name)', then: 'keep = false'
  },
  {
    return: "keep"
  }
]);

const filterWithRules = ruleFactory(thingRules)

function isFiltered(thing: Record<string, string>): boolean {
  const result = filterWithRules({
    thing,
    isConditional: (value:string) => value.endsWith('C'),
    keep: true
  });
  return result;
}

console.dir(things.filter(isFiltered));

dara-rockwell avatar Sep 26 '22 14:09 dara-rockwell

Link to Repl: https://replit.com/@dara-rockwell/DearPortlyEmulator#index.ts

dara-rockwell avatar Sep 26 '22 14:09 dara-rockwell

Found what may be the source of the problem:

import { ruleFactory } from '@elite-libs/rules-machine';

const things = [
  {
    rateCode: "Z2H",
    provider: "Marriott",
    shouldKeep: false
  },
  {
    rateCode: "C13",
    provider: "This is a Marriott Hotel",
    shouldKeep: false
  },
];

const thingRules = ([
  {
    if: 'stringContains(LOWER(thing.provider), "marriott")',
    then: "keep = false"
  },
  {
    return: "keep"
  }
]);

const filterWithRules = ruleFactory(thingRules, { trace: true })

function isFiltered(thing: Record<string, string>): boolean {
  const result = filterWithRules({
    thing,
    stringContains: (value: string, search: string): boolean => value.includes(search),
    keep: true
  });

  console.dir(result.trace)

  return result;
}

console.dir(things.filter(isFiltered));

According to the trace, it appears that stringContains is stripped out of the evaluated string:

  {
    operation: 'expression',
    rule: 'stringContains(LOWER(thing.provider), "marriott")',
    result: [ 'this is a marriott hotel', 'marriott' ],
    stepRow: 0,
    stepCount: 1
  },
  {
    operation: 'if',
    rule: 'stringContains(LOWER(thing.provider), "marriott")',
    result: true,
    currentState: '{"thing":{"rateCode":"C13","provider":"This is a Marriott Hotel","shouldKeep":false},"keep":true}',
    stepRow: 0,
    stepCount: 1
  },

I base this presumption on how it is evaluated if I strip the function name out manually:

{
    operation: 'expression',
    rule: '(LOWER(thing.provider), "marriott")',
    result: [ 'this is a marriott hotel', 'marriott' ],
    stepRow: 0,
    stepCount: 1
  },
  {
    operation: 'if',
    rule: '(LOWER(thing.provider), "marriott")',
    result: true,
    currentState: '{"thing":{"rateCode":"C13","provider":"This is a Marriott Hotel","shouldKeep":false},"keep":true}',
    stepRow: 0,
    stepCount: 1
  },

dara-rockwell avatar Sep 26 '22 16:09 dara-rockwell

@chhatch @justsml

dara-rockwell avatar Sep 26 '22 16:09 dara-rockwell

@chhatch @justsml Replit for the above example:

https://replit.com/@dara-rockwell/Rules-Machine-Custom-Functions#index.ts

dara-rockwell avatar Sep 26 '22 17:09 dara-rockwell

Good spotting @dara-rockwell.

It looks like there is a function safe list thing going on. Which reminds me, I need to put a lot more thought into this - the security 🙀 issues could be many.

justsml avatar Oct 31 '22 07:10 justsml