http-request-manager 18.7.1 → 18.7.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.
@@ -789,7 +789,9 @@ class WebsocketService {
789
789
  })();
790
790
  }
791
791
  sendSubscribe(channelName, user) {
792
- if (this.socket?.readyState === WebSocket.OPEN && !this.isSubscribed) {
792
+ // Check if already subscribed to THIS specific channel (not just any channel)
793
+ const alreadySubscribed = this.subscribedChannels.value.has(channelName);
794
+ if (this.socket?.readyState === WebSocket.OPEN && !alreadySubscribed) {
793
795
  const message = {
794
796
  type: 'subscribe',
795
797
  subscribedChannel: channelName,
@@ -799,11 +801,15 @@ class WebsocketService {
799
801
  }
800
802
  };
801
803
  this.socket.send(JSON.stringify(message));
802
- this.isSubscribed = true; // Set the flag immediately after sending
804
+ // Track this channel as subscribed
805
+ const current = new Set(this.subscribedChannels.value);
806
+ current.add(channelName);
807
+ this.subscribedChannels.next(current);
808
+ this.isSubscribed = true; // Keep for backward compatibility
803
809
  console.log(`[CLIENT] Sent initial subscription to: ${channelName}`);
804
810
  }
805
811
  else {
806
- console.warn(`[CLIENT] Subscription prevented. Open: ${this.socket?.readyState === WebSocket.OPEN}, Subscribed: ${this.isSubscribed}`);
812
+ console.warn(`[CLIENT] Subscription prevented. Open: ${this.socket?.readyState === WebSocket.OPEN}, Already subscribed to ${channelName}: ${alreadySubscribed}`);
807
813
  }
808
814
  }
809
815
  connect(options, jwtToken) {
@@ -823,6 +829,8 @@ class WebsocketService {
823
829
  }
824
830
  }
825
831
  this.isSubscribed = false;
832
+ // Clear tracked subscriptions for new connection
833
+ this.subscribedChannels.next(new Set());
826
834
  const sessionId = this.getSessionId();
827
835
  const URL = (jwtToken) ? `${options.wsServer}?token=${jwtToken}&sessionId=${sessionId}` : `${options.wsServer}?sessionId=${sessionId}`;
828
836
  this.socket = new WebSocket(URL);
@@ -2992,6 +3000,27 @@ class ChannelMessage {
2992
3000
  }
2993
3001
 
2994
3002
  const API_OPTS = new InjectionToken('API_OPTS');
3003
+ /**
3004
+ * Channel type enum for different communication purposes
3005
+ * - STATE: Private channels for state synchronization
3006
+ * - MESSAGE: Messaging/communication channels
3007
+ * - NOTIFICATION: Notification/broadcast channels
3008
+ */
3009
+ var ChannelType;
3010
+ (function (ChannelType) {
3011
+ ChannelType["STATE"] = "SYS";
3012
+ ChannelType["MESSAGE"] = "MES";
3013
+ ChannelType["NOTIFICATION"] = "PUB";
3014
+ })(ChannelType || (ChannelType = {}));
3015
+ /**
3016
+ * Utility function to create prefixed channel name
3017
+ * @param channelType - The type of channel
3018
+ * @param channelName - The base channel name
3019
+ * @returns Prefixed channel name (e.g., 'SYS-USERS123')
3020
+ */
3021
+ function createChannelName(channelType, channelName) {
3022
+ return `${channelType}-${channelName}`;
3023
+ }
2995
3024
  const defaultState = {
2996
3025
  data: [],
2997
3026
  dataObject: null,
@@ -3105,11 +3134,16 @@ class HTTPManagerStateService extends ComponentStore {
3105
3134
  // Compare sender's session ID with current user's ID
3106
3135
  // message.data.sessionId is an object with 'id' property from server
3107
3136
  const stateManagerSenderId = message.data.sessionId?.id || message.data.sessionId;
3137
+ console.log('🔍 State Manager: Sender ID:', stateManagerSenderId, 'Current User ID:', this.user.value?.id);
3108
3138
  if (stateManagerSenderId !== this.user.value?.id) {
3109
3139
  console.log('💬 State Manager Message:', message.data);
3140
+ console.log('📥 Fetching record with path:', message.data.content.path, 'method:', message.data.content.method);
3110
3141
  this.userAction.next(message.data);
3111
3142
  this.fetchRecord(RequestOptions.adapt({ path: message.data.content.path }), message.data.content.method);
3112
3143
  }
3144
+ else {
3145
+ console.log('⏭️ Skipping own message');
3146
+ }
3113
3147
  break;
3114
3148
  case 'channelMessage':
3115
3149
  // Handle channel-based messages (from sendChannelMessage)
@@ -3339,19 +3373,27 @@ class HTTPManagerStateService extends ComponentStore {
3339
3373
  return fetchFromAPI();
3340
3374
  })));
