botversion-sdk 1.0.4 → 1.0.5

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/index.js CHANGED
@@ -10,15 +10,6 @@ var BotVersion = {
10
10
  _initialized: false,
11
11
 
12
12
  init: function (appOrOptions, optionsArg) {
13
- console.log("=== INIT CALLED ===");
14
- console.log("appOrOptions type:", typeof appOrOptions);
15
- console.log(
16
- "appOrOptions is express app:",
17
- appOrOptions && typeof appOrOptions.use === "function",
18
- );
19
- console.log("optionsArg type:", typeof optionsArg);
20
- console.log("optionsArg value:", JSON.stringify(optionsArg));
21
- console.log("===================");
22
13
  var app = null;
23
14
  var options = {};
24
15
 
@@ -35,7 +26,6 @@ var BotVersion = {
35
26
  app = null;
36
27
  }
37
28
 
38
- console.log("options received:", JSON.stringify(options));
39
29
  if (!options.apiKey) {
40
30
  console.error("[BotVersion SDK] ❌ apiKey is required.");
41
31
  return;
@@ -61,7 +51,7 @@ var BotVersion = {
61
51
 
62
52
  this._client = new BotVersionClient({
63
53
  apiKey: options.apiKey,
64
- platformUrl: options.platformUrl || "https://chatbusiness-two.vercel.app",
54
+ platformUrl: options.platformUrl || "http://localhost:3000",
65
55
  debug: options.debug || false,
66
56
  timeout: options.timeout || 30000,
67
57
  });
@@ -92,9 +82,6 @@ var BotVersion = {
92
82
  console.error(
93
83
  "[BotVersion SDK] ❌ Currently supports Express and Next.js only.",
94
84
  );
95
- console.error(
96
- "[BotVersion SDK] ❌ Visit https://docs.botversion.com for supported frameworks.",
97
- );
98
85
  return;
99
86
  }
100
87
  if (debug) {
@@ -111,7 +98,6 @@ var BotVersion = {
111
98
  exclude: options.exclude || [],
112
99
  apiPrefix: options.apiPrefix || null,
113
100
  debug: debug,
114
- getUserContext: options.getUserContext || null,
115
101
  });
116
102
  if (debug) {
117
103
  console.log("[BotVersion SDK] ✅ Runtime interceptor attached");
@@ -128,68 +114,78 @@ var BotVersion = {
128
114
  setTimeout(function () {
129
115
  var endpoints = [];
130
116
 
117
+ // Express scan
131
118
  // Express scan
132
119
  if (app) {
133
120
  console.log("[BotVersion SDK] Scanning Express routes...");
134
- endpoints = scanner.scanExpressRoutes(app);
121
+ var cwd = options.cwd || process.cwd();
122
+ endpoints = scanner.scanExpressRoutes(app, cwd);
135
123
  console.log(
136
124
  "[BotVersion SDK] Found",
137
125
  endpoints.length,
138
126
  "Express routes",
139
127
  );
140
- console.log(
141
- "[BotVersion SDK] Endpoints:",
142
- JSON.stringify(endpoints, null, 2),
143
- );
144
128
 
145
129
  if (endpoints.length === 0) {
146
130
  console.warn("[BotVersion SDK] ⚠ No endpoints found.");
147
131
  console.warn(
148
132
  "[BotVersion SDK] ⚠ Make sure routes are defined BEFORE BotVersion.init()",
149
133
  );
150
- console.warn(
151
- "[BotVersion SDK] ⚠ and BotVersion.init() is called BEFORE app.listen().",
152
- );
153
134
  }
154
135
  }
155
136
 
156
- // Next.js scan — runs if pagesDir is provided (with or without app)
157
- if (options.pagesDir) {
158
- console.log(
159
- "[BotVersion SDK] Scanning Next.js API routes...",
160
- options.pagesDir,
161
- );
162
- var nextRoutes = scanner.scanNextJsRoutes(options.pagesDir);
163
- endpoints = endpoints.concat(nextRoutes);
164
- console.log(
165
- "[BotVersion SDK] Found",
166
- nextRoutes.length,
167
- "Next.js routes",
168
- );
169
- console.log(
170
- "[BotVersion SDK] Next.js routes:",
171
- JSON.stringify(nextRoutes, null, 2),
172
- );
137
+ // Next.js scan
138
+ // Next.js scan — auto detect all possible structures
139
+ if (!app) {
140
+ const fs = require("fs");
141
+ const path = require("path");
142
+ const cwd = process.cwd();
173
143
 
174
- if (nextRoutes.length === 0) {
175
- console.warn("[BotVersion SDK] ⚠ No Next.js routes found.");
176
- console.warn(
177
- "[BotVersion SDK] ⚠ Make sure pagesDir points to your pages folder.",
178
- );
179
- console.warn(
180
- "[BotVersion SDK] ⚠ Example: pagesDir: path.join(process.cwd(), 'pages')",
181
- );
144
+ const possibleAppDirs = [
145
+ path.join(cwd, "app"),
146
+ path.join(cwd, "src", "app"),
147
+ ];
148
+
149
+ const possiblePagesDirs = [
150
+ path.join(cwd, "pages"),
151
+ path.join(cwd, "src", "pages"),
152
+ ];
153
+
154
+ for (const dir of possibleAppDirs) {
155
+ if (fs.existsSync(dir)) {
156
+ console.log("[BotVersion SDK] Scanning App Router routes at:", dir);
157
+ const routes = scanner.scanNextJsAppRoutes(dir);
158
+ endpoints = endpoints.concat(routes);
159
+ console.log(
160
+ "[BotVersion SDK] Found",
161
+ routes.length,
162
+ "App Router routes",
163
+ );
164
+ }
165
+ }
166
+
167
+ for (const dir of possiblePagesDirs) {
168
+ if (fs.existsSync(dir)) {
169
+ console.log(
170
+ "[BotVersion SDK] Scanning Pages Router routes at:",
171
+ dir,
172
+ );
173
+ const routes = scanner.scanNextJsRoutes(dir);
174
+ endpoints = endpoints.concat(routes);
175
+ console.log(
176
+ "[BotVersion SDK] Found",
177
+ routes.length,
178
+ "Pages Router routes",
179
+ );
180
+ }
182
181
  }
183
182
  }
184
183
 
185
184
  // Neither Express nor pagesDir
186
- if (!app && !options.pagesDir) {
187
- console.error("[BotVersion SDK] ❌ No routes to scan.");
185
+ // Neither Express nor Next.js routes found
186
+ if (!app && endpoints.length === 0) {
188
187
  console.error(
189
- "[BotVersion SDK] ❌ For Express: pass your app object — BotVersion.init(app, options)",
190
- );
191
- console.error(
192
- "[BotVersion SDK] ❌ For Next.js: pass pagesDir — BotVersion.init({ apiKey, pagesDir: path.join(process.cwd(), 'pages') })",
188
+ "[BotVersion SDK] ❌ No routes found. Make sure your app/api or pages/api folder exists.",
193
189
  );
194
190
  return;
195
191
  }
@@ -218,6 +214,29 @@ var BotVersion = {
218
214
  });
219
215
  }
220
216
 
217
+ var routePatterns = scanner.scanFrontendRoutes(
218
+ options.cwd || process.cwd(),
219
+ );
220
+ if (routePatterns.length > 0) {
221
+ console.log(
222
+ "[BotVersion SDK] Found",
223
+ routePatterns.length,
224
+ "frontend route patterns",
225
+ );
226
+ self._client
227
+ .registerRoutePatterns(routePatterns)
228
+ .then(function () {
229
+ console.log("[BotVersion SDK] ✅ Route patterns registered");
230
+ })
231
+ .catch(function (err) {
232
+ console.error(
233
+ "[BotVersion SDK] ❌ Failed to register route patterns:",
234
+ err.message,
235
+ );
236
+ });
237
+ }
238
+
239
+ self._client.connect();
221
240
  console.log("[BotVersion SDK] ✅ Initialization complete");
222
241
  }, 500);
223
242
  },
@@ -239,355 +258,18 @@ var BotVersion = {
239
258
  }
240
259
  return this._client.registerEndpoints([endpoint]);
241
260
  },
242
-
243
- chat: function (req, res) {
244
- if (!this._client) {
245
- return res.status(500).json({ error: "BotVersion SDK not initialized." });
246
- }
247
-
248
- var getUserContext = this._options && this._options.getUserContext;
249
- var userContext = getUserContext
250
- ? getUserContext(req)
251
- : extractDefaultContext(req);
252
-
253
- this._client
254
- .agentChat({
255
- message: req.body.message,
256
- conversationHistory: req.body.conversationHistory || [],
257
- pageContext: req.body.pageContext || {},
258
- userContext: userContext,
259
- workspaceKey: this._options.apiKey,
260
- chatbotId: req.body.chatbotId,
261
- })
262
- .then(function (response) {
263
- return res.status(200).json(response);
264
- })
265
- .catch(function (err) {
266
- console.error("[BotVersion SDK] chat error:", err);
267
- return res.status(500).json({ error: "Agent error" });
268
- });
269
- },
270
261
  };
271
262
 
272
- function extractDefaultContext(req) {
273
- var user = req.user || (req.session && req.session.user) || {};
274
- var sensitiveKeys = [
275
- "password",
276
- "passwd",
277
- "pwd",
278
- "token",
279
- "accesstoken",
280
- "refreshtoken",
281
- "bearertoken",
282
- "secret",
283
- "privatesecret",
284
- "apikey",
285
- "api_key",
286
- "privatekey",
287
- "private_key",
288
- "signingkey",
289
- "hash",
290
- "passwordhash",
291
- "salt",
292
- "cvv",
293
- "ssn",
294
- "pin",
295
- "creditcard",
296
- "credit_card",
297
- "cardnumber",
298
- "card_number",
299
- "otp",
300
- "mfa",
301
- "totp",
302
- "image",
303
- "avatar",
304
- "photo",
305
- ];
306
-
307
- // Step 1: Flatten nested objects
308
- function flattenObject(obj, prefix) {
309
- prefix = prefix || "";
310
- var result = {};
311
- Object.keys(obj).forEach(function (key) {
312
- var value = obj[key];
313
- var fullKey = prefix ? prefix + "_" + key : key;
314
- if (value === null || value === undefined) return;
315
- if (typeof value === "object" && !Array.isArray(value)) {
316
- var nested = flattenObject(value, fullKey);
317
- Object.keys(nested).forEach(function (k) {
318
- result[k] = nested[k];
319
- });
320
- } else if (typeof value !== "object") {
321
- result[fullKey] = value;
322
- }
323
- });
324
- return result;
325
- }
326
-
327
- var flatUser = flattenObject(user);
328
-
329
- // Step 2: Strip sensitive keys
330
- var context = {};
331
- Object.keys(flatUser).forEach(function (key) {
332
- var isSensitive = sensitiveKeys.some(function (sk) {
333
- return key.toLowerCase().includes(sk);
334
- });
335
- if (!isSensitive) {
336
- context[key] = flatUser[key];
337
- }
338
- });
339
-
340
- // Step 3: Smart aliasing
341
- var idSuffixes = ["id", "key", "code", "ref", "slug", "uuid", "num", "no"];
342
- var cleanPrefixes = [
343
- "active",
344
- "current",
345
- "selected",
346
- "default",
347
- "my",
348
- "the",
349
- "this",
350
- ];
351
-
352
- Object.keys(context).forEach(function (key) {
353
- var lowerKey = key.toLowerCase();
354
- var isIdField = idSuffixes.some(function (suffix) {
355
- return lowerKey.endsWith(suffix);
356
- });
357
-
358
- if (isIdField && context[key]) {
359
- var cleanKey = key;
360
- cleanPrefixes.forEach(function (prefix) {
361
- var regex = new RegExp("^" + prefix, "i");
362
- if (regex.test(cleanKey)) {
363
- cleanKey = cleanKey.replace(regex, "");
364
- cleanKey = cleanKey.charAt(0).toLowerCase() + cleanKey.slice(1);
365
- }
366
- });
367
-
368
- if (cleanKey !== key && !context[cleanKey]) {
369
- context[cleanKey] = context[key];
370
- }
371
- }
372
- });
373
-
374
- return context;
375
- }
376
-
377
- // Named exports for both CJS and ESM
263
+ // Named exports
378
264
  BotVersion.init = BotVersion.init.bind(BotVersion);
379
265
  BotVersion.getEndpoints = BotVersion.getEndpoints.bind(BotVersion);
380
266
  BotVersion.registerEndpoint = BotVersion.registerEndpoint.bind(BotVersion);
381
- BotVersion.chat = BotVersion.chat.bind(BotVersion);
382
-
383
- BotVersion.nextHandler = function (options) {
384
- options = options || {};
385
- var self = this;
386
- var hasScanned = false;
387
-
388
- return async function handler(req, res) {
389
- // ── Initialize on first request if not already done ──
390
- if (!self._initialized || !self._client) {
391
- var apiKey = options.apiKey;
392
- if (!apiKey) {
393
- console.error(
394
- "[BotVersion SDK] ❌ apiKey is required in nextHandler options.",
395
- );
396
- return res
397
- .status(500)
398
- .json({ error: "BotVersion SDK not configured." });
399
- }
400
-
401
- self._client = new BotVersionClient({
402
- apiKey: apiKey,
403
- platformUrl:
404
- options.platformUrl || "https://chatbusiness-two.vercel.app",
405
- debug: options.debug || false,
406
- timeout: options.timeout || 30000,
407
- });
408
-
409
- global._botVersionClient = self._client;
410
- global._botVersionOptions = options;
411
- self._initialized = true;
412
- self._options = options;
413
-
414
- console.log("[BotVersion SDK] ✅ Initialized from nextHandler");
415
- }
416
-
417
- // Restore from global if hot reload lost the instance
418
- if (!self._client && global._botVersionClient) {
419
- self._client = global._botVersionClient;
420
- self._options = global._botVersionOptions;
421
- }
422
-
423
- // ── Handle the chat request ───────────────────────────────────────────
424
- var session = null;
425
- if (options.getSession) {
426
- session = await options.getSession(req, res);
427
- }
428
-
429
- req.user = (session && session.user) || {};
430
-
431
- var getUserContext =
432
- (self._options && self._options.getUserContext) ||
433
- function (req) {
434
- var user = req.user || {};
435
- var sensitiveKeys = [
436
- "password",
437
- "passwd",
438
- "pwd",
439
- "token",
440
- "accesstoken",
441
- "refreshtoken",
442
- "bearertoken",
443
- "secret",
444
- "privatesecret",
445
- "apikey",
446
- "api_key",
447
- "privatekey",
448
- "private_key",
449
- "signingkey",
450
- "hash",
451
- "passwordhash",
452
- "salt",
453
- "cvv",
454
- "ssn",
455
- "pin",
456
- "creditcard",
457
- "credit_card",
458
- "cardnumber",
459
- "card_number",
460
- "otp",
461
- "mfa",
462
- "totp",
463
- "image",
464
- "avatar",
465
- "photo",
466
- ];
467
-
468
- // Step 1: Flatten nested objects
469
- function flattenObject(obj, prefix) {
470
- prefix = prefix || "";
471
- var result = {};
472
- Object.keys(obj).forEach(function (key) {
473
- var value = obj[key];
474
- var fullKey = prefix ? prefix + "_" + key : key;
475
- if (value === null || value === undefined) return;
476
- if (typeof value === "object" && !Array.isArray(value)) {
477
- var nested = flattenObject(value, fullKey);
478
- Object.keys(nested).forEach(function (k) {
479
- result[k] = nested[k];
480
- });
481
- } else if (typeof value !== "object") {
482
- result[fullKey] = value;
483
- }
484
- });
485
- return result;
486
- }
487
-
488
- var flatUser = flattenObject(user);
489
-
490
- // Step 2: Strip sensitive keys
491
- var context = {};
492
- Object.keys(flatUser).forEach(function (key) {
493
- var isSensitive = sensitiveKeys.some(function (sk) {
494
- return key.toLowerCase().includes(sk);
495
- });
496
- if (!isSensitive) {
497
- context[key] = flatUser[key];
498
- }
499
- });
500
-
501
- // Step 3: Smart aliasing
502
- var idSuffixes = [
503
- "id",
504
- "key",
505
- "code",
506
- "ref",
507
- "slug",
508
- "uuid",
509
- "num",
510
- "no",
511
- ];
512
- var cleanPrefixes = [
513
- "active",
514
- "current",
515
- "selected",
516
- "default",
517
- "my",
518
- "the",
519
- "this",
520
- ];
521
-
522
- Object.keys(context).forEach(function (key) {
523
- var lowerKey = key.toLowerCase();
524
- var isIdField = idSuffixes.some(function (suffix) {
525
- return lowerKey.endsWith(suffix);
526
- });
527
-
528
- if (isIdField && context[key]) {
529
- var cleanKey = key;
530
- cleanPrefixes.forEach(function (prefix) {
531
- var regex = new RegExp("^" + prefix, "i");
532
- if (regex.test(cleanKey)) {
533
- cleanKey = cleanKey.replace(regex, "");
534
- cleanKey = cleanKey.charAt(0).toLowerCase() + cleanKey.slice(1);
535
- }
536
- });
537
-
538
- if (cleanKey !== key && !context[cleanKey]) {
539
- context[cleanKey] = context[key];
540
- }
541
- }
542
- });
543
-
544
- console.log("[BotVersion] userContext being sent:", context);
545
- return context;
546
- };
547
-
548
- return new Promise(function (resolve) {
549
- console.log("[BotVersion] req.body:", JSON.stringify(req.body));
550
- console.log("[BotVersion] chatbotId from body:", req.body.chatbotId);
551
- self._client
552
- .agentChat({
553
- message: req.body.message,
554
- conversationHistory: req.body.conversationHistory || [],
555
- pageContext: req.body.pageContext || {},
556
- userContext: getUserContext(req),
557
- chatbotId: req.body.chatbotId,
558
- publicKey: req.body.publicKey,
559
- })
560
- .then(function (response) {
561
- res.status(200).json(response);
562
- resolve();
563
- })
564
- .catch(function (err) {
565
- console.error("[BotVersion SDK] chat error:", err);
566
- res.status(500).json({ error: "Agent error" });
567
- resolve();
568
- });
569
- });
570
- };
571
- };
572
-
573
- BotVersion.nextHandler = BotVersion.nextHandler.bind(BotVersion);
574
-
575
- BotVersion.appRouterHandler = function () {
576
- throw new Error(
577
- "[BotVersion SDK] appRouterHandler is not supported. " +
578
- "Please run: npx botversion-sdk init --key YOUR_KEY --force " +
579
- "to regenerate the correct route file.",
580
- );
581
- };
582
267
 
583
268
  module.exports = BotVersion;
584
269
  module.exports.default = BotVersion;
585
270
  module.exports.init = BotVersion.init;
586
271
  module.exports.getEndpoints = BotVersion.getEndpoints;
587
272
  module.exports.registerEndpoint = BotVersion.registerEndpoint;
588
- module.exports.chat = BotVersion.chat;
589
- module.exports.nextHandler = BotVersion.nextHandler;
590
- module.exports.appRouterHandler = BotVersion.appRouterHandler;
591
273
 
592
274
  // ── Framework detection ──────────────────────────────────────────────────────
593
275
  function detectFramework(app) {