Skip to main content

Functions

Functions are a fundamental part of AutomatorScript, and are used to define reusable code blocks.

In general, functions in AutomatorScript behave the same as in standard JavaScript, and this MDN guide is an excellent resource to learn how to write and use functions.

You can see some real-world examples of various types of functions, including arrow functions, in the Calendarific integration.

In addition to functions that you write yourself, AutomatorScript also supports:

Abstraction

Many low-code iPaaS platforms model an integration as a fixed sequence of boxes wired together on a canvas. That works for simple flows, but it offers very little abstraction: there is no good way to name a concept, reuse a piece of logic, or describe what a flow does separately from how it does it.

The automator takes the opposite approach. Because you write real code in a real language, you have the full range of abstraction tools: functions, libraries, meaningful names, and the ability to build higher-level operations out of lower-level ones. This is what allows automator packages to stay comprehensible even when the underlying integration is complex.

To use these abstraction tools effectively, we recommend the following practices:

  • Build the entry point at a high level of abstraction. It should explain what the package does, not how.
  • Start with guard clauses. If the input is invalid or there is nothing to do, return early rather than nesting the rest of the package inside an if.
  • Keep functions short and single-purpose, with clear, descriptive names.
  • Keep the code inside a function at a single level of abstraction. Don't mix high-level steps with low-level detail in the same function.
  • Pass a function everything it needs through its parameters, rather than reaching out to globals. This keeps functions easy to read, reuse, and test.
  • Move reusable functions into a library as soon as more than one package needs them.

Example

The following example illustrates these practices.

if (!shouldProcess(request)) {
return; // guard clause: nothing to do
}

let order = fetchOrder(request);

notifyRequester(request, order);

function shouldProcess(request) {
return request.category === 'order' && !request.workflow;
}

function fetchOrder(request) {
return rest_get(`/orders/${request.source_id}`, 'shop');
}

function notifyRequester(request, order) {
sendMail({
to: request.requester.primary_email,
subject: `Your order ${order.reference} is ready!`,
body: "..."
});
}

At the top level, main() reads as three functional steps:

  • Should we process this request?
  • Fetch the order
  • Notify the requester

The details of how an order is fetched or how the requester is notified are one level down, each behind a descriptive name.