3341
3375
  // FETCH RECORD
3342
- this.fetchRecord = (options, method) => this.effect(() => of(RequestOptions.adapt(options)).pipe(switchMap((options) => {
3376
+ this.fetchRecord = (options, method) => this.effect(() => of(RequestOptions.adapt(options)).pipe(tap(() => console.log('🔄 fetchRecord effect triggered with path:', options?.path, 'method:', method)), switchMap((options) => {
3343
3377
  this.streamedResponse = [];
3344
3378
  const requestOptions = this.updateRequestOptions(options?.headers);
3379
+ console.log('🌐 Making GET request to path:', options?.path);
3345
3380
  return this.httpManagerService.getRequest(requestOptions, options?.path)
3346
3381
  .pipe(tap((data) => {
3382
+ console.log('📦 fetchRecord received data:', data);
3347
3383
  data = (!data) ? (this.dataType === DataType.ARRAY) ? [] : {} : data;
3348
3384
  const id = options.path?.length ? options.path[options.path.length - 1] : null;
3349
- if (method === 'DELETE')
3385
+ if (method === 'DELETE') {
3386
+ console.log('🗑️ Deleting record with id:', id);
3350
3387
  this.deleteData$({ id });
3351
- if (method === 'UPDATE')
3388
+ }
3389
+ if (method === 'UPDATE') {
3390
+ console.log('✏️ Updating record:', data);
3352
3391
  this.updateData$(data);
3353
- if (method === 'CREATE')
3392
+ }
3393
+ if (method === 'CREATE') {
3394
+ console.log('➕ Adding record:', data);
3354
3395
  this.addData$(data);
3396
+ }
3355
3397
  }), concatMap((data) => {
3356
3398
  if (this.hasDatabase && this.databaseOptions?.table) {
3357
3399
  const id = options.path?.length ? options.path[options.path.length - 1] : null;
@@ -3480,6 +3522,36 @@ class HTTPManagerStateService extends ComponentStore {
3480
3522
  this.initDBStorage();
3481
3523
  }
3482
3524
  }
3525
+ /**
3526
+ * Add appropriate prefix to a channel name if not already present
3527
+ */
3528
+ prefixChannel(channel, type) {
3529
+ const prefix = `${type}-`;
3530
+ if (channel.startsWith(prefix)) {
3531
+ return channel;
3532
+ }
3533
+ // Remove any other known prefix before adding the correct one
3534
+ const cleanChannel = this.stripChannelPrefix(channel);
3535
+ return `${type}-${cleanChannel}`;
3536
+ }
3537
+ /**
3538
+ * Remove any known prefix from a channel name
3539
+ */
3540
+ stripChannelPrefix(channel) {
3541
+ for (const type of Object.values(ChannelType)) {
3542
+ const prefix = `${type}-`;
3543
+ if (channel.startsWith(prefix)) {
3544
+ return channel.slice(prefix.length);
3545
+ }
3546
+ }
3547
+ return channel;
3548
+ }
3549
+ /**
3550
+ * Get the base channel name without prefix (for display/user reference)
3551
+ */
3552
+ getBaseChannelName(channel) {
3553
+ return this.stripChannelPrefix(channel);
3554
+ }
3483
3555
  setApiRequestOptions(apiOptions, dataType, database) {
3484
3556
  this.apiOptions = ApiRequest.adapt(apiOptions);
3485
3557
  this.dataType = (dataType) ? dataType : DataType.ARRAY;
@@ -3489,6 +3561,10 @@ class HTTPManagerStateService extends ComponentStore {
3489
3561
  this.databaseOptions = (this.hasDatabase) ? DatabaseStorage.adapt(database) : undefined;
3490
3562
  }
3491
3563
  if (this.apiOptions.ws && this.apiOptions.ws.id !== '') {
3564
+ // Auto-prefix channel ID for private state manager channels
3565
+ // This ensures state manager channels are separate from user-defined channels
3566
+ this.apiOptions.ws.id = this.prefixChannel(this.apiOptions.ws.id, ChannelType.STATE);
3567
+ console.log(`🔒 Private state channel: ${this.apiOptions.ws.id}`);
3492
3568
  // Update WebSocket retry settings when options change
3493
3569
  if (this.apiOptions.ws?.retry) {
3494
3570
  this.maxRetries = this.apiOptions.ws.retry.times || 3;
@@ -3638,6 +3714,12 @@ class HTTPManagerStateService extends ComponentStore {
3638
3714
  this.httpManagerService.sendMessageInChannel(wsServer, { method, path, user: this.apiOptions.ws.user });
3639
3715
  }
3640
3716
  }
3717
+ /**
3718
+ * Send a message to channel(s)
3719
+ * @param message - The message content
3720
+ * @param channels - Optional array of channel names (MES- prefix added automatically)
3721
+ * Use 'allChannels' to broadcast to all
3722
+ */
3641
3723
  wsMessaging(message, channels) {
3642
3724
  const user = this.user.value;
3643
3725
  const messageInfo = ChannelMessage.adapt({ ...message, fromUser: user });
@@ -3645,8 +3727,9 @@ class HTTPManagerStateService extends ComponentStore {
3645
3727
  if (this.wsConnection && this.apiOptions.ws) {
3646
3728
  // If specific channels provided, send to each channel
3647
3729
  if (channels && channels.length > 0) {
3648
- console.log(`📤 Sending to ${channels.length} channel(s):`, channels);
3649
- channels.forEach(channel => {
3730
+ const prefixedChannels = channels.map(ch => ch === 'allChannels' ? ch : this.prefixChannel(ch, ChannelType.MESSAGE));
3731
+ console.log(`📤 Sending to ${prefixedChannels.length} channel(s):`, prefixedChannels);
3732
+ prefixedChannels.forEach(channel => {
3650
3733
  if (channel === 'allChannels') {
3651
3734
  this.httpManagerService.sendBroadcast(messageInfo);
3652
3735
  }
@@ -3656,17 +3739,46 @@ class HTTPManagerStateService extends ComponentStore {
3656
3739
  });
3657
3740
  }
3658
3741
  else {
3659
- // Fallback to the primary WS channel
3742
+ // Fallback to the primary WS channel (already prefixed with SYS-)
3660
3743
  const wsChannel = this.apiOptions.ws.id;
3661
- console.log(`📤 Sending to fallback channel:`, wsChannel);
3744
+ console.log(`📤 Sending to state channel:`, wsChannel);
3662
3745
  this.httpManagerService.sendChannelMessage(wsChannel, messageInfo);
3663
3746
  }
3664
3747
  }
3665
3748
  }
3749
+ /**
3750
+ * Subscribe to a messaging channel
3751
+ * @param channel - Base channel name (MES- prefix added automatically)
3752
+ */
3753
+ subscribeToMessageChannel(channel) {
3754
+ if (this.wsConnection) {
3755
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.MESSAGE);
3756
+ this.httpManagerService.subscribeToChannel(prefixedChannel);
3757
+ console.log(`💬 Subscribed to message channel: ${prefixedChannel}`);
3758
+ }
3759
+ else {
3760
+ console.warn('Cannot subscribe to message channel: WebSocket not connected.');
3761
+ }
3762
+ }
3763
+ /**
3764
+ * Unsubscribe from a messaging channel
3765
+ * @param channel - Base channel name (MES- prefix added automatically)
3766
+ */
3767
+ unsubscribeFromMessageChannel(channel) {
3768
+ if (this.wsConnection) {
3769
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.MESSAGE);
3770
+ this.httpManagerService.unsubscribeFromChannel(prefixedChannel);
3771
+ console.log(`💬 Unsubscribed from message channel: ${prefixedChannel}`);
3772
+ }
3773
+ else {
3774
+ console.warn('Cannot unsubscribe from message channel: WebSocket not connected.');
3775
+ }
3776
+ }
3666
3777
  // --------------------------------------------------------------------------------------------------
3667
- // CHANNEL MANAGEMENT
3778
+ // CHANNEL MANAGEMENT (Raw channels - no automatic prefix)
3668
3779
  /**
3669
- * Subscribe to a single channel
3780
+ * Subscribe to a single channel (no automatic prefix)
3781
+ * Use subscribeToMessageChannel() for MES- prefixed channels
3670
3782
  */
3671
3783
  subscribeToChannel(channel) {
3672
3784
  if (this.wsConnection) {
@@ -3755,13 +3867,16 @@ class HTTPManagerStateService extends ComponentStore {
3755
3867
  }
3756
3868
  }
3757
3869
  // --------------------------------------------------------------------------------------------------
3758
- // NOTIFICATION CHANNELS (MES- prefix)
3870
+ // NOTIFICATION CHANNELS (PUB- prefix - managed automatically)
3759
3871
  /**
3760
3872
  * Create a notification channel on the server
3873
+ * @param channel - Base channel name (PUB- prefix added automatically)
3761
3874
  */
3762
3875
  createNotificationChannel(channel) {
3763
3876
  if (this.wsConnection) {
3764
- this.httpManagerService.createNotificationChannel(channel);
3877
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
3878
+ this.httpManagerService.createNotificationChannel(prefixedChannel);
3879
+ console.log(`📢 Creating notification channel: ${prefixedChannel}`);
3765
3880
  }
3766
3881
  else {
3767
3882
  console.warn('Cannot create notification channel: WebSocket not connected.');
@@ -3792,10 +3907,13 @@ class HTTPManagerStateService extends ComponentStore {
3792
3907
  }
3793
3908
  /**
3794
3909
  * Subscribe to a notification channel with optional date filters
3910
+ * @param channel - Base channel name (PUB- prefix added automatically)
3795
3911
  */
3796
3912
  subscribeToNotificationChannel(channel, options, user) {
3797
3913
  if (this.wsConnection) {
3798
- this.httpManagerService.subscribeToNotificationChannel(channel, options, user);
3914
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
3915
+ this.httpManagerService.subscribeToNotificationChannel(prefixedChannel, options, user);
3916
+ console.log(`📢 Subscribing to notification channel: ${prefixedChannel}`);
3799
3917
  }
3800
3918
  else {
3801
3919
  console.warn('Cannot subscribe to notification channel: WebSocket not connected.');
@@ -3803,10 +3921,13 @@ class HTTPManagerStateService extends ComponentStore {
3803
3921
  }
3804
3922
  /**
3805
3923
  * Unsubscribe from a notification channel
3924
+ * @param channel - Base channel name (PUB- prefix added automatically)
3806
3925
  */
3807
3926
  unsubscribeFromNotificationChannel(channel) {
3808
3927
  if (this.wsConnection) {
3809
- this.httpManagerService.unsubscribeFromNotificationChannel(channel);
3928
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
3929
+ this.httpManagerService.unsubscribeFromNotificationChannel(prefixedChannel);
3930
+ console.log(`📢 Unsubscribing from notification channel: ${prefixedChannel}`);
3810
3931
  }
3811
3932
  else {
3812
3933
  console.warn('Cannot unsubscribe from notification channel: WebSocket not connected.');
@@ -3814,10 +3935,13 @@ class HTTPManagerStateService extends ComponentStore {
3814
3935
  }
3815
3936
  /**
3816
3937
  * Send a notification to a channel
3938
+ * @param channel - Base channel name (PUB- prefix added automatically)
3817
3939
  */
3818
3940
  sendNotification(channel, content) {
3819
3941
  if (this.wsConnection) {
3820
- this.httpManagerService.sendNotification(channel, content);
3942
+ const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
3943
+ this.httpManagerService.sendNotification(prefixedChannel, content);
3944
+ console.log(`📢 Sending notification to channel: ${prefixedChannel}`);
3821
3945
  }
3822
3946
  else {
3823
3947
  console.warn('Cannot send notification: WebSocket not connected.');
@@ -4511,7 +4635,7 @@ class StateServiceDemo extends HTTPManagerStateService {
4511
4635
  }),
4512
4636
  adapter: OIDCClient.adapt,
4513
4637
  ws: {
4514
- id: 'SYS-USERS123',
4638
+ id: 'USERS123',
4515
4639
  wsServer,
4516
4640
  jwtToken,
4517
4641
  user,
@@ -6975,5 +7099,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6975
7099
  * Generated bundle index. Do not edit.
6976
7100
  */
6977
7101
 
6978
- export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelInfo, CommunicationType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UtilsService, WSOptions, WSUser, WebsocketService, WithCredentialsInterceptor, countdown, delayedRetry, requestPolling, requestStreaming };
7102
+ export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelInfo, ChannelType, CommunicationType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UtilsService, WSOptions, WSUser, WebsocketService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming };
6979
7103
  //# sourceMappingURL=http-request-manager.mjs.map