How to concatenate two arrays into one in Server Actions? (NodeJS)

Well, I have a repeat, that uses some data from DB.
Each cycle inside the repeat some number generated.
When it is generated I need to add it to the array outside the repeat. Let’s call this variable “MyGlobalArray”.
(It need to be added instantly and not after the repeat is ended, because “MyGlobalArray” itself is used inside repeat)

So I think that inside the repeat it would be step Set Value that sets/changes “MyGlobalArray” = “MyGlobalArray” ADD “some new number”.

E.g “MyGlobalArray” = [23, 45, 67],
“some new number” = 89,
so “MyGlobalArray” after change should be [23, 45, 67, 89]

To answer you question, if my assumption about how it should work is correct, then it would be only one Set Value. One that sets/changes “MyGlobalArray”.

So basically I managed to configure the kind-a-solution for CONCAT [1,2] and [3,4]

  1. Convert arrays to String
  2. Concatenate strings together
  3. Split the string to array
  4. Make a repeat and inside of it set a variable, that takes $value and convert it to number.
  5. Apply flatten for repeat

I like puzzles, but I believe that there must be a more elegant solution for this in Wappler. :slight_smile:

1 Like

Sometimes I wish there was a step to run pure JavaScript code for stuff like this (without custom modules)

You could probably build a custom module(yeah I know…) based on eval(), anonymous functions or even better(and safer) vm2 to run whatever js code you need as a step.

It could be a cool extension and fun to build. I might even give it a try at some point.

Something like this?

Below you have a rough and quick approach. Unfortunately I don’t have much time to work on this but maybe you want to take a go at it if you really need it. There would be a lot of parsing and token filtering required but it’s doable as you can see above.

const { NodeVM } = require('vm2')
const Parser = require('../../../lib/core/parser');
exports.run = function (options) {
    let tokens = (Parser.lexer(options.code))
    let result = []
    tokens.forEach(function (e) {
        if (e.name === 'L_CURLY' || e.name === 'R_CURLY') {
        }
        else if (e.name === 'IDENT') { result.push(JSON.stringify(this.scope.get(e.value))) }
        else {
            result.push(e.value)
        }
    }.bind(this))
    let code = result.join('')
    const vm = new NodeVM();
    return vm.run('module.exports =' + code)
}
1 Like

Uh Jon that is way over complicated.

A simple concat formatter should do just fine @patrick

LOL @George I know. This is not a solution for concat but for:

Ah i see :slight_smile: well we deliverable disallow running any JavaScript in expressions because this can cause security issues.

Indeed it can.

That’s the reason why I selected VM2 as module for it.

1 Like

Aha I see, good idea indeed instead of just eval.
Good to be sandboxed.

1 Like

Thanks for kick-starting! I’ll take a look at it soon, some scary words there, “lexer” :smiley:
(no idea why we need to go such deep to the point of parsing actual strings)

My idea is more like allowing a snippet of JS, like this:

let array1 = [1, 3];
let array2 = [4, 5];
return array1.concat(array2);

Can’t we just call vm.run(whatever_in_textarea)? And in Wappler it would be a textarea instead of single-line input of code.

Pseudo-code of module:

function runCustomCode(snippet) {
    // Wrap snippet inside function()
    let code = "function() {" + snippet + "}()";
    // Run function, and return function result to Wappler
    return vm.run(code)
}

Yes, you can call whatever you want from the text area but wouldn’t you want to reference values stored in Server Connect via the Server Bindings?

Yes, so I need to call this.parse(snippet)? Or do I need that whole token parser thing?

The parse() function will only work with expressions that make sense within SC framework’s scope.

Mixing JS code and SC bindings is not parseable with parse(). We would need to build a new parser for this kind of expressions which is why you can see me calling the lexer function.

Unless you want to have some dynamic generated functions I would just suggest creating custom modules/formatters instead of evaluating javascript.

exports.concat = function(arr1, arr2) {
  if (!Array.isArray(arr1)) arr1 = [arr1];
  if (!Array.isArray(arr2)) arr2 = [arr2];
  return arr1.concat(arr2);
}

Indeed @patrick @George if it’s just for that that’s the perfect solution but it can become cumbersome at some points to create formatters and modules for each single small thing. Specially if there are infinite ways of using a function(think .map())

I was thinking about actually creating a feature request to create a very advance nodejs module that allows running any type of javascript while being able to parse SC expressions. All this from within secured sandbox.

Sometimes you just need to quickly map an array with a custom function or you want to loop through something without having to go through the hassle of creating a custom module/formatter and the hjson that is sometimes very rigid as to what it accepts as options.

What do you think? Would you guys be open to create such custom action by creating a new parser function that can identify what are SC bindings and what is vanilla JS code and execute it in a safe sandbox(i.e. vm2)?

I believe the great majority of low-code solutions out there have some sort of component that allows the end users to run custom JS and inserting their own bindings and I have to assume they do this by using a sandbox.

2 Likes

I can relate to this. In one of my projects, I have around 7 formatters, and most of them are just one single JS function - but I must admit - all of them have some custom tweak.

Not sure how the proposed solution will work, but it sounds like a good tool to have in Wappler’s arsenal.

1 Like

Check:

What about just passing an Object to the custom module and the snippet textarea, and then return the Object modified? Sounds like a good compromise between passing SC variables to inside the sandbox and getting them back. With an Object we can pass practically anything we want without worrying about token parsing and stuff, what do you think?

A Wappler bonus would be to have syntax highlighting in such module textarea