embeddedaichatux 1.9.0 → 2.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.
Files changed (2) hide show
  1. package/EmbeddedChat.js +117 -19
  2. package/package.json +1 -1
package/EmbeddedChat.js CHANGED
@@ -9,7 +9,7 @@
9
9
  this.isPreview = this.options.isPreview || false;
10
10
  this.locale = options.locale || 'en';
11
11
  this.previewParam = this.isPreview ? "?isPreview=true" : "";
12
- this.serverUrl = this.options.serverUrl || 'https://embedgpt.chat/';
12
+ this.serverUrl = this.options.serverUrl || 'https://app.bizdriver.ai/';
13
13
  this.height = options.height || 600; // Default height
14
14
  this.width = options.width || 320; // Default width
15
15
  this.marginBottom = options.marginBottom || 0;
@@ -18,6 +18,13 @@
18
18
  this.mouseInsideChat = false;
19
19
  this.hasRefreshed = false; // Flag to prevent endless loop
20
20
  this.conversationId = null;
21
+ this.userTokenProvider = options.userTokenProvider;
22
+
23
+ try {
24
+ this.targetOrigin = new URL(this.serverUrl).origin;
25
+ } catch {
26
+ this.targetOrigin = "*";
27
+ }
21
28
 
22
29
  // Determine transition styles
23
30
  const transitionStyle = this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : '';
@@ -70,40 +77,81 @@
70
77
  }
71
78
  }
72
79
 
