> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript Modules

> Build lightweight Kodexa modules using inline JavaScript that executes in the kodexa/go-scripting-runtime, ideal for fast deploys and routing logic.

JavaScript modules let you write inline processing logic that runs in the platform's Go-based scripting runtime. Unlike Python modules which require a separate container, JavaScript modules execute directly in the `kodexa/go-scripting-runtime` — making them fast to deploy and ideal for:

* Document metadata enrichment
* Conditional routing and classification
* Lightweight data transformations
* Calling external APIs via service bridges
* LLM-assisted processing

## Module Definition

Create a `module.yml` with `scriptLanguage: "javascript"` and inline your script in the `script` field:

```yaml theme={null}
slug: my-js-module
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: My JavaScript Module
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  script: |
    log.info("Hello from JavaScript module");
    var greeting = parameters.greeting || "Hello";
    log.info(greeting + " world");
    return { result: "done" };
```

Key fields:

* **slug**: Unique identifier within your organization
* **orgSlug**: Your Kodexa organization slug
* **moduleRuntimeRef**: Must be `kodexa/go-scripting-runtime` for JavaScript modules
* **scriptLanguage**: Must be `javascript` (or `js`)
* **script**: Your inline JavaScript code

## Script Structure

Scripts run in a server-side JavaScript runtime. The script is automatically wrapped in an IIFE (Immediately Invoked Function Expression), so you can use `return` at the top level to produce an output value:

```javascript theme={null}
// This is valid — the runtime wraps your code in (function() { ... })()
var result = doSomeWork();
return { status: "completed", output: result };
```

The return value is serialized as JSON and passed back to the platform as the step's output event.

## Available APIs

### Parameters

A `parameters` global object is available containing:

* Any **module options** configured for the execution (from `inferenceOptions` or step config)
* The **execution\_id** for the current execution
* The **pipeline\_context** with execution context metadata

```javascript theme={null}
var threshold = parameters.confidence_threshold || 0.8;
var execId = parameters.execution_id;
log.info("Running execution " + execId + " with threshold " + threshold);
```

### Logging

Two logging APIs are available:

```javascript theme={null}
// Structured log with level — levels: "debug", "info", "warn", "error"
log.info("Processing started");
log.warn("Threshold is very low: " + threshold);
log.error("Something went wrong");

// Console-style logging (always logs at info level)
console.log("Debug output:", someValue);
```

### Module Dependencies

JavaScript modules can load other JavaScript modules as dependencies using the `moduleSidecars` field in `module.yml`. Dependencies are fetched and executed in order before your main script runs, making their functions and variables available in global scope.

```yaml theme={null}
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  moduleSidecars:
    - my-org/string-utils
    - my-org/validation-helpers
  script: |
    // Functions from string-utils and validation-helpers are available here
    var cleaned = cleanText(parameters.rawInput);
    var isValid = validateEmail(cleaned);
    return { valid: isValid };
```

Each sidecar module must also be a JavaScript module with an inline `script`. Sidecar scripts run in global scope (not wrapped in an IIFE), so any functions or variables they declare are available to subsequent sidecars and your main script.

<Note>
  A maximum of 10 module pre-loads are allowed per execution. Exceeding this limit will cause a startup error.
</Note>

### Document API (when used in script steps)

When your JavaScript module is used as a [script step](/guides/script-steps) in an Activity Plan, the full document API is available, including `loadDocument()`, node traversal, tagging, data object creation, and more. See the [Script Steps guide](/guides/script-steps#working-with-documents) for complete documentation.

### Service Bridges (when used in script steps)

Script steps can call external APIs through project-scoped service bridges using `serviceBridge.call()`. See the [Script Steps guide](/guides/script-steps#calling-service-bridges) for details.

### LLM Invocation (when used in script steps)

Script steps can invoke the platform's LLM service using `llm.invoke()` and `llm.invokeWithPromptRef()`. See the [Script Steps guide](/guides/script-steps#making-llm-calls) for details.

## Limits

| Limit                | Value      |
| -------------------- | ---------- |
| Script timeout       | 60 seconds |
| Max module pre-loads | 10         |

## Deployment

Deploy with the KDX CLI:

```bash theme={null}
kdx apply -f module.yml
```

This will:

1. Create or update the module metadata in the platform
2. Store the inline script in the module metadata
3. Make the module available for use in assistants, pipelines, and as a sidecar dependency

To inspect a deployed module's metadata:

```bash theme={null}
kdx get module my-org/my-js-module -o yaml
```

## Example: Document Classifier

Here is a complete example of a JavaScript module that classifies documents based on metadata:

### module.yml

```yaml theme={null}
slug: js-document-classifier
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: JS Document Classifier
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  inferenceOptions:
    - name: default_category
      type: string
      default: "general"
      description: "Default category when no match is found"
  script: |
    var category = parameters.default_category || "general";
    var context = parameters.pipeline_context || {};

    log.info("Classifying document with default: " + category);

    // Check pipeline context for hints
    var filename = (context.filename || "").toLowerCase();

    if (filename.indexOf("invoice") !== -1) {
      category = "invoice";
    } else if (filename.indexOf("contract") !== -1) {
      category = "contract";
    } else if (filename.indexOf("receipt") !== -1) {
      category = "receipt";
    }

    log.info("Classified as: " + category);
    return { category: category };
```

## Example: Reusable Utility Module

This module is designed to be used as a sidecar dependency. It defines utility functions in global scope that other modules can call:

### module.yml

```yaml theme={null}
slug: string-utils
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: String Utilities
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  script: |
    function cleanText(text) {
      if (!text) return "";
      return text.replace(/\s+/g, " ").trim();
    }

    function extractEmails(text) {
      var pattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
      return (text.match(pattern) || []);
    }

    function truncate(text, maxLen) {
      maxLen = maxLen || 200;
      if (text.length <= maxLen) return text;
      return text.substring(0, maxLen) + "...";
    }
```

Other modules can then reference this as a sidecar:

```yaml theme={null}
metadata:
  moduleSidecars:
    - my-org/string-utils
  script: |
    // cleanText, extractEmails, truncate are all available
    var cleaned = cleanText(parameters.rawInput);
    var emails = extractEmails(cleaned);
    log.info("Found " + emails.length + " email addresses");
    return { emails: emails, summary: truncate(cleaned) };
```

## Using Your Module

Once deployed, your JavaScript module can be:

* Added to an **Assistant** in your project
* Referenced as a **sidecar** by other JavaScript modules
* Used in **scheduled jobs** and **pipelines**

See [Working with Modules](/concepts/working_with_modules) for more details.

## Troubleshooting

### Script syntax errors

* JavaScript modules use ES5+ syntax. Features like `let`, `const`, arrow functions, and template literals are supported, but some ES2015+ features may not be available.
* Check that your script does not contain syntax errors by testing locally with Node.js.

### Module sidecar not found

* Verify the sidecar module exists and has been deployed with `kdx get module my-org/sidecar-slug`
* Ensure the sidecar module has a `script` field in its metadata
* Check that the sidecar reference uses the correct `orgSlug/moduleSlug` format

### Script timeout

* The default timeout is 60 seconds. Long-running scripts will be interrupted.
* Optimize loops and avoid blocking operations.
* Consider breaking complex logic into multiple steps.

### Deployment failures

* Verify KDX CLI is configured: `kdx config --list`
* Check the `orgSlug` in module.yml matches your organization
* Ensure module.yml is valid YAML (watch for indentation in the `script` block)
* Run `kdx apply` from the directory containing module.yml
