You are viewing limited content. For full access, please sign in.

Question

Question

Parsing Multivalued input in NodeJS Script

asked on June 24

I am running a script rule from Laserfiche Cloud and I am passing a multivalued input to the Node JS script.  However, I do not know what code is required on the end to retrieve/handle the various input values.  As far as I can tell the multivalued input ends up as a string in node JS.  Here is the code along with the test output.  Any help would be much appreciated.  Full disclosure I am not a developer and my Javascript knowledge and Laserfiche knowledge in general is basic.

 

const process = require('process');

let input1 = process.argv[2];

console.log("outputValue1:"+input1);

0 0

Answer

APPROVED ANSWER SELECTED ANSWER
replied on July 5

Multivalued inputs are passed to the script as a pseudo-JSON string and can generally be parsed using the JSON.parse function.  You might have noticed my hedging in that sentence... there are some gotchas... here are three and how to work around them:

1. If you have multiple input parameters, you need to separate them first

You can use a function like the following (from the help documentation and sample project):

function getArgumentMap(args) {
    if (args == null) {
        throw new Error('Invalid arguments.');
    }

    const argMap = {};

    // eslint-disable-next-line no-plusplus
    for (let i = 2; i < args.length; i++) {
        const arg = args[i];
        const idx = arg.indexOf('=');
        if (idx > 0) {
            const key = arg.substring(0, idx);
            const val = arg.substring(idx + 1);
            argMap[key] = val;
        }
    }

    return argMap;
}

2. You need to remove a pair of wrapping single quotes

Something like this should work:

var inputs = getArgumentMap(process.argv);
var unqoutedList = inputs['List'].substr(1, inputs['List'].length - 2);

3. Individual string values within the multivalue input need to be wrapped in quotes

When testing in the editor:

In Workflow:

For example, I used an Assign Token Values activity to create a multivalued token and it need to look like this:

0 0
replied on August 1

I looked at the sample project template folder and did not see a .js or .cjs file showing how to work with multi-value.

This post is helpful for multi-value inputs, but how do we populate multi-value outputs as well in Node?

0 0
replied on August 2

You can combine multiple outputs with a separator-that-doesn't-appear-in-your-data (e.g., the | character) into a single string and then using the Split token function to create a multi-value token from that output.  Note that the separator can be multiple characters and even use tokens.

The output string can be created from an array of values using JavaScript's array.join method.


And, yes, this is a workaround--as far as I know, there is no direct support for outputting a multi-value token in a NodeJS script.

1 0
replied on August 2 Show version history

Oh I see, I can't select Multi-Value for the output fields in the rule. I saw it but didn't realize it was not selectable. This will work as a workaround. Thanks!

0 0
replied on August 15

I am not having any luck with this function, for example if I send a single token with 2 values

  1. Hello
  2. World

 

I get back "Hello,World" which is just my 2 values in a single comma delimited string

Therefore if I send values

  1. Hello,World
  2. World,Hello

 

I get back "Hello,World,World,Hello" which looks like 4 values not 2

How do we actually For Each on the values we receive from the start?

0 0
replied on August 15 Show version history

If your data contains commas, you can't use comma as your separator.  I suggest using something like | (bar) or even multiple characters together (e.g. |||) such that it's guaranteed to be unique relative to your data.
 

Here's a full example (script + workflow):

Script

var getArgumentMap = function (args) {
    let argMap = {};
    if (args == null) {
        console.error("Invalid arguments.");
    }
    for (let i = 2; i < args.length; i++) {
        try {
            let arg = args[i];
            let idx = arg.indexOf('=');
            if (idx > 0) {
                let key = arg.substring(0, idx);
                let val = arg.substring(idx + 1);
                argMap[key] = val
            }
        }
        catch (e) {
            console.error(`Could not parse arguments: ${args}`);
            throw e;
        }
    }
    return argMap;
};

var setOutputsFromObject = function (obj) {
	for (var key in obj) {
		console.log(`${key}:${obj[key]}`);
	}
};

var unwrapValue = function(value) {
	if (value[0] === "'" && value[value.length - 1] === "'" )
		return value.substr(1, value.length - 2);
	else
		return value;
}

var inputs = getArgumentMap(process.argv);


var unquotedList = unwrapValue(inputs['List']);
var unquotedValue = unwrapValue(inputs['ValueToAppend']);

var list = JSON.parse(unquotedList);
var valueToAdd = JSON.parse(unquotedValue);

list.push(valueToAdd);

var joinedList = list.join('|');

setOutputsFromObject({ 'UpdatedList': joinedList });



Workflow

 

Workflow Instance Results



Side Note: since my script using JSON.Parse to parse the input multivalue token, I needed to wrap my values in quotation marks.  Depending on your data, you may be able to do it the easier way of using a JavaScript split function.  Or you might not even have a multivalue input token.

1 0
replied on August 15

Ok so multi-valued inputs are turned into a comma delimited string by the system, there is no way to receive an array that we can cycle through the raw values. This means we must use some character to wrap the contents of each value and make sure this character is never used in the values.

That is more troublesome then I thought. I was expecting to receive an array I could cycle through the raw values and work with any values that might be passed to the rule.

0 0
replied on August 15

Yes, unfortunately.  I wasn't part of the team that originally designed or implemented this system, so I understand your frustration with the way it works.

I'll put a story in our backlog for improving the way multi-value inputs and outputs are handled by NodeJS scripts, but I can't make any guarantees about when it'll be addressed.

0 0
replied on August 15

That was my biggest confusion as I didn't know I was simply working with a CSV string, I thought I was working with an array from the start. So I will use quotes for now. Now if I can just figure out why my file size is too large, I can actually send this data.

0 0
replied on August 15

To be clear, the multivalue inputs aren't exactly a CSV string... they're pseudo-JSON.  No idea why they're implemented this way, but with some minor transformation, you can usually make them parseable as JSON.  Or, if your content doesn't have commas, you can do something simpler with a JavaScript split function.

 

For output parameters, the goal is to make a delimited string that is easy to split apart (since console.log/stdout doesn't accept multiple values...at least not in a way that the workflow activity can then understand). 

0 0

Replies

You are not allowed to reply in this post.
You are not allowed to follow up in this post.

Sign in to reply to this post.