Code Component Usage

The Code Component

The code component allows you to execute product or industry-specific code within an integration. This page outlines when and how to use a code component.

Why Use a Code Component?

You will likely have integration logic that can't be solved using the standard components Prismatic provides. The portion of your integrations that are specific to your product or industry can be accomplished using code component steps, or custom components.

When to Use a Custom Component Instead

Code component steps should be succinct and integration-specific. If the code you write could be reused in other integrations, or if the code is complex enough that it would benefit from unit tests, etc., you should use a custom component instead.

Adding a Code Component to an Integration

Within the integration designer, add a step to your integration. Select the Code - Custom Code action.

You will be presented with a new code step in your integration, as well as a code editor.

Code Structure

The code component provides a stub function by default. Let's examine the structure of the code:

module.exports = async ({ logger, configVars, credential }, params) => {
return { data: null };
};

The code component requires you to export an asynchronous function. The default code uses arrow function notation to create an async function to return.

Code Component Parameters

This function is provided a few parameters: logger, configVars and params that allow you to log, access config variables, and access previous steps' outputs respectively.

Logging

logger is an object that can be used for logging and debugging. logger has four functions: debug, info, warn, and error. For example:

module.exports = async ({ logger, configVars, credential }, params) => {
logger.info("Things are going great");
logger.warn("Now less great...");
};

Config Vars

configVars provides access to all configuration variables of an integration.

You can add configuration variables to your integration by clicking the Required Config Variables button in the integration designer.

If you create a configuration variable myEndpoint, you could append text to that endpoint with a custom code block:

module.exports = async ({ logger, configVars, credential }, params) => {
const fullEndpoint = `${configVars.myEndpoint}/extrapath`;
logger.info(fullEndpoint);
return { data: fullEndpoint };
};

Notice that the step output on the left-hand side shows a proper endpoint with /extrapath appended to it:

Credentials

The credential object that is passed in to a custom code function contains any credentials that are bound to the function. See the credential documentation on the custom components page for full details on handling credentials - handling of credentials is the same in both custom components and the code component.

Any type of credentials can be associated with a code component.

In this example we have a code component step that accesses a username / private_key pair that is associated with it. It throws an error if no credentials is passed in, or if the credential is of a type other than private_key:

module.exports = async ({ logger, configVars, credential }, params) => {
if (credential?.authorizationMethod !== "private_key") {
throw "This step requires a private key credential.";
}
const { username, private_key } = credential.fields;
console.log(
`This is terrible security practice, but here's your username: "${username}" and private key: "${private_key}"`
);
return { data: null };
};

Referencing Previous Step Outputs

Most steps of an integration return some sort of value. An HTTP - GET action, for example, might return a JSON payload from a REST API. An AWS S3 - Get Object will return a binary file pulled from S3.

The code component can reference those outputs through the params parameter.

Since names of steps can include spaces and non-JavaScript-friendly characters, step names are converted to camelCase. So, a step named Download JSON from API would be converted to downloadJsonFromApi. You can test out step name -> referenceable name conversions here:

For example, suppose the integration is triggered by a webhook, the trigger is named "My integration trigger", and the webhook is provided a payload body.data of {"exampleKey": "exampleValue"}.

That exampleKey would be accessible using params like so:

module.exports = async ({ logger }, params) => {
const exampleKey = params.myIntegrationTrigger.results.body.data.exampleKey;
logger.info(`Received '${exampleKey}'`);
};

Using JavaScript destructuring, you can instead write this:

module.exports = async (
{ logger },
{
myIntegrationTrigger: {
results: {
body: {
data: { exampleKey },
},
},
},
}
) => {
logger.info(`Received '${exampleKey}'`);
};

Notice the logged message in the testing pane

Results from other steps are available through params.stepName.results.

Code Component Return Values

The code component can optionally return a value for use by a subsequent step. The return value can be an object, string, integer, etc., and will retain its type as the value is passed to the next step.

The return value is specified using the data key in the return object.

In this example we return a string with value "https://ipinfo.io/ip":

module.exports = async ({ logger, configVars, credential }, params) => {
return { data: "https://ipinfo.io/ip" };
};

The output can be used as input for the next step by referencing codeComponentStepName.results.

To see an example of returning more complex data structures, and a good example use case for a code component, see the Using a Code Component to Transform Data quickstart.

Returning Binary Data from a Code Component

Sometimes you'll want your code component to return binary data (like a rendered image or PDF). To do that, return an object with a data property of type Buffer (a file buffer), and a contentType property of type String that contains the file's MIME type:

module.exports = async ({ logger, configVars, credential }, params) => {
// ...
const fileBuffer = SomePdfLibrary.generatePdf();
return {
data: fileBuffer,
contentType: "application/pdf",
};
};

To see an example use case for returning binary data from a code component, check out our Generate a PDF with a Code Component.

For More Information: Using a Code Component to Transform Data

Adding Dependencies to a Code Component

If your code component depends on node modules from npm, dependencies will automatically be imported. For example, if your code component reads:

const fetch = require("node-fetch/lib/index.js");
module.exports = async ({ logger, configVars, credential }, params) => {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const responseJson = await response.json();
return { data: responseJson };
};

Then node-fetch will be imported as a dependency automatically from the UNPKG CDN.

You can also specify specific versions of npm packages for your code component:

const lodash = require("lodash@2.4.2");
const fetch = require("node-fetch@2.6.1/lib/index.js");

You can require any file from npm using package[@version][/file] syntax. Note that with the lodash import above, no file was specified. If no file is specified, the main file defined in the npm package's package.json is imported. An explicit path was called out for the node-fetch import because the node-fetch package defaults to importing a browser version of the package, and we want a compiled server version instead.