@experteam-mx/ngx-services 20.8.6 → 20.8.8

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.
@@ -5583,15 +5583,53 @@ var DocumentStatusCode;
5583
5583
  })(DocumentStatusCode || (DocumentStatusCode = {}));
5584
5584
 
5585
5585
  class WebSocketsService {
5586
- pusher;
5586
+ pusher = null;
5587
+ appKey = null;
5588
+ connectPromise = null;
5587
5589
  environments = inject(ENVIRONMENT_TOKEN);
5588
- constructor() {
5589
- this.pusher = null;
5590
- this.connect()
5591
- .then((pusher) => {
5592
- if (!pusher)
5593
- return;
5590
+ /**
5591
+ * Stores the Pusher/Soketi application key without opening a connection.
5592
+ * The first `channelSub` / `eventBind` opens Pusher via `ensureConnected`.
5593
+ *
5594
+ * @param {string} appKey - The Pusher/Soketi application key.
5595
+ */
5596
+ setAppKey(appKey) {
5597
+ this.appKey = appKey;
5598
+ }
5599
+ /**
5600
+ * Connects to Pusher using the given app key and env `sockets` url/port/debug.
5601
+ * No-ops if already connected with the same key; reconnects if the key changed.
5602
+ * Resolves false when `sockets` is missing from the environment.
5603
+ * Apps should store the key with `setAppKey` and let subscribe open the client.
5604
+ *
5605
+ * @param {string} appKey - The Pusher/Soketi application key.
5606
+ * @return {Promise<Pusher | false>} The Pusher instance, or false when sockets are not configured.
5607
+ */
5608
+ connect(appKey) {
5609
+ this.setAppKey(appKey);
5610
+ return new Promise((resolve) => {
5611
+ if (this.pusher && this.appKey === appKey) {
5612
+ return resolve(this.pusher);
5613
+ }
5614
+ const { sockets } = this.environments;
5615
+ if (!sockets)
5616
+ return resolve(false);
5617
+ if (this.pusher) {
5618
+ this.pusher.disconnect();
5619
+ this.pusher = null;
5620
+ }
5621
+ const pusher = new Pusher(appKey, {
5622
+ wsHost: sockets.url,
5623
+ wsPort: sockets.port,
5624
+ enabledTransports: ['wss', 'ws'],
5625
+ forceTLS: false,
5626
+ enableStats: false,
5627
+ });
5628
+ if (sockets.debug) {
5629
+ Pusher.logToConsole = true;
5630
+ }
5594
5631
  this.pusher = pusher;
5632
+ return resolve(pusher);
5595
5633
  });
5596
5634
  }
5597
5635
  /**
@@ -5614,13 +5652,14 @@ class WebSocketsService {
5614
5652
  * @throws {Error} If the subscription fails after the maximum number of retry attempts.
5615
5653
  */
5616
5654
  async channelSub(channelName) {
5655
+ const pusher = await this.ensureConnected();
5617
5656
  const attempts = 3;
5618
5657
  for (let attempt = 0; attempt <= attempts; attempt++) {
5619
- const channel = this.pusher?.channel(channelName);
5658
+ const channel = pusher.channel(channelName);
5620
5659
  if (channel?.subscribed) {
5621
5660
  return channel;
5622
5661
  }
5623
- this.pusher?.subscribe(channelName);
5662
+ pusher.subscribe(channelName);
5624
5663
  if (attempt < attempts) {
5625
5664
  await this.wait();
5626
5665
  }
@@ -5637,13 +5676,21 @@ class WebSocketsService {
5637
5676
  */
5638
5677
  eventBind(channel, event) {
5639
5678
  return new Observable((subscriber) => {
5640
- if (channel?.name) {
5641
- channel.bind(event, (data) => subscriber.next(data));
5642
- }
5643
- else {
5644
- this.pusher?.subscribe(channel)
5645
- .bind(event, (data) => subscriber.next(data));
5646
- }
5679
+ void (async () => {
5680
+ try {
5681
+ 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
+ }
5689
+ }
5690
+ catch (error) {
5691
+ subscriber.error(error);
5692
+ }
5693
+ })();
5647
5694
  });
5648
5695
  }
5649
5696
  /**
@@ -5657,23 +5704,24 @@ class WebSocketsService {
5657
5704
  eventUnbind(channel, event) {
5658
5705
  return new Observable((subscriber) => channel.unbind(event, (data) => subscriber.next(data)));
5659
5706
  }
5660
- connect() {
5661
- return new Promise((resolve) => {
5662
- const { sockets } = this.environments;
5663
- if (!sockets)
5664
- return resolve(false);
5665
- const pusher = new Pusher(sockets.app_key, {
5666
- wsHost: sockets.url,
5667
- wsPort: sockets.port,
5668
- enabledTransports: ['wss', 'ws'],
5669
- forceTLS: false,
5670
- enableStats: false,
5671
- });
5672
- if (sockets.debug) {
5673
- Pusher.logToConsole = true;
5707
+ async ensureConnected() {
5708
+ if (this.pusher)
5709
+ return this.pusher;
5710
+ if (!this.appKey) {
5711
+ throw new Error('The sockets connection is not established.');
5712
+ }
5713
+ this.connectPromise ??= this.connect(this.appKey);
5714
+ try {
5715
+ const pusher = await this.connectPromise;
5716
+ if (!pusher) {
5717
+ throw new Error('The sockets connection is not established.');
5674
5718
  }
5675
- return resolve(pusher);
5676
- });
5719
+ return pusher;
5720
+ }
5721
+ catch (error) {
5722
+ this.connectPromise = null;
5723
+ throw error;
5724
+ }
5677
5725
  }
5678
5726
  async wait() {
5679
5727
  const waitTime = 3 * 1000;
@@ -5687,13 +5735,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
5687
5735
  args: [{
5688
5736
  providedIn: 'root',
5689
5737
  }]
5690
- }], ctorParameters: () => [] });
5738
+ }] });
5691
5739
 
5692
5740
  const AES_KEY_USAGES = ['encrypt', 'decrypt'];
5693
5741
  class CryptoService {
5694
- environments = inject(ENVIRONMENT_TOKEN);
5695
- async encryptAES(plaintext) {
5696
- const cryptoKey = await this.loadKey();
5742
+ async encryptAES(plaintext, secretKey) {
5743
+ const cryptoKey = await this.loadKey(secretKey);
5697
5744
  // Convert the plaintext in Uint8Array
5698
5745
  const encoder = new TextEncoder();
5699
5746
  const encoded = encoder.encode(plaintext);
@@ -5706,13 +5753,13 @@ class CryptoService {
5706
5753
  }, cryptoKey, encoded);
5707
5754
  return `${this.uint8ArrayToBase64(iv)}:${this.arrayBufferToBase64(ciphertext)}`;
5708
5755
  }
5709
- async decryptAES(payload) {
5756
+ async decryptAES(payload, secretKey) {
5710
5757
  // Extract the Initialization Vector (IV), and the cypher text
5711
5758
  const [base64IV, base64Ciphertext] = payload.split(':');
5712
5759
  if (!base64IV || !base64Ciphertext) {
5713
5760
  throw new Error('The payload must contain the IV and the cipher text.');
5714
5761
  }
5715
- const cryptoKey = await this.loadKey();
5762
+ const cryptoKey = await this.loadKey(secretKey);
5716
5763
  const iv = this.base64ToUint8Array(base64IV);
5717
5764
  const cipherText = this.base64ToArrayBuffer(base64Ciphertext);
5718
5765
  // Decrypt the cypher text
@@ -5724,14 +5771,12 @@ class CryptoService {
5724
5771
  const decoder = new TextDecoder();
5725
5772
  return decoder.decode(decrypted);
5726
5773
  }
5727
- async loadKey() {
5728
- if (!this.environments.secretKey) {
5729
- throw new Error('The secret key is not defined in the environment configuration.');
5774
+ async loadKey(secretKey) {
5775
+ if (!secretKey) {
5776
+ throw new Error('The secret key is not defined.');
5730
5777
  }
5731
- // Decode the base64 key to Uint8Array
5732
- const rawKey = this.base64ToUint8Array(this.environments.secretKey);
5733
- // Import the key to API Crypto
5734
- return await crypto.subtle.importKey('raw', rawKey, { name: 'AES-GCM' }, true, AES_KEY_USAGES);
5778
+ const rawKey = new TextEncoder().encode(secretKey);
5779
+ return crypto.subtle.importKey('raw', rawKey, { name: 'AES-GCM' }, true, AES_KEY_USAGES);
5735
5780
  }
5736
5781
  uint8ArrayToBase64(data) {
5737
5782
  let binary = '';