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

# Custom Node.js components

> Run trusted, multi-file Node.js code with an injected RevoEngine SDK runtime.

Custom Node.js components are intended for trusted tenant-authored workloads that need npm packages, multi-file source, or Node.js behavior unavailable in the managed low-code runtime.

## Choose Custom Node.js deliberately

| Requirement                                                                   | Recommended surface                                                            |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Normal platform calls, validation, orchestration, and reusable business rules | JavaScript or TypeScript low-code Component                                    |
| Shared in-process logic for multiple low-code Components                      | Library Component                                                              |
| npm dependencies, a multi-file module, or Node.js-specific processing         | Custom Node.js Component                                                       |
| Untrusted third-party code                                                    | Do not run it as a tenant Component; Custom Node.js is a trusted-code boundary |

Custom Node.js does not replace Endpoints or Jobs. A Component defines the code;
an Endpoint invokes its active runtime revision synchronously, while a Job provides
durable background execution, history, retry controls, and a longer execution
budget.

## Required files

A component includes `index.js`, `package.json`, and any additional relative files. `index.js` exports a named `init` function. RevoEngine injects an execution-bound runtime; component code does not construct a client or receive an API key.

```text theme={null}
index.js                 required entrypoint
package.json             required ESM package manifest
src/normalize-order.js   optional relative module
templates/receipt.txt    optional application asset
```

Paths are relative POSIX paths. Empty segments, `.` or `..`, backslashes,
control characters, absolute paths, and duplicate normalized paths are rejected.
The platform also validates that `package.json` is a JSON object and that
`index.js` is valid JavaScript with a named `init` export before a deployment is
queued.

```js theme={null}
/** @param {import('@revoengine/sdk').RevoRuntime} runtime */
export async function init(runtime) {
  const { api, storage, utils } = runtime;
  const { data: rows } = await api.getDatabaseData('Sales', {
    fields: ['saleId', 'customerId', 'total'],
    take: 100,
  });

  const file = await storage.putObject({
    name: `sales-${utils.randomUUID()}.json`,
    data: JSON.stringify(rows),
    mimeType: 'application/json',
  });

  return { exportedRows: rows.length, storageEntryId: file.storageEntryId };
}
```

```json theme={null}
{
  "type": "module",
  "dependencies": {
    "@revoengine/sdk": "1.0.1"
  }
}
```

<Note>
  The platform selects and enforces its supported SDK release. Use the version generated by RevoEngine rather than replacing it with a range.
</Note>

## Runtime surface

The injected runtime exposes five governed capabilities:

| Member    | Purpose                                                                                  |
| --------- | ---------------------------------------------------------------------------------------- |
| `api`     | Execution context, Databases, Secrets, HTTP, Jobs, Events, and other platform operations |
| `storage` | Folders, objects, upload sessions, retention, downloads, and metadata                    |
| `utils`   | Local validation, identifiers, encoding, hashing, signatures, and cryptography           |
| `agents`  | Authorized Assistant, Agent, run, inbox, and plugin operations                           |
| `batch`   | Request batching limits and failure behavior for bridge-backed calls                     |

Snapshot context calls such as `api.input()` and `api.getExecutionId()` are
synchronous. Platform-backed reads and writes return promises and must be awaited.
Use `runtime.execute()` when Custom Node.js must run a bounded low-code fragment
against the active `lib.Category.Name.ElementKey.X` library surface.

<Warning>
  Runtime types describe callable operations; they do not grant access. The
  execution principal still needs the applicable role, Group membership, resource
  ACL, Secret access, and instance entitlement.
</Warning>

## Deployment lifecycle

Saving source creates an immutable runtime revision and a deployment attempt. The component reports build and readiness state separately from source versioning. In automatic activation mode, a verified ready revision can become active; manual mode lets an operator choose a ready revision for rollout or rollback.

Endpoints execute only the selected ready runtime revision. If no active revision exists, the request fails explicitly rather than using newly saved or failed code.

Each attempt moves through customer-visible deployment states:

