Skip to main content

NestJS module and controllers for Neuroline pipeline APIs with DI support.

English | Русский

neuroline-nestjs

npm Demo GitHub

NestJS integration for Neuroline — dynamic module with full DI support for creating pipeline API controllers.

Installation

yarn add neuroline neuroline-nestjs
# or
npm install neuroline neuroline-nestjs

Features

  • Dynamic ModuleNeurolineModule.forRootAsync() with full NestJS DI support
  • Auto-generated Controllers — no boilerplate, just configuration
  • Guards Support — apply guards per controller
  • PipelineClient Compatible — API format matches neuroline/client expectations
  • NeurolineService — access manager/storage in your services
  • MongoDB Re-exportsMongoPipelineStorage, PipelineSchema included

Quick Start

import { Module } from '@nestjs/common';
import { MongooseModule, getModelToken } from '@nestjs/mongoose';
import { NeurolineModule, MongoPipelineStorage, PipelineSchema } from 'neuroline-nestjs';
import { myPipeline } from './pipelines';
import { AuthGuard } from './guards';

@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/neuroline'),
MongooseModule.forFeature([{ name: 'Pipeline', schema: PipelineSchema }]),

NeurolineModule.forRootAsync({
imports: [MongooseModule],
useFactory: (model) => new MongoPipelineStorage(model),
inject: [getModelToken('Pipeline')],
controllers: [
{
path: 'api/v1/my-pipeline',
pipeline: myPipeline,
guards: [AuthGuard], // guards for entire controller
adminGuards: [AdminGuard], // guards for admin endpoints
// Get jobOptions from request context
getJobOptions: async (input, request) => {
const user = request.user;
return {
myJob: { userId: user?.id, apiKey: process.env.API_KEY },
};
},
},
],
}),
],
})
export class AppModule {}

Using NeurolineService

import { Injectable } from '@nestjs/common';
import { NeurolineService } from 'neuroline-nestjs';

@Injectable()
export class MyService {
constructor(private readonly neuroline: NeurolineService) {}

async runPipeline(data: any) {
const { pipelineId } = await this.neuroline.startPipeline('my-pipeline', data);
return pipelineId;
}

async checkStatus(pipelineId: string) {
return this.neuroline.getStatus(pipelineId);
}
}

Direct DI Access

import { Injectable, Inject } from '@nestjs/common';
import { NEUROLINE_MANAGER, NEUROLINE_STORAGE } from 'neuroline-nestjs';
import type { PipelineManager, PipelineStorage } from 'neuroline';

@Injectable()
export class MyService {
constructor(
@Inject(NEUROLINE_MANAGER) private readonly manager: PipelineManager,
@Inject(NEUROLINE_STORAGE) private readonly storage: PipelineStorage
) {}
}

API Endpoints

The generated controllers expose the following endpoints:

POST /api/v1/my-pipeline

Start a new pipeline. Request body = TInput directly.

Request:

curl -X POST http://localhost:3000/api/v1/my-pipeline \
-H "Content-Type: application/json" \
-d '{ "seed": 123, "name": "test" }'

jobOptions are obtained on the server via getJobOptions(input, request).

Response:

{
"success": true,
"data": {
"pipelineId": "abc123",
"isNew": true
}
}

POST /api/v1/my-pipeline?action=startWithOptions

Admin endpoint: start pipeline with explicit jobOptions. Requires adminGuards.

Request:

curl -X POST "http://localhost:3000/api/v1/my-pipeline?action=startWithOptions" \
-H "Content-Type: application/json" \
-d '{
"input": { "seed": 123, "name": "test" },
"jobOptions": {
"compute": { "multiplier": 2.0 }
}
}'

GET ?action=status&id=xxx

Get pipeline status.

GET ?action=result&id=xxx[&jobName=yyy]

Get job result (artifact). If jobName is not provided, returns the last job result.

GET ?action=list&page=1&limit=10

List pipelines with pagination.

Admin Endpoints

These endpoints return full pipeline/job data (input, options, artifacts) or allow passing jobOptions directly. They are disabled by default. Enable with adminGuards.

