Making it easy to read with $from

When you start to write several OpenAF scripts you will usually start to write a log while/for/do cycles to go through an array and perform so task. Take the following example (which might be hard to read for a beginner):

What this piece of code does is:

var list = io.listFiles("."); 
var found = false, i = 0;
while(!found) {
   var file = list.files[i];
   if (file.isFile && file.filename == "myScript.js") 
      found = true;
   else
      i++;
}
var myRecord = list.files[i];
  • Get an array with all the files and folders on the folder “.” (through io.listFiles). This will result in an array of maps. Similar to:
      {
      "isDirectory": true,
      "isFile": false,
      "filename": "somefile.txt",
      "filepath": "./somefile.txt",
      "canonicalPath": "/some/folder/somefile",
      "lastModified": 1560515651403,
      "createTime": 1560515651374,
      "lastAccess": 1564194441636,
      "size": 640,
      "permissions": "xrw"
    },
    
  • Iterate through each element of the array trying to find a filename equal to “myScript.js” and ensuring it’s a file and not a folder.
  • Once found, break the cycle and store the corresponding map in the variable myRecord

Now let’s rewrite it using $from (a shortcut to the JLinq library):

var myRecord = $from(io.listFiles(".").files)
        .equals("isFile", true)
        .equals("filename", "myScript.js")
        .select();

Doesn’t it look a little bit easier to read? It’s structured like a SQL query where “from” points to the array origin, the “where” comes next is the functions equals to test if it’s a file and for the filename “myScript.js” and finally “select”s all fields keeping the result in myRecord.

Some more examples:

// From a listOfThings array of maps, where type equals "item" and barcode starts with "501"
// return true if there is any matching map.
$from(listOfThings).equals("type", "item").starts("barcode", "501").any();

// From a list of files of the current folder, where it's a directory, count the corresponding
// matching maps.
$from(io.listFiles(".").files).equals("isDirectory", true).count();

// From a files of files of the current folder, where filename matches the regular expression 
// "work.+", select only the field filename from the map (if it doesn't exist replace the 
// missing value with "")
$from(io.listFiles(".").files).match("filename", "work.+").select({ filename: "" });

// From a listOfThings array of maps, where type equals "item", sort the results by name and 
// select the result by running a function passing to it each matching map. The returned result
// of executing the function with each matching map will be returned in an array.
$from(listOfThings)
.equals("type", "item")
.sort("name")
.select((record) => {
   return r.barcode + " - " + r.name;
});

You can check more examples on the jLinq demo or typing, in the openaf-console, “desc $from([])”.