Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Providing Expression Result for Rules for JsonLogic #978

Open
aepfli opened this issue Sep 6, 2023 · 4 comments
Open

Providing Expression Result for Rules for JsonLogic #978

aepfli opened this issue Sep 6, 2023 · 4 comments

Comments

@aepfli
Copy link
Contributor

aepfli commented Sep 6, 2023

Is your feature request related to a problem? Please describe.

We want to use this project to create JsonLogic for OpenFeature targeting rules. This means we need to assign a return value to rules.

Valid JsonLogic for this approach:

{
  "if": [
    {
      "==": [
        {
          "var": "context.product"
        },
        "test"
      ]
    },
    "returnvalue",
    "elseValue"
  ]
}

Describe the solution you'd like

Ideally, we could define each rule's Return-object like a ValueSource.

  • To enable it globally, I suggest adding a configuration property.
  • We could add a checkbox or something similar to enable it per the rule. We can handle it via the global rule (theoretically, a group could also have a return value, and the subrules/groups would then be unable to return a value.

Describe alternatives you've considered

For simple strings, I could increase the cardinality of each operator and add a manipulation step to the output - but this works for strings when returning strings. and it also works for numbers as numbers. But we would love to return any value.

magic and naive transformation
function transformRule(rule: object): { operator: string; values: object[] | object; returner: object | undefined } {
  const operator = Object.keys(rule)[0];

  const values = Object.values(rule)[0] as object[] | object;
  if (Array.isArray(values)) {
    const returner = values.pop();
    return { operator, values, returner };
  } else {
    const subRule = transformRule(Object.values(rule)[0]);
    const values: object = { [subRule.operator]: subRule.values };
    const returner: object | undefined = subRule.returner;
    return { operator, values, returner };
  }
}
export function transformLogic(tree: ImmutableTree, config2: Config) {
  const logicResult = QbUtils.jsonLogicFormat(tree, config2);

  if (logicResult.logic && 'if' in logicResult.logic) {
    const rules = logicResult.logic as JsonLogicIf;
    const ruleContent: any[] = [];
    for (const rule of rules.if) {
      const { operator, values, returner } = transformRule(rule);
      const newRule = {
        [operator]: values,
      };
      ruleContent.push(newRule);
      if (returner) ruleContent.push(returner);
    }
    ruleContent.push('elseValue');
    logicResult.logic = { if: ruleContent } as JsonLogicIf;
  }
  return logicResult;
}

Additional context

So far, I like this query builder's flexibility; it is excellent and easy to configure.

This is not a feature request on its own; I can tackle this and take a look at it. The question is, is it feasible and desirable? Also, let me know your take on this. Furthermore, if you think it is not suited for this tool. Can you think of a solution where I'll not fork the whole repository but would manipulate desired parts? (eg. There is no container factory currently in the settings, so I can't overwrite it - coming from the java world, sorry if that would be easy)

Things I am not sure about:

  • how to handle the else value
  • Is it a desired feature?

Looking forward to the discussions

@aepfli
Copy link
Contributor Author

aepfli commented Sep 8, 2023

I thought a little bit more about it and even played around. And my suggested approach has changed :)

  • I would add a field on the Group Container level (handled like the values and reusing the widget, if possible).
  • Enabling it via a setting in the Behaviour settings, which also defines the "resultType" and "ResultSrc". (Theoretically, we could also enable it per Conjunction if that makes sense.)
  • Initially, I would only focus on JsonLogic to be working and available. I am unsure if this is needed for SQL or other formats, but your thoughts are welcome.

@ukrbublik
Copy link
Owner

There is a demonstration of "switch" mode of query builder (like switch-case, or if-then-else)
https://ukrbublik.github.io/react-awesome-query-builder/#/switch
You can also try locally: run pnpm i and open http://localhost:3001/#/switch
What do you think about UI, does it fit your needs? Select on the right side (with options Foo and Bar) can be customized, you can render any component instead of select.
Switch mode is supported for SpEL for now, but I can add support for JsonLogic

@aepfli
Copy link
Contributor Author

aepfli commented Sep 12, 2023

this is mighty and aweseom and i missed that totally. We ill take a look, and we will most likely also provide a little PR for JsonLogic to be working with this approach. That is really really cool and i am impressed by the flexibility of this tool, truly awesome :)

@jakkubu
Copy link

jakkubu commented Mar 2, 2024

Hi @aepfli did you managed to do this MR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants