diff --git a/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/js.md b/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/js.md new file mode 100644 index 0000000000..97ade6b7ab --- /dev/null +++ b/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/js.md @@ -0,0 +1,66 @@ +--- +id: js +title: JavaScript +--- + +
+ +ToolJet workflows let you import **npm packages** into your workflow so that every JavaScript node can use them. Once a package is added, it is bundled and available across all JavaScript nodes in that workflow version. + +:::info +External library support for workflows is available on **Enterprise Edition** plans. +::: + +## Adding Packages + +1. Open your workflow in the editor. +2. Click the **Packages** icon in the left sidebar to open the package manager panel. +3. Type a package name (e.g., `lodash`) in the search field — results are fetched from the npm registry. +4. Select the package and version you want to install, then click **Add**. +5. The package is added to the workflow's dependency list and a bundle build starts automatically. + +You can add multiple packages before the bundle finishes building. The bundle regenerates with all current dependencies. + +## Bundle Status + +After adding or removing packages, ToolJet generates a bundle in the background. The package manager panel displays the current status: + +| Status | Meaning | +|--------|---------| +| **None** | No packages have been added yet. | +| **Building** | The bundle is being generated. JavaScript nodes will use the previous bundle (if any) until the new one is ready. | +| **Ready** | The bundle is built and available for all JavaScript nodes in this workflow version. | +| **Failed** | Bundle generation encountered an error. Check the error message in the panel and try rebuilding. | + +You can manually trigger a rebuild by clicking the **Rebuild** button in the package manager panel. + +## Using Packages in JavaScript Nodes + +Once the bundle status is **Ready**, you can `import` the packages directly in any JavaScript node: + +```js +import lodash from 'lodash'; +import { v4 as uuidv4 } from 'uuid'; + +const grouped = lodash.groupBy(getOrders.data, 'status'); + +return { + requestId: uuidv4(), + summary: grouped +}; +``` + +Packages are available to all JavaScript nodes in the workflow — you don't need to import them separately per node. + +## Removing Packages + +1. Open the package manager panel. +2. Click the **Remove** icon next to the package you want to remove. +3. The bundle regenerates automatically without the removed package. + +## Limitations + +- **Enterprise only** — package management is not available in the Community Edition. +- **npm packages only** — packages must be published to the npm registry. +- **Bundle per workflow version** — each workflow version maintains its own independent set of dependencies. +- **No native add-ons** — packages that require native C/C++ compilation during install are not supported. Pure JavaScript and pre-compiled packages work. \ No newline at end of file diff --git a/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/py.md b/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/py.md new file mode 100644 index 0000000000..1a129aecec --- /dev/null +++ b/docs/versioned_docs/version-3.16.0-LTS/workflows/external-libraries/py.md @@ -0,0 +1,129 @@ +--- +id: py +title: Python +--- + +
+ +ToolJet workflows let you install **Python packages** from [PyPI](https://pypi.org/) so that every Python node in the workflow can use them. Packages are installed once per workflow version and available across all Python nodes. + +:::info +External library support for workflows is available on **Enterprise Edition** plans. +::: + +## Adding Packages + +1. Open your workflow in the editor. +2. Click the **Packages** icon in the left sidebar to open the package manager panel, then switch to the **Python** tab. +3. Enter the packages you need in `requirements.txt` format — one package per line with a version specifier. + +``` +pydash==8.0.3 +requests==2.31.0 +numpy>=1.24.0 +``` + +4. Click **Install**. ToolJet installs the packages and generates a bundle in the background. + +:::warning +PyPI does not expose a public search API. You need to know the exact package name and version you want to install. You can look up packages at [pypi.org](https://pypi.org/). +::: + + +## Using Packages in Python Nodes + +Once the bundle status is **Ready**, you can `import` the packages directly in any Python node: + +```python +import pydash + +orders = getOrders["data"] +grouped = pydash.group_by(orders, "status") + +result = { + "pending": grouped.get("pending", []), + "shipped": grouped.get("shipped", []) +} +``` + +Packages are available to all Python nodes in the workflow — you don't need to install them separately per node. + +## Updating or Removing Packages + +1. Open the package manager panel and switch to the **Python** tab. +2. Edit the requirements list — update versions or remove lines as needed. +3. Click **Install**. The bundle regenerates automatically with the updated dependency list. + + +### Self-Hosted Deployments + +NsJail requires **privileged container** support (specifically the `SYS_ADMIN` Linux capability) to create the namespaces it uses for isolation. Most standard Docker and Kubernetes deployments support this out of the box. + +However, some managed cloud platforms do not allow privileged containers: + +- **AWS ECS Fargate** — does not support privileged mode +- **Google Cloud Run** — does not support privileged containers +- **Platforms with restrictive pod security policies** — may block the required capabilities + +If your deployment environment does not support NsJail, you have two options: + +**Option A: Bypass the sandbox** + +Set the following environment variable on your ToolJet server: + +``` +TOOLJET_WORKFLOW_SANDBOX_BYPASS=true +``` + +This disables NsJail and executes Python code directly on the host. Use this only when you trust all users who can create workflows, as their code will run without isolation. + +:::danger +Running without the sandbox removes all execution restrictions. User code can access environment variables, the filesystem, and the network. Only enable this in environments where all workflow authors are trusted. +::: + +**Option B: Deploy a worker with privileged access** + +Deploy ToolJet in **worker mode** on a platform that supports privileged containers (e.g., a standard Docker host or a Kubernetes cluster with appropriate security contexts), and route Python workflow execution to that worker. This lets you keep the main ToolJet deployment on a managed platform while still benefiting from sandboxed execution. + + +
+--- + +## Need Help? + +- Reach out via our [Slack Community](https://join.slack.com/t/tooljet/shared_invite/zt-2rk4w42t0-ZV_KJcWU9VL1BBEjnSHLCA) +- Or email us at [support@tooljet.com](mailto:support@tooljet.com) +- Found a bug? Please report it via [GitHub Issues](https://github.com/ToolJet/ToolJet/issues) diff --git a/docs/versioned_docs/version-3.16.0-LTS/workflows/nodes/logic/py.md b/docs/versioned_docs/version-3.16.0-LTS/workflows/nodes/logic/py.md new file mode 100644 index 0000000000..a0f15bedda --- /dev/null +++ b/docs/versioned_docs/version-3.16.0-LTS/workflows/nodes/logic/py.md @@ -0,0 +1,62 @@ +--- +id: py +title: Python Node +--- + +
+ +The **Python** node allows you to run custom server-side Python within your workflow. It can be used to: +- Transform Data +- Run Complex Calculations +- Fine Tune Response +- Implement Business Logic + +This node executes securely inside a sandboxed environment on the server, so it can handle data manipulation at scale, prepare or enrich data for downstream nodes, or create custom responses for external services. + +**Note:** To pass results to subsequent nodes, you can either set a `result` variable or end your code with an expression — the evaluated value of the last expression is automatically returned. + +## Accessing Workflow State + +All previous node outputs, parameters, and workflow variables are injected into the Python execution context as global variables. You can reference them directly in your code. + +```python +# Access results from a previous node named 'getSalesData' +sales = getSalesData['data'] + +# Access workflow parameters +user_id = params['userId'] +``` + +## Example: Fine-Tuning Your Response Using Python + +Refine your response by manipulating data using Python. For example, you can use list slicing to select a subset of data: + +```python +result = { + "sales": getSalesData["data"][:5], + "inventory": getInventory["data"][:5], + "csv": generateCSVData["data"] +} +``` + +## Example: Using External Packages + +You can install external Python packages for your workflow through the package manager. Packages are defined in `requirements.txt` format and installed once per workflow version. + +```python +import pydash + +result = pydash.map_([1, 2, 3], lambda x: x * 2) +# Returns: [2, 4, 6] +``` + +:::info +Only packages with prebuilt wheels (pure Python or manylinux) are supported. Packages that require C compilation during installation are not available. +::: + +## Limitations + +- **Timeout**: Each Python node execution has a 10-second time limit. +- **Memory**: Execution is limited to 512 MB of virtual memory. +- **No network access**: The sandbox does not allow outbound network calls. Use datasource nodes to fetch external data before passing it to a Python node. +- **Return values must be JSON-serializable**: Strings, numbers, lists, dicts, `None`, and booleans are supported. \ No newline at end of file diff --git a/docs/versioned_sidebars/version-3.16.0-LTS-sidebars.json b/docs/versioned_sidebars/version-3.16.0-LTS-sidebars.json index df8327ae66..1c011c0402 100644 --- a/docs/versioned_sidebars/version-3.16.0-LTS-sidebars.json +++ b/docs/versioned_sidebars/version-3.16.0-LTS-sidebars.json @@ -619,6 +619,7 @@ "label": "Logic Nodes", "items": [ "workflows/nodes/logic/js", + "workflows/nodes/logic/py", "workflows/nodes/logic/if-else", "workflows/nodes/logic/loop" ] @@ -637,6 +638,14 @@ "workflows/triggers/webhook", "workflows/triggers/scheduler" ] + }, + { + "type": "category", + "label": "Importing External Libraries", + "items": [ + "workflows/external-libraries/js", + "workflows/external-libraries/py" + ] } ] },