@cstar.help/js 0.16.0 → 0.17.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.
@@ -6,6 +6,7 @@ var RealtimeManager = class {
6
6
  this.channels = /* @__PURE__ */ new Map();
7
7
  this.refreshTimer = null;
8
8
  this.currentToken = null;
9
+ this.destroyed = false;
9
10
  this.options = options;
10
11
  }
11
12
  /**
@@ -13,6 +14,7 @@ var RealtimeManager = class {
13
14
  * Returns true if successful, false if the realtime runtime is unavailable.
14
15
  */
15
16
  init() {
17
+ if (this.destroyed) return Promise.resolve(false);
16
18
  if (this.initPromise) return this.initPromise;
17
19
  this.initPromise = this.doInit();
18
20
  return this.initPromise;
@@ -20,10 +22,12 @@ var RealtimeManager = class {
20
22
  async doInit() {
21
23
  try {
22
24
  const tokenData = await this.options.fetchToken();
25
+ if (this.destroyed) return false;
23
26
  const { createClient } = await import(
24
27
  /* webpackIgnore: true */
25
28
  "@supabase/supabase-js"
26
29
  );
30
+ if (this.destroyed) return false;
27
31
  this.client = createClient(tokenData.realtimeUrl, tokenData.realtimeKey, {
28
32
  auth: { persistSession: false, autoRefreshToken: false },
29
33
  realtime: { params: { eventsPerSecond: 10 } }
@@ -51,10 +55,13 @@ var RealtimeManager = class {
51
55
  this.refreshTimer = setTimeout(() => this.doRefresh(), delay);
52
56
  }
53
57
  async doRefresh() {
58
+ if (this.destroyed) return;
54
59
  try {
55
60
  const tokenData = await this.options.fetchToken();
61
+ if (this.destroyed) return;
56
62
  this.setToken(tokenData);
57
63
  } catch {
64
+ if (this.destroyed) return;
58
65
  this.refreshTimer = setTimeout(() => this.doRefresh(), 3e4);
59
66
  }
60
67
  }
@@ -119,6 +126,7 @@ var RealtimeManager = class {
119
126
  }
120
127
  /** Clean up all channels, timers, and the client. */
121
128
  destroy() {
129
+ this.destroyed = true;
122
130
  if (this.refreshTimer) {
123
131
  clearTimeout(this.refreshTimer);
124
132
  this.refreshTimer = null;
@@ -292,6 +300,94 @@ var ChatClientNetworkError = class extends ChatClientError {
292
300
  }
293
301
  };
294
302
 
303
+ // src/chat/attachments.ts
304
+ var UUID = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i;
305
+ function downloadFilename(header) {
306
+ const extended = header?.match(/(?:^|;)\s*filename\*\s*=\s*UTF-8''([^;]*)/i);
307
+ let name = "";
308
+ if (extended) {
309
+ try {
310
+ name = decodeURIComponent(extended[1]);
311
+ } catch {
312
+ }
313
+ }
314
+ if (!name) {
315
+ const fallback = header?.match(/(?:^|;)\s*filename\s*=\s*(?:"((?:\\.|[^"\\])*)"|([^;]*))/i);
316
+ name = fallback?.[1]?.replace(/\\(.)/g, "$1") ?? fallback?.[2] ?? "";
317
+ }
318
+ return name.split(/[\\/]/).pop()?.replace(/[\x00-\x1f\x7f]/g, "").replace(/^[\s.]+|[\s.]+$/g, "") || "download";
319
+ }
320
+ var AttachmentsApi = class {
321
+ constructor(chat) {
322
+ this.chat = chat;
323
+ }
324
+ async download(reference, options = {}) {
325
+ const assertCurrent = this.chat.captureSession();
326
+ if (!this.chat.getAuthMode())
327
+ throw new ChatClientAuthError("Sign in before downloading a file.");
328
+ const { ticketId, messageId, attachmentIndex } = reference;
329
+ if (typeof ticketId !== "string" || typeof messageId !== "string" || !UUID.test(ticketId) || !UUID.test(messageId) || !Number.isSafeInteger(attachmentIndex) || attachmentIndex < 0) {
330
+ throw new TypeError("A saved ticket, message and nonnegative attachment index are required.");
331
+ }
332
+ const controller = new AbortController();
333
+ const signal = options.signal;
334
+ const download = options.download === false ? "0" : "1";
335
+ const abort = () => controller.abort();
336
+ const assertOwned = () => {
337
+ assertCurrent();
338
+ controller.signal.throwIfAborted();
339
+ };
340
+ const unsubscribe = this.chat.subscribe(() => {
341
+ try {
342
+ assertCurrent();
343
+ } catch {
344
+ abort();
345
+ }
346
+ });
347
+ signal?.addEventListener("abort", abort, { once: true });
348
+ if (signal?.aborted) abort();
349
+ try {
350
+ assertOwned();
351
+ const teamId = await this.chat.ensureTeamId(controller.signal);
352
+ assertOwned();
353
+ const result = await this.chat.fetch(
354
+ "/api/widget/attachments/download",
355
+ {
356
+ method: "GET",
357
+ query: {
358
+ teamId,
359
+ ticketId,
360
+ messageId,
361
+ attachmentIndex: String(attachmentIndex),
362
+ download
363
+ },
364
+ signal: controller.signal,
365
+ cache: "no-store",
366
+ readBody: async (response) => {
367
+ assertOwned();
368
+ const blob = await response.blob();
369
+ assertOwned();
370
+ return {
371
+ blob,
372
+ filename: downloadFilename(response.headers.get("Content-Disposition")),
373
+ contentType: blob.type.split(";")[0] || "application/octet-stream",
374
+ size: blob.size
375
+ };
376
+ }
377
+ }
378
+ );
379
+ assertOwned();
380
+ return result;
381
+ } catch (error) {
382
+ assertOwned();
383
+ throw error;
384
+ } finally {
385
+ unsubscribe();
386
+ signal?.removeEventListener("abort", abort);
387
+ }
388
+ }
389
+ };
390
+
295
391
  // src/chat/index.ts
296
392
  var DEFAULT_BASE_URL = "https://www.cstar.help";
297
393
  var DEFAULT_POLLING_INTERVAL = 3e3;
@@ -301,7 +397,8 @@ var ChatClient = class {
301
397
  this.teamId = null;
302
398
  this.customerId = null;
303
399
  this.authMode = null;
304
- this.pollingTimers = /* @__PURE__ */ new Map();
400
+ this.sessionGeneration = 0;
401
+ this.pollingSubscriptions = /* @__PURE__ */ new Set();
305
402
  this.stateListeners = /* @__PURE__ */ new Set();
306
403
  this.realtimeManager = null;
307
404
  this.presenceManager = null;
@@ -313,6 +410,7 @@ var ChatClient = class {
313
410
  this.realtimeEnabled = config.realtime !== false;
314
411
  this.tickets = new TicketsApi(this);
315
412
  this.messages = new MessagesApi(this);
413
+ this.attachments = new AttachmentsApi(this);
316
414
  this.community = new ChatCommunityApi(this);
317
415
  }
318
416
  /**
@@ -327,6 +425,8 @@ var ChatClient = class {
327
425
  * @param testMode - Whether to use test mode (relaxed timestamp validation)
328
426
  */
329
427
  async identify(customer, signature, testMode = false) {
428
+ const generation = this.retireSession();
429
+ this.assertSession(generation);
330
430
  const response = await this.fetch(
331
431
  "/api/widget/verify-identity",
332
432
  {
@@ -339,15 +439,18 @@ var ChatClient = class {
339
439
  }
340
440
  }
341
441
  );
442
+ this.assertSession(generation);
342
443
  this.sessionToken = response.data.sessionToken;
343
444
  this.teamId = response.data.teamId;
344
445
  this.customerId = response.data.customer.id;
345
446
  this.authMode = "hmac";
346
447
  this.notifyStateChanged();
448
+ this.assertSession(generation);
347
449
  if (this.realtimeEnabled) {
348
450
  this.realtimeInitPromise = this.initRealtime(
349
451
  response.data.customer.id,
350
- response.data.customer.name || customer.name || customer.email
452
+ response.data.customer.name || customer.name || customer.email,
453
+ generation
351
454
  );
352
455
  }
353
456
  return response.data;
@@ -362,11 +465,15 @@ var ChatClient = class {
362
465
  * Supabase session, use `loginWithSession({ accessToken })` instead.
363
466
  */
364
467
  async loginWithCredentials(params) {
468
+ const generation = this.retireSession();
469
+ this.assertSession(generation);
365
470
  const teamId = await this.resolveTeamIdFromSlug();
471
+ this.assertSession(generation);
366
472
  const response = await this.fetch("/api/widget/auth/login", {
367
473
  method: "POST",
368
474
  body: { email: params.email, password: params.password, teamId }
369
475
  });
476
+ this.assertSession(generation);
370
477
  if (!response.accessToken) {
371
478
  throw new ChatClientAuthError({
372
479
  message: "Login succeeded but no session was issued",
@@ -375,11 +482,14 @@ var ChatClient = class {
375
482
  requestId: null
376
483
  });
377
484
  }
378
- await this.loginWithSession({
379
- accessToken: response.accessToken,
380
- teamId,
381
- customerName: response.customer.name ?? response.customer.email
382
- });
485
+ this.applySession(
486
+ {
487
+ accessToken: response.accessToken,
488
+ teamId,
489
+ customerName: response.customer.name ?? response.customer.email
490
+ },
491
+ generation
492
+ );
383
493
  return {
384
494
  customer: {
385
495
  id: this.customerId ?? response.customer.id,
@@ -398,15 +508,22 @@ var ChatClient = class {
398
508
  * every request — there is no client-side validation here.
399
509
  */
400
510
  async loginWithSession(params) {
511
+ const teamId = params.teamId ?? this.teamId;
512
+ const generation = this.retireSession();
513
+ this.applySession({ ...params, ...teamId ? { teamId } : {} }, generation);
514
+ }
515
+ applySession(params, generation) {
516
+ this.assertSession(generation);
401
517
  this.sessionToken = params.accessToken;
402
518
  if (params.teamId) {
403
519
  this.teamId = params.teamId;
404
520
  }
405
521
  this.authMode = "session";
406
522
  this.notifyStateChanged();
523
+ this.assertSession(generation);
407
524
  if (this.realtimeEnabled) {
408
525
  const customerName = params.customerName ?? "";
409
- this.realtimeInitPromise = this.initRealtimeFromSession(customerName);
526
+ this.realtimeInitPromise = this.initRealtimeFromSession(customerName, generation);
410
527
  }
411
528
  }
412
529
  /**
@@ -447,8 +564,11 @@ var ChatClient = class {
447
564
  * @returns Unsubscribe function
448
565
  */
449
566
  onMessage(ticketId, callback) {
567
+ const generation = this.sessionGeneration;
450
568
  if (this.realtimeReady && this.realtimeManager) {
451
- return this.realtimeManager.subscribeToMessages(ticketId, callback);
569
+ return this.realtimeManager.subscribeToMessages(ticketId, (message) => {
570
+ if (generation === this.sessionGeneration) callback(message);
571
+ });
452
572
  }
453
573
  return this.pollMessages(ticketId, callback);
454
574
  }
@@ -459,8 +579,11 @@ var ChatClient = class {
459
579
  * @returns Unsubscribe function
460
580
  */
461
581
  onTyping(ticketId, callback) {
582
+ const generation = this.sessionGeneration;
462
583
  if (this.realtimeReady && this.presenceManager) {
463
- return this.presenceManager.subscribeToTyping(ticketId, callback);
584
+ return this.presenceManager.subscribeToTyping(ticketId, (typing) => {
585
+ if (generation === this.sessionGeneration) callback(typing);
586
+ });
464
587
  }
465
588
  return () => {
466
589
  };
@@ -476,6 +599,10 @@ var ChatClient = class {
476
599
  }
477
600
  /** Disconnect all subscriptions and clean up. */
478
601
  disconnect() {
602
+ this.retireSession();
603
+ }
604
+ retireSession() {
605
+ const generation = ++this.sessionGeneration;
479
606
  if (this.realtimeManager) {
480
607
  this.realtimeManager.destroy();
481
608
  this.realtimeManager = null;
@@ -486,15 +613,29 @@ var ChatClient = class {
486
613
  }
487
614
  this.realtimeReady = false;
488
615
  this.realtimeInitPromise = null;
489
- for (const timer of this.pollingTimers.values()) {
490
- clearInterval(timer);
616
+ for (const unsubscribe of this.pollingSubscriptions) {
617
+ unsubscribe();
491
618
  }
492
- this.pollingTimers.clear();
619
+ this.pollingSubscriptions.clear();
493
620
  this.sessionToken = null;
494
621
  this.teamId = null;
495
622
  this.customerId = null;
496
623
  this.authMode = null;
497
624
  this.notifyStateChanged();
625
+ return generation;
626
+ }
627
+ assertSession(generation) {
628
+ if (generation !== this.sessionGeneration) {
629
+ throw new ChatClientAuthError({
630
+ code: "SESSION_CHANGED",
631
+ message: "Your sign-in session changed. This operation belongs to the previous session."
632
+ });
633
+ }
634
+ }
635
+ /** @internal Keep a public operation owned across its asynchronous prerequisites. */
636
+ captureSession() {
637
+ const generation = this.sessionGeneration;
638
+ return () => this.assertSession(generation);
498
639
  }
499
640
  /**
500
641
  * @internal Make an authenticated request to the widget API.
@@ -509,6 +650,12 @@ var ChatClient = class {
509
650
  * server-confirmed mode.
510
651
  */
511
652
  async fetch(path, options) {
653
+ const generation = this.sessionGeneration;
654
+ const assertRequest = () => {
655
+ this.assertSession(generation);
656
+ options.signal?.throwIfAborted();
657
+ };
658
+ assertRequest();
512
659
  const url = this.buildUrl(path, options.query);
513
660
  const headers = {
514
661
  "Content-Type": "application/json"
@@ -521,14 +668,18 @@ var ChatClient = class {
521
668
  response = await globalThis.fetch(url, {
522
669
  method: options.method,
523
670
  headers,
671
+ ...options.signal ? { signal: options.signal } : {},
672
+ ...options.cache ? { cache: options.cache } : {},
524
673
  body: options.body ? JSON.stringify(options.body) : void 0
525
674
  });
526
675
  } catch (networkErr) {
676
+ assertRequest();
527
677
  throw new ChatClientNetworkError({
528
678
  message: networkErr instanceof Error ? networkErr.message : "Network request failed",
529
679
  originalError: networkErr
530
680
  });
531
681
  }
682
+ assertRequest();
532
683
  const responseHeaders = response.headers && typeof response.headers.get === "function" ? response.headers : null;
533
684
  const headerMode = responseHeaders?.get("X-Cstar-Auth-Mode") ?? null;
534
685
  if (headerMode === "hmac" || headerMode === "session") {
@@ -536,9 +687,11 @@ var ChatClient = class {
536
687
  this.authMode = headerMode;
537
688
  if (previous !== headerMode) this.notifyStateChanged();
538
689
  }
690
+ assertRequest();
539
691
  const requestId = responseHeaders?.get("X-Request-Id") ?? null;
540
692
  if (!response.ok) {
541
693
  const errorBody = await response.json().catch(() => ({ error: { code: "UNKNOWN", message: "Request failed" } }));
694
+ assertRequest();
542
695
  const code = errorBody.error?.code ?? "UNKNOWN";
543
696
  const message = errorBody.error?.message ?? `Widget API error: ${response.status}`;
544
697
  if (response.status === 401 || response.status === 403) {
@@ -575,7 +728,14 @@ var ChatClient = class {
575
728
  requestId
576
729
  });
577
730
  }
578
- return response.json();
731
+ try {
732
+ const body = options.readBody ? await options.readBody(response) : await response.json();
733
+ assertRequest();
734
+ return body;
735
+ } catch (error) {
736
+ assertRequest();
737
+ throw error;
738
+ }
579
739
  }
580
740
  /**
581
741
  * Look up the team UUID from the configured `teamSlug`. Used by
@@ -584,37 +744,41 @@ var ChatClient = class {
584
744
  *
585
745
  * @internal
586
746
  */
587
- async resolveTeamIdFromSlug() {
747
+ async resolveTeamIdFromSlug(signal) {
588
748
  const response = await this.fetch(
589
749
  "/api/widget/team-by-slug",
590
750
  {
591
751
  method: "GET",
752
+ signal,
592
753
  query: { teamSlug: this.teamSlug }
593
754
  }
594
755
  );
595
756
  return response.data.teamId;
596
757
  }
597
758
  /** @internal Bootstrap realtime from a session login (no precomputed customerId). */
598
- async initRealtimeFromSession(customerName) {
759
+ async initRealtimeFromSession(customerName, generation) {
760
+ const manager = new RealtimeManager({ fetchToken: () => this.fetchRealtimeToken(generation) });
761
+ this.realtimeManager = manager;
599
762
  try {
600
- this.realtimeManager = new RealtimeManager({
601
- fetchToken: () => this.fetchRealtimeToken()
602
- });
603
- const ready = await this.realtimeManager.init();
763
+ const ready = await manager.init();
764
+ if (generation !== this.sessionGeneration || this.realtimeManager !== manager) {
765
+ manager.destroy();
766
+ return;
767
+ }
604
768
  if (!ready) return;
605
769
  this.realtimeReady = true;
606
- const token = this.realtimeManager.getCurrentToken();
770
+ const token = manager.getCurrentToken();
607
771
  const customerId = token ? decodeJwtSub(token) : null;
608
772
  if (customerId) {
609
773
  this.customerId = customerId;
610
774
  this.presenceManager = new PresenceManager({ customerId, customerName });
611
- const client = this.realtimeManager.getClient();
775
+ const client = manager.getClient();
612
776
  if (client) {
613
777
  this.presenceManager.setClient(client);
614
778
  }
615
779
  }
616
780
  } catch {
617
- this.realtimeReady = false;
781
+ if (generation === this.sessionGeneration) this.realtimeReady = false;
618
782
  }
619
783
  }
620
784
  /** @internal Get the stored team ID for requests that need it. */
@@ -632,14 +796,19 @@ var ChatClient = class {
632
796
  * `"Missing teamId"` when the chat client was teamSlug-only because the
633
797
  * tickets sub-resource read `getTeamId()` synchronously and bailed.
634
798
  */
635
- async ensureTeamId() {
799
+ async ensureTeamId(signal) {
800
+ const assertCurrent = this.captureSession();
801
+ signal?.throwIfAborted();
636
802
  if (this.teamId) return this.teamId;
637
803
  if (!this.teamSlug) {
638
804
  throw new ChatClientAuthError(
639
805
  "Missing teamId. Construct ChatClient with `teamSlug` or call `setTeamId()` / `identify()` / `loginWithCredentials()` first."
640
806
  );
641
807
  }
642
- this.teamId = await this.resolveTeamIdFromSlug();
808
+ const teamId = await this.resolveTeamIdFromSlug(signal);
809
+ assertCurrent();
810
+ signal?.throwIfAborted();
811
+ this.teamId = teamId;
643
812
  return this.teamId;
644
813
  }
645
814
  /** @internal Set team ID from identify response or other source. */
@@ -652,28 +821,32 @@ var ChatClient = class {
652
821
  await this.realtimeInitPromise;
653
822
  }
654
823
  }
655
- async initRealtime(customerId, customerName) {
824
+ async initRealtime(customerId, customerName, generation) {
825
+ const manager = new RealtimeManager({ fetchToken: () => this.fetchRealtimeToken(generation) });
826
+ this.realtimeManager = manager;
656
827
  try {
657
- this.realtimeManager = new RealtimeManager({
658
- fetchToken: () => this.fetchRealtimeToken()
659
- });
660
- const ready = await this.realtimeManager.init();
828
+ const ready = await manager.init();
829
+ if (generation !== this.sessionGeneration || this.realtimeManager !== manager) {
830
+ manager.destroy();
831
+ return;
832
+ }
661
833
  if (ready) {
662
834
  this.realtimeReady = true;
663
835
  this.presenceManager = new PresenceManager({
664
836
  customerId,
665
837
  customerName
666
838
  });
667
- const client = this.realtimeManager.getClient();
839
+ const client = manager.getClient();
668
840
  if (client) {
669
841
  this.presenceManager.setClient(client);
670
842
  }
671
843
  }
672
844
  } catch {
673
- this.realtimeReady = false;
845
+ if (generation === this.sessionGeneration) this.realtimeReady = false;
674
846
  }
675
847
  }
676
- async fetchRealtimeToken() {
848
+ async fetchRealtimeToken(generation) {
849
+ this.assertSession(generation);
677
850
  const response = await this.fetch(
678
851
  "/api/widget/realtime-token",
679
852
  {
@@ -681,34 +854,47 @@ var ChatClient = class {
681
854
  body: { teamId: this.teamId }
682
855
  }
683
856
  );
857
+ this.assertSession(generation);
684
858
  return response.data;
685
859
  }
686
860
  pollMessages(ticketId, callback) {
687
861
  let lastMessageId = null;
862
+ let initialized = false;
863
+ let active = true;
864
+ let inFlight = false;
688
865
  const poll = async () => {
866
+ if (!active || inFlight) return;
867
+ inFlight = true;
689
868
  try {
690
869
  const messages = await this.messages.list(ticketId);
870
+ if (!active) return;
691
871
  if (messages.length > 0) {
692
872
  const latest = messages[messages.length - 1];
693
- if (lastMessageId && latest.id !== lastMessageId) {
873
+ if (initialized && latest.id !== lastMessageId) {
694
874
  const lastIdx = messages.findIndex((m) => m.id === lastMessageId);
695
- const newMessages = lastIdx >= 0 ? messages.slice(lastIdx + 1) : [latest];
875
+ const newMessages = lastIdx >= 0 ? messages.slice(lastIdx + 1) : lastMessageId ? [latest] : messages;
696
876
  for (const msg of newMessages) {
877
+ if (!active) return;
697
878
  callback(msg);
698
879
  }
699
880
  }
700
881
  lastMessageId = latest.id;
701
882
  }
883
+ initialized = true;
702
884
  } catch {
885
+ } finally {
886
+ inFlight = false;
703
887
  }
704
888
  };
705
889
  poll();
706
890
  const timer = setInterval(poll, this.pollingInterval);
707
- this.pollingTimers.set(ticketId, timer);
708
- return () => {
891
+ const unsubscribe = () => {
892
+ active = false;
709
893
  clearInterval(timer);
710
- this.pollingTimers.delete(ticketId);
894
+ this.pollingSubscriptions.delete(unsubscribe);
711
895
  };
896
+ this.pollingSubscriptions.add(unsubscribe);
897
+ return unsubscribe;
712
898
  }
713
899
  buildUrl(path, query) {
714
900
  const base = `${this.baseUrl}${path}`;
@@ -727,10 +913,12 @@ var TicketsApi = class {
727
913
  }
728
914
  /** List tickets for the identified customer. */
729
915
  async list(params) {
916
+ const assertCurrent = this.chat.captureSession();
730
917
  if (this.chat.getAuthMode() === null) {
731
918
  throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
732
919
  }
733
920
  const teamId = await this.chat.ensureTeamId();
921
+ assertCurrent();
734
922
  const response = await this.chat.fetch("/api/widget/conversations", {
735
923
  method: "GET",
736
924
  query: {
@@ -739,6 +927,7 @@ var TicketsApi = class {
739
927
  cursor: params?.cursor
740
928
  }
741
929
  });
930
+ assertCurrent();
742
931
  const data = response.data.tickets ?? response.data.conversations ?? [];
743
932
  const cursor = response.data.cursor;
744
933
  const hasMore = response.data.hasMore;
@@ -750,10 +939,12 @@ var TicketsApi = class {
750
939
  }
751
940
  /** Create a new ticket. */
752
941
  async create(params) {
942
+ const assertCurrent = this.chat.captureSession();
753
943
  if (this.chat.getAuthMode() === null) {
754
944
  throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
755
945
  }
756
946
  const teamId = await this.chat.ensureTeamId();
947
+ assertCurrent();
757
948
  const response = await this.chat.fetch("/api/widget/tickets", {
758
949
  method: "POST",
759
950
  body: {
@@ -762,6 +953,7 @@ var TicketsApi = class {
762
953
  message: params.message
763
954
  }
764
955
  });
956
+ assertCurrent();
765
957
  const messages = (response.data.messages ?? []).map((m) => ({
766
958
  id: m.id,
767
959
  content: m.content,
@@ -920,6 +1112,7 @@ var MessagesApi = class {
920
1112
  }
921
1113
  /** List messages for a ticket. */
922
1114
  async list(ticketId) {
1115
+ const assertCurrent = this.chat.captureSession();
923
1116
  const teamId = this.chat.getTeamId();
924
1117
  const response = await this.chat.fetch(
925
1118
  "/api/widget/messages",
@@ -931,10 +1124,12 @@ var MessagesApi = class {
931
1124
  }
932
1125
  }
933
1126
  );
1127
+ assertCurrent();
934
1128
  return response.data.messages;
935
1129
  }
936
1130
  /** Send a message to a ticket. */
937
1131
  async send(ticketId, content) {
1132
+ const assertCurrent = this.chat.captureSession();
938
1133
  const teamId = this.chat.getTeamId();
939
1134
  const response = await this.chat.fetch(
940
1135
  "/api/widget/messages",
@@ -947,6 +1142,7 @@ var MessagesApi = class {
947
1142
  }
948
1143
  }
949
1144
  );
1145
+ assertCurrent();
950
1146
  return response.data.message;
951
1147
  }
952
1148
  };