# How to Integrate ApraPipes Using the Node.js Addon API: A Complete Guide

> Learn how to integrate ApraPipes into your Node.js applications with this comprehensive guide. Discover how to use the native N-API addon for seamless C++ pipeline engine integration.

- Repository: [Apra Labs/aprapipes](https://github.com/apra-labs/aprapipes)
- Tags: how-to-guide
- Published: 2026-02-25

---

**You can integrate ApraPipes into Node.js applications by installing the `@apra/pipes` package, which exposes a native N-API addon that wraps the C++ pipeline engine through the `Pipeline` and `Module` JavaScript classes.**

The `apra-labs/aprapipes` repository provides a first-class Node.js addon API that allows developers to control high-performance media processing pipelines directly from JavaScript. By leveraging N-API for binary stability, the addon exposes the full capabilities of the ApraPipes C++ engine—including dynamic module configuration, real-time event streaming, and lifecycle management—without leaving the Node.js ecosystem.

## Understanding the ApraPipes Node.js Addon Architecture

The ApraPipes Node.js addon is built on **N-API**, ensuring compatibility across Node.js versions without recompilation. The addon bridges JavaScript and C++ through a thin wrapper layer that maps JS class methods directly to the underlying pipeline engine.

### Core JavaScript Classes and Their C++ Implementations

The addon exposes two primary JavaScript classes that mirror the C++ architecture:

| JavaScript Class | C++ Implementation File | Purpose |
|------------------|-------------------------|---------|
| `Pipeline` | [`base/bindings/node/pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp) | Creates, configures, and controls processing pipelines |
| `Module` | [`base/bindings/node/module_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/module_wrapper.cpp) | Represents individual processing modules within a pipeline |
| Event Emitter | [`base/bindings/node/event_emitter.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/event_emitter.cpp) | Bridges C++ callbacks to JavaScript event listeners |
| Addon Entry | [`base/bindings/node/addon.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/addon.cpp) | Registers classes with N-API and exports the module |

When you `require('@apra/pipes')`, the addon entry point in [`base/bindings/node/addon.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/addon.cpp) initializes these classes and returns the `Pipeline` and `Module` constructors to your JavaScript code.

## Setting Up Your Environment

You can obtain the ApraPipes Node.js addon either through the npm registry or by building from the source repository.

Install the prebuilt binary via npm:

```bash
npm install @apra/pipes

```

Alternatively, clone the `apra-labs/aprapipes` repository and build the addon from source using the provided build scripts. After installation, the native binary `aprapipes.node` resides alongside the JavaScript entry point, automatically loaded when you import the package.

## Creating and Controlling Pipelines with the Node.js Addon API

The `Pipeline` class constructor accepts a JSON configuration object that follows the same schema used by the C++ command-line interface. This allows you to define modules, connections, and parameters declaratively.

### Loading a Pipeline from JSON

The most common integration pattern involves loading a pre-defined pipeline configuration and executing it:

```javascript
// examples/node/basic_pipeline.js
const { Pipeline } = require('@apra/pipes');
const fs = require('fs');

// Load a declarative pipeline description (same format as CLI)
const json = fs.readFileSync('examples/basic/pipeline.json', 'utf8');
const pipeline = new Pipeline(JSON.parse(json));

// Optional: attach a listener to log status changes
pipeline.on('status', (msg) => console.log('Pipeline status →', msg));

// Initialise internal resources (e.g., allocate buffers)
pipeline.init();

// Start processing
pipeline.run();

// Later … stop gracefully
setTimeout(() => pipeline.stop(), 10000);

```

In [`base/bindings/node/pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp), the constructor parses the JSON and instantiates the corresponding C++ `Pipeline` object, while the `run()` method forwards to the native execution engine.

### Dynamically Adding Modules at Runtime

For scenarios requiring dynamic configuration, you can instantiate individual `Module` objects and inject them into a running pipeline structure:

```javascript
const { Pipeline, Module } = require('@apra/pipes');

// Create an empty pipeline
const pipeline = new Pipeline({ modules: [], connections: [] });

// Define a simple grayscale transform module (C++ side already registered)
const grayModule = new Module('gray', { 
  type: 'ColorConversion', 
  params: { mode: 'GRAY' } 
});

pipeline.addModule(grayModule);
pipeline.connect('source', 'gray');
pipeline.connect('gray', 'sink');

pipeline.run();

```

The `Module` class in [`base/bindings/node/module_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/module_wrapper.cpp) wraps the C++ module factory, allowing JavaScript to configure parameters that are passed directly to the native implementation.

### Handling Real-Time Events

The addon implements an event emitter pattern in [`base/bindings/node/event_emitter.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/event_emitter.cpp), bridging C++ callbacks to JavaScript event listeners:

```javascript
const { Pipeline } = require('@apra/pipes');

const pipeline = new Pipeline(myJson);

// Listen for frame-processed events emitted by a custom module
pipeline.on('myDetector:frame', (frameInfo) => {
  console.log('Detected object at', frameInfo.boundingBox);
});

// Error handling
pipeline.on('error', (err) => {
  console.error('Pipeline error:', err);
});

pipeline.run();

```

Events follow the naming convention `moduleName:eventType`, allowing granular subscription to specific module outputs.

### Integrating with Express.js

You can embed ApraPipes pipelines within web servers to create real-time media endpoints:

```javascript
const express = require('express');
const { Pipeline } = require('@apra/pipes');

const app = express();
const pipeline = new Pipeline(streamPipelineJson);

app.get('/video', (req, res) => {
  // Stream raw video frames directly to the response
  pipeline.on('frame', (buf) => res.write(buf));
  pipeline.run();
});

app.listen(3000, () => console.log('Server listening on :3000'));

```

This pattern leverages the addon's ability to emit raw buffer data, enabling direct streaming to HTTP responses or WebSocket connections.

### Graceful Shutdown Handling

To prevent resource leaks, implement signal handlers that invoke the pipeline's `stop()` method:

```javascript
const { Pipeline } = require('@apra/pipes');
const pipeline = new Pipeline(myJson);

process.on('SIGINT', async () => {
  console.log('Stopping pipeline …');
  await pipeline.stop();   // returns a promise if the wrapper is async-enabled
  process.exit(0);
});

pipeline.run();

```

The `stop()` method in [`base/bindings/node/pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp) triggers the C++ pipeline's shutdown sequence, ensuring all modules release their resources before the Node.js process exits.

## Key Source Files and Implementation Details

Understanding the underlying C++ implementation helps debug integration issues and leverage advanced features.

| File | Role | Link |
|------|------|------|
| [`base/bindings/node/addon.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/addon.cpp) | Registers the N-API module and exposes `Pipeline` & `Module` classes | [view](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/addon.cpp) |
| [`base/bindings/node/pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp) | Implements the JavaScript `Pipeline` class (creation, control, event routing) | [view](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp) |
| [`base/bindings/node/module_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/module_wrapper.cpp) | Implements the `Module` class that mirrors C++ module API | [view](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/module_wrapper.cpp) |
| [`base/bindings/node/event_emitter.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/event_emitter.cpp) | Provides `on/off` semantics and bridges C++ callbacks to JS | [view](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/event_emitter.cpp) |
| [`examples/node/basic_pipeline.js`](https://github.com/apra-labs/aprapipes/blob/main/examples/node/basic_pipeline.js) | Minimal end-to-end usage example | [view](https://github.com/apra-labs/aprapipes/blob/main/examples/node/basic_pipeline.js) |
| [`examples/node/face_detection_demo.js`](https://github.com/apra-labs/aprapipes/blob/main/examples/node/face_detection_demo.js) | Shows how to hook custom detection events | [view](https://github.com/apra-labs/aprapipes/blob/main/examples/node/face_detection_demo.js) |
| [`package.json`](https://github.com/apra-labs/aprapipes/blob/main/package.json) (root) | Declares the Node.js package, its binaries, and peer dependencies | [view](https://github.com/apra-labs/aprapipes/blob/main/package.json) |

These files together form the public API you’ll use from JavaScript. By importing `@apra/pipes` and working with the `Pipeline` class, you get full access to the high-performance, cross-platform media processing capabilities of ApraPipes while staying entirely within the Node.js ecosystem.

## Summary

- **Install the addon** via `npm install @apra/pipes` or build from the `apra-labs/aprapipes` source to obtain the native `aprapipes.node` binary.
- **Instantiate pipelines** using the `Pipeline` class with JSON configurations that match the C++ CLI schema, or build them dynamically using the `Module` class.
- **Control execution** through methods like `run()`, `stop()`, `pause()`, and `step()`, which forward directly to the C++ engine via [`pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/pipeline_wrapper.cpp).
- **Handle events** by listening to the `EventEmitter` interface for pipeline status, errors, and module-specific events bridged through [`event_emitter.cpp`](https://github.com/apra-labs/aprapipes/blob/main/event_emitter.cpp).
- **Integrate seamlessly** with Express.js, WebSockets, or Electron apps to build real-time media servers while ensuring graceful shutdown via `SIGINT` handlers.

## Frequently Asked Questions

### How do I install the ApraPipes Node.js addon if prebuilt binaries are not available for my platform?

If prebuilt binaries are unavailable, clone the `apra-labs/aprapipes` repository and build the addon from source using the provided CMake or node-gyp configuration. The build process compiles [`base/bindings/node/addon.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/addon.cpp) along with its dependencies into `aprapipes.node`, which the [`package.json`](https://github.com/apra-labs/aprapipes/blob/main/package.json) loads via the `main` entry point. Ensure you have the required system dependencies (C++ compiler, CMake, and Node.js headers) installed before building.

### What is the difference between the `init()` and `run()` methods in the Pipeline class?

The `init()` method, implemented in [`base/bindings/node/pipeline_wrapper.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/pipeline_wrapper.cpp), allocates internal C++ resources such as memory buffers and validates module connections without starting data processing. The `run()` method begins the actual execution loop, causing data to flow through the pipeline modules. You should call `init()` once after construction to catch configuration errors early, then invoke `run()` to start processing. Calling `run()` without `init()` may work in some versions but is not guaranteed across all releases.

### How can I handle errors that occur inside C++ modules from my JavaScript code?

The addon bridges C++ exceptions and error states to JavaScript through the `EventEmitter` interface defined in [`base/bindings/node/event_emitter.cpp`](https://github.com/apra-labs/aprapipes/blob/main/base/bindings/node/event_emitter.cpp). Listen for the `'error'` event on your pipeline instance to receive error objects containing message strings and optional error codes. Additionally, synchronous methods like `init()` may throw JavaScript exceptions immediately if the JSON configuration is malformed. For production applications, always attach both `'error'` event listeners and try-catch blocks around initialization calls.

### Can I use the ApraPipes Node.js addon with TypeScript?

While the `apra-labs/aprapipes` repository primarily provides JavaScript examples, you can use the addon with TypeScript by creating type definitions for the `Pipeline` and `Module` classes. The classes expose standard JavaScript constructors and methods like `run()`, `stop()`, and `on()`, which map cleanly to TypeScript interfaces. You would typically declare the `@apra/pipes` module with interfaces matching the JSON configuration schema and the EventEmitter pattern. Community type definitions may be available, or you can generate them from the C++ header files using automated binding generators.