73
- init() {
74
- this.updateIframes();
75
- this.addEventListeners();
80
+ async init() {
81
+ await this.updateIframes();
76
82
  }
77
83
 
78
84
  async updateIframes() {
79
- const cleanedServerUrl = this.serverUrl.endsWith('/') ? this.serverUrl.slice(0, -1) : this.serverUrl;
85
+ const cleanedServerUrl = this.serverUrl.endsWith('/')
86
+ ? this.serverUrl.slice(0, -1)
87
+ : this.serverUrl;
80
88
  const baseIframeUrl = `${cleanedServerUrl}/ChatUX/${this.chatId}`;
81
- const minimizedPositionStyle = `position: fixed; right: 0; bottom: 0; width: ${this.width}px; height: ${this.minimizedHeight}; z-index: 100000; ${this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : ''}`;
89
+ const minimizedPositionStyle = `
90
+ position: fixed; right: 0; bottom: 0;
91
+ width: ${this.width}px;
92
+ height: ${this.minimizedHeight};
93
+ z-index: 100000;
94
+ ${this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : ''}
95
+ `;
96
+
97
+ const params = {
98
+ isPreview: this.isPreview,
99
+ mode: this.mode,
100
+ locale: this.locale,
101
+ conversationId: this.conversationId
102
+ };
82
103
 
83
104
  const iframeHtml = `
84
- <iframe id="embedded-chat" style="${this.positionStyle}; display: none; border:none; overflow:hidden;" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation-by-user-activation" src="${this.buildIframeUrl(baseIframeUrl, { isPreview: this.isPreview, mode: this.mode, locale: this.locale, conversationId: this.conversationId })}"></iframe>
85
- <iframe id="embedded-chat-minimized" style="${minimizedPositionStyle}; display: none; border:none; overflow:hidden;" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src="${this.buildIframeUrl(baseIframeUrl, { isPreview: this.isPreview, isMinimized: true, locale: this.locale, conversationId: this.conversationId })}"></iframe>
86
- `;
87
-
105
+ <iframe
106
+ id="embedded-chat"
107
+ style="${this.positionStyle}; display: none; border:none; overflow:hidden;"
108
+ frameborder="0"
109
+ sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation-by-user-activation"
110
+ src="${this.buildIframeUrl(baseIframeUrl, params)}"
111
+ ></iframe>
112
+ <iframe
113
+ id="embedded-chat-minimized"
114
+ style="${minimizedPositionStyle}; display: none; border:none; overflow:hidden;"
115
+ frameborder="0"
116
+ sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
117
+ src="${this.buildIframeUrl(baseIframeUrl, { ...params, isMinimized: true })}"
118
+ ></iframe>
119
+ `;
120
+
121
+ // inject and capture references
88
122
  this.containerDiv.innerHTML = iframeHtml;
89
- this.iframe = this.containerDiv.querySelector("#embedded-chat");
90
- this.minimizedIframe = this.containerDiv.querySelector("#embedded-chat-minimized");
123
+ this.iframe = this.containerDiv.querySelector('#embedded-chat');
124
+ this.minimizedIframe = this.containerDiv.querySelector('#embedded-chat-minimized');
91
125
 
126
+ // wait for the real <iframe> element to load
92
127
  await this.waitForIframeLoad(this.iframe);
93
128
 
129
+ // now that this.iframe & this.minimizedIframe exist, hook up events
130
+ this.addEventListeners();
131
+
132
+ // Send auth to iframes after load
133
+ await this.postAuthToIframes();
134
+
135
+ // restore your ContactForm logic
94
136
  if (this.mode === 'ContactForm') {
95
- this.iframe.style.maxWidth = "100%";
96
- this.iframe.style.display = "block";
137
+ this.iframe.style.maxWidth = '100%';
138
+ this.iframe.style.display = 'block';
97
139
  }
98
140
  }
99
141
 
100
142
  addEventListeners() {
143
+ if (!this.iframe || !this.minimizedIframe) {
144
+ console.error('EmbeddedChat: iframe or minimizedIframe is not defined when trying to add event listeners.', this.iframe, this.minimizedIframe);
145
+ return;
146
+ }
101
147
  this.iframe.addEventListener("mouseenter", () => { this.mouseInsideChat = true; });
102
148
  this.iframe.addEventListener("mouseleave", () => { this.mouseInsideChat = false; });
103
149
  this.minimizedIframe.addEventListener("mouseenter", () => { this.mouseInsideChat = true; });
104
150
  this.minimizedIframe.addEventListener("mouseleave", () => { this.mouseInsideChat = false; });
105
151
 
106
152
  window.addEventListener("message", (e) => {
153
+ // Only trust messages from our server (when targetOrigin is not "*")
154
+ if (this.targetOrigin !== "*" && e.origin !== this.targetOrigin) return;
107
155
  this.handleMessage(e);
108
156
  });
109
157
 
@@ -128,11 +176,26 @@
128
176
  message: "resize",
129
177
  width: window.innerWidth, // Ensure correct size
130
178
  height: window.innerHeight
131
- }, "*");
179
+ }, this.targetOrigin);
132
180
  }
133
181
  }
134
182
 
135
183
  handleMessage(e) {
184
+ console.log('[EmbeddedChat] Received message:', {
185
+ origin: e.origin,
186
+ type: e.data?.type,
187
+ message: e.data?.message,
188
+ chatId: e.data?.chatId,
189
+ data: e.data
190
+ });
191
+
192
+ // Allow the iframe to request a fresh token
193
+ if (typeof e.data === "object" && e.data?.type === "requestAuth") {
194
+ console.log('[EmbeddedChat] Received requestAuth message, calling postAuthToIframes');
195
+ this.postAuthToIframes();
196
+ return;
197
+ }
198
+
136
199
  if (typeof e.data === "object" && (!e.data.chatId || e.data.chatId === this.chatId)) {
137
200
  const updates = {};
138
201
 
@@ -335,7 +398,7 @@
335
398
  this.iframe.contentWindow.postMessage({
336
399
  message: "show",
337
400
  sessionInfo: this.sessionInfo || null
338
- }, "*");
401
+ }, this.targetOrigin);
339
402
  } else {
340
403
  // Schedule a single retry with a delay
341
404
  setTimeout(() => {
@@ -343,7 +406,7 @@
343
406
  this.iframe.contentWindow.postMessage({
344
407
  message: "show",
345
408
  sessionInfo: this.sessionInfo || null
346
- }, "*");
409
+ }, this.targetOrigin);
347
410
  } else {
348
411
  console.warn("iframe contentWindow is not available.");
349
412
  }
@@ -387,7 +450,7 @@
387
450
 
388
451
  // Send session info immediately if the chat is already maximized
389
452
  if (this.iframe?.contentWindow && this.iframe.style.display !== "none") {
390
- this.iframe.contentWindow.postMessage({ type: 'setSessionInfo', sessionInfo: this.sessionInfo }, "*");
453
+ this.iframe.contentWindow.postMessage({ type: 'setSessionInfo', sessionInfo: this.sessionInfo }, this.targetOrigin);
391
454
  }
392
455
  }
393
456
 
@@ -419,7 +482,7 @@
419
482
  }
420
483
 
421
484
  for (const [key, value] of Object.entries(params)) {
422
- if (key !== 'mode' && key !== 'isPreview' && key !== 'conversationId' && value !== null && value !== undefined) {
485
+ if (key !== 'mode' && key !== 'isPreview' && key !== 'conversationId' && key !== 'userToken' && value !== null && value !== undefined) {
423
486
  urlParams.set(key, value);
424
487
  }
425
488
  }
@@ -447,6 +510,41 @@
447
510
  }, { once: true }); // Ensure the listener is triggered only once
448
511
  });
449
512
  }
513
+
514
+ async postAuthToIframes() {
515
+ console.log('[EmbeddedChat] postAuthToIframes called');
516
+ if (typeof this.userTokenProvider !== 'function') {
517
+ console.warn('[EmbeddedChat] No userTokenProvider function provided');
518
+ return;
519
+ }
520
+
521
+ try {
522
+ console.log('[EmbeddedChat] Calling userTokenProvider...');
523
+ const userToken = await this.userTokenProvider();
524
+
525
+ if (!userToken) {
526
+ console.warn('[EmbeddedChat] userTokenProvider returned null/empty token');
527
+ return;
528
+ }
529
+
530
+ console.log('[EmbeddedChat] Got user token, length:', userToken?.length || 0);
531
+
532
+ if (this.iframe?.contentWindow) {
533
+ console.log('[EmbeddedChat] Sending auth message to iframe with targetOrigin:', this.targetOrigin);
534
+ this.iframe.contentWindow.postMessage({
535
+ type: 'auth',
536
+ userToken: userToken,
537
+ chatId: this.chatId
538
+ }, this.targetOrigin);
539
+ console.log('[EmbeddedChat] Auth message sent successfully');
540
+ } else {
541
+ console.error('[EmbeddedChat] iframe.contentWindow is not available');
542
+ }
543
+ // No longer send auth to minimizedIframe
544
+ } catch (err) {
545
+ console.error('[EmbeddedChat] Failed to get user token:', err);
546
+ }
547
+ }
450
548
  }
451
549
 
452
550
  export function initEmbeddedChat(containerDiv, chatId, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "embeddedaichatux",
3
- "version": "1.9.0",
3
+ "version": "2.0.0",
4
4
  "description": "A lightweight and customizable embedded AI chat UI component that seamlessly integrates into web applications, offering minimized and expanded views, with iframe-based content rendering.",
5
5
  "main": "EmbeddedChat.js",
6
6
  "scripts": {