@chativa/connector-directline 0.7.2 → 0.8.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/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { DirectLine as v, ConnectionStatus as l } from "botframework-directlinejs";
2
- const f = /* @__PURE__ */ Symbol("typing"), k = "application/vnd.microsoft.card.hero", b = "application/vnd.microsoft.card.thumbnail", m = "application/vnd.microsoft.card.adaptive", S = "application/vnd.microsoft.card.signin", H = "application/vnd.microsoft.card.oauth", A = "application/vnd.microsoft.card.receipt", D = "application/vnd.microsoft.card.audio", E = "application/vnd.microsoft.card.video", $ = "application/vnd.microsoft.card.animation", T = "application/vnd.microsoft.card.flex";
3
- function y(i, t) {
2
+ const f = /* @__PURE__ */ Symbol("typing"), k = "application/vnd.microsoft.card.hero", b = "application/vnd.microsoft.card.thumbnail", m = "application/vnd.microsoft.card.adaptive", H = "application/vnd.microsoft.card.signin", A = "application/vnd.microsoft.card.oauth", D = "application/vnd.microsoft.card.receipt", E = "application/vnd.microsoft.card.audio", $ = "application/vnd.microsoft.card.video", N = "application/vnd.microsoft.card.animation", T = "application/vnd.microsoft.card.flex";
3
+ function g(i, t) {
4
4
  if (i.from.id === t) return null;
5
5
  if (i.type === "typing") return f;
6
6
  if (i.type !== "message") return null;
7
7
  const e = i, n = e.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, s = e.timestamp ? new Date(e.timestamp).getTime() : Date.now(), r = e.channelData, o = U(e);
8
8
  if (e.attachments && e.attachments.length > 0) {
9
- const a = N(e, n, s);
9
+ const a = L(e, n, s);
10
10
  return a && (o.length > 0 && (a.actions = o), r && (a.data.channelData = r)), a;
11
11
  }
12
12
  return o.length > 0 ? {
@@ -23,21 +23,21 @@ function y(i, t) {
23
23
  timestamp: s
24
24
  } : null;
25
25
  }
26
- function N(i, t, e) {
26
+ function L(i, t, e) {
27
27
  const n = i.attachments, s = i.attachmentLayout, r = [k, b, T, m];
28
28
  return n.every((a) => r.includes(a.contentType)) && (n.length > 1 || s === "carousel") ? {
29
29
  id: t,
30
30
  type: "carousel",
31
31
  from: "bot",
32
32
  data: {
33
- cards: n.map((a) => a.contentType === m ? R(
33
+ cards: n.map((a) => a.contentType === m ? P(
34
34
  a.content
35
35
  ) : I(a.content))
36
36
  },
37
37
  timestamp: e
38
- } : L(n[0], i, t, e);
38
+ } : R(n[0], i, t, e);
39
39
  }
40
- function L(i, t, e, n) {
40
+ function R(i, t, e, n) {
41
41
  const s = i.contentType;
42
42
  if (s === k || s === b || s === T) {
43
43
  const r = i.content;
@@ -51,7 +51,7 @@ function L(i, t, e, n) {
51
51
  }
52
52
  if (s === m)
53
53
  return _(i.content, e, n);
54
- if (s === S || s === H) {
54
+ if (s === H || s === A) {
55
55
  const r = i.content;
56
56
  return {
57
57
  id: e,
@@ -59,14 +59,14 @@ function L(i, t, e, n) {
59
59
  from: "bot",
60
60
  data: {
61
61
  text: r.text ?? "Please sign in",
62
- buttons: w(r.buttons)
62
+ buttons: C(r.buttons)
63
63
  },
64
64
  timestamp: n
65
65
  };
66
66
  }
67
- if (s === A)
67
+ if (s === D)
68
68
  return O(i.content, e, n);
69
- if (s === E) {
69
+ if (s === $) {
70
70
  const r = i.content, o = r.media?.[0]?.url;
71
71
  return o ? {
72
72
  id: e,
@@ -80,7 +80,7 @@ function L(i, t, e, n) {
80
80
  timestamp: n
81
81
  } : null;
82
82
  }
83
- if (s === D) {
83
+ if (s === E) {
84
84
  const r = i.content, o = r.media?.[0]?.url;
85
85
  return o ? {
86
86
  id: e,
@@ -94,7 +94,7 @@ function L(i, t, e, n) {
94
94
  timestamp: n
95
95
  } : null;
96
96
  }
97
- if (s === $) {
97
+ if (s === N) {
98
98
  const r = i.content, o = r.media?.[0]?.url;
99
99
  return o ? {
100
100
  id: e,
@@ -143,10 +143,10 @@ function I(i) {
143
143
  image: i.images?.[0]?.url,
144
144
  title: i.title ?? "",
145
145
  subtitle: i.subtitle ?? i.text,
146
- buttons: w(i.buttons)
146
+ buttons: C(i.buttons)
147
147
  };
148
148
  }
149
- function w(i) {
149
+ function C(i) {
150
150
  return !i || i.length === 0 ? [] : i.map((t) => {
151
151
  const e = ("title" in t ? t.title : void 0) ?? String(t.value ?? "");
152
152
  switch (t.type) {
@@ -192,7 +192,7 @@ function d(i, t, e, n) {
192
192
  break;
193
193
  }
194
194
  }
195
- function C(i) {
195
+ function w(i) {
196
196
  const t = [];
197
197
  let e;
198
198
  const n = [];
@@ -205,8 +205,8 @@ function C(i) {
205
205
  }
206
206
  ), Array.isArray(i.actions) && x(i.actions, n), { texts: t, image: e, buttons: n };
207
207
  }
208
- function R(i) {
209
- const { texts: t, image: e, buttons: n } = C(i);
208
+ function P(i) {
209
+ const { texts: t, image: e, buttons: n } = w(i);
210
210
  return {
211
211
  image: e,
212
212
  title: t[0] ?? "",
@@ -216,7 +216,7 @@ function R(i) {
216
216
  };
217
217
  }
218
218
  function _(i, t, e) {
219
- const { texts: n, image: s, buttons: r } = C(i), o = i.fallbackText ?? i.speak ?? n.join(`
219
+ const { texts: n, image: s, buttons: r } = w(i), o = i.fallbackText ?? i.speak ?? n.join(`
220
220
  `);
221
221
  return s ? {
222
222
  id: t,
@@ -272,21 +272,24 @@ function O(i, t, e) {
272
272
  timestamp: e
273
273
  };
274
274
  }
275
- const g = "chativa_directline_userId", h = "chativa_directline_conversation";
276
- function P() {
275
+ const y = "chativa_directline_userId", h = "chativa_directline_conversation";
276
+ function S() {
277
+ return Math.random().toString(36).slice(2, 15) + Math.random().toString(36).slice(2, 15);
278
+ }
279
+ function B() {
277
280
  try {
278
- const t = localStorage.getItem(g);
281
+ const t = localStorage.getItem(y);
279
282
  if (t) return t;
280
283
  } catch {
281
284
  }
282
- const i = Math.random().toString(36).slice(2, 15) + Math.random().toString(36).slice(2, 15);
285
+ const i = S();
283
286
  try {
284
- localStorage.setItem(g, i);
287
+ localStorage.setItem(y, i);
285
288
  } catch {
286
289
  }
287
290
  return i;
288
291
  }
289
- function B(i) {
292
+ function F(i) {
290
293
  try {
291
294
  const t = JSON.parse(atob(i.split(".")[1]));
292
295
  return typeof t.exp == "number" ? t.exp * 1e3 : null;
@@ -294,7 +297,7 @@ function B(i) {
294
297
  return null;
295
298
  }
296
299
  }
297
- async function F(i, t) {
300
+ async function j(i, t) {
298
301
  const e = await fetch(
299
302
  "https://directline.botframework.com/v3/directline/tokens/generate",
300
303
  {
@@ -311,7 +314,7 @@ async function F(i, t) {
311
314
  const n = await e.json();
312
315
  return { token: n.token, conversationId: n.conversationId };
313
316
  }
314
- async function j(i) {
317
+ async function M(i) {
315
318
  const t = await fetch(i, { method: "POST" });
316
319
  if (!t.ok)
317
320
  throw new Error(`Token generator failed: ${t.status}`);
@@ -326,7 +329,7 @@ async function u(i, t) {
326
329
  throw new Error(`Token refresh failed: ${n.status}`);
327
330
  return await n.json();
328
331
  }
329
- class J {
332
+ class G {
330
333
  constructor(t) {
331
334
  this.name = "directline", this.addSentToHistory = !0, this.chativaCtx = null, this.messageHandler = null, this.connectHandler = null, this.disconnectHandler = null, this.typingHandler = null, this.messageStatusHandler = null, this.activitySub = null, this.connectionSub = null, this.typingTimeout = null, this.refreshTimer = null, this.pendingIds = [], this.hasConnectedBefore = !1, this.resolveReady = null, this._skipNextJoin = !1, this.options = t;
332
335
  }
@@ -362,7 +365,7 @@ class J {
362
365
  return Object.keys(this.options.eventHandlers ?? {});
363
366
  }
364
367
  async connect() {
365
- this.userId = this.options.userId ?? P(), this.userName = this.options.userName;
368
+ this.userId = this.options.userId ?? (this.options.resumeConversation ? B() : S()), this.userName = this.options.userName;
366
369
  let t = !1;
367
370
  if (this.options.resumeConversation) {
368
371
  const n = this.loadPersistedConversation();
@@ -379,14 +382,14 @@ class J {
379
382
  }
380
383
  if (!t)
381
384
  if (this.options.tokenGeneratorUrl) {
382
- const n = await j(
385
+ const n = await M(
383
386
  this.options.tokenGeneratorUrl
384
387
  );
385
388
  this.token = n.token, n.conversationId && (this.conversationId = n.conversationId), n.userId && (this.userId = n.userId);
386
389
  } else if (this.options.token)
387
390
  this.token = this.options.token;
388
391
  else if (this.options.secret) {
389
- const n = await F(
392
+ const n = await j(
390
393
  this.options.secret,
391
394
  this.userId
392
395
  );
@@ -518,7 +521,7 @@ class J {
518
521
  });
519
522
  continue;
520
523
  }
521
- const c = y(a, this.userId);
524
+ const c = g(a, this.userId);
522
525
  c !== null && c !== f && o.push(c);
523
526
  }
524
527
  return {
@@ -567,13 +570,8 @@ class J {
567
570
  }
568
571
  ), this.activitySub = this.directLine.activity$.subscribe((e) => {
569
572
  try {
570
- if (e.id && (this.watermark = e.id), !this.conversationId && e.conversation?.id && (this.conversationId = e.conversation.id), e.from.id === this.userId) {
571
- if (e.type === "message") {
572
- const s = this.pendingIds.shift();
573
- s && this.messageStatusHandler?.(s, "read");
574
- }
573
+ if (e.id && (this.watermark = e.id), !this.conversationId && e.conversation?.id && (this.conversationId = e.conversation.id), e.from.id === this.userId)
575
574
  return;
576
- }
577
575
  if (e.type === "event" && e.name) {
578
576
  if (e.name === "DisableFeedbackButton" && e.value) {
579
577
  const r = e.value;
@@ -586,12 +584,12 @@ class J {
586
584
  s && s(this.createEventContext(e));
587
585
  return;
588
586
  }
589
- const n = y(e, this.userId);
587
+ const n = g(e, this.userId);
590
588
  if (n === f) {
591
589
  this.handleTyping();
592
590
  return;
593
591
  }
594
- n !== null && (this.clearTypingTimeout(), this.typingHandler?.(!1), this.resolveReady && (this.resolveReady(), this.resolveReady = null), this.messageHandler?.(n), this.options.resumeConversation && this.persistConversation());
592
+ n !== null && (this.clearTypingTimeout(), this.typingHandler?.(!1), this.resolveReady && (this.resolveReady(), this.resolveReady = null), this.flushPendingToRead(), this.messageHandler?.(n), this.options.resumeConversation && this.persistConversation());
595
593
  } catch (n) {
596
594
  console.warn(
597
595
  "[DirectLineConnector] Activity mapping error:",
@@ -654,6 +652,20 @@ class J {
654
652
  data: { ...s.data, feedbackDisabled: !0, feedbackType: e }
655
653
  });
656
654
  }
655
+ /**
656
+ * Mark every still-pending user message as "read" (double-tick).
657
+ * Called only when an actual bot **message** arrives — typing
658
+ * indicators, events, and the WebSocket echo of our own activity
659
+ * do not flush, because none of them are visible "the bot replied"
660
+ * signals from a user perspective.
661
+ */
662
+ flushPendingToRead() {
663
+ if (!(!this.messageStatusHandler || this.pendingIds.length === 0)) {
664
+ for (const t of this.pendingIds)
665
+ this.messageStatusHandler(t, "read");
666
+ this.pendingIds = [];
667
+ }
668
+ }
657
669
  handleTyping() {
658
670
  if (this.clearTypingTimeout(), this.typingHandler?.(!0), this.options.typingUntilMessage)
659
671
  return;
@@ -669,7 +681,7 @@ class J {
669
681
  /** Schedule a token refresh 60 seconds before expiry. */
670
682
  scheduleTokenRefresh() {
671
683
  this.clearRefreshTimer();
672
- const t = B(this.token);
684
+ const t = F(this.token);
673
685
  if (!t) return;
674
686
  const e = t - Date.now() - 6e4;
675
687
  if (e <= 0) {
@@ -750,6 +762,6 @@ class J {
750
762
  }
751
763
  }
752
764
  export {
753
- J as DirectLineConnector
765
+ G as DirectLineConnector
754
766
  };
755
767
  //# sourceMappingURL=index.js.map