Run custom code (JS)
The basics about custom code
The custom code step is an advanced tool for processing data in Relay.app. It can be used to build complex logic that goes beyond the capabilities of Relay.app's Transform data steps.
Custom code is written in JavaScript, and some familiarity with programming is required to use it.
When to use
Common scenarios that work well are:
Data from Using data across steps need to be converted into another format.
Complex logic is required to decide what the workflow should do. Custom code steps are limited to working with local data. Communicating with external services within a custom code step is not possible.
JavaScript support
Code can use all ES2023 language features and the luxon and lodash libraries.
Async support
Custom code can be asynchronous and return a Promise. To use await inside the step, declare the exported function as async:
export default async function (inputs) {
// await any promise-returning operation here
return { /* ... */ };
}The step waits for the returned promise to resolve before passing its value to later steps in the workflow.
Built-in objects
The custom code step runs in a narrow sandbox, not a full Node.js runtime. Only the globals listed below are available. There is no require, no module loader, and no access to the Node.js standard library.
The following globals are exposed:
console— implementsconsole.logto record messages during execution._— the lodash library.Buffer— Node.js-styleBufferfor working with binary data.atob/btoa— base64 encode and decode strings.TextEncoder/TextDecoder— encode and decode between strings andUint8Arraybyte sequences (typically UTF-8).crypto.getRandomValues— fill a typed array with cryptographically strong random values.crypto.randomUUID— generate a random RFC 4122 v4 UUID.crypto.subtle.digest— compute a cryptographic hash (e.g. SHA-256) of a byte sequence.crypto.subtle.importKey— import a key for use with othercrypto.subtleoperations.crypto.subtle.sign— produce a signature over a byte sequence using an imported key.
This is the full list of sandbox globals. Anything not listed here — including most of the Web Platform and Node.js APIs — is not available inside a custom code step.
Date and time data
Custom code uses the luxon library to handle date and time data. Input data with the corresponding type is passed to the function as a DateTime or Duration value. If returning the output of a Luxon call, those values should be typed accordingly in Relay.app (e.g., using Relay.app's Date/DateTime/Duration variable types).
The luxon documentation offers a good overview of formatting and math capabilities. The complete API can be viewed in the API reference.
Limitations
The custom code sandbox is intentionally restrictive. In particular:
No
require— modules cannot be loaded dynamically. Only the built-in objects listed above are available.No
fetchand no outbound network access — custom code cannot call external services, APIs, or websites from inside the step. Use a dedicated HTTP or integration step for that.crypto.subtleis limited — only the operations listed under Built in objects (digest,importKey,sign) are supported. OtherSubtleCryptomethods (such asencrypt,decrypt,verify,deriveKey,generateKey,exportKey,wrapKey,unwrapKey) are not available.importKeysupports binary key formats only —pkcs8,spki, andraware supported. Thejwk(JSON Web Key) format is not supported.
Working with data
Steps in Relay.app define their interface ahead of time. For custom code this requires configuring both inputs and outputs:
Configure the Inputs by selecting data produced by earlier steps of the workflow**.**
Configure the shape of the Outputs returned by your code block. Your code must return a value whose structure matches the Outputs configuration.
Anything configured in Outputs is accessible in later steps of the workflow.
Inputs
The inputs section defines what data from the workflow can be used from the custom code step. Inputs are typed according to the source data. All inputs are passed to the function together as a single object, keyed by their name.
In addition to regular fields the custom code step also supports picking whole data objects. These give access to the underlying raw data used throughout Relay.app.
Use the Interface section in the Inputs tab of the code editor to see the structure of the raw data objects.
Outputs
The output schema defines what data the step will produce when executed. This is required to enable later steps to work with the data.
There are two main recommended patterns for using the custom code step that allow automatic configuration of the output schema:
If the goal is to produce data in a format defined by another step, first build out the full workflow. Next, add the custom code step in the middle. Now the outputs can be configured to match these inputs, which guarantees a perfect fit and full support by the compiler when working on the code.
If the step is used to implement custom logic, first configure the inputs, and then build the code. Running the code via the Test tab will produce an inferred output schema that can be automatically applied to your step. Make sure to test with a variety of inputs, to build confidence that your schema covers all potential outputs.
Using one of these two approaches enables automatic configuration of output schema for the vast majority of use cases. While possible, it should rarely be necessary to configure schemas manually.
Debugging
The Test tab in the code editor offers the best way to quickly verify that code is working correctly. To provide additional visibility into the execution beyond input and output values, use console.log. Anything logged during code execution is displayed in Relay.app alongside your output.
Last updated
Was this helpful?