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.
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`
|