@buni.ai/chatbot-angular 1.0.21 → 1.0.23
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/dist/buni-chat.service.d.ts +3 -3
- package/dist/buni-chat.service.d.ts.map +1 -1
- package/dist/index.esm.js +106 -13
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +106 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { BuniChatOptions, BuniChatState, CustomerData, SessionVariables } from '@buni.ai/chatbot-core';
|
|
3
3
|
export declare class BuniChatService {
|
|
4
|
-
private widget;
|
|
5
|
-
private stateSubject;
|
|
6
|
-
private readySubject;
|
|
4
|
+
private readonly widget;
|
|
5
|
+
private readonly stateSubject;
|
|
6
|
+
private readonly readySubject;
|
|
7
7
|
constructor();
|
|
8
8
|
initialize(options: BuniChatOptions): Promise<void>;
|
|
9
9
|
private setupEventListeners;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buni-chat.service.d.ts","sourceRoot":"","sources":["../src/buni-chat.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AAEnD,OAAO,EAEL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,qBAGa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;
|
|
1
|
+
{"version":3,"file":"buni-chat.service.d.ts","sourceRoot":"","sources":["../src/buni-chat.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,UAAU,EAAE,MAAM,MAAM,CAAC;AAEnD,OAAO,EAEL,eAAe,EACf,aAAa,EACb,YAAY,EACZ,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,qBAGa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAK1B;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuC;;IAM9D,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzD,OAAO,CAAC,mBAAmB;IAgB3B,IAAI,MAAM,IAAI,UAAU,CAAC,aAAa,CAAC,CAEtC;IAED,IAAI,QAAQ,IAAI,UAAU,CAAC,OAAO,CAAC,CAElC;IAED,IAAI,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAIjC;IAED,IAAI,YAAY,IAAI,UAAU,CAAC,MAAM,CAAC,CAIrC;IAGD,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAIZ,MAAM,IAAI,IAAI;IAId,QAAQ,IAAI,IAAI;IAIhB,QAAQ,IAAI,IAAI;IAKhB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAIzC,eAAe,IAAI,YAAY,GAAG,IAAI;IAItC,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAItD,mBAAmB,IAAI,gBAAgB,GAAG,IAAI;IAK9C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC,SAAS,IAAI,IAAI;IAKjB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI;IAIlD,IAAI,IAAI,IAAI;IAIZ,KAAK,IAAI,IAAI;IAKb,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAI3C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI;IAK7C,OAAO,IAAI,IAAI;CAKhB"}
|
package/dist/index.esm.js
CHANGED
|
@@ -38,6 +38,8 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
38
38
|
|
|
39
39
|
// Default BuniAI platform URL
|
|
40
40
|
const BUNI_PLATFORM_URL = "https://www.buni.ai";
|
|
41
|
+
const PARENT_HANDSHAKE_TYPE = "buni:parent_handshake";
|
|
42
|
+
const IFRAME_HANDSHAKE_ACK_TYPE = "buni:iframe_handshake_ack";
|
|
41
43
|
// Core widget loader class
|
|
42
44
|
class BuniChatWidget {
|
|
43
45
|
constructor() {
|
|
@@ -53,6 +55,9 @@ class BuniChatWidget {
|
|
|
53
55
|
this.chatIframe = null;
|
|
54
56
|
this.customerData = null;
|
|
55
57
|
this.sessionVariables = null;
|
|
58
|
+
this.chatTargetOrigin = null;
|
|
59
|
+
this.handshakeComplete = false;
|
|
60
|
+
this.outboundMessageQueue = [];
|
|
56
61
|
}
|
|
57
62
|
async initialize(options) {
|
|
58
63
|
this.options = options;
|
|
@@ -239,7 +244,18 @@ class BuniChatWidget {
|
|
|
239
244
|
chatIframe.onload = () => {
|
|
240
245
|
// Set visibility hidden after iframe loads to allow content initialization
|
|
241
246
|
chatIframe.style.visibility = "hidden";
|
|
247
|
+
// Compute the iframe origin once we know the final src.
|
|
248
|
+
try {
|
|
249
|
+
this.chatTargetOrigin = new URL(chatIframe.src).origin;
|
|
250
|
+
}
|
|
251
|
+
catch (_a) {
|
|
252
|
+
this.chatTargetOrigin = this.getBaseUrl();
|
|
253
|
+
}
|
|
254
|
+
// Reset handshake state for this iframe instance.
|
|
255
|
+
this.handshakeComplete = false;
|
|
256
|
+
this.outboundMessageQueue = [];
|
|
242
257
|
this.setupPostMessageAPI(chatIframe);
|
|
258
|
+
this.sendParentHandshake();
|
|
243
259
|
// Now that both iframes are loaded, resolve the promise
|
|
244
260
|
this.widgetElement = container;
|
|
245
261
|
this.triggerIframe = triggerIframe;
|
|
@@ -251,13 +267,17 @@ class BuniChatWidget {
|
|
|
251
267
|
};
|
|
252
268
|
// Listen for trigger and connection events
|
|
253
269
|
window.addEventListener("message", (event) => {
|
|
254
|
-
var _a;
|
|
255
|
-
|
|
270
|
+
var _a, _b;
|
|
271
|
+
const payload = event.data;
|
|
272
|
+
if (!payload || typeof payload !== "object")
|
|
273
|
+
return;
|
|
274
|
+
if (typeof payload.type !== "string")
|
|
256
275
|
return;
|
|
257
|
-
switch (
|
|
276
|
+
switch (payload.type) {
|
|
258
277
|
case "connection_ready":
|
|
259
278
|
// Check if message is from chat iframe
|
|
260
|
-
if (event.source === ((_a = this.chatIframe) === null || _a === void 0 ? void 0 : _a.contentWindow)
|
|
279
|
+
if (event.source === ((_a = this.chatIframe) === null || _a === void 0 ? void 0 : _a.contentWindow) &&
|
|
280
|
+
event.origin === this.getBaseUrl()) {
|
|
261
281
|
// Connection is ready, show the trigger button
|
|
262
282
|
if (container && !config.hideDefaultTrigger) {
|
|
263
283
|
container.style.display = "block";
|
|
@@ -271,7 +291,10 @@ class BuniChatWidget {
|
|
|
271
291
|
}
|
|
272
292
|
break;
|
|
273
293
|
case "trigger_clicked":
|
|
274
|
-
this.
|
|
294
|
+
if (event.source === ((_b = this.triggerIframe) === null || _b === void 0 ? void 0 : _b.contentWindow) &&
|
|
295
|
+
event.origin === window.location.origin) {
|
|
296
|
+
this.openChat();
|
|
297
|
+
}
|
|
275
298
|
break;
|
|
276
299
|
}
|
|
277
300
|
});
|
|
@@ -386,11 +409,15 @@ class BuniChatWidget {
|
|
|
386
409
|
</div>
|
|
387
410
|
<script>
|
|
388
411
|
function handleClick() {
|
|
389
|
-
|
|
412
|
+
// Trigger iframe is same-origin with parent (about:blank + document.write),
|
|
413
|
+
// so we can safely target the parent's origin.
|
|
414
|
+
window.parent.postMessage({ type: 'trigger_clicked' }, window.location.origin);
|
|
390
415
|
}
|
|
391
416
|
|
|
392
417
|
// Listen for unread count updates
|
|
393
418
|
window.addEventListener('message', function(event) {
|
|
419
|
+
if (event.source !== window.parent) return;
|
|
420
|
+
if (event.origin !== window.location.origin) return;
|
|
394
421
|
if (event.data.type === 'updateUnreadCount') {
|
|
395
422
|
const badge = document.getElementById('badge');
|
|
396
423
|
const count = event.data.count || 0;
|
|
@@ -538,12 +565,24 @@ class BuniChatWidget {
|
|
|
538
565
|
// Listen for messages from the iframe
|
|
539
566
|
window.addEventListener("message", (event) => {
|
|
540
567
|
var _a;
|
|
568
|
+
if (event.source !== iframe.contentWindow) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
541
571
|
// Verify origin for security
|
|
542
572
|
if (event.origin !== this.getBaseUrl()) {
|
|
543
573
|
return;
|
|
544
574
|
}
|
|
545
|
-
const
|
|
575
|
+
const payload = event.data;
|
|
576
|
+
if (!payload || typeof payload !== "object")
|
|
577
|
+
return;
|
|
578
|
+
const { type, data } = payload;
|
|
579
|
+
if (typeof type !== "string")
|
|
580
|
+
return;
|
|
546
581
|
switch (type) {
|
|
582
|
+
case IFRAME_HANDSHAKE_ACK_TYPE:
|
|
583
|
+
this.handshakeComplete = true;
|
|
584
|
+
this.flushOutboundMessageQueue();
|
|
585
|
+
break;
|
|
547
586
|
case "ready":
|
|
548
587
|
this.state.isLoaded = true;
|
|
549
588
|
this.emit("ready", data);
|
|
@@ -575,7 +614,7 @@ class BuniChatWidget {
|
|
|
575
614
|
// Update unread count in trigger
|
|
576
615
|
this.state.unreadCount++;
|
|
577
616
|
if ((_a = this.triggerIframe) === null || _a === void 0 ? void 0 : _a.contentWindow) {
|
|
578
|
-
this.triggerIframe.contentWindow.postMessage({ type: "updateUnreadCount", count: this.state.unreadCount },
|
|
617
|
+
this.triggerIframe.contentWindow.postMessage({ type: "updateUnreadCount", count: this.state.unreadCount }, window.location.origin);
|
|
579
618
|
}
|
|
580
619
|
break;
|
|
581
620
|
case "customer_data_updated":
|
|
@@ -595,17 +634,69 @@ class BuniChatWidget {
|
|
|
595
634
|
}
|
|
596
635
|
});
|
|
597
636
|
}
|
|
637
|
+
sendParentHandshake() {
|
|
638
|
+
var _a, _b;
|
|
639
|
+
const iframeWindow = (_a = this.chatIframe) === null || _a === void 0 ? void 0 : _a.contentWindow;
|
|
640
|
+
if (!iframeWindow)
|
|
641
|
+
return;
|
|
642
|
+
const targetOrigin = (_b = this.chatTargetOrigin) !== null && _b !== void 0 ? _b : this.getBaseUrl();
|
|
643
|
+
try {
|
|
644
|
+
iframeWindow.postMessage({
|
|
645
|
+
type: PARENT_HANDSHAKE_TYPE,
|
|
646
|
+
data: { origin: window.location.origin },
|
|
647
|
+
}, targetOrigin);
|
|
648
|
+
}
|
|
649
|
+
catch (_c) {
|
|
650
|
+
// Best-effort; iframe may fall back to document.referrer for origin discovery.
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
flushOutboundMessageQueue() {
|
|
654
|
+
var _a, _b;
|
|
655
|
+
const iframeWindow = (_a = this.chatIframe) === null || _a === void 0 ? void 0 : _a.contentWindow;
|
|
656
|
+
if (!iframeWindow)
|
|
657
|
+
return;
|
|
658
|
+
const targetOrigin = (_b = this.chatTargetOrigin) !== null && _b !== void 0 ? _b : this.getBaseUrl();
|
|
659
|
+
const queued = this.outboundMessageQueue;
|
|
660
|
+
if (queued.length === 0)
|
|
661
|
+
return;
|
|
662
|
+
this.outboundMessageQueue = [];
|
|
663
|
+
for (const msg of queued) {
|
|
664
|
+
iframeWindow.postMessage({ type: msg.type, data: msg.data }, targetOrigin);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
598
667
|
postMessageToWidget(type, data) {
|
|
599
|
-
var _a;
|
|
600
|
-
|
|
601
|
-
|
|
668
|
+
var _a, _b;
|
|
669
|
+
const iframeWindow = (_a = this.chatIframe) === null || _a === void 0 ? void 0 : _a.contentWindow;
|
|
670
|
+
if (!iframeWindow)
|
|
671
|
+
return;
|
|
672
|
+
const targetOrigin = (_b = this.chatTargetOrigin) !== null && _b !== void 0 ? _b : this.getBaseUrl();
|
|
673
|
+
// Ensure handshake is sent before any other commands; queue until ack.
|
|
674
|
+
if (!this.handshakeComplete && type !== PARENT_HANDSHAKE_TYPE) {
|
|
675
|
+
const queue = this.outboundMessageQueue;
|
|
676
|
+
if (queue.length < 50) {
|
|
677
|
+
queue.push({ type, data });
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
this.outboundMessageQueue = [...queue.slice(-49), { type, data }];
|
|
681
|
+
}
|
|
682
|
+
this.sendParentHandshake();
|
|
683
|
+
return;
|
|
602
684
|
}
|
|
685
|
+
iframeWindow.postMessage({ type, data }, targetOrigin);
|
|
603
686
|
}
|
|
604
687
|
getBaseUrl() {
|
|
688
|
+
var _a, _b;
|
|
605
689
|
// Return the base URL for the BuniAI platform
|
|
606
690
|
// Priority: 1. config.baseUrl, 2. global BUNI_API_URL, 3. default platform URL
|
|
691
|
+
const configUrl = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.baseUrl;
|
|
607
692
|
const globalUrl = globalThis.BUNI_API_URL;
|
|
608
|
-
|
|
693
|
+
const rawUrl = configUrl || globalUrl || BUNI_PLATFORM_URL;
|
|
694
|
+
try {
|
|
695
|
+
return new URL(rawUrl).origin;
|
|
696
|
+
}
|
|
697
|
+
catch (_c) {
|
|
698
|
+
return rawUrl;
|
|
699
|
+
}
|
|
609
700
|
}
|
|
610
701
|
destroy() {
|
|
611
702
|
this.postMessageToWidget("destroy");
|
|
@@ -753,7 +844,6 @@ let BuniChatService = class BuniChatService {
|
|
|
753
844
|
async initialize(options) {
|
|
754
845
|
try {
|
|
755
846
|
await this.widget.initialize({ ...options, framework: "angular" });
|
|
756
|
-
this.readySubject.next(true);
|
|
757
847
|
}
|
|
758
848
|
catch (error) {
|
|
759
849
|
console.error('Failed to initialize BuniChat widget:', error);
|
|
@@ -765,6 +855,9 @@ let BuniChatService = class BuniChatService {
|
|
|
765
855
|
const updateState = () => {
|
|
766
856
|
this.stateSubject.next(this.widget.getState());
|
|
767
857
|
};
|
|
858
|
+
this.widget.on('connection_ready', () => {
|
|
859
|
+
this.readySubject.next(true);
|
|
860
|
+
});
|
|
768
861
|
this.widget.on('ready', updateState);
|
|
769
862
|
this.widget.on('visibility_changed', updateState);
|
|
770
863
|
this.widget.on('minimized', updateState);
|