| State                   | Meaning                                                                    | Operator action                                                                             |
| ----------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `QUEUED`                | The immutable source revision is waiting for deployment.                   | Wait or inspect queue health if it remains unchanged.                                       |
| `DEPLOYING`             | The platform is preparing, building, verifying, or promoting the revision. | Follow the stage and deployment timestamps.                                                 |
| `READY`                 | A verified runtime artifact can be selected for execution.                 | Smoke-test before broader traffic.                                                          |
| `FAILED`                | The attempt did not produce a usable artifact.                             | Read the sanitized error, correct source or dependencies, and retry or save a new revision. |
| `SUPERSEDED`            | A newer deployment replaced this attempt.                                  | Keep it for history; select only an eligible ready revision.                                |
| `CANCELED` or `EXPIRED` | Work ended before readiness.                                               | Confirm no active pointer changed, then retry if still required.                            |

Deployment progress is separate from Component source versioning. A failed new
deployment does not make unverified code executable and does not silently replace
the previous active revision.

## Activation and rollback

In **automatic** activation mode, a successfully verified desired revision can
become active. In **manual** mode, an operator selects a ready revision explicitly.
Activation updates use the current runtime generation so that two administrators
cannot unknowingly overwrite each other's selection.

For a rollback:

1. Open the Component runtime and deployment history.
2. Confirm the previous revision is still `READY`.
3. In manual mode, select that revision using the current generation.
4. Invoke a representative Sandbox or Endpoint request.
5. Verify the Execution ID, Logs, Trace, output contract, and downstream state.

Custom Node.js Endpoints always follow the Component's active runtime revision;
they cannot pin an independent low-code `componentVersion`.

## Package boundary

* Use ESM and export `init`.
* Keep paths relative and portable; absolute paths and traversal are rejected.
* Package installation does not run npm lifecycle scripts.
* Use prebuilt or script-free dependencies.
* Keep large file transfer in Storage upload sessions instead of buffering it in the worker.

Native dependencies must be compatible with the managed runtime. Prefer small,
maintained, script-free packages and commit a reviewed lock file when the editor
workflow supports it. Treat every dependency update as an application change: save
a new immutable revision, observe deployment, test it, and only then activate it.

## Failure and recovery

| Failure                                  | Expected behavior                                                                            |
| ---------------------------------------- | -------------------------------------------------------------------------------------------- |
| Source or manifest validation fails      | The save is rejected and no deployment is queued.                                            |
| Dependency installation or build fails   | The deployment becomes `FAILED`; the previous active revision remains available.             |
| No active ready revision exists          | Endpoint or Job execution fails explicitly as not ready.                                     |
| The execution deadline is reached        | The caller receives a timeout; remote effects accepted before cancellation may still exist.  |
| A bridge-backed API call is unauthorized | The operation fails under the runtime principal; changing source cannot bypass the policy.   |
| A client disconnects                     | Cancellation is requested, but external and durable mutations must be verified before retry. |

Do not retry a payment, notification, or provider write only because the caller saw
a timeout. Persist an idempotency key, inspect platform evidence and the remote
system, then retry through a controlled Job or operator action.

## Production checklist

* Keep `init(runtime)` small and move cohesive logic into reviewed relative modules.
* Bound Database reads and memory use; stream large payloads through Storage.
* Resolve Secrets immediately before the target call and never log their values.
* Add idempotency around every retryable external side effect.
* Inspect deployment readiness separately from source-save success.
* Use manual activation when a release requires an explicit promotion decision.
* Test the exact Endpoint or Job principal, not only an editor session.
* Capture Execution ID and operation ID in application-safe diagnostics.
* Keep the previous ready revision available until the new one passes production verification.

<Warning>
  This runtime separates customer code from credential handling, but it is not an adversarial-code sandbox. Review tenant code and dependencies before deployment.
</Warning>

See [Hosted Node.js SDK](/developers/sdk-hosted) for the complete injected runtime
contract, [Component configuration](/build/component-configuration) for common
fields, and [Jobs](/operate/jobs) for durable background execution.
