@experteam-mx/ngx-services 20.8.8 → 20.8.10

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.
@@ -5582,11 +5582,14 @@ var DocumentStatusCode;
5582
5582
  DocumentStatusCode[DocumentStatusCode["WITH_ERRORS"] = 3] = "WITH_ERRORS";
5583
5583
  })(DocumentStatusCode || (DocumentStatusCode = {}));
5584
5584
 
5585
+ const SOCKETS_AUTH_PATH = '/sockets/auth';
5585
5586
  class WebSocketsService {
5586
5587
  pusher = null;
5587
5588
  appKey = null;
5588
5589
  connectPromise = null;
5589
5590
  environments = inject(ENVIRONMENT_TOKEN);
5591
+ getAuthToken = null;
5592
+ channelAuthHeaders = {};
5590
5593
  /**
5591
5594
  * Stores the Pusher/Soketi application key without opening a connection.
5592
5595
  * The first `channelSub` / `eventBind` opens Pusher via `ensureConnected`.
@@ -5596,6 +5599,15 @@ class WebSocketsService {
5596
5599
  setAppKey(appKey) {
5597
5600
  this.appKey = appKey;
5598
5601
  }
5602
+ /**
5603
+ * Registers a live token provider used when authorizing private/presence channels.
5604
+ * The provider is called at subscribe/authorize time; the token is not snapshotted here.
5605
+ *
5606
+ * @param {() => string | null} getToken - Returns the current session token, or null.
5607
+ */
5608
+ setAuthTokenProvider(getToken) {
5609
+ this.getAuthToken = getToken;
5610
+ }
5599
5611
  /**
5600
5612
  * Connects to Pusher using the given app key and env `sockets` url/port/debug.
5601
5613
  * No-ops if already connected with the same key; reconnects if the key changed.
@@ -5618,13 +5630,27 @@ class WebSocketsService {
5618
5630
  this.pusher.disconnect();
5619
5631
  this.pusher = null;
5620
5632
  }
5621
- const pusher = new Pusher(appKey, {
5633
+ const options = {
5622
5634
  wsHost: sockets.url,
5623
5635
  wsPort: sockets.port,
5624
5636
  enabledTransports: ['wss', 'ws'],
5625
5637
  forceTLS: false,
5626
5638
  enableStats: false,
5627
- });
5639
+ };
5640
+ const { apiSecurityUrl } = this.environments;
5641
+ if (apiSecurityUrl) {
5642
+ this.refreshChannelAuthHeader();
5643
+ options.channelAuthorization = {
5644
+ transport: 'ajax',
5645
+ endpoint: `${apiSecurityUrl}${SOCKETS_AUTH_PATH}`,
5646
+ headers: this.channelAuthHeaders,
5647
+ headersProvider: () => {
5648
+ this.refreshChannelAuthHeader();
5649
+ return this.channelAuthHeaders;
5650
+ },
5651
+ };
5652
+ }
5653
+ const pusher = new Pusher(appKey, options);
5628
5654
  if (sockets.debug) {
5629
5655
  Pusher.logToConsole = true;
5630
5656
  }
@@ -5645,26 +5671,40 @@ class WebSocketsService {
5645
5671
  return channel.trigger(`client-${eventName}`, data);
5646
5672
  }
5647
5673
  /**
5648
- * Subscribes to a specified channel, retrying multiple times upon failure.
5674
+ * Subscribes to a specified channel and resolves when Pusher reports success.
5649
5675
  *
5650
5676
  * @param {string} channelName - The name of the channel to be subscribed to.
5651
5677
  * @return {Promise<Channel>} A promise that resolves to the subscribed channel object if successful.
5652
- * @throws {Error} If the subscription fails after the maximum number of retry attempts.
5678
+ * @throws {Error} If the subscription fails.
5653
5679
  */
5654
5680
  async channelSub(channelName) {
5655
5681
  const pusher = await this.ensureConnected();
5656
- const attempts = 3;
5657
- for (let attempt = 0; attempt <= attempts; attempt++) {
5658
- const channel = pusher.channel(channelName);
5659
- if (channel?.subscribed) {
5660
- return channel;
5661
- }
5662
- pusher.subscribe(channelName);
5663
- if (attempt < attempts) {
5664
- await this.wait();
5665
- }
5682
+ this.refreshChannelAuthHeader();
5683
+ const existing = pusher.channel(channelName);
5684
+ if (existing?.subscribed) {
5685
+ return existing;
5666
5686
  }
5667
- throw new Error(`Failed to subscribe to channel "${channelName}" after ${attempts} attempts.`);
5687
+ const channel = pusher.subscribe(channelName);
5688
+ if (channel.subscribed) {
5689
+ return channel;
5690
+ }
5691
+ await new Promise((resolve, reject) => {
5692
+ const onSuccess = () => {
5693
+ cleanup();
5694
+ resolve();
5695
+ };
5696
+ const onError = () => {
5697
+ cleanup();
5698
+ reject(new Error(`Failed to subscribe to channel "${channelName}".`));
5699
+ };
5700
+ const cleanup = () => {
5701
+ channel.unbind('pusher:subscription_succeeded', onSuccess);
5702
+ channel.unbind('pusher:subscription_error', onError);
5703
+ };
5704
+ channel.bind('pusher:subscription_succeeded', onSuccess);
5705
+ channel.bind('pusher:subscription_error', onError);
5706
+ });
5707
+ return channel;
5668
5708
  }
5669
5709
  /**
5670
5710
  * Binds an event listener to a specified event on a given channel using Pusher or a Channel object,
@@ -5676,16 +5716,16 @@ class WebSocketsService {
5676
5716
  */
5677
5717
  eventBind(channel, event) {
5678
5718
  return new Observable((subscriber) => {
5719
+ if (channel?.name) {
5720
+ channel.bind(event, (data) => subscriber.next(data));
5721
+ return;
5722
+ }
5679
5723
  void (async () => {
5680
5724
  try {
5681
5725
  const pusher = await this.ensureConnected();
5682
- if (channel?.name) {
5683
- channel.bind(event, (data) => subscriber.next(data));
5684
- }
5685
- else {
5686
- pusher.subscribe(channel)
5687
- .bind(event, (data) => subscriber.next(data));
5688
- }
5726
+ this.refreshChannelAuthHeader();
5727
+ pusher.subscribe(channel)
5728
+ .bind(event, (data) => subscriber.next(data));
5689
5729
  }
5690
5730
  catch (error) {
5691
5731
  subscriber.error(error);
@@ -5704,6 +5744,14 @@ class WebSocketsService {
5704
5744
  eventUnbind(channel, event) {
5705
5745
  return new Observable((subscriber) => channel.unbind(event, (data) => subscriber.next(data)));
5706
5746
  }
5747
+ /**
5748
+ * Unsubscribes from a channel by name.
5749
+ *
5750
+ * @param {string} channelName - The channel name previously passed to subscribe.
5751
+ */
5752
+ unsubscribe(channelName) {
5753
+ this.pusher?.unsubscribe(channelName);
5754
+ }
5707
5755
  async ensureConnected() {
5708
5756
  if (this.pusher)
5709
5757
  return this.pusher;
@@ -5723,9 +5771,14 @@ class WebSocketsService {
5723
5771
  throw error;
5724
5772
  }
5725
5773
  }
5726
- async wait() {
5727
- const waitTime = 3 * 1000;
5728
- return new Promise((resolve) => setTimeout(resolve, waitTime));
5774
+ refreshChannelAuthHeader() {
5775
+ const token = this.getAuthToken?.() ?? null;
5776
+ if (token) {
5777
+ this.channelAuthHeaders['Authorization'] = `Bearer ${token}`;
5778
+ }
5779
+ else {
5780
+ delete this.channelAuthHeaders['Authorization'];
5781
+ }
5729
5782
  }
5730
5783
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: WebSocketsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5731
5784
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: WebSocketsService, providedIn: 'root' });