0

I have a react application, using webpack. In my application, I allow users to overwrite default behaviors with their own custom behavior.

For example lets say the application has a button that when clicked would alert a message to the user and this user would rather not be annoyed with an alert box they would rather it be a console.log statement. In the admin console, they would upload a class, that class must have an method named exec(). Then they would click on the button (in an admin console) and change its onClick functionality to be the name of their custom class.

Currently, when they upload a file, after checking to make sure it is valid js class with a exec method, the class is stored in a database as text.

What I want, is that when the application starts is that the applications reads all the classes and store them as a map with their names as the key. I can retrieve the classes from the database (as text) how can I turn that into an object?

edit added code here is an example class

class CustomClass {

  exec(params) {
  console.log('you are in a custom class');
 }
}

getting the custom classes

 const apiUrl = 'https://api.example.com/customClasses';
    fetch(apiUrl)
      .then((response) => response.json())
      .then((data) => console.log(data));

this would give a json that looks like

{
    "CustomClass":  "class CustomClass {\r\n\r\n  exec(params) {\r\n  console.log(\"you are in a custom class\");\r\n }\r\n}",
    "CustomClass2":  "class CustomClass2 {\r\n\r\n  exec(params) {\r\n  console.log(\"you are in a custom class2\");\r\n }\r\n}"    
}
user889829
  • 388
  • 2
  • 7
  • 20
  • Please write some code, some minimal example of how you store "classes" in text and what your component will do with it after it loads it. Otherwise `eval` could be used to parse the text. – Ivar Jan 14 '21 at 18:46
  • @Aivaras I added some code – user889829 Jan 14 '21 at 19:16

2 Answers2

1

So, it turns out you can just use eval with parenthesis as seen here

let userClasses = {
    "CustomClass":  "class CustomClass {\r\n\r\n  exec(params) {\r\n  console.log(\"you are in a custom class\");\r\n }\r\n}",
    "CustomClass2":  "class CustomClass2 {\r\n\r\n  exec(params) {\r\n  console.log(\"you are in a custom class2\");\r\n }\r\n}"    
}

for (const userClassName in userClasses) {
    const userClass = eval(`(${userClasses[userClassName]})`);
    let userClassObject = new userClass();
    userClassObject.exec();
}

Would this solve your problem?

Gunther
  • 1,297
  • 9
  • 15
0

I see you alredy did this part when loading from database

starts is that the applications reads all the classes and store them as a map with their names as the key

Since you can assume the object has only one method called exec you should probably just save the contents of the function, so that the response from you request is like

{
    "CustomClass":  "console.log(\"you are in a custom class\");",
    "CustomClass2":  "console.log(\"you are in a custom class2\");"    
}

This removes the having to parse the code from the string, then you can just do this

const classesMethods = json.parse(input);
{
    "CustomClass":  "console.log(\"you are in a custom class\");",
    "CustomClass2":  "console.log(\"you are in a custom class2\");"    
}

for (const method in classesMethods) {
    const newObj = {};
    newObj.exec = new Function(classesMethods[method]);
    newObj.exec();
}

I'm assuming the parameters you're giving these functions have always the same name.

Here the result of this.

Edit: As you can see I tested it in firefox console, not node, you might have some problems with that, I don't really use node.

Gunther
  • 1,297
  • 9
  • 15
  • thank you for your answer, the example that I used was a simple example. In reality there are usually multiple methods in the class with class level variables as well – user889829 Jan 14 '21 at 19:40
  • Well, that requires a completly different answer I'll take another look at it later – Gunther Jan 14 '21 at 19:54