http-request-manager 18.7.11 → 18.7.12

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
@@ -1,128 +1,44 @@
1
- # Request Manager Service Documentation
1
+ # HTTP Request Manager - Angular Library
2
2
 
3
- ## Overview
3
+ [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=flat&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
4
+ [![Angular](https://img.shields.io/badge/Angular-DD0031?style=flat&logo=angular&logoColor=white)](https://angular.io/)
5
+ [![RxJS](https://img.shields.io/badge/RxJS-B7178C?style=flat&logo=reactivex&logoColor=white)](https://rxjs.dev/)
4
6
 
5
- The `http-request-manager` is a comprehensive Angular library that provides enterprise-grade HTTP request management, state management, real-time communication, and local data persistence. It simplifies complex data flows and provides a unified API for handling HTTP, WebSocket, and storage operations.
7
+ A comprehensive Angular library providing enterprise-grade HTTP request management, state management, real-time communication, and local data persistence.
8
+
9
+ ## 🚀 Features
6
10
 
7
11
  ### Core Capabilities
8
12
 
9
- #### 🌐 HTTP Request Management
10
-
11
- - **Observable-based** service (`HTTPManagerService`) for reactive programming
12
- - **Signal-based** service (`HTTPManagerSignalsService`) for modern Angular applications
13
- - Automatic retry logic with configurable attempts and delays
14
- - Polling support with countdown timers
15
- - Streaming response handling (NDJSON, Server-Sent Events)
16
- - Request/response adapters and mappers for data transformation
17
- - Built-in error handling with optional toast notifications
18
- - File download support with progress tracking
19
-
20
- #### 🔄 State Management
21
-
22
- - **ComponentStore integration** (`HTTPManagerStateService`) for robust state management
23
- - Automatic CRUD state updates (Create, Read, Update, Delete)
24
- - Built-in selectors for data access and filtering
25
- - Pagination support with state tracking
26
- - Real-time state synchronization via WebSocket
27
- - IndexedDB caching for offline-first applications
28
- - Persistent state with LocalStorage/SessionStorage
29
-
30
- #### 💬 Real-Time Communication (WebSocket)
31
-
32
- - **Dual-mode messaging system:**
33
- - **Messaging (PUB- channels)**: Real-time chat/collaboration
34
- - **Notifications (MES- channels)**: Database-persisted notifications with date-range queries
35
- - Automatic reconnection with exponential backoff
36
- - JWT authentication support
37
- - Channel-based architecture (STATE, MESSAGE, NOTIFICATION)
38
- - Subscribe/unsubscribe to channels dynamically
39
- - Broadcast, channel, and user-specific messaging
40
- - Connection status monitoring
41
- - Session persistence across reconnections
42
-
43
- #### 💾 Data Persistence
44
-
45
- - **LocalStorage/SessionStorage** with encryption and expiration
46
- - **IndexedDB** integration via Dexie.js for complex queries
47
- - Automatic cache invalidation based on time
48
- - Secure encryption using symmetrical encryption service
49
- - Reactive storage observables for UI synchronization
50
-
51
- #### 🎯 Advanced Features
52
-
53
- - Request interception (credentials, headers, error handling)
54
- - Automatic loading state management
55
- - Database-backed notification history with epoch filtering
56
- - Define and load previous day's notification channels
57
- - Bulk operations for IndexedDB
58
- - Model adapters for type safety
59
- - Configurable global defaults via `forRoot()`
13
+ | Feature | Description | Service |
14
+ |---------|-------------|---------|
15
+ | **🌐 HTTP Request Management** | Observable-based & Signal-based HTTP services with retry logic, polling, and streaming | [`HTTPManagerService`](services/http-manager/README.md) |
16
+ | **🔄 State Management** | ComponentStore integration with automatic CRUD state updates | [`HTTPManagerStateService`](services/http-state/README.md) |
17
+ | **💬 Real-Time Communication** | WebSocket messaging with channel-based architecture | [`WebSocketService`](services/websocket/README.md) |
18
+ | **💾 Data Persistence** | LocalStorage/SessionStorage with encryption & IndexedDB caching | [`LocalStorageManagerService`](services/local-storage/README.md) |
19
+ | **🗄️ Database Management** | IndexedDB integration via Dexie.js with Observable API | [`DatabaseManagerService`](services/database/README.md) |
20
+ | **⚡ Utility Functions** | JSON handling, expiration, conversions, and validation | [`UtilsService`](services/utils/README.md) |
60
21
 
61
22
  ### Key Benefits
62
23
 
63
- ✅ **Reduced Boilerplate** - Eliminates repetitive HTTP and state management code
64
- ✅ **Type-Safe** - Full TypeScript support with generics
65
- ✅ **Offline-First** - Built-in IndexedDB caching for resilient applications
66
- ✅ **Real-Time Ready** - Seamless WebSocket integration with state management
67
- ✅ **Secure** - Encryption support for sensitive local data
68
- ✅ **Scalable** - ComponentStore-based architecture for complex state
69
- ✅ **Flexible** - Works with Observables or Signals based on preference
70
- ✅ **Battle-Tested** - Production-ready with comprehensive error handling
71
-
72
- ### Use Cases
73
-
74
- | Scenario | Solution |
75
- |----------|----------|
76
- | Simple API calls with loading states | `HTTPManagerService` |
77
- | Modern reactive UI with Signals | `HTTPManagerSignalsService` |
78
- | CRUD operations with auto state sync | `HTTPManagerStateService` |
79
- | Real-time chat/collaboration | `HTTPManagerStateService` + WebSocket (PUB- channels) |
80
- | Persistent notifications/alerts | `HTTPManagerStateService` + WebSocket (MES- channels) |
81
- | User preferences/settings | `LocalStorageManagerService` |
82
- | Offline-first data access | `DatabaseManagerService` + `HTTPManagerStateService` |
83
- | Large local datasets | `DatabaseManagerService` with Dexie.js |
84
- | Polling for live updates | `HTTPManagerService` with polling |
85
- | File downloads | `HTTPManagerService.downloadRequest()` |
86
-
87
- ---
88
-
89
- ## Demo Component (`HttpRequestServicesDemoComponent`)
90
-
91
- The `HttpRequestServicesDemoComponent` is a comprehensive demonstration component that showcases the various services available in the `http-request-manager` library. It allows you to interactively test and visualize the functionality of HTTP services, state management, WebSockets, and local storage.
92
-
93
- ### Usage
94
-
95
- To use the demo component in your application, simply add the selector to your template and provide the necessary inputs.
96
-
97
- ```html
98
- <app-http-request-services-demo
99
- [server]="'http://localhost:8080'"
100
- [wsServer]="'ws://localhost:8080'"
101
- [jwtToken]="'your-jwt-token'"
102
- [adapter]="myAdapterFunction"
103
- [mapper]="myMapperFunction">
104
- </app-http-request-services-demo>
105
- ```
106
-
107
- ### Inputs
108
-
109
- | Input | Type | Description | Default |
110
- | :--- | :--- | :--- | :--- |
111
- | `server` | `string` | The base URL for HTTP requests used in the demo. | `'http://localhost:8080'` |
112
- | `wsServer` | `string` | The WebSocket server URL for testing WS connections. | `'ws://localhost:8080'` |
113
- | `jwtToken` | `string` | A JWT token used for authenticating WebSocket connections. | `''` |
114
- | `adapter` | `Function` | An optional adapter function to transform incoming API data. | `undefined` |
115
- | `mapper` | `Function` | An optional mapper function to transform outgoing request payloads. | `undefined` |
24
+ - ✅ **Type-Safe** - Full TypeScript support with generics
25
+ - ✅ **Offline-First** - Built-in IndexedDB caching
26
+ - ✅ **Real-Time Ready** - Seamless WebSocket integration
27
+ - ✅ **Secure** - Encryption support for sensitive data
28
+ - ✅ **Scalable** - ComponentStore-based architecture
29
+ - ✅ **Flexible** - Works with Observables or Signals
116
30
 
117
- ---
118
-
119
- ## Summary
31
+ ## 📋 Table of Contents
120
32
 
121
- The `http-request-manager` library provides a comprehensive set of services for handling HTTP requests, state management, local storage, and WebSocket communications in Angular applications.
122
-
123
- ---
33
+ - [Quick Start](#quick-start)
34
+ - [Configuration](#configuration)
35
+ - [Services Overview](#services-overview)
36
+ - [Architecture](#architecture)
37
+ - [Interceptors](#interceptors)
38
+ - [Demo Examples](#demo-examples)
39
+ - [Migration Guide](#migration-guide)
124
40
 
125
- ## Quick Start Guide
41
+ ## 🚀 Quick Start
126
42
 
127
43
  ### Installation & Setup (2 minutes)
128
44
 
@@ -160,9 +76,9 @@ import { APP_ID } from '@angular/core';
160
76
  export class AppModule { }
161
77
  ```
162
78
 
163
- ### Quick Examples
79
+ ### Simple Examples
164
80
 
165
- #### Example 1: Simple HTTP GET Request
81
+ #### Basic HTTP Request
166
82
 
167
83
  ```typescript
168
84
  import { Component, inject } from '@angular/core';
@@ -191,18 +107,9 @@ export class UsersComponent {
191
107
  }
192
108
  ```
193
109
 
194
- #### Example 2: State Management with CRUD
110
+ #### State Management with CRUD
195
111
 
196
112
  ```typescript
197
- import { Injectable } from '@angular/core';
198
- import { HTTPManagerStateService, ApiRequest, DataType } from 'http-request-manager';
199
-
200
- interface User {
201
- id: number;
202
- name: string;
203
- email: string;
204
- }
205
-
206
113
  @Injectable({ providedIn: 'root' })
207
114
  export class UsersStore extends HTTPManagerStateService<User> {
208
115
 
@@ -239,288 +146,11 @@ export class UsersComponent {
239
146
  }
240
147
  ```
241
148
 
242
- #### Example 3: WebSocket Real-Time Messaging
243
-
244
- ```typescript
245
- @Injectable({ providedIn: 'root' })
246
- export class ChatStore extends HTTPManagerStateService<Message> {
247
-
248
- constructor() {
249
- super(
250
- ApiRequest.adapt({
251
- server: 'http://localhost:8080',
252
- path: ['messages'],
253
- ws: {
254
- id: 'CHAT_WS',
255
- wsServer: 'ws://localhost:8080',
256
- jwtToken: '' // Add token if needed
257
- }
258
- }),
259
- DataType.ARRAY
260
- );
261
- }
262
-
263
- joinChat(channel: string) {
264
- this.createChannel(channel);
265
- this.subscribeToChannel(channel);
266
- }
267
-
268
- sendMessage(channel: string, text: string, user: any) {
269
- this.wsMessaging(
270
- ChannelMessage.adapt({
271
- sessionId: user,
272
- content: { message: text }
273
- }),
274
- [channel]
275
- );
276
- }
277
- }
278
-
279
- // Component
280
- @Component({
281
- template: `
282
- <div *ngFor="let msg of chatStore.communicationMessages$ | async">
283
- {{ msg.content.message }}
284
- </div>
285
- <input [(ngModel)]="messageText">
286
- <button (click)="send()">Send</button>
287
- `
288
- })
289
- export class ChatComponent {
290
- chatStore = inject(ChatStore);
291
- messageText = '';
292
-
293
- ngOnInit() {
294
- this.chatStore.joinChat('general');
295
- }
296
-
297
- send() {
298
- this.chatStore.sendMessage('general', this.messageText, {
299
- id: 1,
300
- name: 'John'
301
- });
302
- this.messageText = '';
303
- }
304
- }
305
- ```
306
-
307
- #### Example 4: Persistent Notifications with Database
308
-
309
- ```typescript
310
- @Injectable({ providedIn: 'root' })
311
- export class NotificationStore extends HTTPManagerStateService<any> {
312
-
313
- constructor() {
314
- super(
315
- ApiRequest.adapt({
316
- server: 'http://localhost:8080',
317
- ws: {
318
- id: 'NOTIFICATIONS',
319
- wsServer: 'ws://localhost:8080'
320
- }
321
- }),
322
- DataType.ARRAY
323
- );
324
- }
325
-
326
- initNotifications(user: any) {
327
- // Get today's notification channels
328
- this.getTodaysNotificationChannels();
329
-
330
- // Subscribe to alerts with 24h history
331
- this.subscribeToNotificationChannel('alerts', {
332
- startEpoch: Math.floor(Date.now() / 1000) - 86400
333
- }, user);
334
- }
335
-
336
- sendAlert(message: string, priority: 'low' | 'high') {
337
- this.sendNotification('alerts', {
338
- message,
339
- priority,
340
- timestamp: Date.now()
341
- });
342
- }
343
-
344
- loadPreviousDayChannels() {
345
- this.definePreviousNotificationChannels();
346
- }
347
- }
348
-
349
- // Component
350
- @Component({
351
- template: `
352
- <div *ngFor="let notif of store.notificationMessages$ | async">
353
- <strong>{{ notif.user_name }}</strong>: {{ notif.content.message }}
354
- <span>{{ notif.created * 1000 | date:'short' }}</span>
355
- </div>
356
- <button (click)="store.loadPreviousDayChannels()">
357
- Load Previous Day Channels
358
- </button>
359
- `
360
- })
361
- export class NotificationsComponent {
362
- store = inject(NotificationStore);
363
-
364
- ngOnInit() {
365
- this.store.initNotifications({
366
- id: 1,
367
- name: 'John',
368
- email: 'john@example.com'
369
- });
370
- }
371
- }
372
- ```
373
-
374
- #### Example 5: Local Storage with Encryption
375
-
376
- ```typescript
377
- import { Component, inject } from '@angular/core';
378
- import { LocalStorageManagerService, SettingOptions } from 'http-request-manager';
379
-
380
- @Component({
381
- selector: 'app-settings'
382
- })
383
- export class SettingsComponent {
384
- storage = inject(LocalStorageManagerService);
385
-
386
- saveSettings(settings: any) {
387
- this.storage.setItem(
388
- 'user-preferences',
389
- settings,
390
- SettingOptions.adapt({
391
- encrypted: true,
392
- expiresIn: '30d'
393
- })
394
- );
395
- }
396
-
397
- loadSettings() {
398
- return this.storage.getItem('user-preferences');
399
- }
400
-
401
- clearSettings() {
402
- this.storage.removeItem('user-preferences');
403
- }
404
- }
405
- ```
406
-
407
- #### Example 6: IndexedDB Caching for Offline-First
408
-
409
- ```typescript
410
- @Injectable({ providedIn: 'root' })
411
- export class ProductStore extends HTTPManagerStateService<Product> {
412
-
413
- constructor() {
414
- super(
415
- ApiRequest.adapt({
416
- server: 'http://localhost:8080',
417
- path: ['products'],
418
- adapter: (data: any) => data as Product // Required for DB
419
- }),
420
- DataType.ARRAY,
421
- DatabaseStorage.adapt({
422
- table: 'products-cache',
423
- expiresIn: '1d' // Cache for 1 day
424
- })
425
- );
426
- }
427
-
428
- loadProducts() {
429
- // First checks IndexedDB cache, then fetches from server if expired
430
- this.fetchRecords();
431
- }
432
- }
433
- ```
434
-
435
- #### Example 7: Polling for Live Updates
436
-
437
- ```typescript
438
- export class StatusComponent {
439
- httpManager = inject(HTTPManagerService);
440
-
441
- status$ = this.httpManager.data$;
442
- countdown$ = this.httpManager.countdown$;
443
-
444
- ngOnInit() {
445
- this.httpManager.getRequest(
446
- ApiRequest.adapt({
447
- path: ['server-status'],
448
- polling: 10 // Poll every 10 seconds
449
- })
450
- ).subscribe();
451
- }
452
-
453
- ngOnDestroy() {
454
- this.httpManager.stopPolling();
455
- }
456
- }
457
- ```
458
-
459
- ### Common Use Cases
460
-
461
- | Use Case | Service to Use | Key Features |
462
- |----------|---------------|--------------|
463
- | Simple API calls | `HTTPManagerService` | Observables, retry, polling |
464
- | Modern reactive UI | `HTTPManagerSignalsService` | Angular Signals |
465
- | CRUD operations | `HTTPManagerStateService` | Auto state updates |
466
- | Real-time chat | `HTTPManagerStateService` + WS | Messaging channels |
467
- | Persistent notifications | `HTTPManagerStateService` + WS | Database-backed |
468
- | User preferences | `LocalStorageManagerService` | Encryption, expiration |
469
- | Offline-first | `DatabaseManagerService` | IndexedDB |
470
- | Large local datasets | `DatabaseManagerService` | Querying, indexing |
471
-
472
- ---
473
-
474
- ## Initialization
475
-
476
- ### 1. Module Initialization (`forRoot`)
477
-
478
- To use the library, import `HttpRequestManagerModule` in your `AppModule` and configure it using the `forRoot` method.
479
-
480
- #### Configuration Options (`ConfigOptions`)
481
-
482
- | Option | Type | Description | Default |
483
- | :--- | :--- | :--- | :--- |
484
- | `httpRequestOptions` | `ConfigHTTPOptions` | Global configuration for HTTP requests. | `undefined` |
485
- | `LocalStorageOptions` | `LocalStorageOptions` | Global configuration for Local Storage management. | `undefined` |
486
-
487
- #### HTTP Options (`ConfigHTTPOptions`)
488
-
489
- | Option | Type | Description | Default |
490
- | :--- | :--- | :--- | :--- |
491
- | `server` | `string` | The base URL for API requests. | `''` |
492
- | `path` | `any[]` | Default path segments to append to the server URL. | `[]` |
493
- | `headers` | `any` | Default headers to include in every request. | `{}` |
494
- | `polling` | `number` | Default polling interval in seconds (0 = disabled). | `0` |
495
- | `retry` | `RetryOptions` | Default retry configuration. | `{ times: 0, delay: 3 }` |
496
- | `stream` | `boolean` | Whether to enable streaming by default. | `false` |
497
- | `displayError` | `boolean` | Whether to display toast notifications for errors by default. | `false` |
498
-
499
- #### Retry Options (`RetryOptions`)
500
-
501
- | Option | Type | Description | Default |
502
- | :--- | :--- | :--- | :--- |
503
- | `times` | `number` | The number of retry attempts. | `0` |
504
- | `delay` | `number` | The delay between retries in seconds. | `3` |
505
-
506
- #### Local Storage Options (`LocalStorageOptions`)
507
-
508
- | Option | Type | Description | Default |
509
- | :--- | :--- | :--- | :--- |
510
- | `storageName` | `string` | The key used to store data in localStorage/sessionStorage. | `'storage'` |
511
- | `storageSettingsName` | `string` | The key used to store settings metadata. | `'global-storage'` |
512
- | `options` | `SettingOptions` | Default settings for stored items. | `{ storage: StorageType.GLOBAL, expires: 0, expiresIn: '', encrypted: false }` |
513
-
514
- #### Setting Options (`SettingOptions`)
149
+ ## ⚙️ Configuration
515
150
 
516
- | Option | Type | Description | Default |
517
- | :--- | :--- | :--- | :--- |
518
- | `storage` | `StorageType` | The type of storage to use (`StorageType.GLOBAL` or `StorageType.SESSION`). | `StorageType.GLOBAL` |
519
- | `expires` | `number` | Expiration timestamp (epoch). Usually calculated from `expiresIn`. | `0` |
520
- | `expiresIn` | `string` | Duration string (e.g., '1d', '2h') for expiration. | `''` |
521
- | `encrypted` | `boolean` | Whether to encrypt the stored data. | `false` |
151
+ ### Module Initialization (`forRoot`)
522
152
 
523
- #### Example
153
+ Configure the library globally using the `forRoot` method:
524
154
 
525
155
  ```typescript
526
156
  import { HttpRequestManagerModule } from 'http-request-manager';
@@ -543,943 +173,254 @@ import { HttpRequestManagerModule } from 'http-request-manager';
543
173
  }
544
174
  }
545
175
  })
546
- ],
547
- // ...
548
- })
549
- export class AppModule { }
550
- ```
551
-
552
- ### 2. AppService Initialization
553
-
554
- The `AppService` (used by `LocalStorageManagerService` for encryption) requires a unique `APP_ID` to be provided in your `AppModule`.
555
-
556
- ```typescript
557
- import { APP_ID } from '@angular/core';
558
-
559
- @NgModule({
560
- providers: [
561
- {
562
- provide: APP_ID,
563
- useValue: "your-unique-guid-here", // e.g., "056991ac-3537-43ab-b5b9-83edf6554eff"
564
- },
565
- // ...
566
- ],
567
- // ...
176
+ ]
568
177
  })
569
178
  export class AppModule { }
570
179
  ```
571
180
 
572
- ## Services Documentation
573
-
574
- ### 1. Request Manager Service (`HTTPManagerService`)
575
-
576
- **Path:** `request-manager-services/http-manager.service.ts`
577
-
578
- A robust HTTP client service using RxJS `BehaviorSubject` for state management.
579
-
580
- **What it does:**
581
- This service acts as a wrapper around Angular's `HttpClient`, providing a centralized way to manage HTTP requests. It handles the entire lifecycle of a request, including loading states, error handling, and data updates, exposing them as Observables.
582
-
583
- **Features:**
584
-
585
- - **State Management:** Exposes `data$`, `isPending$`, `error$`, and `countdown$` observables.
586
- - **Polling:** Supports automatic polling of endpoints with a configurable interval and countdown timer.
587
- - **Retries:** Automatically retries failed requests based on configuration (number of attempts and delay).
588
- - **Adapters & Mappers:** Supports `adapter` functions to transform incoming data and `mapper` functions for outgoing payloads.
589
- - **Streaming:** Handles streaming responses when configured.
590
- - **Error Handling:** Centralized error handling with optional Toast notifications.
591
- - **CRUD Support:** Provides methods for `getRequest`, `postRequest`, `putRequest`, `deleteRequest`, and `downloadRequest`.
592
-
593
- **Usage:**
594
- Inject `HTTPManagerService` to make API requests. It handles loading state, errors, and data updates via Observables.
181
+ ### Configuration Options
595
182
 
596
- #### API Request Options (`ApiRequest`)
183
+ #### HTTP Options (`ConfigHTTPOptions`)
597
184
 
598
185
  | Option | Type | Description | Default |
599
- | :--- | :--- | :--- | :--- |
600
- | `server` | `string` | The base URL for the request. | `''` |
601
- | `path` | `any[]` | Path segments to append to the URL. | `[]` |
602
- | `headers` | `any` | Custom headers for the request. | `{}` |
603
- | `adapter` | `function` | Function to transform the response data. | `undefined` |
604
- | `mapper` | `function` | Function to transform the request payload. | `undefined` |
605
- | `polling` | `number` | Polling interval in seconds (0 = disabled). | `0` |
606
- | `retry` | `RetryOptions` | Retry configuration. | `{ times: 0, delay: 3 }` |
607
- | `stream` | `boolean` | Enable streaming response handling. | `false` |
608
- | `displayError` | `boolean` | Show toast notification on error. | `false` |
609
- | `saveAs` | `string` | Filename for file downloads. | `undefined` |
610
- | `ws` | `WSOptions` | WebSocket configuration options. | `undefined` |
611
-
612
- #### HTTPManagerService Example
613
-
614
- ```typescript
615
- export class MyComponent {
616
- httpManager = inject(HTTPManagerService);
617
-
618
- data$ = this.httpManager.data$;
619
- isLoading$ = this.httpManager.isPending$;
620
- error$ = this.httpManager.error$;
621
-
622
- fetchData() {
623
- const options = ApiRequest.adapt({
624
- path: ['users'],
625
- polling: 5, // Poll every 5 seconds
626
- retry: { times: 3, delay: 1 },
627
- adapter: User.adapt // Transform response to User model
628
- });
629
-
630
- this.httpManager.getRequest(options).subscribe();
631
- }
632
- }
633
- ```
634
-
635
- #### Advanced Features
636
-
637
- | Feature | Description | Configuration |
638
- | :--- | :--- | :--- |
639
- | **Streaming** | Handle streaming responses (e.g., NDJSON). | Set `stream: true` in `ApiRequest`. |
640
- | **Polling** | Automatically poll the endpoint at a specified interval. | Set `polling: number` (seconds) in `ApiRequest`. |
641
- | **Retry** | Automatically retry failed requests. | Configure `retry: { times: 3, delay: 3 }` in `ApiRequest`. |
642
- | **Adapters** | Transform incoming API response data before it reaches the state. | Use `adapter: (data) => transformedData` in `ApiRequest`. |
643
- | **Mappers** | Transform outgoing payload data before sending to the API. | Use `mapper: (data) => transformedData` in `ApiRequest`. |
644
-
645
- ```typescript
646
- const options = ApiRequest.adapt({
647
- path: ['users'],
648
- polling: 5, // Poll every 5 seconds
649
- retry: { times: 3, delay: 1 },
650
- adapter: User.adapt // Transform response to User model
651
- });
652
- ```
653
-
654
- ### 2. Request Manager Signal Service (`HTTPManagerSignalsService`)
655
-
656
- **Path:** `request-manager-services/http-manager-signals.service.ts`
657
-
658
- A modern alternative to `HTTPManagerService` using Angular Signals for state management.
659
-
660
- **What it does:**
661
- This service provides the same functionality as `HTTPManagerService` but exposes state using Angular Signals instead of RxJS Observables. This is ideal for modern Angular applications leveraging fine-grained reactivity.
662
-
663
- **Features:**
664
-
665
- - **Signal-Based State:** Exposes `data`, `isPending`, `error`, and `countdown` as Signals.
666
- - **Feature Parity:** Supports all features of `HTTPManagerService` including polling, retries, adapters, and streaming.
667
- - **Optimized for Signals:** Designed to work seamlessly with Angular's Signal-based components and templates.
668
-
669
- **Usage:**
670
- Ideal for components using Angular Signals.
671
-
672
- ```typescript
673
- export class MyComponent {
674
- httpManager = inject(HTTPManagerSignalsService);
675
-
676
- data = this.httpManager.data; // Signal
677
- isLoading = this.httpManager.isPending; // Signal
678
- error = this.httpManager.error; // Signal
679
-
680
- fetchData() {
681
- const options = ApiRequest.adapt({ path: ['users'] });
682
- this.httpManager.getRequest(options).subscribe();
683
- }
684
- }
685
- ```
686
-
687
- ### 3. Request Manager State Service (`HTTPManagerStateService`)
688
-
689
- **Path:** `request-manager-state-service/http-manager-state.store.ts`
690
-
691
- An extension of `ComponentStore` designed for managing entity state (CRUD) with built-in HTTP request handling and WebSocket integration.
692
-
693
- **What it does:**
694
- This service combines HTTP requests with local state management. It automatically updates the local store when CRUD operations succeed, eliminating the need to manually refresh data. It also integrates with WebSockets to keep the state synchronized with server-side changes.
695
-
696
- **Features:**
697
-
698
- - **ComponentStore Integration:** Extends NGRX `ComponentStore` for robust state management.
699
- - **Automatic CRUD Updates:** `createRecord`, `updateRecord`, and `deleteRecord` automatically update the local state upon success.
700
- - **WebSocket Sync:** Listens for WebSocket messages to update, create, or delete records in real-time.
701
- - **Database Support:** Can be configured to use IndexedDB for caching (via `DatabaseStorage`).
702
- - **Selectors:** Provides selectors like `data$` and `selectRecord$(id)` for easy data access.
703
- - **Pagination Support:** Includes state for pagination (`page$`, `totalPages$`).
704
-
705
- **Usage:**
706
- Extend this service to create a store for a specific feature. You must call `super()` with `ApiRequest`, `DataType`, and `DatabaseStorage`.
707
-
708
- ```typescript
709
- @Injectable()
710
- export class UsersStore extends HTTPManagerStateService<User> {
711
- constructor() {
712
- super(
713
- ApiRequest.adapt({
714
- server: 'api',
715
- path: ['users'],
716
- adapter: User.adapt // Required for Database Storage
717
- }),
718
- DataType.ARRAY,
719
- DatabaseStorage.adapt({
720
- table: 'users-cache',
721
- expiresIn: '1d'
722
- })
723
- );
724
- }
725
-
726
- // Wrap CRUD methods for cleaner component usage
727
- getUsers() {
728
- this.fetchRecords();
729
- }
730
-
731
- addUser(user: User) {
732
- this.createRecord(user);
733
- }
734
- }
735
- ```
736
-
737
- **Features:**
738
-
739
- - **Automatic State Updates:** `createRecord`, `updateRecord`, and `deleteRecord` automatically update the local state upon success.
740
- - **Selectors:** `data$`, `selectRecord$(id)`.
741
- - **WebSocket Integration:** Automatically connects to WS if configured in `ApiRequest`. Syncs state on 'create', 'update', 'delete' events from WS.
742
- - **Runtime Configuration:** Use `setApiRequestOptions()` to update API or WS settings dynamically.
743
-
744
- ### 4. Request Manager Signal State Service
745
-
746
- *Note: Currently, the state management service (`HTTPManagerStateService`) is based on `ComponentStore` (RxJS). A dedicated Signal-based state manager is not yet available in this library.*
747
-
748
- ### 5. Local Storage Manager Service (`LocalStorageManagerService`)
749
-
750
- **Path:** `local-storage-manager-service/local-storage-manager.service.ts`
751
-
752
- Manages `localStorage` and `sessionStorage` with encryption and expiration support.
753
-
754
- **What it does:**
755
- This service provides a secure and managed way to interact with browser storage. It treats storage as a state, allowing you to subscribe to changes. It also handles data encryption and expiration automatically.
756
-
757
- **Features:**
186
+ |--------|------|-------------|---------|
187
+ | `server` | `string` | Base URL for API requests | `''` |
188
+ | `path` | `any[]` | Default path segments | `[]` |
189
+ | `headers` | `any` | Default headers | `{}` |
190
+ | `polling` | `number` | Default polling interval (seconds) | `0` |
191
+ | `retry` | `RetryOptions` | Default retry configuration | `{ times: 0, delay: 3 }` |
192
+ | `stream` | `boolean` | Enable streaming by default | `false` |
193
+ | `displayError` | `boolean` | Show toast errors by default | `false` |
758
194
 
759
- - **Encryption:** Encrypts data before saving to storage using `SymmetricalEncryptionService` (requires `APP_ID`).
760
- - **Expiration:** Supports setting an expiration time (`expiresIn`) for stored items. Automatically cleans up expired items.
761
- - **Storage Types:** Supports both `localStorage` (Global) and `sessionStorage` (Session).
762
- - **Reactive:** Exposes storage items as Observables, allowing components to react to storage changes.
763
- - **Metadata Management:** Keeps track of storage settings (encryption, expiration) separately from the data.
764
-
765
- **Usage:**
766
-
767
- ```typescript
768
- localStorageManager = inject(LocalStorageManagerService);
769
-
770
- // Create/Set a store
771
- this.localStorageManager.setStore({
772
- name: 'user-settings',
773
- data: { theme: 'dark' },
774
- options: {
775
- storage: StorageType.GLOBAL, // or StorageType.SESSION
776
- encrypted: true,
777
- expiresIn: '1d'
778
- }
779
- });
780
-
781
- // Select a store (returns data)
782
- settings$ = this.localStorageManager.store$('user-settings');
783
-
784
- // Select store settings (returns metadata)
785
- meta$ = this.localStorageManager.setting$('user-settings');
786
-
787
- // Reset all stores
788
- this.localStorageManager.resetStore();
789
- ```
790
-
791
- ### 6. Store State Manager Service (`StoreStateManagerService`)
792
-
793
- **Path:** `store-state-manager-service/store-state-manager.service.ts`
794
-
795
- A service that extends `ComponentStore` to provide persistent state management synchronized with local or session storage.
796
-
797
- **What it does:**
798
- This service bridges the gap between in-memory state (ComponentStore) and persistent storage. It ensures that your state is automatically saved to storage when it changes and restored from storage when the service is initialized.
799
-
800
- **Features:**
801
-
802
- - **Persistence:** Automatically saves state changes to `localStorage` or `sessionStorage`.
803
- - **State Restoration:** Restores state from storage on initialization.
804
- - **Reactivity:** Extends `ComponentStore`, providing all its benefits (selectors, updaters, effects).
805
- - **Encryption Support:** Leverages `LocalStorageManagerService` for optional encryption.
806
- - **Model Adaptation:** Supports using a model adapter to ensure state structure.
807
-
808
- **Usage:**
809
- Extend this service to create a persistent store.
810
-
811
- ```typescript
812
- @Injectable({
813
- providedIn: 'root'
814
- })
815
- export class SettingsStateService extends StoreStateManagerService {
816
-
817
- constructor() {
818
- super(
819
- StateStorageOptions.adapt({
820
- store: 'my-settings-store', // Unique store name
821
- options: SettingOptions.adapt({
822
- storage: StorageType.SESSION, // or StorageType.GLOBAL (Local Storage)
823
- encrypted: false
824
- }),
825
- model: Settings.adapt, // Model adapter for initial state
826
- })
827
- );
828
- }
829
-
830
- // Update specific part of state
831
- updateSetting(value: any) {
832
- this.updateData(value);
833
- }
834
-
835
- // Select specific part of state
836
- getSetting(key: string) {
837
- return this.data$.pipe(map(state => state[key]));
838
- }
839
- }
840
- ```
841
-
842
- **Features:**
843
-
844
- - **Persistence:** Automatically saves state changes to LocalStorage or SessionStorage.
845
- - **Reactivity:** Extends `ComponentStore`, providing `data$` selector and `updater` methods.
846
- - **Encryption:** Supports encrypted storage via `LocalStorageManagerService`.
847
-
848
- ### 7. WebSocket Manager Service (`WebsocketService`)
849
-
850
- **Path:** `ws-manager-service/services/websocket.service.ts`
851
-
852
- Handles WebSocket connections, channel subscriptions, and messaging. It is used internally by `HTTPManagerStateService` but can be used standalone.
853
-
854
- **What it does:**
855
- This service manages the lifecycle of a WebSocket connection. It handles authentication, connection stability, and message routing. It supports a channel-based architecture for organizing communication.
856
-
857
- **Features:**
858
-
859
- - **Connection Management:** Handles connecting, disconnecting, and reconnecting.
860
- - **Authentication:** Supports JWT-based authentication for secure connections.
861
- - **Channels:** Allows subscribing and unsubscribing to specific channels.
862
- - **Channel Management:** Create and delete channels dynamically.
863
- - **Messaging:** Supports sending messages to specific channels, users, or broadcasting to all.
864
- - **Observables:** Exposes `messages$`, `connectionStatus$`, and `subscribedChannels$` for reactive integration.
865
- - **Session Persistence:** Automatically generates and persists session IDs for reconnection scenarios.
866
-
867
- **Usage:**
868
-
869
- ```typescript
870
- wsService = inject(WebsocketService);
871
-
872
- // Connect with options
873
- this.wsService.connect({
874
- id: 'my-primary-channel',
875
- wsServer: 'wss://api.example.com/ws',
876
- user: { ldap: 'jdoe', name: 'John Doe' },
877
- channels: ['PUB-notifications', 'PUB-updates']
878
- }, 'jwt-token');
879
-
880
- // Subscribe to additional channels
881
- this.wsService.subscribeToChannel('PUB-my-channel');
882
-
883
- // Unsubscribe from a channel
884
- this.wsService.unsubscribeFromChannel('PUB-my-channel');
885
-
886
- // Listen to messages
887
- this.wsService.messages$.subscribe(msg => console.log(msg));
888
-
889
- // Send message to a channel
890
- this.wsService.sendChannelMessage('PUB-my-channel', { text: 'Hello!' });
891
-
892
- // Track subscribed channels
893
- this.wsService.subscribedChannels$.subscribe(channels => console.log([...channels]));
894
-
895
- // Create/Delete channels
896
- this.wsService.createChannel('PUB-new-channel');
897
- this.wsService.deleteChannel('PUB-old-channel');
898
-
899
- // Get all available channels
900
- this.wsService.getAllChannels();
901
-
902
- // Get users in a channel
903
- this.wsService.getUsersInChannel('PUB-my-channel');
904
- ```
905
-
906
- #### Channel Naming Conventions
907
-
908
- The WebSocket service and state manager use a **channel type system** to organize communication. Channel prefixes are managed automatically by the state service.
909
-
910
- ##### Channel Types (`ChannelType` Enum)
911
-
912
- ```typescript
913
- import { ChannelType, createChannelName } from 'http-request-manager';
914
-
915
- export enum ChannelType {
916
- STATE = 'SYS', // Private state synchronization channels
917
- MESSAGE = 'MES', // Messaging/communication channels (persisted notifications)
918
- NOTIFICATION = 'PUB' // Public notification/broadcast channels
919
- }
920
-
921
- // Utility function to create prefixed channel name
922
- createChannelName(ChannelType.STATE, 'USERS123'); // Returns 'SYS-USERS123'
923
- createChannelName(ChannelType.MESSAGE, 'alerts'); // Returns 'MES-alerts'
924
- createChannelName(ChannelType.NOTIFICATION, 'chat'); // Returns 'PUB-chat'
925
- ```
926
-
927
- | Channel Type | Prefix | Description | Visibility | Persistence |
928
- | :--- | :--- | :--- | :--- | :--- |
929
- | `STATE` | `SYS-` | Private channels for state synchronization (CRUD operations) | Hidden from users | In-memory only |
930
- | `MESSAGE` | `MES-` | Messaging channels for notifications (persisted to database) | Visible to users | Database persisted |
931
- | `NOTIFICATION` | `PUB-` | Public channels for real-time messaging/chat | Visible to users | In-memory only |
932
-
933
- **Important:** When using `HTTPManagerStateService`, channel prefixes are automatically managed. You only need to provide the base channel name.
934
-
935
- **Example:**
936
-
937
- ```typescript
938
- // State service automatically adds SYS- prefix for state channels
939
- // User provides: 'USERS123'
940
- // State service uses: 'SYS-USERS123'
941
-
942
- // For messaging channels, use subscribeToMessageChannel()
943
- stateService.subscribeToMessageChannel('alerts'); // Uses 'MES-alerts'
195
+ #### Local Storage Options (`LocalStorageOptions`)
944
196
 
945
- // For notification channels, use subscribeToNotificationChannel()
946
- stateService.subscribeToNotificationChannel('announcements'); // Uses 'PUB-announcements'
947
- ```
197
+ | Option | Type | Description | Default |
198
+ |--------|------|-------------|---------|
199
+ | `storageName` | `string` | Key for storing data | `'storage'` |
200
+ | `storageSettingsName` | `string` | Key for settings metadata | `'global-storage'` |
201
+ | `options` | `SettingOptions` | Default storage settings | `{ storage: StorageType.GLOBAL, expires: 0, expiresIn: '', encrypted: false }` |
948
202
 
949
- #### WebSocket Message Types
950
-
951
- | Type | Description | Direction |
952
- | :--- | :--- | :--- |
953
- | `subscribe` | Subscribe to a channel | Client → Server |
954
- | `unsubscribe` | Unsubscribe from a channel | Client → Server |
955
- | `message` | Send message to channel subscribers | Client → Server |
956
- | `broadcast` | Broadcast to all connected clients | Client → Server |
957
- | `userMessage` | Send message to specific user | Client → Server |
958
- | `createChannel` | Create a new channel | Client → Server |
959
- | `deleteChannel` | Delete an existing channel | Client → Server |
960
- | `getChannels` | Request list of all channels | Client → Server |
961
- | `getUsers` | Get users in a channel | Client → Server |
962
- | `channelsList` | List of available channels | Server → Client |
963
- | `subscribed` | Subscription confirmation | Server → Client |
964
- | `unsubscribed` | Unsubscription confirmation | Server → Client |
965
- | `incomingMessage` | Message received in a channel | Server → Client |
966
-
967
- #### WebSocket Options (`WSOptions`)
203
+ #### Retry Options (`RetryOptions`)
968
204
 
969
205
  | Option | Type | Description | Default |
970
- | :--- | :--- | :--- | :--- |
971
- | `id` | `string` | Unique identifier for the WebSocket connection. | `''` |
972
- | `wsServer` | `string` | The WebSocket server URL. | `''` |
973
- | `jwtToken` | `string` | JWT token for authentication. | `''` |
974
- | `permissions` | `string[]` | List of permissions associated with the connection. | `[]` |
975
- | `channels` | `string[]` | List of channels to subscribe to upon connection. | `undefined` |
976
- | `userAdapter` | `WSUser` | Adapter for mapping user data. | `undefined` |
977
- | `retry` | `RetryOptions` | Retry configuration for connection attempts. | `undefined` |
206
+ |--------|------|-------------|---------|
207
+ | `times` | `number` | Number of retry attempts | `0` |
208
+ | `delay` | `number` | Delay between retries (seconds) | `3` |
209
+
210
+ ## 📚 Services Overview
211
+
212
+ | Service | Description | Use Case |
213
+ |---------|-------------|----------|
214
+ | [`HTTPManagerService`](services/http-manager/README.md) | Observable-based HTTP client | Simple API calls with loading states |
215
+ | [`HTTPManagerSignalsService`](services/http-signals/README.md) | Signal-based HTTP client | Modern reactive UI with Angular Signals |
216
+ | [`HTTPManagerStateService`](services/http-state/README.md) | ComponentStore with HTTP & WebSocket | CRUD operations with auto state sync |
217
+ | [`WebsocketService`](services/websocket/README.md) | WebSocket connection management | Real-time messaging and notifications |
218
+ | [`LocalStorageManagerService`](services/local-storage/README.md) | Secure local storage | User preferences, session data |
219
+ | [`DatabaseManagerService`](services/database/README.md) | IndexedDB wrapper | Offline-first data access |
220
+ | [`StoreStateManagerService`](services/store-state-manager/README.md) | Persistent ComponentStore | Application state persistence |
221
+ | [`UtilsService`](services/utils/README.md) | Utility functions | JSON handling, expiration, conversions |
222
+
223
+ ### Common Use Cases
978
224
 
979
- #### Integration with HTTPManagerStateService
225
+ | Use Case | Service to Use | Key Features |
226
+ |----------|---------------|--------------|
227
+ | Simple API calls | `HTTPManagerService` | Observables, retry, polling |
228
+ | Modern reactive UI | `HTTPManagerSignalsService` | Angular Signals |
229
+ | CRUD operations | `HTTPManagerStateService` | Auto state updates |
230
+ | Real-time chat | `HTTPManagerStateService` + WebSocket | Messaging channels |
231
+ | Persistent notifications | `HTTPManagerStateService` + WebSocket | Database-backed |
232
+ | User preferences | `LocalStorageManagerService` | Encryption, expiration |
233
+ | Offline-first | `DatabaseManagerService` | IndexedDB |
234
+ | Large local datasets | `DatabaseManagerService` | Querying, indexing |
980
235
 
981
- You can configure `HTTPManagerStateService` to automatically handle WebSocket connections by providing `ws` options in `ApiRequest`.
236
+ ## 🏗️ Architecture
237
+
238
+ For detailed system architecture, data flows, and design patterns, see:
239
+
240
+ 📋 **[Architecture Documentation](architecture/README.md)**
241
+
242
+ ### System Overview
243
+
244
+ ```
245
+ ┌─────────────────────────────────────────────────────────────────┐
246
+ │ Angular Application │
247
+ ├─────────────────────────────────────────────────────────────────┤
248
+ │ ┌────────────────┐ ┌────────────────┐ ┌──────────────────┐ │
249
+ │ │ Components │ │ Components │ │ Components │ │
250
+ │ │ (Signals) │ │ (Observables) │ │ (State Store) │ │
251
+ │ └───────┬────────┘ └───────┬────────┘ └────────┬─────────┘ │
252
+ │ │ │ │ │
253
+ │ ▼ ▼ ▼ │
254
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
255
+ │ │HTTPManager │ │HTTPManager │ │HTTPManager │ │
256
+ │ │SignalsService│ │Service │ │StateService │ │
257
+ │ └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │
258
+ │ │ │ │ │
259
+ │ └───────────────────┴──────────────────────┘ │
260
+ │ │ │
261
+ │ ▼ │
262
+ │ ┌─────────────────┐ │
263
+ │ │ HttpClient │ │
264
+ │ │ (Angular) │ │
265
+ │ └────────┬────────┘ │
266
+ │ │ │
267
+ ├─────────────────────────────┼────────────────────────────────────┤
268
+ │ │ │
269
+ │ ┌──────────────────────────┼──────────────────────┐ │
270
+ │ │ Storage Layer │ │
271
+ │ ├──────────────────────────┼──────────────────────┤ │
272
+ │ │ ┌────────────────┐ │ ┌─────────────┐│ │
273
+ │ │ │LocalStorage │ │ │IndexedDB ││ │
274
+ │ │ │Manager Service │ │ │(Dexie.js) ││ │
275
+ │ │ └────────────────┘ │ └─────────────┘│ │
276
+ │ └──────────────────────────┼──────────────────────┘ │
277
+ │ │ │
278
+ │ ┌──────────────────────────┼──────────────────────┐ │
279
+ │ │ WebSocket Layer │ │
280
+ │ ├──────────────────────────┼──────────────────────┤ │
281
+ │ │ ┌─────────────────────────────────────┐ │ │
282
+ │ │ │ WebsocketService │ │ │
283
+ │ │ └─────────────────────────────────────┘ │ │
284
+ │ └─────────────────────────────────────────────────┘ │
285
+ └─────────────────────────────────────────────────────────────────┘
286
+ ```
287
+
288
+ ## 🔧 Interceptors
289
+
290
+ The library provides several HTTP interceptors that are automatically configured:
291
+
292
+ 📋 **[Interceptors Documentation](interceptors/README.md)**
293
+
294
+ ### Available Interceptors
295
+
296
+ - **RequestErrorInterceptor** - Handles 400/500 errors with toast notifications
297
+ - **WithCredentialsInterceptor** - Adds `withCredentials: true` to requests
298
+ - **RequestHeadersInterceptor** - Adds common headers (Content-Type, Accept-Language, Current-Date)
299
+
300
+ ### Manual Configuration
982
301
 
983
302
  ```typescript
984
- @Injectable()
985
- export class UsersStore extends HTTPManagerStateService<User> {
986
- constructor() {
987
- super(
988
- ApiRequest.adapt({
989
- server: 'api',
990
- path: ['users'],
991
- // WebSocket Configuration
992
- ws: {
993
- id: 'WS-USERS',
994
- wsServer: 'wss://api.example.com/ws',
995
- jwtToken: 'your-token',
996
- wsChannels: ['allChannels'],
997
- retry: { times: 3, delay: 5 }
998
- }
999
- }),
1000
- DataType.ARRAY,
1001
- DatabaseStorage.adapt()
1002
- );
1003
- }
1004
- }
303
+ // app.module.ts
304
+ providers: [
305
+ { provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
306
+ { provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
307
+ { provide: HTTP_INTERCEPTORS, useClass: RequestErrorInterceptor, multi: true }
308
+ ]
1005
309
  ```
1006
310
 
1007
- ---
1008
-
1009
- ## Real-Time Features
1010
-
1011
- The `http-request-manager` library provides two distinct real-time communication features:
1012
-
1013
- 1. **Messaging (PUB- channels)** - Real-time chat/messaging between users
1014
- 2. **Notifications (MES- channels)** - Persistent notifications stored in database
1015
-
1016
- Both features integrate seamlessly with `HTTPManagerStateService` and automatically manage channel prefixes.
1017
-
1018
- ### Messaging Feature (PUB- Channels)
1019
-
1020
- **Purpose:** Real-time messaging/chat functionality for communication between users.
1021
-
1022
- **Characteristics:**
1023
-
1024
- - Messages are broadcast in real-time to subscribed users
1025
- - Messages are stored in-memory only (not persisted to database)
1026
- - Uses `PUB-` prefix (automatically added)
1027
- - Ideal for chat applications, live collaboration, etc.
311
+ ## 🎮 Demo Examples
1028
312
 
1029
- #### Messaging Observables
313
+ Comprehensive demo components showcase all library features:
1030
314
 
1031
- | Observable | Type | Description |
1032
- | :--- | :--- | :--- |
1033
- | `channels$` | `Observable<string[]>` | List of all available channels |
1034
- | `communicationMessages$` | `Observable<any[]>` | All received messages |
1035
- | `latestCommunicationMessages$` | `Observable<any>` | Most recent message received |
1036
- | `connectionStatus$` | `Observable<boolean>` | WebSocket connection status |
1037
- | `user$` | `Observable<WSUser>` | Current user information |
315
+ 📋 **[Demo Examples Documentation](demos/README.md)**
1038
316
 
1039
- #### Messaging Methods
317
+ ### Available Demos
1040
318
 
1041
- ```typescript
1042
- // Create a new messaging channel
1043
- stateService.createChannel('general-chat'); // Creates PUB-general-chat
1044
-
1045
- // Subscribe to a channel to receive messages
1046
- stateService.subscribeToChannel('general-chat'); // Subscribes to PUB-general-chat
1047
-
1048
- // Unsubscribe from a channel
1049
- stateService.unsubscribeFromChannel('general-chat');
1050
-
1051
- // Get all available channels
1052
- stateService.getAllChannels();
1053
-
1054
- // Send a message to specific channels
1055
- stateService.wsMessaging(
1056
- ChannelMessage.adapt({
1057
- sessionId: currentUser,
1058
- content: { message: 'Hello everyone!' }
1059
- }),
1060
- ['general-chat', 'team-updates'] // Channels (PUB- prefix added automatically)
1061
- );
1062
- ```
319
+ - **HttpRequestServicesDemoComponent** - Main demo component
320
+ - **RequestManagerDemoComponent** - HTTP service demonstrations
321
+ - **RequestManagerStateDemoComponent** - State management examples
322
+ - **RequestManagerWsDemoComponent** - WebSocket functionality
323
+ - **LocalStorageDemoComponent** - Local storage examples
324
+ - **DatabaseDataDemoComponent** - IndexedDB operations
1063
325
 
1064
- #### Demo Component: `WsMessagingComponent`
1065
-
1066
- The library includes a demo component showcasing messaging functionality:
326
+ ### Usage
1067
327
 
1068
328
  ```html
1069
- <app-ws-messaging
329
+ <app-http-request-services-demo
1070
330
  [server]="'http://localhost:8080'"
1071
331
  [wsServer]="'ws://localhost:8080'"
1072
332
  [jwtToken]="'your-jwt-token'"
1073
- [user]="{ ldap: 'jdoe', name: 'John Doe', email: 'jdoe@example.com' }">
1074
- </app-ws-messaging>
333
+ [adapter]="myAdapterFunction"
334
+ [mapper]="myMapperFunction">
335
+ </app-http-request-services-demo>
1075
336
  ```
1076
337
 
1077
- **Features demonstrated:**
338
+ ## 📖 Migration Guide
1078
339
 
1079
- - Create public channels
1080
- - Subscribe/unsubscribe to channels
1081
- - Send messages to multiple channels
1082
- - View real-time message stream
1083
- - Toast notifications for incoming messages
1084
-
1085
- ---
1086
-
1087
- ### Notifications Feature (MES- Channels)
1088
-
1089
- **Purpose:** Persistent notifications that are stored in the database and can be retrieved with date filters.
1090
-
1091
- **Characteristics:**
1092
-
1093
- - Notifications are persisted to the server database
1094
- - Supports date-range queries (startEpoch, endEpoch)
1095
- - Uses `MES-` prefix (automatically added)
1096
- - Retrieves historical notifications on subscription
1097
- - Ideal for announcements, alerts, audit logs, etc.
1098
-
1099
- #### Notification Observables
1100
-
1101
- | Observable | Type | Description |
1102
- | :--- | :--- | :--- |
1103
- | `notificationChannels$` | `Observable<string[]>` | In-memory notification channels from server |
1104
- | `todaysNotificationChannels$` | `Observable<string[]>` | Channels with notifications posted today (from DB) |
1105
- | `notificationMessages$` | `Observable<any[]>` | All notification messages |
1106
- | `latestNotification$` | `Observable<any>` | Most recent notification received |
1107
-
1108
- #### Notification Methods
340
+ ### From HttpClient to HTTPManagerService
1109
341
 
342
+ **Before:**
1110
343
  ```typescript
1111
- // Create a notification channel
1112
- stateService.createNotificationChannel('alerts'); // Creates MES-alerts
1113
-
1114
- // Get all notification channels (in-memory)
1115
- stateService.getNotificationChannels();
1116
-
1117
- // Get today's notification channels (from database)
1118
- stateService.getTodaysNotificationChannels();
1119
-
1120
- // Define and load previous day's notification channels
1121
- // This retrieves channels from the previous day's database records,
1122
- // creates them in memory if needed, and broadcasts the updated list
1123
- stateService.definePreviousNotificationChannels();
1124
-
1125
- // Subscribe to notifications with optional date filter
1126
- stateService.subscribeToNotificationChannel('alerts', {
1127
- startEpoch: Math.floor(Date.now() / 1000) - 86400, // Last 24 hours
1128
- endEpoch: Math.floor(Date.now() / 1000)
1129
- });
1130
-
1131
- // Unsubscribe from notifications
1132
- stateService.unsubscribeFromNotificationChannel('alerts');
1133
-
1134
- // Send a notification (persisted to database)
1135
- stateService.sendNotification('alerts', {
1136
- title: 'System Alert',
1137
- message: 'Scheduled maintenance at midnight',
1138
- priority: 'high'
344
+ http.get('api/users').subscribe(users => {
345
+ this.users = users;
346
+ this.loading = false;
1139
347
  });
1140
348
  ```
1141
349
 
1142
- #### Notification Message Structure
1143
-
350
+ **After:**
1144
351
  ```typescript
1145
- interface NotificationMessage {
1146
- id: number;
1147
- channel: string; // e.g., 'MES-alerts'
1148
- created: number; // epoch seconds
1149
- user_name: string; // sender's name
1150
- sessionId: any; // sender's session info
1151
- content: any; // notification payload
1152
- }
1153
- ```
1154
-
1155
- #### Demo Component: `WsNotificationsComponent`
352
+ httpManager.getRequest(
353
+ ApiRequest.adapt({ path: ['users'] })
354
+ ).subscribe();
1156
355
 
1157
- The library includes a demo component showcasing notification functionality:
1158
-
1159
- ```html
1160
- <app-ws-notifications
1161
- [server]="'http://localhost:8080'"
1162
- [wsServer]="'ws://localhost:8080'"
1163
- [jwtToken]="'your-jwt-token'"
1164
- [user]="{ ldap: 'jdoe', name: 'John Doe', email: 'jdoe@example.com' }">
1165
- </app-ws-notifications>
356
+ data$ = this.httpManager.data$;
357
+ isLoading$ = this.httpManager.isPending$;
1166
358
  ```
1167
359
 
1168
- **Features demonstrated:**
1169
-
1170
- - Create notification channels
1171
- - View today's notification channels (from database)
1172
- - Define previous day's channels (loads channels from previous day's data)
1173
- - Subscribe with date range filters
1174
- - Connect/disconnect from channels
1175
- - Send notifications (persisted)
1176
- - View historical notifications in a table
1177
-
1178
- ---
1179
-
1180
- ### Creating a Custom State Service with Messaging & Notifications
1181
-
1182
- Here's a complete example of a state service that utilizes all real-time features:
360
+ ### From Manual State to HTTPManagerStateService
1183
361
 
362
+ **Before:**
1184
363
  ```typescript
1185
- import { Injectable } from '@angular/core';
1186
- import { HTTPManagerStateService, ChannelType, createChannelName } from 'http-request-manager';
1187
- import { ApiRequest, DataType, DatabaseStorage } from 'http-request-manager';
1188
-
1189
- export interface User {
1190
- id: number;
1191
- name: string;
1192
- email: string;
364
+ users: User[] = [];
365
+ loading = false;
366
+
367
+ loadUsers() {
368
+ this.loading = true;
369
+ this.http.get('api/users').subscribe(users => {
370
+ this.users = users;
371
+ this.loading = false;
372
+ });
1193
373
  }
1194
374
 
1195
- @Injectable({
1196
- providedIn: 'root'
1197
- })
1198
- export class UserStateService extends HTTPManagerStateService<User> {
1199
-
1200
- constructor() {
1201
- super(
1202
- ApiRequest.adapt({
1203
- server: 'http://localhost:8080',
1204
- path: ['api', 'users'],
1205
- adapter: (data: any) => data as User,
1206
- ws: {
1207
- id: 'USERS123', // Base name - automatically becomes SYS-USERS123
1208
- wsServer: 'ws://localhost:8080',
1209
- jwtToken: '',
1210
- retry: { times: 3, delay: 5 }
1211
- }
1212
- }),
1213
- DataType.ARRAY,
1214
- DatabaseStorage.adapt({ table: 'users-cache', expiresIn: '1d' })
1215
- );
1216
- }
1217
-
1218
- // Initialize connection with user info
1219
- initializeConnection(wsServer: string, jwtToken: string, user: any) {
1220
- this.setApiRequestOptions(
1221
- ApiRequest.adapt({
1222
- ...this.ApiRequestOptions,
1223
- ws: {
1224
- ...this.ApiRequestOptions.ws,
1225
- wsServer,
1226
- jwtToken,
1227
- user
1228
- }
1229
- })
1230
- );
1231
- }
1232
-
1233
- // === MESSAGING (PUB- channels) ===
1234
-
1235
- createChatRoom(roomName: string) {
1236
- this.createChannel(roomName); // Creates PUB-{roomName}
1237
- }
1238
-
1239
- joinChatRoom(roomName: string) {
1240
- this.subscribeToChannel(roomName);
1241
- }
1242
-
1243
- leaveChatRoom(roomName: string) {
1244
- this.unsubscribeFromChannel(roomName);
1245
- }
1246
-
1247
- sendChatMessage(content: string, rooms: string[]) {
1248
- this.wsMessaging(
1249
- { content: { message: content } },
1250
- rooms
1251
- );
1252
- }
1253
-
1254
- // === NOTIFICATIONS (MES- channels) ===
1255
-
1256
- createNotificationStream(streamName: string) {
1257
- this.createNotificationChannel(streamName); // Creates MES-{streamName}
1258
- }
1259
-
1260
- subscribeToAlerts(streamName: string, lastHours: number = 24) {
1261
- const now = Math.floor(Date.now() / 1000);
1262
- const startEpoch = now - (lastHours * 3600);
1263
-
1264
- this.subscribeToNotificationChannel(streamName, {
1265
- startEpoch,
1266
- endEpoch: now
1267
- });
1268
- }
1269
-
1270
- sendAlert(streamName: string, alert: { title: string; message: string; priority: string }) {
1271
- this.sendNotification(streamName, alert);
1272
- }
375
+ addUser(user: User) {
376
+ this.http.post('api/users', user).subscribe(newUser => {
377
+ this.users = [...this.users, newUser];
378
+ });
1273
379
  }
1274
380
  ```
1275
381
 
1276
- **Usage in Component:**
1277
-
382
+ **After:**
1278
383
  ```typescript
1279
- @Component({
1280
- selector: 'app-dashboard',
1281
- template: `
1282
- <div *ngIf="connectionStatus$ | async">
1283
- <!-- Chat Messages -->
1284
- <div *ngFor="let msg of chatMessages$ | async">
1285
- {{ msg.content.message }}
1286
- </div>
1287
-
1288
- <!-- Notifications -->
1289
- <div *ngFor="let notification of notifications$ | async">
1290
- {{ notification.content.title }}: {{ notification.content.message }}
1291
- </div>
1292
- </div>
1293
- `
1294
- })
1295
- export class DashboardComponent implements OnInit {
1296
- userState = inject(UserStateService);
1297
-
1298
- connectionStatus$ = this.userState.connectionStatus$;
1299
- chatMessages$ = this.userState.communicationMessages$;
1300
- notifications$ = this.userState.notificationMessages$;
1301
-
1302
- ngOnInit() {
1303
- // Initialize WebSocket connection
1304
- this.userState.initializeConnection(
1305
- 'ws://localhost:8080',
1306
- 'jwt-token',
1307
- { ldap: 'jdoe', name: 'John Doe' }
1308
- );
1309
-
1310
- // Join a chat room
1311
- this.userState.joinChatRoom('general');
1312
-
1313
- // Subscribe to alerts from last 24 hours
1314
- this.userState.subscribeToAlerts('system-alerts', 24);
1315
- }
1316
-
1317
- sendMessage(text: string) {
1318
- this.userState.sendChatMessage(text, ['general']);
1319
- }
1320
-
1321
- sendAlert() {
1322
- this.userState.sendAlert('system-alerts', {
1323
- title: 'Update Available',
1324
- message: 'A new version is available',
1325
- priority: 'medium'
1326
- });
384
+ @Injectable()
385
+ export class UsersStore extends HTTPManagerStateService<User> {
386
+ constructor() {
387
+ super(ApiRequest.adapt({ path: ['users'] }), DataType.ARRAY);
1327
388
  }
389
+
390
+ loadUsers() { this.fetchRecords(); }
391
+ addUser(user: User) { this.createRecord(user); }
1328
392
  }
1329
- ```
1330
-
1331
- ---
1332
-
1333
- ### 8. Database Manager Service (`DatabaseManagerService`)
1334
-
1335
- **Path:** `database-manager-service/database.manager.service.ts`
1336
-
1337
- A wrapper service for Dexie.js to manage IndexedDB interactions using RxJS Observables.
1338
-
1339
- **What it does:**
1340
-
1341
- This service simplifies interactions with IndexedDB by providing a clean, Observable-based API. It handles database initialization, table creation, and all standard CRUD operations. It is designed to work seamlessly with the `HTTPManagerStateService` for caching but can also be used independently.
1342
-
1343
- **Features:**
1344
-
1345
- - **Table Management:** Create and manage database tables with flexible schemas.
1346
- - **CRUD Operations:** Full support for Create, Read, Update, and Delete operations on single or multiple records.
1347
- - **Querying:** Find records by specific column values.
1348
- - **Bulk Operations:** Optimized methods for creating and deleting multiple records at once.
1349
- - **Schema Inspection:** Methods to check for table existence and retrieve schema definitions.
1350
-
1351
- **Usage:**
1352
-
1353
- ```typescript
1354
- dbManager = inject(DatabaseManagerService);
1355
-
1356
- // 1. Initialize Table
1357
- const tableDef = TableSchemaDef.adapt({
1358
- table: 'users',
1359
- schema: '++id, name, age' // Dexie.js schema syntax
1360
- });
1361
-
1362
- this.dbManager.createDatabaseTable(tableDef).subscribe(() => {
1363
- console.log('Table initialized');
1364
- });
1365
-
1366
- // 2. CRUD Operations
1367
- // Create
1368
- this.dbManager.createTableRecord('users', { name: 'John', age: 30 }).subscribe();
1369
-
1370
- // Read
1371
- this.dbManager.getTableRecords('users').subscribe(users => console.log(users));
1372
- this.dbManager.getTableRecord('users', 1).subscribe(user => console.log(user));
1373
-
1374
- // Update
1375
- this.dbManager.updateTableRecord('users', { id: 1, name: 'John Doe', age: 31 }).subscribe();
1376
-
1377
- // Delete
1378
- this.dbManager.deleteTableRecord('users', 1).subscribe();
1379
-
1380
- // 3. Bulk Operations
1381
- const users = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 28 }];
1382
- this.dbManager.createTableRecords('users', users).subscribe();
1383
-
1384
- // 4. Querying
1385
- this.dbManager.findTableRecords('users', 'age', 25).subscribe(results => console.log(results));
1386
-
1387
- // 5. Metadata
1388
- this.dbManager.hasDatabaseTable('users').subscribe(exists => console.log(exists));
1389
- ```
1390
-
1391
- #### Database Storage Configuration (`DatabaseStorage`)
1392
-
1393
- When using `HTTPManagerStateService`, you can configure local database caching using `DatabaseStorage.adapt()`.
1394
393
 
1395
- ##### Options
1396
-
1397
- | Option | Type | Description | Default |
1398
- | :--- | :--- | :--- | :--- |
1399
- | `table` | `string` | The name of the table in IndexedDB where records will be stored. | `''` |
1400
- | `expiresIn` | `string` | The duration for which the data remains valid. Format: `'1d'` (days), `'1h'` (hours), `'30m'` (minutes). | `''` |
1401
-
1402
- ##### Database Storage Example
1403
-
1404
- ```typescript
1405
- import { DatabaseStorage } from 'http-request-manager';
1406
-
1407
- const dbConfig = DatabaseStorage.adapt({
1408
- table: 'my-feature-cache',
1409
- expiresIn: '6h' // Cache expires in 6 hours
1410
- });
394
+ // Component
395
+ data$ = this.usersStore.data$;
396
+ isLoading$ = this.usersStore.isPending$;
1411
397
  ```
1412
398
 
1413
- ### 9. Utils (`UtilsService`)
399
+ ## 📋 API Reference
1414
400
 
1415
- **Path:** `utils/utils.service.ts`
401
+ ### Core Models
1416
402
 
1417
- Provides utility functions for common tasks.
403
+ - **ApiRequest** - HTTP request configuration
404
+ - **RetryOptions** - Retry behavior settings
405
+ - **DataType** - Data structure type (ARRAY, OBJECT)
406
+ - **DatabaseStorage** - IndexedDB configuration
407
+ - **SettingOptions** - Storage settings
408
+ - **WSOptions** - WebSocket configuration
1418
409
 
1419
- **What it does:**
1420
- A collection of helper functions used throughout the library and available for application use. It simplifies common tasks related to data manipulation, validation, and time calculations.
410
+ ### Enums
1421
411
 
1422
- **Features:**
412
+ - **StreamType** - Streaming response types
413
+ - **StorageType** - Storage scope (GLOBAL, SESSION)
414
+ - **CommunicationType** - WebSocket message types
1423
415
 
1424
- - **JSON Handling:** Safe `stringToJSON` and `JSONToString` methods.
1425
- - **Type Checking:** `isString`, `isObject`, `isJSON`.
1426
- - **Expiration:** `expires(string)` converts duration strings (e.g., '1d', '2h') to epoch timestamps. `hasExpired(timestamp)` checks if a timestamp has passed.
1427
- - **Conversions:** `base32ToHex`, `binaryToHex`.
1428
- - **Object Equality:** `objectsEqual` for deep comparison.
416
+ ## 🤝 Contributing
1429
417
 
1430
- **Usage:**
418
+ This library is designed to be enterprise-ready and production-safe. All features include comprehensive error handling, TypeScript support, and extensive configuration options.
1431
419
 
1432
- ```typescript
1433
- utils = inject(UtilsService);
1434
-
1435
- // Check expiration
1436
- const isExpired = this.utils.hasExpired(expiryTimestamp);
420
+ ## 📄 License
1437
421
 
1438
- // Convert JSON
1439
- const json = this.utils.stringToJSON(jsonString);
1440
-
1441
- // Calculate Expiry
1442
- const expiryEpoch = this.utils.expires('1d'); // Returns epoch for 1 day from now
1443
- ```
422
+ This project is part of the Angular application library suite.
1444
423
 
1445
424
  ---
1446
425
 
1447
- ## Available Interceptors
1448
-
1449
- There are 3 interceptors that you can import into your project for api requests.
1450
-
1451
- You may add these interceptors in your `AppModule` file as providers and import them into as providers.
1452
-
1453
- ```typescript
1454
- providers: [
1455
- { provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
1456
- { provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
1457
- { provide: HTTP_INTERCEPTORS, useClass: RequestErrorInterceptor, multi: true }
1458
- ],
1459
- ```
1460
-
1461
- Or you can use all intercepts above by importing the `HttpRequestManagerModule` in your `AppModule`
1462
-
1463
- - **RequestErrorInterceptor**
1464
-
1465
- This interceptor handles errors of type 400 and 500. This interceptor is applicable when you need to display UI for the user to indicate a server or request error has occurred. The Status and Error Text is displayed in a `toast-message` modal.
1466
-
1467
- - **WithCredentialsInterceptor**
1468
-
1469
- Adds to your request header
1470
-
1471
- ```json
1472
- { credentials: true }
1473
- ```
1474
-
1475
- - **RequestHeadersInterceptor**
1476
-
1477
- Adds to your request - current local `language` (i18n) selection and `current date` to every request
1478
-
1479
- ```json
1480
- {
1481
- 'Content-Type': 'application/json',
1482
- 'Accept-Language': this.language || 'en-CA',
1483
- 'Current-Date': this.currentDate
1484
- }
1485
- ```
426
+ **Need help?** Check out the detailed documentation for each service, explore the demo examples, or review the architecture documentation for implementation guidance.