ScriptEval

The Do It All Swiss Army Knife Valve

Introduction

Valve for evaluating scripts using the Java Scripting API (javax.script) and GraalJS/GraalVM.

Type of script supported (JavaScript/ECMA, Python, Ruby etc) is depending on the script engine used. By default this valve (and the examples) uses the graal.js engine with support for JavaScript.

For more information, see:

https://www.graalvm.org/

Configuration

Valve name: ScriptEval

NameDescriptionDefault valueMandatoryExpanded

engine

The script engine to use.

"graal.js"

source

The script to evaluate (Mandatory unless config.path is configured)

path

Path to script to evaluate.

Context

During script evaluation the following objects are available in the script context:

NameDescription

request

The current request. Object is read-only and can not be modified.

state

Object representing the current pipe state.

session

Object representing the current session

items

Object providing access to the current set of items.

log

The current valve logger.

context

The raw pipe context. Use only if objects above are not sufficient. Type: foss.pipes.valves.item.api.PipeContextItem

Request parameters

Pipe request parameters are accessed using the request object in script context:

// Read request parameter and assign to variable
var msg = request.message;

// Do stuff based on existence of a request parameter
if (request.xxx) {
    // xxx is truthy
}

// Do stuff based on the value of a request parameter
if (request.username === "johnd") {
    // Parameter is of type string and has the value "johnd"
}

State

Pipe state can be accessed using the state script context object. Properties stored in state are available to all valves in a pipe and also included in the pipe response.

// Set or update a state property named 'name01'
state.name01 = "value01";

// Read property from state and assign
var name01 = state.name01;

// Remove property from state
delete state.name01

Session

The current session can be accessed using the session script context object.

Session has two reserved properties that can not be modified:

  • id

  • trace_id

// Read "reserved" session properties (can not modified)
const sid = session.id;
const tid = session.trace_id;

// Read property from session
var username = session.username;

// Set property in session
session.username = request.username;

// Remove property from state
delete session.username;

Items

Items is an API that provides access to the current item set. Using this API items can be created, loaded by id, removed and iterated.

Item objects returned by this api has an id property (reserved and read only) and an arbitrary number of other properties.

Note: Item properties are always of type string

// Check if items exist
if (!items.isEmpty()) {
    // At least one item exist
}

// Get the number of items
const itemCount = items.size();

// Get first item
// Note: items are not ordered, there is no guarantee which item is "first"
//       unless only one exist.
const firstItem = items.first();

// Create a new item with id 'johnd'
// Note: item id must be unique, if an item with specified id 
//       already exist null is returned
const item = items.create("johnd");
item.created = true;

// Load specific item by id (returns null if not existing)
const item = items.item("johnd")

// Get and set item properties
var value = item.value;
item.value = "new value";

// Check if item with specific id exist
if (items.item('johnd')) {
    // Item exist
}

// Remove property from item
delete item.name;

// Get all items as an array
const array = items.all();
if (array.length > 0) {
    // Not empty
}

// Iterate current items with lambda
// First lambda argument (id) is item id
// Second lambda argument (item) is the actual item
items.forEach((id, item) => {    
    // Do stuff with item
});

// Remove item (supports both item (object) and id (string))
items.remove(id);
items.remove(item);

Logging

Logging in scripts can be done using the standard console object:

console.log('log'); // Same as 'console.debug'
console.trace('trace')
console.debug('debug');
console.info('info');
console.warn('warn');
console.error('error');

or using the Fortified Logging API Logger object also supporting "printf" formatting:

log.trace('trace');
log.trace('string: %s', "string arg");
log.debug('debug');
log.debug('int: %d', 99);
log.info('info');
log.info('boolean: %b', true);
log.warn('warn');
log.warn('Multiple args: %s (%d) %b', "string", 99, false);
log.error('error');

Troubleshooting

Syntax error

Bad script syntax result in a syntax error in the log (WARN) and a flow failure.

A syntax error typically looks like this and contains a location, description and the bad line:

SyntaxError: <eval>:43:24 Missing close quote
print('Hello, World!'');
                        ^

Advanced

Java types

To access java types in script use:

var FileClass = Java.type("java.io.File");

or (backwards-compatible syntax):

var FileClass = java.io.File;
var file = new FileClass("myFile.md");

For more information regarding script interoperability with java, see: https://www.graalvm.org/reference-manual/js/JavaInteroperability/

Engine configuration

Script engine log can be configured using the following system property:

-Dpolyglot.log.file=<path>