http-request-manager 18.7.2 → 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.
package/README.md
CHANGED
|
@@ -468,21 +468,45 @@ this.wsService.getUsersInChannel('PUB-my-channel');
|
|
|
468
468
|
|
|
469
469
|
#### Channel Naming Conventions
|
|
470
470
|
|
|
471
|
-
The WebSocket service
|
|
471
|
+
The WebSocket service and state manager use a **channel type system** to organize communication. Channel prefixes are managed automatically by the state service.
|
|
472
472
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
473
|
+
##### Channel Types (`ChannelType` Enum)
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import { ChannelType, createChannelName } from 'http-request-manager';
|
|
477
|
+
|
|
478
|
+
export enum ChannelType {
|
|
479
|
+
STATE = 'SYS', // Private state synchronization channels
|
|
480
|
+
MESSAGE = 'MES', // Messaging/communication channels (persisted notifications)
|
|
481
|
+
NOTIFICATION = 'PUB' // Public notification/broadcast channels
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Utility function to create prefixed channel name
|
|
485
|
+
createChannelName(ChannelType.STATE, 'USERS123'); // Returns 'SYS-USERS123'
|
|
486
|
+
createChannelName(ChannelType.MESSAGE, 'alerts'); // Returns 'MES-alerts'
|
|
487
|
+
createChannelName(ChannelType.NOTIFICATION, 'chat'); // Returns 'PUB-chat'
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
| Channel Type | Prefix | Description | Visibility | Persistence |
|
|
491
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
492
|
+
| `STATE` | `SYS-` | Private channels for state synchronization (CRUD operations) | Hidden from users | In-memory only |
|
|
493
|
+
| `MESSAGE` | `MES-` | Messaging channels for notifications (persisted to database) | Visible to users | Database persisted |
|
|
494
|
+
| `NOTIFICATION` | `PUB-` | Public channels for real-time messaging/chat | Visible to users | In-memory only |
|
|
495
|
+
|
|
496
|
+
**Important:** When using `HTTPManagerStateService`, channel prefixes are automatically managed. You only need to provide the base channel name.
|
|
477
497
|
|
|
478
498
|
**Example:**
|
|
479
499
|
|
|
480
500
|
```typescript
|
|
481
|
-
//
|
|
482
|
-
|
|
501
|
+
// State service automatically adds SYS- prefix for state channels
|
|
502
|
+
// User provides: 'USERS123'
|
|
503
|
+
// State service uses: 'SYS-USERS123'
|
|
483
504
|
|
|
484
|
-
//
|
|
485
|
-
|
|
505
|
+
// For messaging channels, use subscribeToMessageChannel()
|
|
506
|
+
stateService.subscribeToMessageChannel('alerts'); // Uses 'MES-alerts'
|
|
507
|
+
|
|
508
|
+
// For notification channels, use subscribeToNotificationChannel()
|
|
509
|
+
stateService.subscribeToNotificationChannel('announcements'); // Uses 'PUB-announcements'
|
|
486
510
|
```
|
|
487
511
|
|
|
488
512
|
#### WebSocket Message Types
|
|
@@ -543,6 +567,326 @@ export class UsersStore extends HTTPManagerStateService<User> {
|
|
|
543
567
|
}
|
|
544
568
|
```
|
|
545
569
|
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## Real-Time Features
|
|
573
|
+
|
|
574
|
+
The `http-request-manager` library provides two distinct real-time communication features:
|
|
575
|
+
|
|
576
|
+
1. **Messaging (PUB- channels)** - Real-time chat/messaging between users
|
|
577
|
+
2. **Notifications (MES- channels)** - Persistent notifications stored in database
|
|
578
|
+
|
|
579
|
+
Both features integrate seamlessly with `HTTPManagerStateService` and automatically manage channel prefixes.
|
|
580
|
+
|
|
581
|
+
### Messaging Feature (PUB- Channels)
|
|
582
|
+
|
|
583
|
+
**Purpose:** Real-time messaging/chat functionality for communication between users.
|
|
584
|
+
|
|
585
|
+
**Characteristics:**
|
|
586
|
+
|
|
587
|
+
- Messages are broadcast in real-time to subscribed users
|
|
588
|
+
- Messages are stored in-memory only (not persisted to database)
|
|
589
|
+
- Uses `PUB-` prefix (automatically added)
|
|
590
|
+
- Ideal for chat applications, live collaboration, etc.
|
|
591
|
+
|
|
592
|
+
#### Messaging Observables
|
|
593
|
+
|
|
594
|
+
| Observable | Type | Description |
|
|
595
|
+
| :--- | :--- | :--- |
|
|
596
|
+
| `channels$` | `Observable<string[]>` | List of all available channels |
|
|
597
|
+
| `communicationMessages$` | `Observable<any[]>` | All received messages |
|
|
598
|
+
| `latestCommunicationMessages$` | `Observable<any>` | Most recent message received |
|
|
599
|
+
| `connectionStatus$` | `Observable<boolean>` | WebSocket connection status |
|
|
600
|
+
| `user$` | `Observable<WSUser>` | Current user information |
|
|
601
|
+
|
|
602
|
+
#### Messaging Methods
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
// Create a new messaging channel
|
|
606
|
+
stateService.createChannel('general-chat'); // Creates PUB-general-chat
|
|
607
|
+
|
|
608
|
+
// Subscribe to a channel to receive messages
|
|
609
|
+
stateService.subscribeToChannel('general-chat'); // Subscribes to PUB-general-chat
|
|
610
|
+
|
|
611
|
+
// Unsubscribe from a channel
|
|
612
|
+
stateService.unsubscribeFromChannel('general-chat');
|
|
613
|
+
|
|
614
|
+
// Get all available channels
|
|
615
|
+
stateService.getAllChannels();
|
|
616
|
+
|
|
617
|
+
// Send a message to specific channels
|
|
618
|
+
stateService.wsMessaging(
|
|
619
|
+
ChannelMessage.adapt({
|
|
620
|
+
sessionId: currentUser,
|
|
621
|
+
content: { message: 'Hello everyone!' }
|
|
622
|
+
}),
|
|
623
|
+
['general-chat', 'team-updates'] // Channels (PUB- prefix added automatically)
|
|
624
|
+
);
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
#### Demo Component: `WsMessagingComponent`
|
|
628
|
+
|
|
629
|
+
The library includes a demo component showcasing messaging functionality:
|
|
630
|
+
|
|
631
|
+
```html
|
|
632
|
+
<app-ws-messaging
|
|
633
|
+
[server]="'http://localhost:8080'"
|
|
634
|
+
[wsServer]="'ws://localhost:8080'"
|
|
635
|
+
[jwtToken]="'your-jwt-token'"
|
|
636
|
+
[user]="{ ldap: 'jdoe', name: 'John Doe', email: 'jdoe@example.com' }">
|
|
637
|
+
</app-ws-messaging>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Features demonstrated:**
|
|
641
|
+
|
|
642
|
+
- Create public channels
|
|
643
|
+
- Subscribe/unsubscribe to channels
|
|
644
|
+
- Send messages to multiple channels
|
|
645
|
+
- View real-time message stream
|
|
646
|
+
- Toast notifications for incoming messages
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
### Notifications Feature (MES- Channels)
|
|
651
|
+
|
|
652
|
+
**Purpose:** Persistent notifications that are stored in the database and can be retrieved with date filters.
|
|
653
|
+
|
|
654
|
+
**Characteristics:**
|
|
655
|
+
|
|
656
|
+
- Notifications are persisted to the server database
|
|
657
|
+
- Supports date-range queries (startEpoch, endEpoch)
|
|
658
|
+
- Uses `MES-` prefix (automatically added)
|
|
659
|
+
- Retrieves historical notifications on subscription
|
|
660
|
+
- Ideal for announcements, alerts, audit logs, etc.
|
|
661
|
+
|
|
662
|
+
#### Notification Observables
|
|
663
|
+
|
|
664
|
+
| Observable | Type | Description |
|
|
665
|
+
| :--- | :--- | :--- |
|
|
666
|
+
| `notificationChannels$` | `Observable<string[]>` | In-memory notification channels from server |
|
|
667
|
+
| `todaysNotificationChannels$` | `Observable<string[]>` | Channels with notifications posted today (from DB) |
|
|
668
|
+
| `notificationMessages$` | `Observable<any[]>` | All notification messages |
|
|
669
|
+
| `latestNotification$` | `Observable<any>` | Most recent notification received |
|
|
670
|
+
|
|
671
|
+
#### Notification Methods
|
|
672
|
+
|
|
673
|
+
```typescript
|
|
674
|
+
// Create a notification channel
|
|
675
|
+
stateService.createNotificationChannel('alerts'); // Creates MES-alerts
|
|
676
|
+
|
|
677
|
+
// Get all notification channels (in-memory)
|
|
678
|
+
stateService.getNotificationChannels();
|
|
679
|
+
|
|
680
|
+
// Get today's notification channels (from database)
|
|
681
|
+
stateService.getTodaysNotificationChannels();
|
|
682
|
+
|
|
683
|
+
// Subscribe to notifications with optional date filter
|
|
684
|
+
stateService.subscribeToNotificationChannel('alerts', {
|
|
685
|
+
startEpoch: Math.floor(Date.now() / 1000) - 86400, // Last 24 hours
|
|
686
|
+
endEpoch: Math.floor(Date.now() / 1000)
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
// Unsubscribe from notifications
|
|
690
|
+
stateService.unsubscribeFromNotificationChannel('alerts');
|
|
691
|
+
|
|
692
|
+
// Send a notification (persisted to database)
|
|
693
|
+
stateService.sendNotification('alerts', {
|
|
694
|
+
title: 'System Alert',
|
|
695
|
+
message: 'Scheduled maintenance at midnight',
|
|
696
|
+
priority: 'high'
|
|
697
|
+
});
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
#### Notification Message Structure
|
|
701
|
+
|
|
702
|
+
```typescript
|
|
703
|
+
interface NotificationMessage {
|
|
704
|
+
id: number;
|
|
705
|
+
channel: string; // e.g., 'MES-alerts'
|
|
706
|
+
created: number; // epoch seconds
|
|
707
|
+
user_name: string; // sender's name
|
|
708
|
+
sessionId: any; // sender's session info
|
|
709
|
+
content: any; // notification payload
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
#### Demo Component: `WsNotificationsComponent`
|
|
714
|
+
|
|
715
|
+
The library includes a demo component showcasing notification functionality:
|
|
716
|
+
|
|
717
|
+
```html
|
|
718
|
+
<app-ws-notifications
|
|
719
|
+
[server]="'http://localhost:8080'"
|
|
720
|
+
[wsServer]="'ws://localhost:8080'"
|
|
721
|
+
[jwtToken]="'your-jwt-token'"
|
|
722
|
+
[user]="{ ldap: 'jdoe', name: 'John Doe', email: 'jdoe@example.com' }">
|
|
723
|
+
</app-ws-notifications>
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
**Features demonstrated:**
|
|
727
|
+
|
|
728
|
+
- Create notification channels
|
|
729
|
+
- View today's notification channels (from database)
|
|
730
|
+
- Subscribe with date range filters
|
|
731
|
+
- Connect/disconnect from channels
|
|
732
|
+
- Send notifications (persisted)
|
|
733
|
+
- View historical notifications in a table
|
|
734
|
+
|
|
735
|
+
---
|
|
736
|
+
|
|
737
|
+
### Creating a Custom State Service with Messaging & Notifications
|
|
738
|
+
|
|
739
|
+
Here's a complete example of a state service that utilizes all real-time features:
|
|
740
|
+
|
|
741
|
+
```typescript
|
|
742
|
+
import { Injectable } from '@angular/core';
|
|
743
|
+
import { HTTPManagerStateService, ChannelType, createChannelName } from 'http-request-manager';
|
|
744
|
+
import { ApiRequest, DataType, DatabaseStorage } from 'http-request-manager';
|
|
745
|
+
|
|
746
|
+
export interface User {
|
|
747
|
+
id: number;
|
|
748
|
+
name: string;
|
|
749
|
+
email: string;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
@Injectable({
|
|
753
|
+
providedIn: 'root'
|
|
754
|
+
})
|
|
755
|
+
export class UserStateService extends HTTPManagerStateService<User> {
|
|
756
|
+
|
|
757
|
+
constructor() {
|
|
758
|
+
super(
|
|
759
|
+
ApiRequest.adapt({
|
|
760
|
+
server: 'http://localhost:8080',
|
|
761
|
+
path: ['api', 'users'],
|
|
762
|
+
adapter: (data: any) => data as User,
|
|
763
|
+
ws: {
|
|
764
|
+
id: 'USERS123', // Base name - automatically becomes SYS-USERS123
|
|
765
|
+
wsServer: 'ws://localhost:8080',
|
|
766
|
+
jwtToken: '',
|
|
767
|
+
retry: { times: 3, delay: 5 }
|
|
768
|
+
}
|
|
769
|
+
}),
|
|
770
|
+
DataType.ARRAY,
|
|
771
|
+
DatabaseStorage.adapt({ table: 'users-cache', expiresIn: '1d' })
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Initialize connection with user info
|
|
776
|
+
initializeConnection(wsServer: string, jwtToken: string, user: any) {
|
|
777
|
+
this.setApiRequestOptions(
|
|
778
|
+
ApiRequest.adapt({
|
|
779
|
+
...this.ApiRequestOptions,
|
|
780
|
+
ws: {
|
|
781
|
+
...this.ApiRequestOptions.ws,
|
|
782
|
+
wsServer,
|
|
783
|
+
jwtToken,
|
|
784
|
+
user
|
|
785
|
+
}
|
|
786
|
+
})
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// === MESSAGING (PUB- channels) ===
|
|
791
|
+
|
|
792
|
+
createChatRoom(roomName: string) {
|
|
793
|
+
this.createChannel(roomName); // Creates PUB-{roomName}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
joinChatRoom(roomName: string) {
|
|
797
|
+
this.subscribeToChannel(roomName);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
leaveChatRoom(roomName: string) {
|
|
801
|
+
this.unsubscribeFromChannel(roomName);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
sendChatMessage(content: string, rooms: string[]) {
|
|
805
|
+
this.wsMessaging(
|
|
806
|
+
{ content: { message: content } },
|
|
807
|
+
rooms
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// === NOTIFICATIONS (MES- channels) ===
|
|
812
|
+
|
|
813
|
+
createNotificationStream(streamName: string) {
|
|
814
|
+
this.createNotificationChannel(streamName); // Creates MES-{streamName}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
subscribeToAlerts(streamName: string, lastHours: number = 24) {
|
|
818
|
+
const now = Math.floor(Date.now() / 1000);
|
|
819
|
+
const startEpoch = now - (lastHours * 3600);
|
|
820
|
+
|
|
821
|
+
this.subscribeToNotificationChannel(streamName, {
|
|
822
|
+
startEpoch,
|
|
823
|
+
endEpoch: now
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
sendAlert(streamName: string, alert: { title: string; message: string; priority: string }) {
|
|
828
|
+
this.sendNotification(streamName, alert);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
**Usage in Component:**
|
|
834
|
+
|
|
835
|
+
```typescript
|
|
836
|
+
@Component({
|
|
837
|
+
selector: 'app-dashboard',
|
|
838
|
+
template: `
|
|
839
|
+
<div *ngIf="connectionStatus$ | async">
|
|
840
|
+
<!-- Chat Messages -->
|
|
841
|
+
<div *ngFor="let msg of chatMessages$ | async">
|
|
842
|
+
{{ msg.content.message }}
|
|
843
|
+
</div>
|
|
844
|
+
|
|
845
|
+
<!-- Notifications -->
|
|
846
|
+
<div *ngFor="let notification of notifications$ | async">
|
|
847
|
+
{{ notification.content.title }}: {{ notification.content.message }}
|
|
848
|
+
</div>
|
|
849
|
+
</div>
|
|
850
|
+
`
|
|
851
|
+
})
|
|
852
|
+
export class DashboardComponent implements OnInit {
|
|
853
|
+
userState = inject(UserStateService);
|
|
854
|
+
|
|
855
|
+
connectionStatus$ = this.userState.connectionStatus$;
|
|
856
|
+
chatMessages$ = this.userState.communicationMessages$;
|
|
857
|
+
notifications$ = this.userState.notificationMessages$;
|
|
858
|
+
|
|
859
|
+
ngOnInit() {
|
|
860
|
+
// Initialize WebSocket connection
|
|
861
|
+
this.userState.initializeConnection(
|
|
862
|
+
'ws://localhost:8080',
|
|
863
|
+
'jwt-token',
|
|
864
|
+
{ ldap: 'jdoe', name: 'John Doe' }
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
// Join a chat room
|
|
868
|
+
this.userState.joinChatRoom('general');
|
|
869
|
+
|
|
870
|
+
// Subscribe to alerts from last 24 hours
|
|
871
|
+
this.userState.subscribeToAlerts('system-alerts', 24);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
sendMessage(text: string) {
|
|
875
|
+
this.userState.sendChatMessage(text, ['general']);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
sendAlert() {
|
|
879
|
+
this.userState.sendAlert('system-alerts', {
|
|
880
|
+
title: 'Update Available',
|
|
881
|
+
message: 'A new version is available',
|
|
882
|
+
priority: 'medium'
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
---
|
|
889
|
+
|
|
546
890
|
### 8. Database Manager Service (`DatabaseManagerService`)
|
|
547
891
|
|
|
548
892
|
**Path:** `database-manager-service/database.manager.service.ts`
|
|
@@ -829,6 +829,8 @@ class WebsocketService {
|
|
|
829
829
|
}
|
|
830
830
|
}
|
|
831
831
|
this.isSubscribed = false;
|
|
832
|
+
// Clear tracked subscriptions for new connection
|
|
833
|
+
this.subscribedChannels.next(new Set());
|
|
832
834
|
const sessionId = this.getSessionId();
|
|
833
835
|
const URL = (jwtToken) ? `${options.wsServer}?token=${jwtToken}&sessionId=${sessionId}` : `${options.wsServer}?sessionId=${sessionId}`;
|
|
834
836
|
this.socket = new WebSocket(URL);
|
|
@@ -2998,6 +3000,27 @@ class ChannelMessage {
|
|
|
2998
3000
|
}
|
|
2999
3001
|
|
|
3000
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
|
+
}
|
|
3001
3024
|
const defaultState = {
|
|
3002
3025
|
data: [],
|
|
3003
3026
|
dataObject: null,
|
|
@@ -3499,6 +3522,36 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3499
3522
|
this.initDBStorage();
|
|
3500
3523
|
}
|
|
3501
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
|
+
}
|
|
3502
3555
|
setApiRequestOptions(apiOptions, dataType, database) {
|
|
3503
3556
|
this.apiOptions = ApiRequest.adapt(apiOptions);
|
|
3504
3557
|
this.dataType = (dataType) ? dataType : DataType.ARRAY;
|
|
@@ -3508,6 +3561,10 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3508
3561
|
this.databaseOptions = (this.hasDatabase) ? DatabaseStorage.adapt(database) : undefined;
|
|
3509
3562
|
}
|
|
3510
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}`);
|
|
3511
3568
|
// Update WebSocket retry settings when options change
|
|
3512
3569
|
if (this.apiOptions.ws?.retry) {
|
|
3513
3570
|
this.maxRetries = this.apiOptions.ws.retry.times || 3;
|
|
@@ -3657,6 +3714,12 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3657
3714
|
this.httpManagerService.sendMessageInChannel(wsServer, { method, path, user: this.apiOptions.ws.user });
|
|
3658
3715
|
}
|
|
3659
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
|
+
*/
|
|
3660
3723
|
wsMessaging(message, channels) {
|
|
3661
3724
|
const user = this.user.value;
|
|
3662
3725
|
const messageInfo = ChannelMessage.adapt({ ...message, fromUser: user });
|
|
@@ -3664,8 +3727,9 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3664
3727
|
if (this.wsConnection && this.apiOptions.ws) {
|
|
3665
3728
|
// If specific channels provided, send to each channel
|
|
3666
3729
|
if (channels && channels.length > 0) {
|
|
3667
|
-
|
|
3668
|
-
|
|
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 => {
|
|
3669
3733
|
if (channel === 'allChannels') {
|
|
3670
3734
|
this.httpManagerService.sendBroadcast(messageInfo);
|
|
3671
3735
|
}
|
|
@@ -3675,17 +3739,46 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3675
3739
|
});
|
|
3676
3740
|
}
|
|
3677
3741
|
else {
|
|
3678
|
-
// Fallback to the primary WS channel
|
|
3742
|
+
// Fallback to the primary WS channel (already prefixed with SYS-)
|
|
3679
3743
|
const wsChannel = this.apiOptions.ws.id;
|
|
3680
|
-
console.log(`📤 Sending to
|
|
3744
|
+
console.log(`📤 Sending to state channel:`, wsChannel);
|
|
3681
3745
|
this.httpManagerService.sendChannelMessage(wsChannel, messageInfo);
|
|
3682
3746
|
}
|
|
3683
3747
|
}
|
|
3684
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
|
+
}
|
|
3685
3777
|
// --------------------------------------------------------------------------------------------------
|
|
3686
|
-
// CHANNEL MANAGEMENT
|
|
3778
|
+
// CHANNEL MANAGEMENT (Raw channels - no automatic prefix)
|
|
3687
3779
|
/**
|
|
3688
|
-
* Subscribe to a single channel
|
|
3780
|
+
* Subscribe to a single channel (no automatic prefix)
|
|
3781
|
+
* Use subscribeToMessageChannel() for MES- prefixed channels
|
|
3689
3782
|
*/
|
|
3690
3783
|
subscribeToChannel(channel) {
|
|
3691
3784
|
if (this.wsConnection) {
|
|
@@ -3774,13 +3867,16 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3774
3867
|
}
|
|
3775
3868
|
}
|
|
3776
3869
|
// --------------------------------------------------------------------------------------------------
|
|
3777
|
-
// NOTIFICATION CHANNELS (
|
|
3870
|
+
// NOTIFICATION CHANNELS (PUB- prefix - managed automatically)
|
|
3778
3871
|
/**
|
|
3779
3872
|
* Create a notification channel on the server
|
|
3873
|
+
* @param channel - Base channel name (PUB- prefix added automatically)
|
|
3780
3874
|
*/
|
|
3781
3875
|
createNotificationChannel(channel) {
|
|
3782
3876
|
if (this.wsConnection) {
|
|
3783
|
-
this.
|
|
3877
|
+
const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
|
|
3878
|
+
this.httpManagerService.createNotificationChannel(prefixedChannel);
|
|
3879
|
+
console.log(`📢 Creating notification channel: ${prefixedChannel}`);
|
|
3784
3880
|
}
|
|
3785
3881
|
else {
|
|
3786
3882
|
console.warn('Cannot create notification channel: WebSocket not connected.');
|
|
@@ -3811,10 +3907,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3811
3907
|
}
|
|
3812
3908
|
/**
|
|
3813
3909
|
* Subscribe to a notification channel with optional date filters
|
|
3910
|
+
* @param channel - Base channel name (PUB- prefix added automatically)
|
|
3814
3911
|
*/
|
|
3815
3912
|
subscribeToNotificationChannel(channel, options, user) {
|
|
3816
3913
|
if (this.wsConnection) {
|
|
3817
|
-
this.
|
|
3914
|
+
const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
|
|
3915
|
+
this.httpManagerService.subscribeToNotificationChannel(prefixedChannel, options, user);
|
|
3916
|
+
console.log(`📢 Subscribing to notification channel: ${prefixedChannel}`);
|
|
3818
3917
|
}
|
|
3819
3918
|
else {
|
|
3820
3919
|
console.warn('Cannot subscribe to notification channel: WebSocket not connected.');
|
|
@@ -3822,10 +3921,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3822
3921
|
}
|
|
3823
3922
|
/**
|
|
3824
3923
|
* Unsubscribe from a notification channel
|
|
3924
|
+
* @param channel - Base channel name (PUB- prefix added automatically)
|
|
3825
3925
|
*/
|
|
3826
3926
|
unsubscribeFromNotificationChannel(channel) {
|
|
3827
3927
|
if (this.wsConnection) {
|
|
3828
|
-
this.
|
|
3928
|
+
const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
|
|
3929
|
+
this.httpManagerService.unsubscribeFromNotificationChannel(prefixedChannel);
|
|
3930
|
+
console.log(`📢 Unsubscribing from notification channel: ${prefixedChannel}`);
|
|
3829
3931
|
}
|
|
3830
3932
|
else {
|
|
3831
3933
|
console.warn('Cannot unsubscribe from notification channel: WebSocket not connected.');
|
|
@@ -3833,10 +3935,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
3833
3935
|
}
|
|
3834
3936
|
/**
|
|
3835
3937
|
* Send a notification to a channel
|
|
3938
|
+
* @param channel - Base channel name (PUB- prefix added automatically)
|
|
3836
3939
|
*/
|
|
3837
3940
|
sendNotification(channel, content) {
|
|
3838
3941
|
if (this.wsConnection) {
|
|
3839
|
-
this.
|
|
3942
|
+
const prefixedChannel = this.prefixChannel(channel, ChannelType.NOTIFICATION);
|
|
3943
|
+
this.httpManagerService.sendNotification(prefixedChannel, content);
|
|
3944
|
+
console.log(`📢 Sending notification to channel: ${prefixedChannel}`);
|
|
3840
3945
|
}
|
|
3841
3946
|
else {
|
|
3842
3947
|
console.warn('Cannot send notification: WebSocket not connected.');
|
|
@@ -4530,7 +4635,7 @@ class StateServiceDemo extends HTTPManagerStateService {
|
|
|
4530
4635
|
}),
|
|
4531
4636
|
adapter: OIDCClient.adapt,
|
|
4532
4637
|
ws: {
|
|
4533
|
-
id: '
|
|
4638
|
+
id: 'USERS123',
|
|
4534
4639
|
wsServer,
|
|
4535
4640
|
jwtToken,
|
|
4536
4641
|
user,
|
|
@@ -6994,5 +7099,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6994
7099
|
* Generated bundle index. Do not edit.
|
|
6995
7100
|
*/
|
|
6996
7101
|
|
|
6997
|
-
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 };
|
|
6998
7103
|
//# sourceMappingURL=http-request-manager.mjs.map
|