Use the following libraries and common code resources compiled here to help you write flows.
Libraries
App Xchange supports the NodeJS v18.15.0 version of JavaScript.
The App Xchange flow engine supports the following JavaScript libraries:
Day.js
Numeral.js
Lodash
uuid
Day.js
Go to the Day.js library documentation.
V1.11.7
The flow engine supports all methods including the following plugins:
Numeral.js
Go to the Numeral.js library documentation.
V2.06
The flow engine supports all methods.
Lodash
Go to the Lodash library documentation.
V4.17.21
All methods are supported. To call lodash functions, use the standard _.method().
uuid
Go to the uuid library documentation.
V9.0.0
The most common method for generating GUIDs is uuid.v4().
Flow Helpers
The App Xchange flow engine uses the following helper code snippets, created specifically to help you access data when writing flows. Helpers are organized by the namespaces they access:
workspace
info()
Access data of the Flow Workspace: workspace.info()
Access the Workspace id: workspace.info().id
Access the Workspace name: workspace.info().name
appNetwork
fileUrl(fileId: string)
Generate an App Network file url: appNetwork.fileUrl('fileGuid')
legacyFileUrl(fileId: string)
Generate a Legacy App Network file url: appNetwork.legacyFileUrl('fileGuid')
flow
info()
Access flow info: flow.info()
Access the flow registration ID: flow.info().registrationId
Access the flow URL: flow.info().url
config
Access the flow's config: flow.config
Access a property on the flow's config: flow.config.myProperty || flow.config[myProperty]
loopItem()
Access item data (only available for a For Each in a List step): flow.loopItem()
mapItem()
Access item data (only available in the context of mapping data in a Map step or Connector Action step): flow.mapItem()
trigger
Access the flow's trigger event: flow.trigger.event
Access the flow's trigger data: flow.trigger.data
Check if the flow run was triggered by a cache record create event: flow.trigger.isCacheCreate()
Check if the flow run was triggered by a cache record update event: flow.trigger.isCacheUpdate()
Check if the flow run was triggered by a cache record delete event: flow.trigger.isCacheDelete()
Check if the flow run was triggered by an action closed out as successful: flow.trigger.isActionSuccess()
Check if the flow run was triggered by an action closed out as failed: flow.trigger.isActionFail()
step(stepId: string)
Access a property on the output data of a previously executed step: flow.step("step-id").output.JobCode
Access the action response of a previously executed step: flow.step("step-id").actionResponse
Access the action request of a previously executed step: flow.step("step-id").actionRequest
Check if a previously executed step has an action status of Success: flow.step("step-id").isActionSuccess()
Check if a previously executed step has an action status of Fail: flow.step("step-id").isActionFail()
Check if a previously executed step has an action status of Queue Action Success: flow.step("step-id").isQueueActionSuccess()
Dates
return today’s date
use Vista standard formatting for Batch creation
Note: Will set to 1st day of current month.
compare a date to the current day
create a date variable, set it equal to an input value, and output it in a specific format
safely convert a value to a date, or default to today’s date
calculate the next closest Friday after a given date
Note: Replace the example date with your date variable.
calculate the last day in a month
calculate the last day in a week
compare two dates
Strings
know if a string contains specified text
find the first position of a specified value
Will return a -1 if not found.
convert to upper or lower case
Note: You should convert to lowercase or uppercase prior to string comparison! For example, converting an email address, vendor name, or payment type name to lowercase prior to comparison will make it case-insensitive and protect you against capitalization errors.
Lodash also gives us the following:
return the length of the string
delete or keep part of the string
Javascript has a substring() method, but we recommend slice(). You can read why here if interested.
slice() takes a startIndex and an optional endIndex and returns the string between the start and the end indexes.
If no endIndex is supplied, slice() preserves thru the end of the string.
This is non-destructive. It returns a new string from the start index to the end index while leaving the original string intact. vTest remains unchanged. You will have to assign this to a new variable in order to access it.
replace all instances of a string with another
Use replace to strip out special characters. It is a great and easy way to make sure your string is sanitized and does not contain special characters that can cause problems.
Non-destructive
remove starting and ending white space
Trim should be one of the most common functions used with strings. Be sure to use it to get rid of any leading or trailing whitespace that can cause issues. Whitespace has been known to cause support tickets and delays in onboarding, and is very tough to track down. Use Trim and eliminate this headache!
evaluate if a value is blank or null
Always check for null or empty prior to using the value. You can then create a hierarchy of data, for example, checking allocation fields first and if blank/null then checking the expense detail fields and if blank/null then defaulting to something. This type of defensive coding will keep flows from failing or remediation tasks from being created for missing data.
format data as currency
split a string into parts
As with previous JS string methods, these are non-destructive to the original string and must be assigned to new variables.
If the string does not contain the character or string you are splitting on, it returns undefined.
add characters to the beginning or ending of a string
Numbers
parse a number from a string
format a number into dollars
Arrays
create a hardcoded array, e.g. for use with the In operator in a filter expression
Use extreme care when hardcoding something. Make sure it is future proof and will not need to be changed in the future.
determine if any element in an array contain a value matching the criteria
determine if all elements of an array contain a value matching the criteria
sort an array by a column in descending order and then return the first value (highest value).
sort() mutates the original array. The default sort order is ascending. The time and space complexity of the sort cannot be guaranteed as it depends on the implementation.
Lodash is another option:
evaluate if a lookup step had any records
How to access element in lookup
map a filter step's output array
add each value in an array to a list or a string
sum all values in a field of an array or list
The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.
The first time that the callback is run there is no "return value of the previous calculation". If supplied, an initial value may be used in its place. Otherwise the array element at index 0 is used as the initial value and iteration starts from the next element (index 1 instead of index 0).
assign a value based on looking up a value in an array
do something for each item in an array
sort the Input for a MAP step, to intentionally order lines in an invoice
Remember sort() will mutate the original array where as _.orderBy() will return a new array.
Other Helpful Coding Tips
create two lists and then find the values from one that doesn’t exist in the other
Create the two lookup steps
lookup-ineight-employees-ocakj
lookup-vista-employees-xy6c9
Create the filter step
List
Test Expression
use null coalesce (double question marks)
These are both the same
How to fix if node does not contain something
Note the . before ["Concur_Approver"]
use regex for any file containing “KPC” and ending in .CSV
call a configured variable
If the variable is a single object
If the variable is a “Multiple Text Items”
reference a configuration property set as multiple text items
check if the Config Value is empty
create a map step without any input
Set “List or Object” [] or {}
dynamically determine start row for a Parse Delimited File step
You have to edit the JSON of the flow, but then you can change the property to any value you want. Must resolve to a number.
StartingRowNumber:
create a random string
TryParse
set the field to get data from via a configuration
This is helpful if you want to be able to use a configuration on a shared flow so that you can set a different ud field to reference for each customer.
Everything inside the brackets is just a string value, so this method can be used in a number of ways.
You could also create other dynamic situations.