npm package: @peopl-health/nexus
Description: Core messaging and assistant library for WhatsApp communication platforms
Author: PEOPL Health Tech
Latest version: 3.10.4

# @peopl-health/nexus

A concise, configurable messaging and assistant toolkit for WhatsApp. It supports Twilio (production‑ready) and Baileys (limited), optional Mongo storage, OpenAI assistants, templates/flows via Twilio Content API, and an event/middleware model so apps can customize behavior.

## Install

```bash
npm install @peopl-health/nexus
# Providers / AI
npm install twilio baileys openai
```

## Quick Start (Twilio)

```js
const express = require('express');
const { Nexus, setupDefaultRoutes } = require('@peopl-health/nexus');

const nexus = new Nexus();
await nexus.initialize({
  provider: 'twilio',
  providerConfig: {
    accountSid: process.env.TWILIO_ACCOUNT_SID,
    authToken: process.env.TWILIO_AUTH_TOKEN,
    phoneNumber: process.env.TWILIO_PHONE_NUMBER
  },
  // Storage (MongoStorage) and Mongo convenience
  storage: 'mongo',
  storageConfig: { dbName: 'nexus' },   // other options
  mongoUri: process.env.MONGODB_URI,    // convenience: passed into storageConfig.mongoUri

  // Media convenience (inject only bucket name)
  media: { bucketName: process.env.AWS_S3_BUCKET_NAME },

  // Airtable convenience (pick default base or pass a Base ID)
  airtable: {
    base: 'calendar',                   // friendly key or base ID
    apiKey: process.env.AIRTABLE_API_KEY
  },

  // Optional LLM (OpenAI)
  llm: 'openai',
  llmConfig: { apiKey: process.env.OPENAI_API_KEY }
});

// Built‑in routes (assistant, conversation, media, message, template)
const app = express();
app.use(express.json());
setupDefaultRoutes(app);

// Incoming webhooks
app.post('/webhook', async (req, res) => {
  await nexus.processMessage(req.body);
  res.sendStatus(200);
});
```

## Templates & Approvals (Twilio)

Nexus auto‑injects the active Twilio provider into the template controllers during `initialize`. Default routes under `/api/template` work immediately:
- `GET /api/template` list templates
- `GET /api/template/:id` get one
- `POST /api/template/text` create text template
- `POST /api/template/approval` submit for approval
- `GET /api/template/status/:sid` check status
- `DELETE /api/template/:id` delete

Programmatic use:
```js
const provider = nexus.getMessaging().getProvider();
const content = await provider.createTemplate({
  friendly_name: 'hello_' + Date.now(),
  language: 'es',
  variables: { '1': 'Nombre' },
  types: { 'twilio/text': { body: 'Hola {{1}}' } }
});
await provider.submitForApproval(content.sid, 'hello', 'UTILITY');
const status = await provider.checkApprovalStatus(content.sid);
```

## Interactive & Flows

Provider‑agnostic APIs with Twilio mapping (Baileys: not supported):
```js
const { registerFlow, sendInteractive, registerInteractiveHandler, attachInteractiveRouter } = require('@peopl-health/nexus');

registerFlow('greeting_qr', {
  type: 'quick-reply', language: 'es', body: 'Hola {{1}}', variables: { '1': 'Nombre' },
  buttons: [{ text: 'Sí' }, { text: 'No' }]
});
await sendInteractive(nexus, { code: '+521555...', id: 'greeting_qr' });

registerInteractiveHandler({ type: 'button', id: /sí|si/i }, async (msg, messaging) => {
  await messaging.sendMessage({ code: msg.from, message: '¡Confirmado!' });
});
attachInteractiveRouter(nexus);
```

## Storage (Adapters)

- Built‑in: `mongo` (default), `noop`.
- Register your adapter or pass an instance directly.
```js
const { registerStorage } = require('@peopl-health/nexus/lib/storage/registry');
registerStorage('src', MyStorageClass);
await nexus.initialize({ storage: 'src', storageConfig: { /* ... */ } });
// OR
await nexus.initialize({ storage: new MyStorageClass(/* ... */) });
```