EndpointDescription
POST ?action=startWithOptionsStart pipeline with explicit jobOptions
POST ?action=runManualJob&id=xxxTrigger a manual job
GET ?action=job&id=xxx&jobName=yyyJob details (input, options, artifact)
GET ?action=pipeline&id=xxxFull pipeline state
// Admin доступен только авторизованным
adminGuards: [AdminGuard];

// Admin доступен всем (открытый доступ)
adminGuards: [];

// Admin отключён (по умолчанию)
// просто не указывайте adminGuards

Serverless / Vercel

In serverless environments (Vercel, AWS Lambda), the Node.js process terminates immediately after sending the HTTP response. Since PipelineManager.startPipeline launches execution asynchronously after responding, the execution promise gets killed before completion.

Use the onExecutionStart option to bind the execution promise to the serverless function lifecycle:

import { waitUntil } from '@vercel/functions';

NeurolineModule.forRootAsync({
onExecutionStart: process.env.VERCEL ? (promise) => waitUntil(promise) : undefined,
// ...other options
});

The callback is applied globally to all pipelines in the module — both startPipeline and restartPipelineFromJob calls.

Multiple Pipelines

NeurolineModule.forRootAsync({
imports: [MongooseModule],
useFactory: (model) => new MongoPipelineStorage(model),
inject: [getModelToken('Pipeline')],
controllers: [
{
path: 'api/v1/demo',
pipeline: demoPipeline,
},
{
path: 'api/v1/analytics',
pipeline: analyticsPipeline,
guards: [AdminGuard],
},
],
});

Exports

ExportTypeDescription
NeurolineModuleClassDynamic module with forRootAsync()
NeurolineServiceClassService for accessing manager/storage
NEUROLINE_MANAGERTokenDI token for PipelineManager
NEUROLINE_STORAGETokenDI token for PipelineStorage
MongoPipelineStorageClassMongoDB storage (re-export)
PipelineSchemaSchemaMongoose schema (re-export)
PipelineControllerOptionsTypeController configuration
NeurolineModuleAsyncOptionsTypeModule configuration

License

UNLICENSED


neuroline-nestjs

npm Demo GitHub

Интеграция NestJS для Neuroline — динамический модуль с полной поддержкой DI для создания API-контроллеров.

Установка

yarn add neuroline neuroline-nestjs
# или
npm install neuroline neuroline-nestjs

Возможности

  • Динамический модульNeurolineModule.forRootAsync() с полной поддержкой NestJS DI
  • Автогенерация контроллеров — без boilerplate, только конфигурация
  • Поддержка Guards — применяйте guards для каждого контроллера
  • Совместимость с PipelineClient — формат API соответствует neuroline/client
  • NeurolineService — доступ к manager/storage в ваших сервисах
  • Реэкспорт MongoDBMongoPipelineStorage, PipelineSchema включены

Быстрый старт

import { Module } from '@nestjs/common';
import { MongooseModule, getModelToken } from '@nestjs/mongoose';
import { NeurolineModule, MongoPipelineStorage, PipelineSchema } from 'neuroline-nestjs';
import { myPipeline } from './pipelines';
import { AuthGuard } from './guards';

@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/neuroline'),
MongooseModule.forFeature([{ name: 'Pipeline', schema: PipelineSchema }]),

NeurolineModule.forRootAsync({
imports: [MongooseModule],
useFactory: (model) => new MongoPipelineStorage(model),
inject: [getModelToken('Pipeline')],
controllers: [
{
path: 'api/v1/my-pipeline',
pipeline: myPipeline,
guards: [AuthGuard], // guards для всего контроллера
adminGuards: [AdminGuard], // guards для admin-эндпоинтов
// Получение jobOptions из контекста запроса
getJobOptions: async (input, request) => {
const user = request.user;
return {
myJob: { userId: user?.id, apiKey: process.env.API_KEY },
};
},
},
],
}),
],
})
export class AppModule {}

Использование NeurolineService

import { Injectable } from '@nestjs/common';
import { NeurolineService } from 'neuroline-nestjs';

@Injectable()
export class MyService {
constructor(private readonly neuroline: NeurolineService) {}

async runPipeline(data: any) {
const { pipelineId } = await this.neuroline.startPipeline('my-pipeline', data);
return pipelineId;
}

async checkStatus(pipelineId: string) {
return this.neuroline.getStatus(pipelineId);
}
}

Прямой доступ через DI

