> For the complete documentation index, see [llms.txt](https://docs.coherent.global/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coherent.global/spark-apis/transforms-api/transform-types/nodejs22.md).

# Nodejs22

{% hint style="warning" %}
This feature is only enabled on certain environments and tenants. Please contact [Support](/support/support.md) for more information about this feature.
{% endhint %}

With the [Transforms API](/spark-apis/transforms-api.md) we are able to support many types of transform definitions. This document describes the transform type `Nodejs22`.

This transform type offers the ability for increased customization by giving access to [Node.js v22](https://nodejs.org/docs/latest-v22.x/api/) to program actions for each call to the transform endpoint in [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript).

We recommend this transform type if you have complex requirements involving multiple API calls. Some examples of how this could be used include:

* Combine multiple [Execute API](/spark-apis/execute-api.md) calls together.
* Apply [JSONtransforms](/spark-apis/transforms-api/transform-types/jsontransforms.md) for multiple API calls.
* Orchestrate other [Spark APIs](/spark-apis/getting-started.md) to facilitate data transformation and processing.

For this particular transform type, the [npm](https://www.npmjs.com/) packages for [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) or [JSONata](https://jsonata.org) are also included allow for enhanced capabilities to parse [JSON](https://www.json.org/) and [XML](https://aws.amazon.com/what-is/xml/) content.

<figure><img src="/files/IiBbkT6tvutPlExiyUJ5" alt=""><figcaption></figcaption></figure>

## Build transforms

To build transforms you can follow the instructions for the specific transform on this page. For JavaScript developers there is also the [Node Transform Document Builder](https://github.com/floherent/node-transform-builder) that can be used to assist with the development.

## Transform document

[Transform documents](/spark-apis/transforms-api/transform-documents.md) are used to define the code relating to a transform. For `Nodejs22`, the transform document is a JSON document defined by the following objects:

| Key                                  | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |       |      |      |                                                                                                                                                                                                                                                                                              |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transform_type`                     | `Nodejs22_v1.0.0`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |       |      |      |                                                                                                                                                                                                                                                                                              |
| `transform_code`                     | <p>Single string containing the code for the transform code.</p><p>The code must contain the function <code>async function handler(event) {}</code>.</p><p>When the transform is invoked, this function is called. Parameters from the transform request are passed into the <code>event</code> parameter as an object. This function should return:</p><ul><li><code>http\_status\_code</code> for the HTTP status code.</li><li><code>headers</code> for response headers.</li><li><code>body</code> for the response body.</li></ul><p>This design pattern follows the <a href="https://docs.aws.amazon.com/lambda/">AWS Lambda</a>  <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html">Define Lambda function handler in Node.js</a>. See the <a data-mention href="#examples">#examples</a> for more details.</p> |       |      |      |                                                                                                                                                                                                                                                                                              |
| `transform_log_level`                | <p>Optional parameter.<br>This controls the level of logging that will be recorded during the execution.</p><ul><li>This can take the values of <code>TRACE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | DEBUG | INFO | WARN | ERROR</code>.</li><li><code>TRACE</code> is the most verbose and <code>ERROR</code> is the least verbose.</li><li><code>INFO</code> is needed to return <code>console.info()</code> and <code>console.log()</code> statements.</li></ul><p>If omitted, the default is <code>INFO</code>.</p> |
| `transform_log_visible`              | <p><strong>NOTE: This configuration is not available yet.</strong></p><p>Optional parameter.</p><p>This controls whether the execution logs will be made available in the response headers. These can be used for reviewing the execution and debugging.</p><p>If omitted, the default is <code>false</code>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |       |      |      |                                                                                                                                                                                                                                                                                              |
| `transform_allowed_external_domains` | <p>Optional parameter.<br>Array containing a list of external domains that the transform is allowed to access during the course of execution. These domains must be resolvable using <a href="https://www.nslookup.io/">NsLookup</a>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |       |      |      |                                                                                                                                                                                                                                                                                              |

### Create the transform document

The transform document can be manually created and uploaded to Spark using the *New transforms* featur&#x65;*.*

1. The `transform_type` is `Nodejs22_v1.0.0`.
2. The `transform_code` must be a single string containing the code for the transform.
   1. If you are using either [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) or [JSONata](https://jsonata.org), make sure to include the [`require()`](https://nodejs.org/docs/latest-v22.x/api/modules.html#requireid) statements to import the modules for either [`fast-xml-parser`](https://www.npmjs.com/package/fast-xml-parser) or [`jsonata`](https://www.npmjs.com/package/jsonata/).
   2. Remove any lines containing comments.
   3. Any double quotation marks `"` need to be escaped, i.e. `"` is replaced with `\"`.
      * Note that [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) allows for single quotation marks `'` to be interchanged with double quotation marks `"`. If `'` are used exclusively in lieu or `"`, then the escape character is not needed.
   4. If you are using [Visual Studio Code](https://code.visualstudio.com/), you can use the *Join lines* feature to make it easy to combine multiple lines into a single string.
      1. Select the transform text that you would like to combine onto a single line.
         1. Access the *Command Palette* `F1` or `Ctrl+Shift+P` on Windows or `Shift+⌘+P` on Mac.
         2. Type in the command *Join lines* and select it.
   5. As an alternative to *Join lines*, line breaks `Ctrl+Enter` can be replaced with the new line character `\n`.
3. Follow the instructions on [Transform documents](/spark-apis/transforms-api/transform-documents.md) to upload the transform document to Spark.

## Transforms API

These details are specific to this transform in addition to information in [Transforms API](/spark-apis/transforms-api.md).

### Request headers

<table data-full-width="false"><thead><tr><th>Key</th><th>Value</th></tr></thead><tbody><tr><td><code>x-meta</code> or <code>x-request-meta</code></td><td>Optional parameter.<br>This can be used to introduce key-value pairs into the <code>event.context</code> parameter object. See <a data-mention href="#examine-the-event-parameter-object">#examine-the-event-parameter-object</a>for more details.<br>Example: <br><code>"{\"call_purpose\":\"Transform mainframe request\"}"</code></td></tr><tr><td><code>Content-Type</code></td><td><code>application/json</code>, <code>application/xml</code>, or <code>text/xml</code>  </td></tr><tr><td>+ any other request headers...</td><td>These will be passed into <code>event.request.headers</code> as key-value pairs. See <a data-mention href="#examine-the-event-parameter-object">#examine-the-event-parameter-object</a>for more details.</td></tr></tbody></table>

### Limitations

* The API call has a maximum lifetime of `120 s`.
* API calls can only be made to the `coherent.global` domain only unless defined by `transform_allowed_external_domains`.
* Not all built-in [Node.js v22](https://nodejs.org/docs/latest-v22.x/api/) modules are accessible.

<details>

<summary>Restricted <a href="https://nodejs.org/docs/latest-v22.x/api/">Node.js v22</a> modules</summary>

| Restricted module   | Restricted functionality                                 |
| ------------------- | -------------------------------------------------------- |
| `fs`                | Read/write access to the file system.                    |
| `child_process`     | Run arbitrary system commands (`exec`, `spawn`, etc.).   |
| `net` / `dgram`     | Create raw TCP/UDP sockets.                              |
| `http`, `https`     | Make network requests. Use `fetch` instead.              |
| `vm`                | Create a nested sandbox.                                 |
| `process`           | Access environment variables or exit the process.        |
| `os`                | Access system information.                               |
| `cluster`           | Fork additional worker processes.                        |
| `worker_threads`    | Run threads that outside of the memory or sandbox space. |
| `require` (general) | Loading of unsupported modules.                          |

</details>

### HTTP status code

This is determined by the `handler()` function `return{}` of `http_status_code` object.

This can also be invoked with a response header `x-spark-transform-response-httpstatuscode` .

### Response headers

This is determined by the `handler()` function `return{}` of `headers()`.  object. We would suggest at the minimum to return the appropriate `Content-Type` for your response data.

### Response body

This is determined by the `handler()` function `return{}` of the `body()` object.

## Examples

### Start with a Hello, World! transform

The aim of this transform is to demonstrate a simple standalone application. When called, the response will include a custom header and response body with the message `Hello, World!`.

{% tabs %}
{% tab title="JavaScript" %}

```javascript
async function handler(event) {
    return {
        http_status_code: 200,
        headers: {
            "Content-Type": "application/json",
            myresponseheader: "Hello, World!",
        },
        body:
            {
                myresponsebody: "Hello, World!",
            },
    }
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "async function handler(event) { return { http_status_code: 200, headers: { \"Content-Type\": \"application/json\", myresponseheader: \"Hello, World!\", }, body: { myresponsebody: \"Hello, World!\", }, } }"
}
```

{% file src="/files/5HO7iHI95tPl6NOPu7RC" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/HelloWorld`.
* The `/run` endpoint is called because this does not relate to a particular service.

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/HelloWorld/run' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data ''
```

{% endtab %}

{% tab title="Sample response" %}

```json
{
    "myresponsebody": "Hello, World!"
}
```

{% endtab %}
{% endtabs %}

### Examine the `event` parameter object

When the `handler()` function is invoked, the `event` parameter is used to provide information about the request details. These can be used as inputs for the program.

We can create a transform specifically to help us to better understand the `event` parameter object.

{% tabs %}
{% tab title="JavaScript" %}

```javascript
async function handler(event) {
    return {
        http_status_code: 200,
        headers: { "Content-Type": "application/json" },
        body: { event }
    };
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "async function handler(event) { return { http_status_code: 200, headers: { \"Content-Type\": \"application/json\" }, body: { event } }; }"
}
```

{% file src="/files/l4SygfUZOxjyBVNA2HyL" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/EventViewer`.
* The `/run` endpoint is called because this does not relate to a particular service.

```javascript
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/EventViewer/for/myfolder/myservice' \
--header 'Content-Type: application/json' \
--header 'myrequestheaderkey: myrequestheadervalue' \
--header 'x-meta: "{\"call_purpose\":\"Event viewer\"}"' \
--header 'Authorization: Bearer {Token}' \
--data '{
    "request_data": {
        "inputs": {
            "A": 1,
            "B": 2
        }
    }
}'
```

{% endtab %}

{% tab title="Sample response" %}

```json
{
    "event": {
        "request": {
            "body": {
                "request_data": {
                    "inputs": {
                        "A": 1,
                        "B": 2
                    }
                }
            },
            "headers": {
                "Accept": "*/*",
                "Host": "excel.myenvironment.coherent.global",
                "User-Agent": "curl/7.88.1",
                "Accept-Encoding": "gzip, deflate, br",
                "Authorization": "Bearer {Token}",
                "Content-Type": "application/json",
                "Content-Length": 107,
                "X-Forwarded-For": "129.6.15.28",
                "X-Forwarded-Proto": "https",
                "X-Forwarded-Port": 443,
                "X-Trace-Id": "Root=1-6839b403-09c360963bf7aec943477e9g",
                "myrequestheaderkey": "myrequestheadervalue",
                "x-meta": "{\"call_purpose\":\"Event viewer\",\"correlation_id\":\"91496134-6357-4bc7-a230-f9ad31855254\"}"
            }
        },
        "whitelisted_domains": [
            "*.coherent.global"
        ],
        "total_allowed_run_time_ms": 60000,
        "context": {
            "tenant": "coherent",
            "service_uri": "/folders/myfolder/services/myservice",
            "call_purpose": "Event viewer",
            "correlation_id": "91496134-6357-4bc7-a230-f9ad31855254",
            "spark_url": "https://excel.myenvironment.coherent.global",
            "log_level": ""
        },
        "secrets": {
            "authorization": "Bearer {Token}"
        }
    }
}
```

{% endtab %}
{% endtabs %}

### Emulate a passthrough to the Execute API (v3)

In this example, the transform endpoint acts as a passthrough to send inputs to the [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md). This example is useful for building up transforms that make API calls to Spark.

{% tabs %}
{% tab title="JavaScript" %}

* Note the `encodeURI()` function that is used in the `fetchResource` declaration. This is needed because folders or services that contain a space   in the name need to be encoded to `%20` in order for [`fetch()`](https://nodejs.org/en/learn/getting-started/fetch) to work.
* The `Authorization` to the `/execute` API call is handled by using the token available in `event.secrets.authorization`.
* Trying to return all of the headers from the `/execute` call may lead to errors. See [#known-errors](#known-errors "mention").

```javascript
async function handler(event) {

    const fetchResource = `${event.context.spark_url}/${event.context.tenant}/api/v3${encodeURI(event.context.service_uri)}/execute`;

    const fetchOptions = {
        method: "POST",
        headers: {
            Authorization: event.secrets.authorization,
            "Content-Type": "application/json",
            "x-tenant-name": event.context.tenant,
        },
        body: JSON.stringify(event.request.body),
    };

    const response = await fetch(fetchResource, fetchOptions);
    const responseBody = await response.json();

    return {
        http_status_code: response.status,
        headers: { "Content-Type": response.headers.get("content-type") },
        body: responseBody,
    };
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "async function handler(event) { const fetchResource = `${event.context.spark_url}/${event.context.tenant}/api/v3${encodeURI(event.context.service_uri)}/execute`; const fetchOptions = { method: \"POST\", headers: { Authorization: event.secrets.authorization, \"Content-Type\": \"application/json\", \"x-tenant-name\": event.context.tenant, }, body: JSON.stringify(event.request.body), }; const response = await fetch(fetchResource, fetchOptions); const responseBody = await response.json(); return { http_status_code: response.status, headers: { \"Content-Type\": response.headers.get(\"content-type\") }, body: responseBody, }; }"
}
```

{% file src="/files/gLRFhvpxkQFpqOv2Nhah" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/EventViewer`  and the service `myfoldername/AplusB`.
* The endpoint includes a reference to `myfolder/myservice` which will be the target for this API call.

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/v3Execute/for/myfolder/myservice' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data '{
    "request_data": {
        "inputs": {
            "A": 1,
            "B": 2
        }
    }
}'
```

{% endtab %}

{% tab title="Sample response" %}

```json
{
    "status": "Success",
    "response_data": {
        "outputs": {
            "AplusB": 3
        },
        "warnings": null,
        "errors": null,
        "service_chain": null
    },
    "response_meta": {
        "service_id": "8b750c74-9e33-470f-8c2c-4173970112c7",
        "version_id": "cb577a09-12a6-412d-99d5-2b6a6aba794c",
        "version": "0.3.0",
        "process_time": 1,
        "call_id": "6798bf8e-1827-4cfd-ab0f-b3bef11adf02",
        "compiler_type": "Neuron",
        "compiler_version": "1.22.8",
        "source_hash": null,
        "engine_id": "C70FF0EF6EF466B551756ADE3289475B",
        "correlation_id": "",
        "parameterset_version_id": null,
        "system": "SPARK",
        "request_timestamp": "2025-05-29T11:07:51.132Z"
    },
    "error": null
}

```

{% endtab %}
{% endtabs %}

### Transform JSON with JSONata

[JSONata](https://jsonata.org) is a "lightweight query and transformation language for JSON data". You can test your [JSONata](https://jsonata.org) transforms in the [JSONata Exerciser](https://try.jsonata.org/). Note the [JSONata](https://jsonata.org) package version used in [Update roadmap](/spark-apis/transforms-api/transform-types/update-roadmap.md).

Including [JSONata](https://jsonata.org) in this transform provides more flexibility than what can be done in [JSONtransforms](/spark-apis/transforms-api/transform-types/jsontransforms.md).

This example is based on [Example nodejs application](https://docs.jsonata.org/using-nodejs#example-nodejs-application).

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const jsonata = require("jsonata");

async function handler(event) {
    const data = {
        example: [
            { value: 4 },
            { value: 7 },
            { value: 13 }
        ]
    };
    const expression = jsonata("$sum(example.value)");
    const result = await expression.evaluate(data);
    return { http_status_code: 200, headers: { "Content-Type": "application/json" }, body: { sum: result } };
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "const jsonata = require(\"jsonata\"); async function handler(event) { const data = { example: [ { value: 4 }, { value: 7 }, { value: 13 } ] }; const expression = jsonata(\"$sum(example.value)\"); const result = await expression.evaluate(data); return { http_status_code: 200, headers: { \"Content-Type\": \"application/json\" }, body: { sum: result } }; }"
}
```

{% file src="/files/8pRLii3TbPyJ7vdUGz55" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/JSONata`.
* The `/run` endpoint is called because this does not relate to a particular service.

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/JSONata/run' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data ''
```

{% endtab %}

{% tab title="Sample response" %}

```json
{
    "sum": 24
}
```

{% endtab %}
{% endtabs %}

### Transform XML with fast-xml-parser

[fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) is the most popular package to manipulate XML in JavaScript. This package has been included with the `Nodejs22` transform to empower XML parsing capabilities. Note the [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) package version used in [Update roadmap](/spark-apis/transforms-api/transform-types/update-roadmap.md).

This example is based on [3.XMLBuilder.md](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/docs/v4/3.XMLBuilder.md#arraynodename).

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const fastXmlParser = require("fast-xml-parser");

async function handler(event) {
    const { XMLBuilder } = require("fast-xml-parser");

    const XmlBuilderOptions = {
        ignoreAttributes: false,
        format: true,
        arrayNodeName: "car"
    };

    const cars = [
        {
            "color": "purple",
            "type": "minivan",
            "registration": "2020-02-03",
            "capacity": 7
        },
        {
            "color": "orange",
            "type": "SUV",
            "registration": "2021-05-17",
            "capacity": 4
        },
    ];

    const builder = new XMLBuilder(XmlBuilderOptions);
    const output = builder.build(cars);

    return {
        http_status_code: 200,
        headers: {
            'Content-Type': 'application/xml'
        },
        body: output,
    };
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "const fastXmlParser = require(\"fast-xml-parser\"); async function handler(event) { const { XMLBuilder } = require(\"fast-xml-parser\"); const XmlBuilderOptions = { ignoreAttributes: false, format: false, arrayNodeName: \"car\" }; const cars = [ { \"color\": \"purple\", \"type\": \"minivan\", \"registration\": \"2020-02-03\", \"capacity\": 7 }, { \"color\": \"orange\", \"type\": \"SUV\", \"registration\": \"2021-05-17\", \"capacity\": 4 }, ]; const builder = new XMLBuilder(XmlBuilderOptions); const output = builder.build(cars); return { http_status_code: 200, headers: { 'Content-Type': 'application/xml' }, body: output, }; }"
}
```

{% file src="/files/bZkZTKmVGO2J01GejaIb" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/XML`.
* The `/run` endpoint is called because this does not relate to a particular service.

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/XML/run' \
--header 'Content-Type: application/xml' \
--header 'Authorization: Bearer {token}' \
--data ''
```

{% endtab %}

{% tab title="Sample response" %}

```xml
<car>
    <color>purple</color>
    <type>minivan</type>
    <registration>2020-02-03</registration>
    <capacity>7</capacity>
</car>
<car>
    <color>orange</color>
    <type>SUV</type>
    <registration>2021-05-17</registration>
    <capacity>4</capacity>
</car>
```

{% endtab %}
{% endtabs %}

### Make an external API call

In this example, we exctract the contents from the `www.google.com` homepage.

{% tabs %}
{% tab title="JavaScript" %}

```javascript
async function handler(event) {

    const fetchResource = "https://www.google.com";
    const fetchOptions = {method: "GET"};

    const response = await fetch(fetchResource, fetchOptions);
    const responseText = await response.text();
    const responseBody = {outputs: { page_content: responseText } };
    return {
        http_status_code: response.status,
        headers: { "content-type": "application/json" },
        body: responseBody,
    };
}
```

{% endtab %}

{% tab title="Transform document" %}

```json
{
  "transform_type": "Nodejs22_v1.0.0",
  "transform_code": "async function handler(event) { const fetchResource = \"https://www.google.com\"; const fetchOptions = {method: \"GET\"}; const response = await fetch(fetchResource, fetchOptions); const responseText = await response.text(); const responseBody = {outputs: { page_content: responseText } }; return { http_status_code: response.status, headers: { \"content-type\": \"application/json\" }, body: responseBody, }; }",
  "transform_allowed_external_domains": ["www.google.com"]
}
```

{% file src="/files/gxvQlGZ11DZlyAqr4DUH" %}
{% endtab %}

{% tab title="Sample request" %}

* The request is made to the transform `mytransformsfolder/HeyGoogle`.
* The `/run` endpoint is called because this does not relate to a particular service.

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/HeyGoogle/run' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data ''
```

{% endtab %}

{% tab title="Sample response" %}

* The response has been abbreivated..

```json
{
    "outputs": {
        "page_content":"<!doctype html><html itemscope=\"\" itemtype=\"http://schema.org/WebPage\" lang=\"en-SG\"></html>"
    }
}
```

{% endtab %}
{% endtabs %}

## Recommended development process

To run this locally, you will need to have [Node.js v22](https://nodejs.org/en/download) installed. This process is not dissimilar to [Building Lambda functions with Node.js](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html).

1. Decide how you would like to construct the request to the `/transforms` endpoint, including the structure of the request line, as well as request and response headers and body.
2. Create the transform described in [#examine-the-event-parameter-object](#examine-the-event-parameter-object "mention"). Run the proposed `/transforms` request against it and from the response copy the `event` object.
3. Test your script locally using the `runHandler.js` script below.
   1. Paste in the `event` object from above into `TEST_EVENT` of `runHandler.js`.
   2. Work on the `handler()` function in `runHandler.js`.
   3. If your script calls other [Spark APIs](/spark-apis/getting-started.md), your `Authorization` may expire as you develop the program. You may need to update your `event` object periodically with a new bearer token.
   4. Test your script in your terminal using the command `node runHandler.js`. It will print the `handler()` function `return`.
4. Compose and upload the transform document using the directions in [#transform-document](#transform-document "mention").
5. Test API calls against the `/transforms` endpoint to make sure you are getting the same result as the `runHander.js` script.

{% file src="/files/qdht44ZL1puy2k8YlG3O" %}

### Known errors

Sometimes code will work locally but fail to run on Spark. Some examples where this may occur:

* Trying to return all of the headers from the `/execute` API call in [#emulate-a-passthrough-to-the-execute-api-v3](#emulate-a-passthrough-to-the-execute-api-v3 "mention") to the `/transforms` response headers may fail due to content encoding discrepancies.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.coherent.global/spark-apis/transforms-api/transform-types/nodejs22.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
