novapsis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Vercel, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # ⚑ novapsis (SDK Oficial)
2
+
3
+ > SDK oficial de **Novapsis SM** para Node.js, Next.js, Express, NestJS y TypeScript. Conecta WhatsApp Business Cloud API, Onboarding Hosted B2B (Marca Blanca), CRM, Agentes de IA y VerificaciΓ³n HMAC de Webhooks en minutos.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/novapsis.svg)](https://www.npmjs.com/package/novapsis)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## πŸ“¦ InstalaciΓ³n
11
+
12
+ ```bash
13
+ # Con pnpm (recomendado)
14
+ pnpm add novapsis
15
+
16
+ # Con npm
17
+ npm install novapsis
18
+
19
+ # Con yarn
20
+ yarn add novapsis
21
+ ```
22
+
23
+ ---
24
+
25
+ ## πŸš€ Inicio RΓ‘pido
26
+
27
+ ObtΓ©n tu API Key (`nvs_live_...` o `nvs_test_...`) desde el panel de control de [Novapsis SM](https://app.novapsis.com).
28
+
29
+ ```typescript
30
+ import { Novapsis } from 'novapsis';
31
+
32
+ const novapsis = new Novapsis({
33
+ apiKey: process.env.NOVAPSIS_API_KEY!,
34
+ });
35
+ ```
36
+
37
+ ---
38
+
39
+ ## πŸ“± 1. EnvΓ­o de Mensajes por WhatsApp
40
+
41
+ ### Mensaje de Texto
42
+ ```typescript
43
+ await novapsis.whatsapp.sendText({
44
+ to: '34600112233', // TelΓ©fono internacional sin '+' ni espacios
45
+ text: 'Β‘Hola! Tu pedido ha sido confirmado con Γ©xito.',
46
+ });
47
+ ```
48
+
49
+ ### Documentos / Facturas PDF
50
+ ```typescript
51
+ await novapsis.whatsapp.sendDocument({
52
+ to: '34600112233',
53
+ documentUrl: 'https://tu-dominio.com/factura-1024.pdf',
54
+ filename: 'factura_1024.pdf',
55
+ caption: 'Adjuntamos tu factura correspondiente a este mes.',
56
+ });
57
+ ```
58
+
59
+ ### ImΓ‘genes y Multimedia
60
+ ```typescript
61
+ // Imagen
62
+ await novapsis.whatsapp.sendImage({
63
+ to: '34600112233',
64
+ imageUrl: 'https://tu-dominio.com/promo.png',
65
+ caption: 'πŸ”₯ Descuento especial exclusivo para ti.',
66
+ });
67
+
68
+ // Audio / Nota de Voz
69
+ await novapsis.whatsapp.sendAudio({
70
+ to: '34600112233',
71
+ audioUrl: 'https://tu-dominio.com/audio.mp3',
72
+ });
73
+
74
+ // UbicaciΓ³n en el Mapa
75
+ await novapsis.whatsapp.sendLocation({
76
+ to: '34600112233',
77
+ latitude: 40.416775,
78
+ longitude: -3.703790,
79
+ name: 'Oficina Central Madrid',
80
+ address: 'Calle Gran VΓ­a 28, Madrid, EspaΓ±a',
81
+ });
82
+ ```
83
+
84
+ ### Plantillas Oficiales de Meta (Templates)
85
+ ```typescript
86
+ await novapsis.whatsapp.sendTemplate({
87
+ to: '34600112233',
88
+ templateName: 'recordatorio_cita',
89
+ languageCode: 'es',
90
+ components: [
91
+ {
92
+ type: 'body',
93
+ parameters: [
94
+ { type: 'text', text: 'Carlos' },
95
+ { type: 'text', text: 'MaΓ±ana a las 10:00 AM' },
96
+ ],
97
+ },
98
+ ],
99
+ });
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 🏒 2. Multi-Tenant y Sedes (B2B Tech Provider)
105
+
106
+ Si tienes un CRM o plataforma multi-tenant y quieres que tus clientes o sedes conecten su propio nΓΊmero de WhatsApp con su cuenta de Meta:
107
+
108
+ ```typescript
109
+ // 1. Genera una sesiΓ³n de conexiΓ³n hosted
110
+ const session = await novapsis.onboarding.createSession({
111
+ clientName: 'Sede Barcelona',
112
+ redirectUrl: 'https://tu-crm.com/sedes/12/whatsapp-callback',
113
+ logoUrl: 'https://tu-crm.com/logo.png', // Marca blanca (Plan PRO)
114
+ brandColor: '#0ea5e9', // Marca blanca (Plan PRO)
115
+ metadata: { sede_id: 'sede_12' },
116
+ });
117
+
118
+ // 2. Abre session.session_url en un modal o ventana popup en tu frontend
119
+ console.log(session.session_url);
120
+ ```
121
+
122
+ Cuando envΓ­es mensajes para esa sede, solo pasa el `connectionId`:
123
+ ```typescript
124
+ await novapsis.whatsapp.sendText({
125
+ connectionId: 'UUID_DE_LA_SEDE',
126
+ to: '34600112233',
127
+ text: 'Hola desde la Sede Barcelona.',
128
+ });
129
+ ```
130
+
131
+ ---
132
+
133
+ ## πŸ”’ 3. Webhooks & VerificaciΓ³n HMAC
134
+
135
+ Garantiza que todos los webhooks entrantes son 100% legΓ­timos y no han sido manipulados:
136
+
137
+ ### En Next.js (App Router: `app/api/webhooks/novapsis/route.ts`)
138
+ ```typescript
139
+ import { NextResponse } from 'next/server';
140
+ import { Novapsis } from 'novapsis';
141
+
142
+ const novapsis = new Novapsis({
143
+ apiKey: process.env.NOVAPSIS_API_KEY!,
144
+ });
145
+
146
+ export async function POST(req: Request) {
147
+ const rawBody = await req.text();
148
+ const signature = req.headers.get('x-novapsis-signature');
149
+
150
+ // Validar firma criptogrΓ‘fica
151
+ const isValid = novapsis.webhooks.verifySignature(
152
+ rawBody,
153
+ signature,
154
+ process.env.NOVAPSIS_WEBHOOK_SECRET!
155
+ );
156
+
157
+ if (!isValid) {
158
+ return NextResponse.json({ error: 'Firma invΓ‘lida' }, { status: 401 });
159
+ }
160
+
161
+ const payload = JSON.parse(rawBody);
162
+
163
+ if (payload.event === 'whatsapp.message_received') {
164
+ const { connection_id, external_user_id, content, media_url } = payload.data;
165
+ console.log(`Mensaje de ${external_user_id} recibido: ${content}`);
166
+ }
167
+
168
+ return NextResponse.json({ ok: true });
169
+ }
170
+ ```
171
+
172
+ ---
173
+
174
+ ## πŸ€– 4. Agentes de Inteligencia Artificial (RAG)
175
+
176
+ ```typescript
177
+ const result = await novapsis.ai.execute({
178
+ agentId: 'ag_prod_consultas_ia',
179
+ message: 'ΒΏCuΓ‘les son los horarios de atenciΓ³n al cliente?',
180
+ });
181
+
182
+ console.log(result.response);
183
+ ```
184
+
185
+ ---
186
+
187
+ ## πŸ›‘οΈ Manejo de Errores Tipado
188
+
189
+ ```typescript
190
+ import { Novapsis, NovapsisAPIError } from 'novapsis';
191
+
192
+ try {
193
+ await novapsis.whatsapp.sendText({
194
+ to: '34600112233',
195
+ text: 'Hola',
196
+ });
197
+ } catch (error) {
198
+ if (error instanceof NovapsisAPIError) {
199
+ console.error(`Error de API [${error.code}] (HTTP ${error.status}):`, error.message);
200
+ console.error('Detalles:', error.details);
201
+ } else {
202
+ console.error('Error inesperado:', error);
203
+ }
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## πŸ“„ Licencia
210
+
211
+ MIT Β© [Novapsis Technologies](https://app.novapsis.com)
package/dist/index.cjs ADDED
@@ -0,0 +1,354 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var crypto = require('crypto');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var crypto__default = /*#__PURE__*/_interopDefault(crypto);
10
+
11
+ // src/index.ts
12
+ var NovapsisAPIError = class extends Error {
13
+ code;
14
+ status;
15
+ details;
16
+ constructor(message, code = "API_ERROR", status = 500, details) {
17
+ super(message);
18
+ this.name = "NovapsisAPIError";
19
+ this.code = code;
20
+ this.status = status;
21
+ this.details = details;
22
+ }
23
+ };
24
+ var HttpClient = class {
25
+ apiKey;
26
+ baseUrl;
27
+ timeoutMs;
28
+ maxRetries;
29
+ constructor(options) {
30
+ this.apiKey = options.apiKey;
31
+ this.baseUrl = (options.baseUrl || "https://app.novapsis.com").replace(/\/+$/, "");
32
+ this.timeoutMs = options.timeoutMs || 15e3;
33
+ this.maxRetries = options.maxRetries ?? 2;
34
+ }
35
+ async request(method, path, body, query) {
36
+ let url = `${this.baseUrl}/api/v1${path.startsWith("/") ? path : `/${path}`}`;
37
+ if (query && Object.keys(query).length > 0) {
38
+ const qs = new URLSearchParams(query).toString();
39
+ url += `?${qs}`;
40
+ }
41
+ let lastError = null;
42
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
43
+ const controller = new AbortController();
44
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
45
+ try {
46
+ const response = await fetch(url, {
47
+ method,
48
+ headers: {
49
+ "Authorization": `Bearer ${this.apiKey}`,
50
+ "Content-Type": "application/json",
51
+ "User-Agent": "Novapsis-SDK-Node/1.0.0"
52
+ },
53
+ body: body ? JSON.stringify(body) : void 0,
54
+ signal: controller.signal
55
+ });
56
+ clearTimeout(timeoutId);
57
+ const data = await response.json().catch(() => ({
58
+ success: false,
59
+ error: { code: "INVALID_JSON_RESPONSE", message: `HTTP ${response.status} Sin cuerpo JSON v\xE1lido.` }
60
+ }));
61
+ if (!response.ok || !data.success) {
62
+ throw new NovapsisAPIError(
63
+ data.error?.message || `Error en petici\xF3n HTTP ${response.status}`,
64
+ data.error?.code || `HTTP_${response.status}`,
65
+ response.status,
66
+ data.error?.details
67
+ );
68
+ }
69
+ return data.data;
70
+ } catch (err) {
71
+ clearTimeout(timeoutId);
72
+ lastError = err;
73
+ if (err instanceof NovapsisAPIError && err.status >= 400 && err.status < 500) {
74
+ throw err;
75
+ }
76
+ if (attempt === this.maxRetries) {
77
+ break;
78
+ }
79
+ await new Promise((resolve) => setTimeout(resolve, 300 * Math.pow(3, attempt)));
80
+ }
81
+ }
82
+ throw lastError || new NovapsisAPIError("Error de red al comunicarse con Novapsis API", "NETWORK_ERROR", 0);
83
+ }
84
+ };
85
+ var WhatsAppService = class {
86
+ constructor(http) {
87
+ this.http = http;
88
+ }
89
+ http;
90
+ /** EnvΓ­a un mensaje de texto plano */
91
+ async sendText(options) {
92
+ return this.http.request("POST", "/whatsapp/messages", {
93
+ recipient: options.to,
94
+ connection_id: options.connectionId,
95
+ type: "text",
96
+ text: options.text
97
+ });
98
+ }
99
+ /** EnvΓ­a una imagen o fotografΓ­a */
100
+ async sendImage(options) {
101
+ return this.http.request("POST", "/whatsapp/messages", {
102
+ recipient: options.to,
103
+ connection_id: options.connectionId,
104
+ type: "image",
105
+ media_url: options.imageUrl,
106
+ caption: options.caption
107
+ });
108
+ }
109
+ /** EnvΓ­a un archivo de audio o nota de voz */
110
+ async sendAudio(options) {
111
+ return this.http.request("POST", "/whatsapp/messages", {
112
+ recipient: options.to,
113
+ connection_id: options.connectionId,
114
+ type: "audio",
115
+ media_url: options.audioUrl
116
+ });
117
+ }
118
+ /** EnvΓ­a un documento (PDF, Word, Excel, etc.) con nombre de archivo personalizado */
119
+ async sendDocument(options) {
120
+ return this.http.request("POST", "/whatsapp/messages", {
121
+ recipient: options.to,
122
+ connection_id: options.connectionId,
123
+ type: "document",
124
+ media_url: options.documentUrl,
125
+ filename: options.filename,
126
+ caption: options.caption
127
+ });
128
+ }
129
+ /** EnvΓ­a un video */
130
+ async sendVideo(options) {
131
+ return this.http.request("POST", "/whatsapp/messages", {
132
+ recipient: options.to,
133
+ connection_id: options.connectionId,
134
+ type: "video",
135
+ media_url: options.videoUrl,
136
+ caption: options.caption
137
+ });
138
+ }
139
+ /** EnvΓ­a una ubicaciΓ³n con coordenadas y direcciΓ³n en el mapa */
140
+ async sendLocation(options) {
141
+ return this.http.request("POST", "/whatsapp/messages", {
142
+ recipient: options.to,
143
+ connection_id: options.connectionId,
144
+ type: "location",
145
+ latitude: options.latitude,
146
+ longitude: options.longitude,
147
+ location_name: options.name,
148
+ location_address: options.address
149
+ });
150
+ }
151
+ /** EnvΓ­a una tarjeta de contacto (vCard) interactiva */
152
+ async sendContact(options) {
153
+ return this.http.request("POST", "/whatsapp/messages", {
154
+ recipient: options.to,
155
+ connection_id: options.connectionId,
156
+ type: "contacts",
157
+ contact_name: options.name,
158
+ contact_phone: options.phone
159
+ });
160
+ }
161
+ /** EnvΓ­a una plantilla oficial aprobada por Meta con variables dinΓ‘micas */
162
+ async sendTemplate(options) {
163
+ return this.http.request("POST", "/whatsapp/messages", {
164
+ recipient: options.to,
165
+ connection_id: options.connectionId,
166
+ type: "template",
167
+ template_name: options.templateName,
168
+ language_code: options.languageCode || "es",
169
+ components: options.components || []
170
+ });
171
+ }
172
+ /** Marca un mensaje o chat como leΓ­do */
173
+ async markAsRead(options) {
174
+ return this.http.request("POST", "/whatsapp/messages", {
175
+ recipient: options.to,
176
+ connection_id: options.connectionId,
177
+ type: "mark_read",
178
+ message_id: options.messageId
179
+ });
180
+ }
181
+ /** Obtiene la lista de lΓ­neas y nΓΊmeros de WhatsApp conectados en la organizaciΓ³n */
182
+ async listConnections() {
183
+ const res = await this.http.request("GET", "/whatsapp/connections");
184
+ return res.connections;
185
+ }
186
+ /** Obtiene las plantillas oficiales de Meta aprobadas */
187
+ async getTemplates() {
188
+ const res = await this.http.request("GET", "/whatsapp/templates");
189
+ return res.templates;
190
+ }
191
+ /** Crea una nueva plantilla para enviar a revisiΓ³n a Meta */
192
+ async createTemplate(options) {
193
+ return this.http.request("POST", "/whatsapp/templates", {
194
+ name: options.name,
195
+ category: options.category,
196
+ components: [{ type: "BODY", text: options.bodyText }]
197
+ });
198
+ }
199
+ /** Lista las campaΓ±as masivas de WhatsApp configuradas */
200
+ async listCampaigns() {
201
+ const res = await this.http.request("GET", "/whatsapp/campaigns");
202
+ return res.campaigns;
203
+ }
204
+ /** Ejecuta una campaΓ±a masiva */
205
+ async executeCampaign(campaignId) {
206
+ return this.http.request("POST", `/whatsapp/campaigns/${campaignId}/execute`);
207
+ }
208
+ };
209
+ var OnboardingService = class {
210
+ constructor(http) {
211
+ this.http = http;
212
+ }
213
+ http;
214
+ /**
215
+ * Crea una sesiΓ³n de conexiΓ³n hosted para que un cliente o sede vincule su WhatsApp.
216
+ * Devuelve `session_url` que puedes abrir en un modal o popup en tu CRM.
217
+ */
218
+ async createSession(options = {}) {
219
+ return this.http.request("POST", "/onboarding/sessions", {
220
+ client_name: options.clientName,
221
+ redirect_url: options.redirectUrl,
222
+ logo_url: options.logoUrl,
223
+ brand_color: options.brandColor,
224
+ metadata: options.metadata
225
+ });
226
+ }
227
+ /** Consulta el estado de una sesiΓ³n de onboarding por su ID */
228
+ async getSessionStatus(sessionId) {
229
+ return this.http.request("GET", `/onboarding/sessions/${sessionId}`);
230
+ }
231
+ };
232
+ var WebhookService = class {
233
+ constructor(http) {
234
+ this.http = http;
235
+ }
236
+ http;
237
+ /** Suscribe una URL de tu backend para recibir eventos en tiempo real */
238
+ async subscribe(options) {
239
+ return this.http.request("POST", "/webhooks/subscriptions", {
240
+ name: options.name,
241
+ url: options.url,
242
+ events: options.events,
243
+ secret: options.secret,
244
+ is_active: true
245
+ });
246
+ }
247
+ /** Lista todas las suscripciones de webhooks activas */
248
+ async list() {
249
+ const res = await this.http.request("GET", "/webhooks/subscriptions");
250
+ return res.subscriptions;
251
+ }
252
+ /** Elimina una suscripciΓ³n de webhook */
253
+ async delete(webhookId) {
254
+ const res = await this.http.request("DELETE", `/webhooks/subscriptions/${webhookId}`);
255
+ return res.success;
256
+ }
257
+ /**
258
+ * Valida la firma criptogrΓ‘fica HMAC SHA-256 de un webhook recibido de Novapsis SM.
259
+ * Evita ataques de suplantaciΓ³n garantizando que la peticiΓ³n proviene de Novapsis.
260
+ *
261
+ * @param rawBody - El cuerpo crudo recibido en el request (string sin parsear)
262
+ * @param signatureHeader - El header 'X-Novapsis-Signature'
263
+ * @param secret - Tu secreto de webhook de Novapsis
264
+ */
265
+ verifySignature(rawBody, signatureHeader, secret) {
266
+ if (!signatureHeader || !secret || !rawBody) return false;
267
+ try {
268
+ const computed = crypto__default.default.createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
269
+ return crypto__default.default.timingSafeEqual(Buffer.from(computed), Buffer.from(signatureHeader));
270
+ } catch {
271
+ return false;
272
+ }
273
+ }
274
+ };
275
+ var ContactsService = class {
276
+ constructor(http) {
277
+ this.http = http;
278
+ }
279
+ http;
280
+ /** Lista contactos del CRM */
281
+ async list() {
282
+ const res = await this.http.request("GET", "/contacts");
283
+ return res.contacts;
284
+ }
285
+ /** Crea o actualiza un contacto por nΓΊmero de telΓ©fono */
286
+ async upsert(options) {
287
+ return this.http.request("POST", "/contacts", options);
288
+ }
289
+ };
290
+ var AIService = class {
291
+ constructor(http) {
292
+ this.http = http;
293
+ }
294
+ http;
295
+ /** Lista los agentes de IA configurados con sus modelos */
296
+ async listAgents() {
297
+ const res = await this.http.request("GET", "/ai/agents");
298
+ return res.agents;
299
+ }
300
+ /** Ejecuta una consulta contra un agente de IA con su base de conocimiento RAG */
301
+ async execute(options) {
302
+ return this.http.request("POST", `/ai/agents/${options.agentId}/execute`, {
303
+ message: options.message
304
+ });
305
+ }
306
+ };
307
+ var Novapsis = class {
308
+ http;
309
+ /** MΓ©todos para envΓ­os y operaciones de WhatsApp */
310
+ whatsapp;
311
+ /** MΓ©todos para onboarding hosted y vinculaciΓ³n B2B */
312
+ onboarding;
313
+ /** MΓ©todos para suscripciΓ³n y validaciΓ³n de Webhooks */
314
+ webhooks;
315
+ /** MΓ©todos para contactos del CRM */
316
+ contacts;
317
+ /** MΓ©todos para Agentes de Inteligencia Artificial */
318
+ ai;
319
+ constructor(options) {
320
+ if (!options.apiKey) {
321
+ throw new NovapsisAPIError("Se requiere una apiKey v\xE1lida para inicializar el cliente de Novapsis.", "CONFIG_ERROR", 400);
322
+ }
323
+ this.http = new HttpClient(options);
324
+ this.whatsapp = new WhatsAppService(this.http);
325
+ this.onboarding = new OnboardingService(this.http);
326
+ this.webhooks = new WebhookService(this.http);
327
+ this.contacts = new ContactsService(this.http);
328
+ this.ai = new AIService(this.http);
329
+ }
330
+ };
331
+ var index_default = Novapsis;
332
+ /**
333
+ * novapsis - Official TypeScript / JavaScript SDK
334
+ * ══════════════════════════════════════════════════════════════════════════════
335
+ * Official SDK for Novapsis SM.
336
+ * Universal typed client for WhatsApp Business Cloud API, Hosted Onboarding,
337
+ * CRM, AI Agents and HMAC Webhook Verification.
338
+ *
339
+ * @version 1.0.0
340
+ * @author Novapsis Technologies
341
+ * @license MIT
342
+ * ══════════════════════════════════════════════════════════════════════════════
343
+ */
344
+
345
+ exports.AIService = AIService;
346
+ exports.ContactsService = ContactsService;
347
+ exports.Novapsis = Novapsis;
348
+ exports.NovapsisAPIError = NovapsisAPIError;
349
+ exports.OnboardingService = OnboardingService;
350
+ exports.WebhookService = WebhookService;
351
+ exports.WhatsAppService = WhatsAppService;
352
+ exports.default = index_default;
353
+ //# sourceMappingURL=index.cjs.map
354
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * novapsis - Official TypeScript / JavaScript SDK\n * ══════════════════════════════════════════════════════════════════════════════\n * Official SDK for Novapsis SM.\n * Universal typed client for WhatsApp Business Cloud API, Hosted Onboarding,\n * CRM, AI Agents and HMAC Webhook Verification.\n *\n * @version 1.0.0\n * @author Novapsis Technologies\n * @license MIT\n * ══════════════════════════════════════════════════════════════════════════════\n */\n\nimport crypto from 'crypto';\n\n// ── TYPES & DEFINITIONS ──────────────────────────────────────────────────────\n\nexport interface NovapsisClientOptions {\n /** Clave de API de Novapsis (empieza por nvs_live_ o nvs_test_) */\n apiKey: string;\n /** URL base de la API (por defecto: https://app.novapsis.com) */\n baseUrl?: string;\n /** Timeout en milisegundos para peticiones HTTP (por defecto: 15000) */\n timeoutMs?: number;\n /** NΓΊmero mΓ‘ximo de reintentos automΓ‘ticos ante fallos de red transitorios (por defecto: 2) */\n maxRetries?: number;\n}\n\nexport interface APIResponse<T = any> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n details?: any;\n };\n}\n\nexport class NovapsisAPIError extends Error {\n public readonly code: string;\n public readonly status: number;\n public readonly details?: any;\n\n constructor(message: string, code = 'API_ERROR', status = 500, details?: any) {\n super(message);\n this.name = 'NovapsisAPIError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\n// ── WHATSAPP TYPES ───────────────────────────────────────────────────────────\n\nexport interface SendBaseOptions {\n /** NΓΊmero destinatario con cΓ³digo de paΓ­s, sin '+' ni espacios (ej: '34600112233') */\n to: string;\n /** UUID de la conexiΓ³n o Phone Number ID de Meta desde el cual enviar. Si se omite, usa la lΓ­nea principal. */\n connectionId?: string;\n}\n\nexport interface SendTextOptions extends SendBaseOptions {\n /** Cuerpo del mensaje de texto */\n text: string;\n /** Si es true, genera vista previa de los enlaces web incluidos en el texto */\n previewUrl?: boolean;\n}\n\nexport interface SendImageOptions extends SendBaseOptions {\n /** URL HTTPS pΓΊblica de la imagen (JPG, PNG, WebP) */\n imageUrl: string;\n /** Pie de foto opcional */\n caption?: string;\n}\n\nexport interface SendAudioOptions extends SendBaseOptions {\n /** URL HTTPS pΓΊblica del archivo de audio (MP3, AAC, OGG, M4A) */\n audioUrl: string;\n}\n\nexport interface SendDocumentOptions extends SendBaseOptions {\n /** URL HTTPS pΓΊblica del documento o PDF */\n documentUrl: string;\n /** Nombre visible del archivo (ej: 'factura_2026.pdf') */\n filename?: string;\n /** DescripciΓ³n o pie opcional */\n caption?: string;\n}\n\nexport interface SendVideoOptions extends SendBaseOptions {\n /** URL HTTPS pΓΊblica del video (MP4, 3GP) */\n videoUrl: string;\n /** Pie de video opcional */\n caption?: string;\n}\n\nexport interface SendLocationOptions extends SendBaseOptions {\n /** Coordenada de latitud decimal (ej: 40.416775) */\n latitude: number | string;\n /** Coordenada de longitud decimal (ej: -3.703790) */\n longitude: number | string;\n /** Nombre del lugar o establecimiento (ej: 'Sede Central Madrid') */\n name?: string;\n /** DirecciΓ³n postal completa */\n address?: string;\n}\n\nexport interface SendContactCardOptions extends SendBaseOptions {\n /** Nombre completo del contacto a compartir */\n name: string;\n /** NΓΊmero de telΓ©fono del contacto compartido */\n phone: string;\n}\n\nexport interface SendTemplateOptions extends SendBaseOptions {\n /** Nombre exacto de la plantilla aprobada en Meta */\n templateName: string;\n /** CΓ³digo de idioma (por defecto: 'es') */\n languageCode?: string;\n /** Componentes y variables dinΓ‘micas de la plantilla */\n components?: Array<{\n type: 'header' | 'body' | 'button';\n sub_type?: string;\n index?: string | number;\n parameters?: Array<{\n type: 'text' | 'image' | 'document' | 'video' | 'currency' | 'date_time';\n text?: string;\n [key: string]: any;\n }>;\n }>;\n}\n\nexport interface SendMessageResult {\n message_id: string;\n recipient: string;\n type: string;\n status: string;\n conversation_id: string | null;\n}\n\nexport interface WhatsAppConnection {\n id: string;\n display_name: string;\n phone_number: string | null;\n phone_number_id: string;\n verified_name: string | null;\n status: string;\n webhook_subscribed: boolean;\n}\n\nexport interface WhatsAppTemplate {\n id: string;\n name: string;\n category: string;\n language: string;\n status: string;\n components: any[];\n}\n\n// ── ONBOARDING TYPES ─────────────────────────────────────────────────────────\n\nexport interface CreateOnboardingSessionOptions {\n /** Nombre de la empresa, cliente o sede a mostrar en la pantalla de conexiΓ³n */\n clientName?: string;\n /** URL de retorno a la que redirigir al usuario cuando vincule su WhatsApp */\n redirectUrl?: string;\n /** URL del logotipo de la empresa cliente para marca blanca */\n logoUrl?: string;\n /** Color hexadecimal corporativo para la interfaz de conexiΓ³n (ej: '#0ea5e9') */\n brandColor?: string;\n /** Metadata personalizada para tracking en tu CRM */\n metadata?: Record<string, any>;\n}\n\nexport interface OnboardingSession {\n id: string;\n session_id: string;\n session_url: string;\n status: 'started' | 'completed' | 'expired' | 'failed';\n expires_at: string;\n created_at: string;\n}\n\n// ── WEBHOOK TYPES ────────────────────────────────────────────────────────────\n\nexport type NovapsisWebhookEvent =\n | 'whatsapp.message_received'\n | 'whatsapp.message_sent'\n | 'whatsapp.connected'\n | 'conversation.started'\n | 'lead.completed'\n | 'call.completed'\n | 'review.received'\n | '*';\n\nexport interface CreateWebhookSubscriptionOptions {\n /** Nombre descriptivo de la suscripciΓ³n (ej: 'CRM Sincronizador') */\n name: string;\n /** URL HTTPS de tu backend que recibirΓ‘ los eventos POST */\n url: string;\n /** Lista de eventos a escuchar */\n events: NovapsisWebhookEvent[];\n /** Secreto opcional para firma HMAC. Si se omite, Novapsis generarΓ‘ uno automΓ‘ticamente. */\n secret?: string;\n}\n\nexport interface WebhookSubscription {\n id: string;\n name: string;\n url: string;\n events: string[];\n secret: string;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface InboundWebhookPayload<T = any> {\n event: NovapsisWebhookEvent;\n timestamp: string;\n organization_id: string;\n data: T;\n}\n\n// ── CRM & CONTACTS TYPES ─────────────────────────────────────────────────────\n\nexport interface UpsertContactOptions {\n phone: string;\n name?: string;\n email?: string;\n tags?: string[];\n metadata?: Record<string, any>;\n}\n\nexport interface Contact {\n id: string;\n phone: string;\n name: string | null;\n email: string | null;\n tags: string[];\n created_at: string;\n}\n\n// ── INTERNAL HTTP CLIENT ────────────────────────────────────────────────────\n\nclass HttpClient {\n private apiKey: string;\n private baseUrl: string;\n private timeoutMs: number;\n private maxRetries: number;\n\n constructor(options: NovapsisClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl || 'https://app.novapsis.com').replace(/\\/+$/, '');\n this.timeoutMs = options.timeoutMs || 15000;\n this.maxRetries = options.maxRetries ?? 2;\n }\n\n async request<T>(method: string, path: string, body?: any, query?: Record<string, string>): Promise<T> {\n let url = `${this.baseUrl}/api/v1${path.startsWith('/') ? path : `/${path}`}`;\n if (query && Object.keys(query).length > 0) {\n const qs = new URLSearchParams(query).toString();\n url += `?${qs}`;\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'Novapsis-SDK-Node/1.0.0',\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const data: APIResponse<T> = await response.json().catch(() => ({\n success: false,\n error: { code: 'INVALID_JSON_RESPONSE', message: `HTTP ${response.status} Sin cuerpo JSON vΓ‘lido.` },\n }));\n\n if (!response.ok || !data.success) {\n throw new NovapsisAPIError(\n data.error?.message || `Error en peticiΓ³n HTTP ${response.status}`,\n data.error?.code || `HTTP_${response.status}`,\n response.status,\n data.error?.details\n );\n }\n\n return data.data as T;\n } catch (err: any) {\n clearTimeout(timeoutId);\n lastError = err;\n\n // No reintentar errores de validaciΓ³n de cliente 4xx\n if (err instanceof NovapsisAPIError && err.status >= 400 && err.status < 500) {\n throw err;\n }\n\n // Si es el ΓΊltimo intento, lanzar el error\n if (attempt === this.maxRetries) {\n break;\n }\n\n // Backoff exponencial: 300ms, 900ms...\n await new Promise((resolve) => setTimeout(resolve, 300 * Math.pow(3, attempt)));\n }\n }\n\n throw lastError || new NovapsisAPIError('Error de red al comunicarse con Novapsis API', 'NETWORK_ERROR', 0);\n }\n}\n\n// ── SDK SERVICES ────────────────────────────────────────────────────────────\n\n/** Servicio para envΓ­os y gestiΓ³n de WhatsApp Cloud API */\nexport class WhatsAppService {\n constructor(private http: HttpClient) {}\n\n /** EnvΓ­a un mensaje de texto plano */\n async sendText(options: SendTextOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'text',\n text: options.text,\n });\n }\n\n /** EnvΓ­a una imagen o fotografΓ­a */\n async sendImage(options: SendImageOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'image',\n media_url: options.imageUrl,\n caption: options.caption,\n });\n }\n\n /** EnvΓ­a un archivo de audio o nota de voz */\n async sendAudio(options: SendAudioOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'audio',\n media_url: options.audioUrl,\n });\n }\n\n /** EnvΓ­a un documento (PDF, Word, Excel, etc.) con nombre de archivo personalizado */\n async sendDocument(options: SendDocumentOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'document',\n media_url: options.documentUrl,\n filename: options.filename,\n caption: options.caption,\n });\n }\n\n /** EnvΓ­a un video */\n async sendVideo(options: SendVideoOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'video',\n media_url: options.videoUrl,\n caption: options.caption,\n });\n }\n\n /** EnvΓ­a una ubicaciΓ³n con coordenadas y direcciΓ³n en el mapa */\n async sendLocation(options: SendLocationOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'location',\n latitude: options.latitude,\n longitude: options.longitude,\n location_name: options.name,\n location_address: options.address,\n });\n }\n\n /** EnvΓ­a una tarjeta de contacto (vCard) interactiva */\n async sendContact(options: SendContactCardOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'contacts',\n contact_name: options.name,\n contact_phone: options.phone,\n });\n }\n\n /** EnvΓ­a una plantilla oficial aprobada por Meta con variables dinΓ‘micas */\n async sendTemplate(options: SendTemplateOptions): Promise<SendMessageResult> {\n return this.http.request<SendMessageResult>('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'template',\n template_name: options.templateName,\n language_code: options.languageCode || 'es',\n components: options.components || [],\n });\n }\n\n /** Marca un mensaje o chat como leΓ­do */\n async markAsRead(options: { to: string; connectionId?: string; messageId?: string }): Promise<any> {\n return this.http.request('POST', '/whatsapp/messages', {\n recipient: options.to,\n connection_id: options.connectionId,\n type: 'mark_read',\n message_id: options.messageId,\n });\n }\n\n /** Obtiene la lista de lΓ­neas y nΓΊmeros de WhatsApp conectados en la organizaciΓ³n */\n async listConnections(): Promise<WhatsAppConnection[]> {\n const res = await this.http.request<{ connections: WhatsAppConnection[] }>('GET', '/whatsapp/connections');\n return res.connections;\n }\n\n /** Obtiene las plantillas oficiales de Meta aprobadas */\n async getTemplates(): Promise<WhatsAppTemplate[]> {\n const res = await this.http.request<{ templates: WhatsAppTemplate[] }>('GET', '/whatsapp/templates');\n return res.templates;\n }\n\n /** Crea una nueva plantilla para enviar a revisiΓ³n a Meta */\n async createTemplate(options: {\n name: string;\n category: 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';\n bodyText: string;\n }): Promise<any> {\n return this.http.request('POST', '/whatsapp/templates', {\n name: options.name,\n category: options.category,\n components: [{ type: 'BODY', text: options.bodyText }],\n });\n }\n\n /** Lista las campaΓ±as masivas de WhatsApp configuradas */\n async listCampaigns(): Promise<any[]> {\n const res = await this.http.request<{ campaigns: any[] }>('GET', '/whatsapp/campaigns');\n return res.campaigns;\n }\n\n /** Ejecuta una campaΓ±a masiva */\n async executeCampaign(campaignId: string): Promise<any> {\n return this.http.request('POST', `/whatsapp/campaigns/${campaignId}/execute`);\n }\n}\n\n/** Servicio para onboarding y conexiΓ³n de WhatsApp de clientes B2B (Marca Blanca) */\nexport class OnboardingService {\n constructor(private http: HttpClient) {}\n\n /**\n * Crea una sesiΓ³n de conexiΓ³n hosted para que un cliente o sede vincule su WhatsApp.\n * Devuelve `session_url` que puedes abrir en un modal o popup en tu CRM.\n */\n async createSession(options: CreateOnboardingSessionOptions = {}): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('POST', '/onboarding/sessions', {\n client_name: options.clientName,\n redirect_url: options.redirectUrl,\n logo_url: options.logoUrl,\n brand_color: options.brandColor,\n metadata: options.metadata,\n });\n }\n\n /** Consulta el estado de una sesiΓ³n de onboarding por su ID */\n async getSessionStatus(sessionId: string): Promise<OnboardingSession> {\n return this.http.request<OnboardingSession>('GET', `/onboarding/sessions/${sessionId}`);\n }\n}\n\n/** Servicio para gestionar Webhooks salientes en tiempo real */\nexport class WebhookService {\n constructor(private http: HttpClient) {}\n\n /** Suscribe una URL de tu backend para recibir eventos en tiempo real */\n async subscribe(options: CreateWebhookSubscriptionOptions): Promise<WebhookSubscription> {\n return this.http.request<WebhookSubscription>('POST', '/webhooks/subscriptions', {\n name: options.name,\n url: options.url,\n events: options.events,\n secret: options.secret,\n is_active: true,\n });\n }\n\n /** Lista todas las suscripciones de webhooks activas */\n async list(): Promise<WebhookSubscription[]> {\n const res = await this.http.request<{ subscriptions: WebhookSubscription[] }>('GET', '/webhooks/subscriptions');\n return res.subscriptions;\n }\n\n /** Elimina una suscripciΓ³n de webhook */\n async delete(webhookId: string): Promise<boolean> {\n const res = await this.http.request<{ success: boolean }>('DELETE', `/webhooks/subscriptions/${webhookId}`);\n return res.success;\n }\n\n /**\n * Valida la firma criptogrΓ‘fica HMAC SHA-256 de un webhook recibido de Novapsis SM.\n * Evita ataques de suplantaciΓ³n garantizando que la peticiΓ³n proviene de Novapsis.\n *\n * @param rawBody - El cuerpo crudo recibido en el request (string sin parsear)\n * @param signatureHeader - El header 'X-Novapsis-Signature'\n * @param secret - Tu secreto de webhook de Novapsis\n */\n verifySignature(rawBody: string, signatureHeader: string | null | undefined, secret: string): boolean {\n if (!signatureHeader || !secret || !rawBody) return false;\n try {\n const computed = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');\n return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signatureHeader));\n } catch {\n return false;\n }\n }\n}\n\n/** Servicio para gestionar Contactos del CRM */\nexport class ContactsService {\n constructor(private http: HttpClient) {}\n\n /** Lista contactos del CRM */\n async list(): Promise<Contact[]> {\n const res = await this.http.request<{ contacts: Contact[] }>('GET', '/contacts');\n return res.contacts;\n }\n\n /** Crea o actualiza un contacto por nΓΊmero de telΓ©fono */\n async upsert(options: UpsertContactOptions): Promise<Contact> {\n return this.http.request<Contact>('POST', '/contacts', options);\n }\n}\n\n/** Servicio para interactuar con Agentes de Inteligencia Artificial */\nexport class AIService {\n constructor(private http: HttpClient) {}\n\n /** Lista los agentes de IA configurados con sus modelos */\n async listAgents(): Promise<any[]> {\n const res = await this.http.request<{ agents: any[] }>('GET', '/ai/agents');\n return res.agents;\n }\n\n /** Ejecuta una consulta contra un agente de IA con su base de conocimiento RAG */\n async execute(options: { agentId: string; message: string }): Promise<{ response: string; tokens_used?: number }> {\n return this.http.request('POST', `/ai/agents/${options.agentId}/execute`, {\n message: options.message,\n });\n }\n}\n\n// ── MAIN CLIENT ─────────────────────────────────────────────────────────────\n\n/**\n * Cliente oficial de Novapsis SM.\n * Punto de entrada principal para interactuar con todos los servicios.\n *\n * @example\n * ```typescript\n * import { Novapsis } from 'novapsis';\n *\n * const client = new Novapsis({\n * apiKey: 'nvs_live_OfnAAb6sEGztGcdbR5IKnhFpPrDJSTq7',\n * });\n *\n * // Enviar mensaje de texto\n * await client.whatsapp.sendText({\n * to: '34600112233',\n * text: 'Β‘Hola desde Novapsis SDK!'\n * });\n * ```\n */\nexport class Novapsis {\n private http: HttpClient;\n\n /** MΓ©todos para envΓ­os y operaciones de WhatsApp */\n public readonly whatsapp: WhatsAppService;\n /** MΓ©todos para onboarding hosted y vinculaciΓ³n B2B */\n public readonly onboarding: OnboardingService;\n /** MΓ©todos para suscripciΓ³n y validaciΓ³n de Webhooks */\n public readonly webhooks: WebhookService;\n /** MΓ©todos para contactos del CRM */\n public readonly contacts: ContactsService;\n /** MΓ©todos para Agentes de Inteligencia Artificial */\n public readonly ai: AIService;\n\n constructor(options: NovapsisClientOptions) {\n if (!options.apiKey) {\n throw new NovapsisAPIError('Se requiere una apiKey vΓ‘lida para inicializar el cliente de Novapsis.', 'CONFIG_ERROR', 400);\n }\n this.http = new HttpClient(options);\n this.whatsapp = new WhatsAppService(this.http);\n this.onboarding = new OnboardingService(this.http);\n this.webhooks = new WebhookService(this.http);\n this.contacts = new ContactsService(this.http);\n this.ai = new AIService(this.http);\n }\n}\n\n// Default export\nexport default Novapsis;\n"]}