4

I come from a database programming background (e.g., Oracle PL/SQL) and had to learn some typescript for a recent project due to the difficulty in hiring web developers. I did ok - it was very clunky back-endish type code I was writing. It just had to work and it did.

I feel like there's a programming modality familiar to the world of databases that I can't see how to accomplish in Typescript. Consider this working fragment of code to evaluate a business rule:

public br_12(contractBid: WFO.ContractBid) {
  const condition1 =  (contractBid.n_tax_per <= 0.003);
  const condition2 =  (this.br_12(contractBid) === 0 && this.br_18(contractBid)) === 0 && contractBid.n_tax_per <= 0.005;
  if (condition1 || condition2)
      {
        return Math.ceil ( ( this.br_2(contractBid) * contractBid.n_tax_per) * 100 / 100 ) ;
    } else {
      return 0;
    }
  }

I would like to be able to store the business rules, specifically the conditions, externally in a JSON file - or other external data source - and sometimes reference them arbitrarily and programmatically. And be able to update them without "changing any code" - of course I know the app would have to be rebuilt and redeployed when they change. So to write very rough sample code:

{
    "business rules conditions": {
        "condition1": "(contractBid.n_tax_per <= 0.003)",
        "condition2": "(this.br_12(contractBid) === 0 && this.br_18(contractBid)) === 0 && contractBid.n_tax_per <= 0.005"
    }
}

public br_12(contractBid: WFO.ContractBid) {
  if (this.external.condition1 || this.external.condition2)
      {
        return Math.ceil ( ( this.br_2(contractBid) * contractBid.n_tax_per) * 100 / 100 ) ;
    } else {
      return 0;
    }
  }

Nevermind that I'm crazy to want to do such a thing - is there a way to do it?

ghybs
  • 47,565
  • 6
  • 74
  • 99
Bowtied
  • 43
  • 4
  • 1
    Why does it have to be JSON and why can't it be a typescript file? it sounds like you've already accepted you're going to rebuild and redeploy so what's the motivation? – Evert Aug 03 '22 at 05:35
  • @Evert - see motivation below. Although I have accepted the need to rebuild and redeploy...it would actually be nice if there were a way around that. But first things first. – Bowtied Aug 03 '22 at 12:32
  • "it's so that an "analyst" as opposed to a "coder", can tweak the business rules," is the reason I see. Isn't javascript-in-JSON *harder* to understand than plain Javascript? Javascript *is* a text format, I don't understand the problem. – Evert Aug 03 '22 at 23:50

2 Answers2

2

Unfortunately JavaScript / TypeScript treats data as non executable.

So you would need to store your rules as strings, and convert them to code e.g. using:

  • eval, which is considered bad practice (because it is an easy attack vector target)
  • text parsing, i.e. build a mini syntax / Domain Specific Language

But if I understand correctly, in the first place you want to separate the definition of the business rules from where they are used. Maybe so that they are all gathered in a single place, it is easier to review and maintain them, etc.

In that case, there are many other possible solutions:

  • make each business rule a simple function, all exported in a single module
  • methods of a singleton class (essentially similar to previous point, but can be more familiar to OOP developers)

You could even consider ignoring that file from source control (in case you want to swap it depending on the environment, "without changing any code"), although for such use case, since it involves code, we would rather commit all different code versions, and import the appropriate module depending on an environment variable only (e.g. using a tsconfig import path alias).

ghybs
  • 47,565
  • 6
  • 74
  • 99
  • "Maybe so that they are all gathered in a single place, it is easier to review and maintain them, etc." Yes that is exactly the rationale. It's so that an "analyst" as opposed to a "coder", can tweak the business rules, and thus that aspect of the operation of the app, without having to "know how to code". And I just used JSON as an example. It could be a text file with a certain configuration, it could be an XML, and could well end up being a sharepoint list...because we can have more fine grained access control on that. – Bowtied Aug 03 '22 at 12:23
  • "make each business rule a simple function, all exported in a single module" Yes in the couple hours of research I'd already done on this, modules were the only feature of angular/typescript that seemed like they could possibly work. But I couldn't find any example doing something like this. If anyone can point me to one, I'd be very appreciative. – Bowtied Aug 03 '22 at 12:27
  • "essentially similar to previous point" - I'm sorry, which post were you referring to? – Bowtied Aug 03 '22 at 12:28
  • Thank you for your feedback. By "previous point", I was referring to the above bullet point, i.e. a module with exported functions. – ghybs Aug 03 '22 at 15:52
  • If you _do_ need to avoid rebuild of the full app, you could use an old school global JavaScript file import from the HTML file. You can have TS configured to accept such global usage. But whatever you do, you will still need a deployment (full app or specific separate file). – ghybs Aug 03 '22 at 15:59
  • OK thanks for clarification. So now I just need to figure how to get started with "make each business rule a simple function, all exported in a single module". – Bowtied Aug 03 '22 at 18:14
0

Actually, I just found this...about using the transpile function with eval. Seems to be 'kosher' enough? Eval not going to be a huge concern as an attack vector because this is a very closed access business system, not a public website. And anyhow the configuration script/JSON/sharepoint list will even more limited in access.

Evaluate Typescript from string?

Bowtied
  • 43
  • 4