import { Injectable, Inject } from '@nestjs/common';
import { NEUROLINE_MANAGER, NEUROLINE_STORAGE } from 'neuroline-nestjs';
import type { PipelineManager, PipelineStorage } from 'neuroline';

@Injectable()
export class MyService {
constructor(
@Inject(NEUROLINE_MANAGER) private readonly manager: PipelineManager,
@Inject(NEUROLINE_STORAGE) private readonly storage: PipelineStorage
) {}
}

API Эндпоинты

Сгенерированные контроллеры предоставляют следующие эндпоинты:

POST /api/v1/my-pipeline

Запустить новый pipeline. Тело запроса = TInput напрямую.

Запрос:

curl -X POST http://localhost:3000/api/v1/my-pipeline \
-H "Content-Type: application/json" \
-d '{ "seed": 123, "name": "test" }'

jobOptions получаются на сервере через getJobOptions(input, request).

Ответ:

{
"success": true,
"data": {
"pipelineId": "abc123",
"isNew": true
}
}

POST /api/v1/my-pipeline?action=startWithOptions

Admin-эндпоинт: запуск pipeline с явными jobOptions. Требует adminGuards.

Запрос:

curl -X POST "http://localhost:3000/api/v1/my-pipeline?action=startWithOptions" \
-H "Content-Type: application/json" \
-d '{
"input": { "seed": 123, "name": "test" },
"jobOptions": {
"compute": { "multiplier": 2.0 }
}
}'

GET ?action=status&id=xxx

Получить статус pipeline.

GET ?action=result&id=xxx[&jobName=yyy]

Получить результат job (артефакт). Если jobName не передан, возвращается результат последней job.

GET ?action=list&page=1&limit=10

Список pipelines с пагинацией.

Admin-эндпоинты

Эти эндпоинты возвращают полные данные pipeline/job (input, options, artifacts) или позволяют передавать jobOptions напрямую. Отключены по умолчанию. Включите через adminGuards.

ЭндпоинтОписание
POST ?action=startWithOptionsЗапуск pipeline с явными jobOptions
POST ?action=runManualJob&id=xxxЗапуск manual job
GET ?action=job&id=xxx&jobName=yyyДетали job (input, options, artifact)
GET ?action=pipeline&id=xxxПолное состояние pipeline
// Admin доступен только авторизованным
adminGuards: [AdminGuard];

// Admin доступен всем (открытый доступ)
adminGuards: [];

// Admin отключён (по умолчанию)
// просто не указывайте adminGuards

Serverless / Vercel

В serverless окружениях (Vercel, AWS Lambda) процесс Node.js завершается сразу после отправки HTTP ответа. Поскольку PipelineManager.startPipeline запускает выполнение асинхронно после ответа клиенту, promise выполнения убивается до завершения.

Используйте опцию onExecutionStart, чтобы привязать promise выполнения к жизненному циклу serverless функции:

import { waitUntil } from '@vercel/functions';

NeurolineModule.forRootAsync({
onExecutionStart: process.env.VERCEL ? (promise) => waitUntil(promise) : undefined,
// ...остальные опции
});

Callback применяется глобально ко всем pipeline в модуле — и к startPipeline, и к restartPipelineFromJob.

Несколько Pipelines

NeurolineModule.forRootAsync({
imports: [MongooseModule],
useFactory: (model) => new MongoPipelineStorage(model),
inject: [getModelToken('Pipeline')],
controllers: [
{
path: 'api/v1/demo',
pipeline: demoPipeline,
},
{
path: 'api/v1/analytics',
pipeline: analyticsPipeline,
guards: [AdminGuard],
},
],
});

Экспорты

ЭкспортТипОписание
NeurolineModuleClassДинамический модуль с forRootAsync()
NeurolineServiceClassСервис для доступа к manager/storage
NEUROLINE_MANAGERTokenDI токен для PipelineManager
NEUROLINE_STORAGETokenDI токен для PipelineStorage
MongoPipelineStorageClassMongoDB storage (реэкспорт)
PipelineSchemaSchemaMongoose схема (реэкспорт)
PipelineControllerOptionsTypeКонфигурация контроллера
NeurolineModuleAsyncOptionsTypeКонфигурация модуля

Лицензия

UNLICENSED