brainerce 1.46.2 → 1.47.3

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.
@@ -33,12 +33,29 @@ interface BrainerceBotOptions {
33
33
  variantId?: string | null;
34
34
  quantity: number;
35
35
  }) => boolean | Promise<boolean>;
36
+ /**
37
+ * Part 2 (order-lookup login gating) — a SAME-ORIGIN path (e.g. `/api/store`, the
38
+ * Next.js template's own BFF proxy) that forwards to the backend and attaches the
39
+ * shopper's customer-session cookie as a Bearer header. When set, the widget calls
40
+ * `${customerSessionProxyPath}/api/storefront-bot/:connectionId/customer-session`
41
+ * (through THIS path, not `baseUrl` — a cross-origin request to `baseUrl` would
42
+ * never carry the httpOnly session cookie) to learn login state and obtain a
43
+ * short-lived token it attaches to its normal direct-to-backend /chat call, so
44
+ * streaming is completely unaffected. Omit entirely on any site without such a
45
+ * proxy — checkOrderStatus then simply always answers as a guest, no error.
46
+ */
47
+ customerSessionProxyPath?: string;
36
48
  }
37
49
  declare class BrainerceBot {
38
50
  private readonly connectionId;
39
51
  private readonly baseUrl;
40
52
  private readonly storageKey;
41
53
  private readonly onAddToCart?;
54
+ private readonly customerSessionProxyPath?;
55
+ /** Part 2 (order-lookup login gating) — short-lived, in-memory only (never
56
+ * persisted): refreshed opportunistically before a chat send when stale. */
57
+ private botSessionToken;
58
+ private botSessionFetchedAt;
42
59
  private host?;
43
60
  private root?;
44
61
  private windowEl?;
@@ -83,6 +100,15 @@ declare class BrainerceBot {
83
100
  private toggleExpand;
84
101
  /** First open: restore the server thread, or show the greeting. */
85
102
  private primeThread;
103
+ /**
104
+ * Part 2 (order-lookup login gating) — refresh the short-lived bot-session token
105
+ * if this site opted in (`customerSessionProxyPath` set) and the current one is
106
+ * stale or absent. Comfortably under the backend's 5-minute expiry so a token
107
+ * fetched here is never expired by the time /chat reads it. Fails silently on any
108
+ * error (offline, no proxy configured server-side, etc.) — a guest must always be
109
+ * able to chat regardless of this call's outcome.
110
+ */
111
+ private refreshCustomerSession;
86
112
  private send;
87
113
  private handleFrame;
88
114
  private appendCard;
package/dist/bot/index.js CHANGED
@@ -164,6 +164,10 @@ function renderRich(el, text) {
164
164
  }
165
165
  var BrainerceBot = class _BrainerceBot {
166
166
  constructor(options) {
167
+ /** Part 2 (order-lookup login gating) — short-lived, in-memory only (never
168
+ * persisted): refreshed opportunistically before a chat send when stale. */
169
+ this.botSessionToken = null;
170
+ this.botSessionFetchedAt = 0;
167
171
  this.settings = { enabled: false };
168
172
  this.locale = "en";
169
173
  this.sessionId = null;
@@ -185,6 +189,7 @@ var BrainerceBot = class _BrainerceBot {
185
189
  this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
186
190
  this.storageKey = `brainerce-bot:${this.connectionId}`;
187
191
  this.onAddToCart = options.onAddToCart;
192
+ this.customerSessionProxyPath = options.customerSessionProxyPath?.replace(/\/$/, "");
188
193
  }
189
194
  /** Boot the widget. Resolves to null when the bot is disabled server-side. */
190
195
  static async mount(options) {
@@ -749,6 +754,30 @@ var BrainerceBot = class _BrainerceBot {
749
754
  // --------------------------------------------------------------------------
750
755
  // The chat turn
751
756
  // --------------------------------------------------------------------------
757
+ /**
758
+ * Part 2 (order-lookup login gating) — refresh the short-lived bot-session token
759
+ * if this site opted in (`customerSessionProxyPath` set) and the current one is
760
+ * stale or absent. Comfortably under the backend's 5-minute expiry so a token
761
+ * fetched here is never expired by the time /chat reads it. Fails silently on any
762
+ * error (offline, no proxy configured server-side, etc.) — a guest must always be
763
+ * able to chat regardless of this call's outcome.
764
+ */
765
+ async refreshCustomerSession() {
766
+ if (!this.customerSessionProxyPath) return;
767
+ const FOUR_MINUTES_MS = 4 * 60 * 1e3;
768
+ if (this.botSessionToken && Date.now() - this.botSessionFetchedAt < FOUR_MINUTES_MS) return;
769
+ try {
770
+ const res = await fetch(
771
+ `${this.customerSessionProxyPath}/api/storefront-bot/${encodeURIComponent(this.connectionId)}/customer-session`,
772
+ { credentials: "include" }
773
+ );
774
+ if (!res.ok) return;
775
+ const data = await res.json();
776
+ this.botSessionToken = data.loggedIn && data.botSessionToken ? data.botSessionToken : null;
777
+ this.botSessionFetchedAt = Date.now();
778
+ } catch {
779
+ }
780
+ }
752
781
  async send(text) {
753
782
  const message = text.trim();
754
783
  if (!message || this.busy) return;
@@ -763,6 +792,7 @@ var BrainerceBot = class _BrainerceBot {
763
792
  this.cardIds = /* @__PURE__ */ new Set();
764
793
  let botBubble = null;
765
794
  try {
795
+ await this.refreshCustomerSession();
766
796
  const res = await fetch(
767
797
  `${this.baseUrl}/api/storefront-bot/${encodeURIComponent(this.connectionId)}/chat`,
768
798
  {
@@ -773,7 +803,8 @@ var BrainerceBot = class _BrainerceBot {
773
803
  turnId: randomId("trn_"),
774
804
  ...this.conversationId ? { conversationId: this.conversationId } : {},
775
805
  ...this.sessionId ? { anonymousSessionId: this.sessionId } : {},
776
- locale: this.locale
806
+ locale: this.locale,
807
+ ...this.botSessionToken ? { botSessionToken: this.botSessionToken } : {}
777
808
  })
778
809
  }
779
810
  );
@@ -138,6 +138,10 @@ function renderRich(el, text) {
138
138
  }
139
139
  var BrainerceBot = class _BrainerceBot {
140
140
  constructor(options) {
141
+ /** Part 2 (order-lookup login gating) — short-lived, in-memory only (never
142
+ * persisted): refreshed opportunistically before a chat send when stale. */
143
+ this.botSessionToken = null;
144
+ this.botSessionFetchedAt = 0;
141
145
  this.settings = { enabled: false };
142
146
  this.locale = "en";
143
147
  this.sessionId = null;
@@ -159,6 +163,7 @@ var BrainerceBot = class _BrainerceBot {
159
163
  this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
160
164
  this.storageKey = `brainerce-bot:${this.connectionId}`;
161
165
  this.onAddToCart = options.onAddToCart;
166
+ this.customerSessionProxyPath = options.customerSessionProxyPath?.replace(/\/$/, "");
162
167
  }
163
168
  /** Boot the widget. Resolves to null when the bot is disabled server-side. */
164
169
  static async mount(options) {
@@ -723,6 +728,30 @@ var BrainerceBot = class _BrainerceBot {
723
728
  // --------------------------------------------------------------------------
724
729
  // The chat turn
725
730
  // --------------------------------------------------------------------------
731
+ /**
732
+ * Part 2 (order-lookup login gating) — refresh the short-lived bot-session token
733
+ * if this site opted in (`customerSessionProxyPath` set) and the current one is
734
+ * stale or absent. Comfortably under the backend's 5-minute expiry so a token
735
+ * fetched here is never expired by the time /chat reads it. Fails silently on any
736
+ * error (offline, no proxy configured server-side, etc.) — a guest must always be
737
+ * able to chat regardless of this call's outcome.
738
+ */
739
+ async refreshCustomerSession() {
740
+ if (!this.customerSessionProxyPath) return;
741
+ const FOUR_MINUTES_MS = 4 * 60 * 1e3;
742
+ if (this.botSessionToken && Date.now() - this.botSessionFetchedAt < FOUR_MINUTES_MS) return;
743
+ try {
744
+ const res = await fetch(
745
+ `${this.customerSessionProxyPath}/api/storefront-bot/${encodeURIComponent(this.connectionId)}/customer-session`,
746
+ { credentials: "include" }
747
+ );
748
+ if (!res.ok) return;
749
+ const data = await res.json();
750
+ this.botSessionToken = data.loggedIn && data.botSessionToken ? data.botSessionToken : null;
751
+ this.botSessionFetchedAt = Date.now();
752
+ } catch {
753
+ }
754
+ }
726
755
  async send(text) {
727
756
  const message = text.trim();
728
757
  if (!message || this.busy) return;
@@ -737,6 +766,7 @@ var BrainerceBot = class _BrainerceBot {
737
766
  this.cardIds = /* @__PURE__ */ new Set();
738
767
  let botBubble = null;
739
768
  try {
769
+ await this.refreshCustomerSession();
740
770
  const res = await fetch(
741
771
  `${this.baseUrl}/api/storefront-bot/${encodeURIComponent(this.connectionId)}/chat`,
742
772
  {
@@ -747,7 +777,8 @@ var BrainerceBot = class _BrainerceBot {
747
777
  turnId: randomId("trn_"),
748
778
  ...this.conversationId ? { conversationId: this.conversationId } : {},
749
779
  ...this.sessionId ? { anonymousSessionId: this.sessionId } : {},
750
- locale: this.locale
780
+ locale: this.locale,
781
+ ...this.botSessionToken ? { botSessionToken: this.botSessionToken } : {}
751
782
  })
752
783
  }
753
784
  );