## Middleware & Events

Add middleware per type or global; subscribe to events.
```js
const bus = nexus.getMessaging().getEventBus();
bus.on('message:received', (m) => console.log('rx', m.id));

nexus.getMessaging().use('message', async (msg, nx, next) => {
  // sanitize/annotate
  return next();
});
```

## Assistants (Optional)

Register assistant classes and (optionally) a custom resolver. OpenAI is supported via `llm: 'openai'`.
```js
await nexus.initialize({
  provider: 'twilio',
  llm: 'openai', llmConfig: { apiKey: process.env.OPENAI_API_KEY },
  assistants: {
    registry: { SUPPORT: SupportAssistantClass, SALES: SalesAssistantClass },
    getAssistantById: (id, thread) => null // optional override
  }
});
```

## Routes (Importable)

Use `setupDefaultRoutes(app)` to mount everything, or pick from `routes` + `createRouter()` to mount subsets.

## Examples

See:
- examples/basic-usage.js
- examples/assistants/



## Configuration

You can configure Nexus via environment variables or at runtime using simple injection helpers. For production apps, prefer passing options or DI, and use envs as a fallback.

- Providers/AI
  - TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE_NUMBER
  - OPENAI_API_KEY

- Mongo
  - MONGODB_URI (or pass `mongoUri` when calling `initializeMongoDB()`)

- Airtable
  - AIRTABLE_API_KEY
  - AIRTABLE_BASE_ID (or specific IDs below)
  - AIRTABLE_CALENDAR_ID, AIRTABLE_CONFIG_ID, AIRTABLE_HISTORIAL_CLINICO_ID
  - AIRTABLE_LOGGING_ID, AIRTABLE_MONITOREO_ID, AIRTABLE_PROGRAMA_JUNTAS_ID
  - AIRTABLE_SYMPTOMS_ID, AIRTABLE_WEBINARS_LEADS_ID

- AWS (S3)
  - AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION (default: us-east-1)
  - AWS_S3_BUCKET_NAME (or inject via `configureMediaController`)

- Misc
  - NODE_ENV (affects logging and helpers)
  - USER_DB_MONGO (used as author in message controller)

Injection points (dependency injection)

- Message scheduling (use your Agenda/Bull model + scheduler):
```js
const { configureMessageController } = require('@peopl-health/nexus/lib/controllers/messageController');
const { AgendaMessage } = require('./src/models/agendaMessageModel');
const { sendScheduledMessage: appSchedule } = require('./src/messaging/scheduledMessageService');

const provider = nexus.getMessaging().getProvider(); // e.g., TwilioProvider
configureMessageController({
  ScheduledMessage: AgendaMessage, // must expose create/find/findById/deleteOne
  sendScheduledMessage: (saved) => appSchedule(provider.twilioClient, saved),
  // Optional: only if you use bulk‑airtable
  getRecordByFilter: require('@peopl-health/nexus/lib/services/airtableService').getRecordByFilter
});
```

- Media (inject only your bucket name; AWS SDK is loaded by the lib):
```js
const { configureMediaController } = require('@peopl-health/nexus/lib/controllers/mediaController');
configureMediaController({ bucketName: process.env.AWS_S3_BUCKET_NAME });
```

- Storage settings (MongoStorage only):
```js
// Store once; Nexus auto-injects media bucket from storage at startup
await nexus.getStorage().setConfig('media.bucketName', process.env.AWS_S3_BUCKET_NAME);
```

Tips
- Connect Mongo before `app.listen()` to avoid Mongoose buffering timeouts.
- If you initialize OpenAI, pass `llm: 'openai'` and `llmConfig: { apiKey }` to `nexus.initialize`.
- Use the event bus + middleware for custom routing and transformations without forking the default handlers.