http-request-manager 18.16.4 → 18.16.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -16,12 +16,13 @@ This README is the main documentation hub for the library. Detailed service guid
|
|
|
16
16
|
|
|
17
17
|
| Feature | Description | Angular 14-18 / Observable + NgRx | Angular 19+ / Signals |
|
|
18
18
|
|---------|-------------|----------------------------------|------------------------|
|
|
19
|
-
| **🌐 HTTP Request Management** | Retry, polling, streaming, file downloads | [`HTTPManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_MANAGER_README.md) | [`HTTPManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/
|
|
19
|
+
| **🌐 HTTP Request Management** | Retry, polling, streaming, file downloads | [`HTTPManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_MANAGER_README.md) | [`HTTPManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_SIGNALS_MANAGER_README.md) |
|
|
20
20
|
| **🔄 State Management** | CRUD state, persistence, derived state | [`HTTPManagerStateService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_STATE_MANAGER_README.md) and [`StoreStateManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/STORE_STATE_MANAGER_README.md) | [`StoreStateManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/STORE_STATE_SIGNALS_README.md) |
|
|
21
21
|
| **💬 Real-Time Communication** | WebSocket channels, tracking, messaging | [`WebSocketManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WS_MANAGER_README.md), [`WebSocketMessageService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WEBSOCKET_MESSAGE_SERVICE.md), and [`MessageTrackerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/MESSAGE_TRACKER_README.md) | [`WebSocketSignalsManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WEBSOCKET_SIGNALS_README.md) and [`MessageTrackerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/MESSAGE_TRACKER_SIGNALS_README.md) |
|
|
22
22
|
| **💾 Data Persistence** | Local/session storage and offline caching | [`LocalStorageManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOCAL_STORAGE_README.md) and [`DatabaseManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/DATABASE_README.md) | [`LocalStorageSignalsManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOCAL_STORAGE_SIGNALS_README.md) |
|
|
23
|
-
| **🗄️
|
|
23
|
+
| **🗄️ Database Queries** | MySQL-syntax SQL queries on IndexedDB — the recommended way to query data | [`DexieSqlService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/SQL_DIXIE_README.md) | Uses the same service |
|
|
24
24
|
| **⚡ Utility Functions** | JSON handling, encryption, headers, validation, logging | [`UtilsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/UTILS_README.md), [`Encryption`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/ENCRYPTION_README.md), [`Logger`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOGGER_README.md) | Uses the same utility layer |
|
|
25
|
+
| **🔧 Utility Services** | Headers, path/query, merging, base request classes | [`Utility Services`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/UTILS_SERVICES_README.md) | Internal and helper services |
|
|
25
26
|
|
|
26
27
|
### Key Benefits
|
|
27
28
|
|
|
@@ -37,12 +38,28 @@ Note on clearing persisted data:
|
|
|
37
38
|
- **Clear full DB (fire-and-forget)**: To wipe the entire IndexedDB for this library and its associated localStorage metadata, call `DatabaseManagerService.clearDatabase()`. This method subscribes internally and is intentionally fire-and-forget — callers should simply call `databaseManager.clearDatabase()` (no `.subscribe()` required). The method also clears related localStorage metadata via `LocalStorageManagerService`.
|
|
38
39
|
- **Clear a specific table (Observable)**: To remove records from a specific table, use `DatabaseManagerService.clearTableRecords(tableName)` which returns an `Observable<void>`; callers should `.subscribe()` or use RxJS operators to react to completion.
|
|
39
40
|
|
|
40
|
-
###
|
|
41
|
+
### �️ Database Access
|
|
42
|
+
|
|
43
|
+
The library provides two complementary services for working with IndexedDB data:
|
|
44
|
+
|
|
45
|
+
| Task | Service | Example |
|
|
46
|
+
|------|---------|---------|
|
|
47
|
+
| **Query data** (recommended) | `DexieSqlService` | `sql.query('SELECT * FROM orders WHERE status = "open"')` |
|
|
48
|
+
| **Create tables** | `DatabaseManagerService` | `db.createDatabaseTable(tableDef)` |
|
|
49
|
+
| **Insert / update records** | `DatabaseManagerService` | `db.createTableRecord('orders', record)` |
|
|
50
|
+
| **Delete records** | `DatabaseManagerService` | `db.deleteTableRecord('orders', id)` |
|
|
51
|
+
| **Clear / reset database** | `DatabaseManagerService` | `db.clearDatabase()` |
|
|
52
|
+
|
|
53
|
+
Use `DexieSqlService` for all read queries — it supports SELECT with WHERE, JOIN, ORDER BY, LIMIT, COUNT, DISTINCT, and more. Use `DatabaseManagerService` for table creation and write operations.
|
|
54
|
+
|
|
55
|
+
See the full SQL syntax reference: [`DexieSqlService Guide`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/SQL_DIXIE_README.md)
|
|
56
|
+
|
|
57
|
+
### �🚀 Advanced Features
|
|
41
58
|
|
|
42
59
|
| Feature | Description | Learn More |
|
|
43
60
|
|---------|-------------|------------|
|
|
44
61
|
| **🔐 Enterprise Encryption** | AES symmetric + RSA asymmetric encryption | [`Encryption Utils`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/ENCRYPTION_README.md) |
|
|
45
|
-
| **🗄️
|
|
62
|
+
| **🗄️ Database Queries** | MySQL-syntax SQL queries on IndexedDB — the recommended way to query data (SELECT, WHERE, JOIN, ORDER BY, LIMIT, COUNT, DISTINCT) | [`DexieSqlService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/SQL_DIXIE_README.md) |
|
|
46
63
|
| **📡 Streaming Support** | NDJSON & Server-Sent Events (SSE) | [`HTTP Manager`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_MANAGER_README.md#streaming) |
|
|
47
64
|
| **📄 File Downloads** | Progress tracking for large files | [`HTTP Manager`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_MANAGER_README.md#file-downloads) |
|
|
48
65
|
| **📤 File Uploads** | Multi-file upload with progress, validation, and form-data config | [`Upload Request`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/UPLOAD_REQUEST_README.md) |
|
|
@@ -270,6 +287,42 @@ export class AppModule { }
|
|
|
270
287
|
| `times` | `number` | Number of retry attempts | `0` |
|
|
271
288
|
| `delay` | `number` | Delay between retries (seconds) | `3` |
|
|
272
289
|
|
|
290
|
+
#### WebSocket Options (`WSOptions`)
|
|
291
|
+
|
|
292
|
+
| Option | Type | Description | Default |
|
|
293
|
+
|--------|------|-------------|---------|
|
|
294
|
+
| `id` | `string` | Channel identifier (used to construct channel names) | `''` |
|
|
295
|
+
| `wsServer` | `string` | WebSocket server URL | `''` |
|
|
296
|
+
| `jwtToken` | `string` | JWT token for authentication | `''` |
|
|
297
|
+
| `permissions` | `string[]` | Permission levels for the connection | `[]` |
|
|
298
|
+
| `channels` | `string[]` | Additional channels to subscribe to | `[]` |
|
|
299
|
+
| `user` | `any` | User information for presence tracking | `undefined` |
|
|
300
|
+
| `retry` | `RetryOptions` | Retry configuration for reconnection | `{ times: 0, delay: 3 }` |
|
|
301
|
+
|
|
302
|
+
### Injection Tokens
|
|
303
|
+
|
|
304
|
+
| Token | Type | Purpose | Required |
|
|
305
|
+
|-------|------|---------|----------|
|
|
306
|
+
| `CONFIG_SETTINGS_TOKEN` | `ConfigOptions` | Global library configuration (provided by `forRoot()`) | Yes (via `forRoot()`) |
|
|
307
|
+
| `APP_ID` | `string` | Unique application ID for encryption key generation | Yes (if using encryption) |
|
|
308
|
+
|
|
309
|
+
### Providing APP_ID
|
|
310
|
+
|
|
311
|
+
If using encryption features (localStorage encryption, AES/RSA encryption), you must provide a unique `APP_ID`:
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
import { APP_ID } from '@angular/core';
|
|
315
|
+
|
|
316
|
+
@NgModule({
|
|
317
|
+
providers: [
|
|
318
|
+
{ provide: APP_ID, useValue: 'your-unique-app-guid-here' }
|
|
319
|
+
]
|
|
320
|
+
})
|
|
321
|
+
export class AppModule { }
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
> **Important:** The `APP_ID` is used as the encryption key for `SymmetricalEncryptionService`. Use a strong, unique value per application.
|
|
325
|
+
|
|
273
326
|
## 📚 Services Overview
|
|
274
327
|
|
|
275
328
|
### Angular 14-18: Observable + NgRx Services
|
|
@@ -289,7 +342,7 @@ export class AppModule { }
|
|
|
289
342
|
|
|
290
343
|
| Service | Description | Use Case |
|
|
291
344
|
|---------|-------------|----------|
|
|
292
|
-
| [`HTTPManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/
|
|
345
|
+
| [`HTTPManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_SIGNALS_MANAGER_README.md) | Signal-based HTTP client for modern reactive UI | Modern Angular with Signals |
|
|
293
346
|
| [`LocalStorageSignalsManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOCAL_STORAGE_SIGNALS_README.md) | Signal-based local/session storage | Reactive persisted UI state |
|
|
294
347
|
| [`StoreStateManagerSignalsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/STORE_STATE_SIGNALS_README.md) | Signal-based persistent state service | App state persistence with computed derivations |
|
|
295
348
|
| [`WebSocketSignalsManagerService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WEBSOCKET_SIGNALS_README.md) | Signal-based WebSocket manager | Signal-driven real-time dashboards and messaging |
|
|
@@ -300,6 +353,7 @@ export class AppModule { }
|
|
|
300
353
|
| Service | Description | Use Case |
|
|
301
354
|
|---------|-------------|----------|
|
|
302
355
|
| [`UtilsService`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/UTILS_README.md) | Utilities: encryption, headers, merging, path/query | Helper functions |
|
|
356
|
+
| [`Utility Services`](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/UTILS_SERVICES_README.md) | Headers, path/query, merging, base request classes | Internal and helper services |
|
|
303
357
|
|
|
304
358
|
### Common Use Cases
|
|
305
359
|
|
|
@@ -339,7 +393,7 @@ All detailed service guides live in `src/docs/`. Use this README as the entry po
|
|
|
339
393
|
| Category | Documentation |
|
|
340
394
|
|----------|---------------|
|
|
341
395
|
| Overview | [Signal Services Overview](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/SIGNAL_SERVICES_README.md) |
|
|
342
|
-
| HTTP | [HTTP Manager Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/
|
|
396
|
+
| HTTP | [HTTP Manager Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_SIGNALS_MANAGER_README.md) |
|
|
343
397
|
| State | [Store State Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/STORE_STATE_SIGNALS_README.md) |
|
|
344
398
|
| Real-Time | [WebSocket Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WEBSOCKET_SIGNALS_README.md) and [Message Tracker Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/MESSAGE_TRACKER_SIGNALS_README.md) |
|
|
345
399
|
| Persistence | [Local Storage Signals](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOCAL_STORAGE_SIGNALS_README.md) |
|
|
@@ -465,7 +519,7 @@ For in-depth documentation on each service and component, refer to the following
|
|
|
465
519
|
| Documentation | Description |
|
|
466
520
|
|---------------|-------------|
|
|
467
521
|
| 📖 [Signal Services Overview](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/SIGNAL_SERVICES_README.md) | Overview of the signal-based service set and migration guidance |
|
|
468
|
-
| 📖 [HTTP Manager Signals Service](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/
|
|
522
|
+
| 📖 [HTTP Manager Signals Service](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/HTTP_SIGNALS_MANAGER_README.md) | Signal-based HTTP client for modern reactive UI with Angular Signals |
|
|
469
523
|
| 📖 [Local Storage Signals Manager Service](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/LOCAL_STORAGE_SIGNALS_README.md) | Signal-based persisted storage patterns |
|
|
470
524
|
| 📖 [Store State Signals Manager Service](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/STORE_STATE_SIGNALS_README.md) | Signal-based state persistence and computed state |
|
|
471
525
|
| 📖 [WebSocket Signals Manager Service](https://github.com/micheleboni/npm-angular/tree/main/projects/http-request-manager/src/docs/WEBSOCKET_SIGNALS_README.md) | Signal-driven WebSocket connection and subscription management |
|
|
@@ -908,54 +908,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
908
908
|
}]
|
|
909
909
|
}], ctorParameters: () => [] });
|
|
910
910
|
|
|
911
|
-
class NormalizedRequestOptionsModel {
|
|
912
|
-
constructor(pathKey = '', query = {}, hasQuery = false) {
|
|
913
|
-
this.pathKey = pathKey;
|
|
914
|
-
this.query = query;
|
|
915
|
-
this.hasQuery = hasQuery;
|
|
916
|
-
}
|
|
917
|
-
static adapt(item) {
|
|
918
|
-
return new NormalizedRequestOptionsModel(item?.pathKey, item?.query, item?.hasQuery);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
class PathTrackerStateModel {
|
|
923
|
-
constructor(consumedValuesByKey = {}, watchExpiresAt) {
|
|
924
|
-
this.consumedValuesByKey = consumedValuesByKey;
|
|
925
|
-
this.watchExpiresAt = watchExpiresAt;
|
|
926
|
-
}
|
|
927
|
-
static adapt(item) {
|
|
928
|
-
return new PathTrackerStateModel(item?.consumedValuesByKey && typeof item.consumedValuesByKey === 'object' ? item.consumedValuesByKey : {}, item?.watchExpiresAt);
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
class QueryTrackerStateModel {
|
|
933
|
-
constructor(paths = {}) {
|
|
934
|
-
this.paths = paths;
|
|
935
|
-
}
|
|
936
|
-
static adapt(item) {
|
|
937
|
-
const paths = {};
|
|
938
|
-
if (item?.paths && typeof item.paths === 'object') {
|
|
939
|
-
Object.keys(item.paths).forEach((key) => {
|
|
940
|
-
paths[key] = PathTrackerStateModel.adapt(item.paths[key]);
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
return new QueryTrackerStateModel(paths);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
class QueryParamsTrackerOptionsModel {
|
|
948
|
-
constructor(mode, watchParams, watchExpiresAt, watchParamsExpire) {
|
|
949
|
-
this.mode = mode;
|
|
950
|
-
this.watchParams = watchParams;
|
|
951
|
-
this.watchExpiresAt = watchExpiresAt;
|
|
952
|
-
this.watchParamsExpire = watchParamsExpire;
|
|
953
|
-
}
|
|
954
|
-
static adapt(item) {
|
|
955
|
-
return new QueryParamsTrackerOptionsModel(item?.mode, Array.isArray(item?.watchParams) ? item.watchParams : [], item?.watchExpiresAt, item?.watchParamsExpire);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
|
|
959
911
|
class StreamConfigModel {
|
|
960
912
|
constructor(streamType = StreamType.AI_STREAMING, totalHeader = 'X-Total-Count') {
|
|
961
913
|
this.streamType = streamType;
|
|
@@ -5156,17 +5108,15 @@ class ApiRequest {
|
|
|
5156
5108
|
}
|
|
5157
5109
|
|
|
5158
5110
|
class RequestOptions {
|
|
5159
|
-
constructor(path = [], headers = {}, forceRefresh, ignoreQueryParams, queryParamsExpiresIn
|
|
5111
|
+
constructor(path = [], headers = {}, forceRefresh, ignoreQueryParams, queryParamsExpiresIn) {
|
|
5160
5112
|
this.path = path;
|
|
5161
5113
|
this.headers = headers;
|
|
5162
5114
|
this.forceRefresh = forceRefresh;
|
|
5163
5115
|
this.ignoreQueryParams = ignoreQueryParams;
|
|
5164
5116
|
this.queryParamsExpiresIn = queryParamsExpiresIn;
|
|
5165
|
-
this.watchParams = watchParams;
|
|
5166
|
-
this.watchExpiresAt = watchExpiresAt;
|
|
5167
5117
|
}
|
|
5168
5118
|
static adapt(item) {
|
|
5169
|
-
return new RequestOptions(item?.path, item?.headers, item?.forceRefresh, Array.isArray(item?.ignoreQueryParams) ? item.ignoreQueryParams : [], item?.queryParamsExpiresIn
|
|
5119
|
+
return new RequestOptions(item?.path, item?.headers, item?.forceRefresh, Array.isArray(item?.ignoreQueryParams) ? item.ignoreQueryParams : [], item?.queryParamsExpiresIn);
|
|
5170
5120
|
}
|
|
5171
5121
|
}
|
|
5172
5122
|
|
|
@@ -6573,7 +6523,6 @@ class ChannelMessage {
|
|
|
6573
6523
|
}
|
|
6574
6524
|
}
|
|
6575
6525
|
|
|
6576
|
-
// import { QueryParamsTrackerService } from '../utils/query-params-tracker.service';
|
|
6577
6526
|
const API_OPTS = new InjectionToken('API_OPTS');
|
|
6578
6527
|
/**
|
|
6579
6528
|
* Channel type enum for different communication purposes
|
|
@@ -6616,7 +6565,6 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
6616
6565
|
this.localStorageManagerService = inject(LocalStorageManagerService);
|
|
6617
6566
|
this.utils = inject(UtilsService);
|
|
6618
6567
|
this.logger = inject(LoggerService);
|
|
6619
|
-
// private queryParamsTrackerService = inject(QueryParamsTrackerService)
|
|
6620
6568
|
this.error$ = this.httpManagerService.error$;
|
|
6621
6569
|
this.isPending$ = this.httpManagerService.isPending$.pipe(delay(1));
|
|
6622
6570
|
this.operationSuccess = new BehaviorSubject(null);
|
|
@@ -7240,7 +7188,8 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7240
7188
|
this.createRecord = (data, options) => this.effect(() => of(data).pipe(switchMap((data) => {
|
|
7241
7189
|
this.streamedResponse = [];
|
|
7242
7190
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7243
|
-
|
|
7191
|
+
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7192
|
+
return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
|
|
7244
7193
|
.pipe(tap((data) => {
|
|
7245
7194
|
data = (!data) ? (this.dataType === DataType.ARRAY) ? [] : {} : data;
|
|
7246
7195
|
this.addData$(data);
|
|
@@ -7258,7 +7207,8 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7258
7207
|
this.updateRecord = (data, options) => this.effect(() => of(data).pipe(concatMap((data) => {
|
|
7259
7208
|
this.streamedResponse = [];
|
|
7260
7209
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7261
|
-
|
|
7210
|
+
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7211
|
+
return this.httpManagerService.putRequest(data, requestOptions, effectiveParams)
|
|
7262
7212
|
.pipe(tap((data) => {
|
|
7263
7213
|
data = (!data) ? (this.dataType === DataType.ARRAY) ? [] : {} : data;
|
|
7264
7214
|
this.updateData$(data);
|
|
@@ -7276,7 +7226,8 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7276
7226
|
this.deleteRecord = (options) => this.effect(() => of(options).pipe(concatMap((data) => {
|
|
7277
7227
|
this.streamedResponse = [];
|
|
7278
7228
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7279
|
-
|
|
7229
|
+
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7230
|
+
return this.httpManagerService.deleteRequest(requestOptions, effectiveParams)
|
|
7280
7231
|
.pipe(tap((data) => {
|
|
7281
7232
|
data = (!data) ? (this.dataType === DataType.ARRAY) ? [] : {} : data;
|
|
7282
7233
|
this.deleteData$(data);
|
|
@@ -7294,7 +7245,8 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
7294
7245
|
// FETCH STREAM
|
|
7295
7246
|
this.createStream = (data, options) => this.effect(() => of(data).pipe(tap(() => this.httpManagerService.isPending.next(true)), switchMap((data) => {
|
|
7296
7247
|
const requestOptions = this.updateRequestOptions(options?.headers);
|
|
7297
|
-
|
|
7248
|
+
const effectiveParams = this.getEffectiveParams(options?.path);
|
|
7249
|
+
return this.httpManagerService.postRequest(data, requestOptions, effectiveParams)
|
|
7298
7250
|
.pipe(tap((res) => {
|
|
7299
7251
|
if (res.length > 0)
|
|
7300
7252
|
this.setData$(res);
|
|
@@ -8091,12 +8043,9 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8091
8043
|
const effective = this.getEffectiveParams(params);
|
|
8092
8044
|
return effective ? [...basePath, ...effective] : [...basePath];
|
|
8093
8045
|
}
|
|
8094
|
-
|
|
8095
|
-
if (!Array.isArray(params) || params.length === 0) {
|
|
8096
|
-
return undefined;
|
|
8097
|
-
}
|
|
8046
|
+
stripBasePathPrefix(params) {
|
|
8098
8047
|
const basePath = Array.isArray(this.apiOptions.path) ? this.apiOptions.path : [];
|
|
8099
|
-
if (basePath.length
|
|
8048
|
+
if (basePath.length === 0 || params.length < basePath.length) {
|
|
8100
8049
|
return params;
|
|
8101
8050
|
}
|
|
8102
8051
|
const normalizePart = (value) => {
|
|
@@ -8105,8 +8054,25 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8105
8054
|
}
|
|
8106
8055
|
return String(value);
|
|
8107
8056
|
};
|
|
8108
|
-
const
|
|
8109
|
-
return
|
|
8057
|
+
const startsWithBase = basePath.every((part, index) => normalizePart(part) === normalizePart(params[index]));
|
|
8058
|
+
return startsWithBase ? params.slice(basePath.length) : params;
|
|
8059
|
+
}
|
|
8060
|
+
getEffectiveParams(params) {
|
|
8061
|
+
if (!Array.isArray(params) || params.length === 0) {
|
|
8062
|
+
return undefined;
|
|
8063
|
+
}
|
|
8064
|
+
const basePath = Array.isArray(this.apiOptions.path) ? this.apiOptions.path : [];
|
|
8065
|
+
if (basePath.length === params.length) {
|
|
8066
|
+
const normalizePart = (value) => {
|
|
8067
|
+
if (value && typeof value === 'object') {
|
|
8068
|
+
return JSON.stringify(this.normalizeObject(value));
|
|
8069
|
+
}
|
|
8070
|
+
return String(value);
|
|
8071
|
+
};
|
|
8072
|
+
const samePath = params.every((part, index) => normalizePart(part) === normalizePart(basePath[index]));
|
|
8073
|
+
return samePath ? undefined : params;
|
|
8074
|
+
}
|
|
8075
|
+
return this.stripBasePathPrefix(params);
|
|
8110
8076
|
}
|
|
8111
8077
|
buildRequestSignature(method, requestOptions, params) {
|
|
8112
8078
|
const signaturePayload = {
|
|
@@ -8161,6 +8127,9 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8161
8127
|
this._requestCachePaths.set(tableName, this.resolvePath(options?.path).filter(p => typeof p === 'string' || typeof p === 'number').map(String));
|
|
8162
8128
|
this.localStorageManagerService.store$(tableName).pipe(take(1), tap((storeData) => {
|
|
8163
8129
|
const currentCache = storeData?.requestCache || {};
|
|
8130
|
+
const currentEntry = currentCache[type] || {};
|
|
8131
|
+
const currentQueryParams = { ...(currentEntry.queryParams || {}) };
|
|
8132
|
+
const currentQueryParamsExpires = currentEntry.queryParamsExpires ?? null;
|
|
8164
8133
|
this.localStorageManagerService.updateStore({
|
|
8165
8134
|
name: tableName,
|
|
8166
8135
|
data: {
|
|
@@ -8168,11 +8137,13 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8168
8137
|
requestCache: {
|
|
8169
8138
|
...currentCache,
|
|
8170
8139
|
[type]: {
|
|
8171
|
-
...
|
|
8140
|
+
...currentEntry,
|
|
8172
8141
|
signature,
|
|
8173
8142
|
savedAt: Date.now(),
|
|
8174
8143
|
path: this.resolvePath(options?.path),
|
|
8175
|
-
headers: this.filterHeaders(options?.headers)
|
|
8144
|
+
headers: this.filterHeaders(options?.headers),
|
|
8145
|
+
queryParams: currentQueryParams,
|
|
8146
|
+
queryParamsExpires: currentQueryParamsExpires,
|
|
8176
8147
|
}
|
|
8177
8148
|
}
|
|
8178
8149
|
}
|
|
@@ -8192,7 +8163,6 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8192
8163
|
}
|
|
8193
8164
|
}
|
|
8194
8165
|
if (Array.isArray(pathArray) && pathArray.length > 0) {
|
|
8195
|
-
// this.queryParamsTrackerService.clearTrackingForPath(pathArray.join('/'))
|
|
8196
8166
|
this._requestCachePaths.delete(tableName);
|
|
8197
8167
|
}
|
|
8198
8168
|
if (!storeData)
|
|
@@ -8338,11 +8308,11 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
8338
8308
|
accepted = true;
|
|
8339
8309
|
}
|
|
8340
8310
|
});
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8311
|
+
const newExpiry = this.trackerBuildExpiryEpoch(options?.queryParamsExpiresIn);
|
|
8312
|
+
if (newExpiry !== null) {
|
|
8313
|
+
queryParamsExpires = newExpiry;
|
|
8314
|
+
}
|
|
8315
|
+
if (accepted || newExpiry !== null) {
|
|
8346
8316
|
this.localStorageManagerService.store$(tableName).pipe(take(1), tap((latestStoreData) => {
|
|
8347
8317
|
const currentCache = latestStoreData?.requestCache || {};
|
|
8348
8318
|
const currentEntry = currentCache[type] || {};
|
|
@@ -8714,10 +8684,11 @@ class SqlParser {
|
|
|
8714
8684
|
if (ast.type !== 'select') {
|
|
8715
8685
|
throw new SqlParseError('Only SELECT statements are supported');
|
|
8716
8686
|
}
|
|
8687
|
+
const stripPrefix = (list) => list.map(entry => entry.split('::').pop() ?? entry);
|
|
8717
8688
|
return {
|
|
8718
8689
|
ast,
|
|
8719
|
-
tableList: result.tableList ?? [],
|
|
8720
|
-
columnList: result.columnList ?? [],
|
|
8690
|
+
tableList: stripPrefix(result.tableList ?? []),
|
|
8691
|
+
columnList: stripPrefix(result.columnList ?? []),
|
|
8721
8692
|
};
|
|
8722
8693
|
}
|
|
8723
8694
|
}
|
|
@@ -8988,7 +8959,9 @@ class QueryPlanner {
|
|
|
8988
8959
|
const where = ast.where;
|
|
8989
8960
|
const boundedFilters = [];
|
|
8990
8961
|
if (where) {
|
|
8991
|
-
this._flattenAnd(where.operator === 'AND'
|
|
8962
|
+
this._flattenAnd(where.operator === 'AND'
|
|
8963
|
+
? where
|
|
8964
|
+
: { type: 'binary_expr', operator: 'AND', left: where, right: null })
|
|
8992
8965
|
.filter(Boolean)
|
|
8993
8966
|
.forEach((c) => boundedFilters.push(this._nodeToStep(c, aliases, mainTable)));
|
|
8994
8967
|
}
|
|
@@ -9021,6 +8994,7 @@ class QueryPlanner {
|
|
|
9021
8994
|
}
|
|
9022
8995
|
else if (vals.length === 1) {
|
|
9023
8996
|
plan.limit = vals[0].value;
|
|
8997
|
+
plan.offset = null;
|
|
9024
8998
|
}
|
|
9025
8999
|
}
|
|
9026
9000
|
// Projection
|
|
@@ -10686,7 +10660,7 @@ class RequestManagerStateDemoComponent {
|
|
|
10686
10660
|
const apiOptions = ApiRequest.adapt({ ...currentOptions, path: pathReq });
|
|
10687
10661
|
return { apiOptions: apiOptions, path: pathReq };
|
|
10688
10662
|
}
|
|
10689
|
-
|
|
10663
|
+
parseIgnoreParams(value) {
|
|
10690
10664
|
if (!value || typeof value !== 'string') {
|
|
10691
10665
|
return [];
|
|
10692
10666
|
}
|
|
@@ -10695,25 +10669,16 @@ class RequestManagerStateDemoComponent {
|
|
|
10695
10669
|
.map((item) => item.trim())
|
|
10696
10670
|
.filter((item) => item.length > 0);
|
|
10697
10671
|
}
|
|
10698
|
-
normalizeWatchExpiry(value) {
|
|
10699
|
-
if (typeof value === 'undefined' || value === null || value === '') {
|
|
10700
|
-
return undefined;
|
|
10701
|
-
}
|
|
10702
|
-
if (typeof value === 'string' && value.trim().toLowerCase() === 'never') {
|
|
10703
|
-
return undefined;
|
|
10704
|
-
}
|
|
10705
|
-
return value;
|
|
10706
|
-
}
|
|
10707
10672
|
buildDemoRequestOptions(path, headers) {
|
|
10708
10673
|
const dbValue = this.database || {};
|
|
10709
10674
|
const isDbEnabled = !!this.DBState?.checked;
|
|
10710
|
-
const
|
|
10675
|
+
const parsedIgnoreQueryParams = this.parseIgnoreParams(dbValue?.ignoreQueryParams);
|
|
10711
10676
|
return RequestOptions.adapt({
|
|
10712
10677
|
path,
|
|
10713
10678
|
headers,
|
|
10714
10679
|
forceRefresh: false,
|
|
10715
|
-
|
|
10716
|
-
|
|
10680
|
+
ignoreQueryParams: isDbEnabled && parsedIgnoreQueryParams.length > 0 ? parsedIgnoreQueryParams : undefined,
|
|
10681
|
+
queryParamsExpiresIn: isDbEnabled ? dbValue?.queryParamsExpiresIn : undefined,
|
|
10717
10682
|
});
|
|
10718
10683
|
}
|
|
10719
10684
|
onSetStateOptions() {
|
|
@@ -11936,13 +11901,24 @@ class WsDataControlComponent {
|
|
|
11936
11901
|
.pipe(switchMap$1((action) => timer(3 * 1000).pipe(map$1(() => null), startWith$1(action))));
|
|
11937
11902
|
this.data$ = this.stateDataRequestService.data$;
|
|
11938
11903
|
this.isUser = (user, userItem) => {
|
|
11939
|
-
return user.
|
|
11904
|
+
return user.id === userItem?.id;
|
|
11905
|
+
};
|
|
11906
|
+
this.getUserLabel = (user) => {
|
|
11907
|
+
const name = user.name || user.ldap || 'Anonymous';
|
|
11908
|
+
const shortId = user.id ? user.id.substring(0, 8) : '';
|
|
11909
|
+
return shortId ? `${name} (${shortId})` : name;
|
|
11940
11910
|
};
|
|
11941
11911
|
}
|
|
11942
11912
|
ngOnInit() {
|
|
11943
11913
|
this.stateDataRequestService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
|
|
11944
11914
|
this.stateDataRequestService.getData();
|
|
11945
11915
|
}
|
|
11916
|
+
ngOnChanges(changes) {
|
|
11917
|
+
if (changes['jwtToken'] && !changes['jwtToken'].firstChange) {
|
|
11918
|
+
this.stateDataRequestService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
|
|
11919
|
+
this.stateDataRequestService.getData();
|
|
11920
|
+
}
|
|
11921
|
+
}
|
|
11946
11922
|
onGetData() {
|
|
11947
11923
|
this.stateDataRequestService.getData();
|
|
11948
11924
|
}
|
|
@@ -11951,12 +11927,15 @@ class WsDataControlComponent {
|
|
|
11951
11927
|
}
|
|
11952
11928
|
onUpdateData(data) {
|
|
11953
11929
|
const num = RandomNumber(1000, 9999);
|
|
11930
|
+
const firstName = this.user?.name?.split(' ')[0] || 'mike';
|
|
11931
|
+
const lastName = this.user?.name?.split(' ').slice(1).join(' ') || 'boni';
|
|
11932
|
+
const email = this.user?.email || 'mikeboni@hotmail.com';
|
|
11954
11933
|
const newData = {
|
|
11955
11934
|
"spiffe": `wavecoders.com/developer/${num}`,
|
|
11956
11935
|
"id": 63,
|
|
11957
|
-
"last_name":
|
|
11958
|
-
"email":
|
|
11959
|
-
"first_name":
|
|
11936
|
+
"last_name": lastName,
|
|
11937
|
+
"email": email,
|
|
11938
|
+
"first_name": firstName
|
|
11960
11939
|
};
|
|
11961
11940
|
this.stateDataRequestService.updateData(newData);
|
|
11962
11941
|
}
|
|
@@ -12023,11 +12002,11 @@ class WsDataControlComponent {
|
|
|
12023
12002
|
});
|
|
12024
12003
|
}
|
|
12025
12004
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsDataControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
12026
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, ngImport: i0, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track $index) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ user
|
|
12005
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, usesOnChanges: true, ngImport: i0, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track $index) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ getUserLabel(user) }}\n </mat-chip>\n }\n </mat-chip-set>\n </div>\n }\n <div style=\"margin-top: 1rem; margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div class=\"box\" style=\"margin-bottom: 1rem;\" *ngIf=\"(userAction$ | async) as userAction\">\n {{ userAction?.content?.user?.name }} has {{ userAction?.content?.method }}\n </div>\n\n <h3 style=\"margin: 0;\">Data Actions</h3>\n <div style=\"display: flex; gap: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onGetData()\">Get Data</button>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button color=\"accent\" (click)=\"onUpdateData(data)\">Update Data</button>\n <button mat-stroked-button color=\"warn\" (click)=\"onRemoveData(data)\">Remove Data</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onAddData()\">Add Data</button>\n </div>\n\n <h3 style=\"margin: 0; margin-top: 1rem;\">WebSocketMessageService Test</h3>\n\n <p style=\"font-size: 0.875rem; color: #666; margin: 0;\">\n <strong>Note:</strong> \"Fake SessionId\" will be received and processed. \"Current SessionId\" will be filtered out (self-message).\n @if (data.length > 0) {\n <div>\n <table mat-table [dataSource]=\"data\" style=\"border: 1px solid grey;\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n <ng-container matColumnDef=\"spiffe\">\n <th mat-header-cell *matHeaderCellDef> Spiffe </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.spiffe}} </td>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.first_name}} {{element.last_name}}</td>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef> Email </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.email}} </td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"['id', 'spiffe', 'name', 'email']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['id', 'spiffe', 'name', 'email'];\"></tr>\n </table>\n <div style=\"border: 1px solid grey; padding: .5rem; border-top: none;\">\n <h3 style=\"margin: 0;\">Total Records {{ data.length }}</h3>\n </div>\n </div>\n } @else {\n <div style=\"margin-top: 1rem; font-style: italic;\">\n No Data Available\n </div>\n }\n\n <div style=\"margin-bottom: 1rem; margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem; margin-bottom: 1rem;\">\n <button mat-flat-button color=\"primary\" (click)=\"onTestDirectStateMessage(63, true)\">\n Test UPDATE (Fake Id)\n </button>\n <button mat-stroked-button (click)=\"onTestDirectStateMessage(63, false)\">\n Test UPDATE (Current Id)\n </button>\n <button mat-stroked-button (click)=\"onTestDirectStateMessage(63, false, 'custom-session-123')\">\n Test UPDATE (Custom Id)\n </button>\n </div>\n\n </div>\n}\n\n", styles: [".user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}.user-chip--primary :is(.mdc-evolution-chip__text-label,.mdc-evolution-chip__action,.mdc-evolution-chip__cell,.mat-mdc-chip-action-label){color:#fff!important}.user-chip--primary,.user-chip--primary *{color:#fff!important}:host ::ng-deep .user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}:host ::ng-deep .user-chip--primary .mdc-evolution-chip__text-label,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__action,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__cell,:host ::ng-deep .user-chip--primary .mat-mdc-chip-action-label,:host ::ng-deep .user-chip--primary *{color:#fff!important}.box{padding:.5rem;border:1px solid rgb(174,174,13);background-color:#ececaf}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i3$1.MatChipSet, selector: "mat-chip-set", inputs: ["disabled", "role", "tabIndex"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
|
|
12027
12006
|
}
|
|
12028
12007
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WsDataControlComponent, decorators: [{
|
|
12029
12008
|
type: Component,
|
|
12030
|
-
args: [{ selector: 'app-ws-data-control', standalone: false, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track $index) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ user
|
|
12009
|
+
args: [{ selector: 'app-ws-data-control', standalone: false, template: "@if ((data$ | async); as data) {\n <div style=\"margin: 1rem;\">\n @if ((users$ |async); as users) {\n <div>\n @if (users.length > 0) {\n <h3 style=\"margin: 0;\">Connected Users</h3>\n } @else {\n <h3 style=\"margin: 0;\">No Users</h3>\n }\n <mat-chip-set>\n @for (user of users; track $index) {\n <mat-chip\n [class.user-chip--primary]=\"isUser(user, (user$ | async))\"\n [style.color]=\"isUser(user, (user$ | async)) ? '#fff' : null\"\n [disableRipple]=\"true\"\n >\n {{ getUserLabel(user) }}\n </mat-chip>\n }\n </mat-chip-set>\n </div>\n }\n <div style=\"margin-top: 1rem; margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div class=\"box\" style=\"margin-bottom: 1rem;\" *ngIf=\"(userAction$ | async) as userAction\">\n {{ userAction?.content?.user?.name }} has {{ userAction?.content?.method }}\n </div>\n\n <h3 style=\"margin: 0;\">Data Actions</h3>\n <div style=\"display: flex; gap: 1rem; margin-bottom: 1rem;\">\n <button mat-stroked-button (click)=\"onGetData()\">Get Data</button>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button color=\"accent\" (click)=\"onUpdateData(data)\">Update Data</button>\n <button mat-stroked-button color=\"warn\" (click)=\"onRemoveData(data)\">Remove Data</button>\n <button mat-stroked-button color=\"primary\" (click)=\"onAddData()\">Add Data</button>\n </div>\n\n <h3 style=\"margin: 0; margin-top: 1rem;\">WebSocketMessageService Test</h3>\n\n <p style=\"font-size: 0.875rem; color: #666; margin: 0;\">\n <strong>Note:</strong> \"Fake SessionId\" will be received and processed. \"Current SessionId\" will be filtered out (self-message).\n @if (data.length > 0) {\n <div>\n <table mat-table [dataSource]=\"data\" style=\"border: 1px solid grey;\">\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n <ng-container matColumnDef=\"spiffe\">\n <th mat-header-cell *matHeaderCellDef> Spiffe </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.spiffe}} </td>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Name </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.first_name}} {{element.last_name}}</td>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef> Email </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.email}} </td>\n </ng-container>\n <tr mat-header-row *matHeaderRowDef=\"['id', 'spiffe', 'name', 'email']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['id', 'spiffe', 'name', 'email'];\"></tr>\n </table>\n <div style=\"border: 1px solid grey; padding: .5rem; border-top: none;\">\n <h3 style=\"margin: 0;\">Total Records {{ data.length }}</h3>\n </div>\n </div>\n } @else {\n <div style=\"margin-top: 1rem; font-style: italic;\">\n No Data Available\n </div>\n }\n\n <div style=\"margin-bottom: 1rem; margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"display: flex; gap: 0.5rem; margin-bottom: 1rem;\">\n <button mat-flat-button color=\"primary\" (click)=\"onTestDirectStateMessage(63, true)\">\n Test UPDATE (Fake Id)\n </button>\n <button mat-stroked-button (click)=\"onTestDirectStateMessage(63, false)\">\n Test UPDATE (Current Id)\n </button>\n <button mat-stroked-button (click)=\"onTestDirectStateMessage(63, false, 'custom-session-123')\">\n Test UPDATE (Custom Id)\n </button>\n </div>\n\n </div>\n}\n\n", styles: [".user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}.user-chip--primary :is(.mdc-evolution-chip__text-label,.mdc-evolution-chip__action,.mdc-evolution-chip__cell,.mat-mdc-chip-action-label){color:#fff!important}.user-chip--primary,.user-chip--primary *{color:#fff!important}:host ::ng-deep .user-chip--primary{background-color:var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5))!important;color:#fff!important;--mdc-evolution-chip-container-color: var(--mdc-theme-primary, var(--md-sys-color-primary, #3f51b5));--mdc-evolution-chip-label-text-color: #fff}:host ::ng-deep .user-chip--primary .mdc-evolution-chip__text-label,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__action,:host ::ng-deep .user-chip--primary .mdc-evolution-chip__cell,:host ::ng-deep .user-chip--primary .mat-mdc-chip-action-label,:host ::ng-deep .user-chip--primary *{color:#fff!important}.box{padding:.5rem;border:1px solid rgb(174,174,13);background-color:#ececaf}\n"] }]
|
|
12031
12010
|
}], propDecorators: { server: [{
|
|
12032
12011
|
type: Input
|
|
12033
12012
|
}], wsServer: [{
|
|
@@ -12448,8 +12427,13 @@ class RequestManagerWsDemoComponent {
|
|
|
12448
12427
|
ngOnInit() {
|
|
12449
12428
|
this.stateService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
|
|
12450
12429
|
}
|
|
12430
|
+
ngOnChanges(changes) {
|
|
12431
|
+
if (changes['jwtToken'] && !changes['jwtToken'].firstChange) {
|
|
12432
|
+
this.stateService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
|
|
12433
|
+
}
|
|
12434
|
+
}
|
|
12451
12435
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
12452
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2 style=\"display: flex;\">\n <span style=\"flex:1\">HTTP Request State Manager - Websockets</span>\n @if ((connectionStatus$ | async); as connected) {\n <span>\n WS -\n <span style=\"color: green;\">Connected</span>\n </span>\n } @else if (connectionError$ | async) {\n <span style=\"color: red;\">{{ connectionError$ | async }}</span>\n } @else if (isConnecting$ | async) {\n <span style=\"color: orange;\">Connecting... {{ retryCount$ | async }} / {{ maxRetries$ | async }}</span>\n } @else {\n <span style=\"color: red;\">Disconnected</span>\n }\n </h2>\n\n <div>\n\n @if ((user$ | async); as userInfo) {\n <div>\n <mat-toolbar>\n <div style=\"display: flex; flex:1\">\n <div style=\"flex:1\">{{ userInfo.name }}</div>\n <div>({{ userInfo.ldap }})</div>\n </div>\n </mat-toolbar>\n </div>\n }\n\n @if ((isConnecting$ | async) && !(connectionStatus$ | async) && !(connectionError$ | async)) {\n <div style=\"display: flex; align-items: center; gap: 1rem; padding: 0.5rem; background: #e3f2fd; border-radius: 4px; margin-bottom: 0.5rem;\">\n <span>Connecting to WebSocket...</span>\n <mat-progress-bar mode=\"indeterminate\" style=\"flex: 1;\"></mat-progress-bar>\n </div>\n }\n\n @if (connectionError$ | async; as errorMsg) {\n <div style=\"padding: 0.75rem 1rem; background: #fdecea; color: #b00020; border-left: 4px solid #b00020; border-radius: 2px; margin-bottom: 0.5rem;\">\n {{ errorMsg }}\n </div>\n }\n\n <mat-tab-group animationDuration=\"0ms\" [selectedIndex]=\"1\">\n\n <mat-tab label=\"WS - Data Control\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- DATA CONTROL -->\n <app-ws-data-control\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-data-control>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Messaging\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- MESSAGING -->\n <app-ws-messaging\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-messaging>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Notifications\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- WS - Notifications -->\n <app-ws-notifications\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n ></app-ws-notifications>\n </mat-tab>\n\n <mat-tab label=\"WS - Chats\" [disabled]=\"true\">\n <!-- WS - Chats -->\n <app-ws-chats></app-ws-chats>\n </mat-tab>\n\n <mat-tab label=\"WS - AI Messaging\" [disabled]=\"true\">\n <!-- WS - AI Messaging -->\n <app-ws-ai-messaging></app-ws-ai-messaging>\n </mat-tab>\n\n </mat-tab-group>\n</div>\n\n</div>\n\n", styles: [""], dependencies: [{ kind: "component", type: i1$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i1$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: ["server", "wsServer", "jwtToken", "user"] }, { kind: "component", type: WsAiMessagingComponent, selector: "app-ws-ai-messaging" }, { kind: "component", type: WsChatsComponent, selector: "app-ws-chats" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
|
|
12436
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: RequestManagerWsDemoComponent, selector: "app-request-manager-ws-demo", inputs: { server: "server", wsServer: "wsServer", jwtToken: "jwtToken", user: "user", path: "path" }, usesOnChanges: true, ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <h2 style=\"display: flex;\">\n <span style=\"flex:1\">HTTP Request State Manager - Websockets</span>\n @if ((connectionStatus$ | async); as connected) {\n <span>\n WS -\n <span style=\"color: green;\">Connected</span>\n </span>\n } @else if (connectionError$ | async) {\n <span style=\"color: red;\">{{ connectionError$ | async }}</span>\n } @else if (isConnecting$ | async) {\n <span style=\"color: orange;\">Connecting... {{ retryCount$ | async }} / {{ maxRetries$ | async }}</span>\n } @else {\n <span style=\"color: red;\">Disconnected</span>\n }\n </h2>\n\n <div>\n\n @if ((user$ | async); as userInfo) {\n <div>\n <mat-toolbar>\n <div style=\"display: flex; flex:1\">\n <div style=\"flex:1\">{{ userInfo.name }}</div>\n <div>({{ userInfo.ldap }})</div>\n </div>\n </mat-toolbar>\n </div>\n }\n\n @if ((isConnecting$ | async) && !(connectionStatus$ | async) && !(connectionError$ | async)) {\n <div style=\"display: flex; align-items: center; gap: 1rem; padding: 0.5rem; background: #e3f2fd; border-radius: 4px; margin-bottom: 0.5rem;\">\n <span>Connecting to WebSocket...</span>\n <mat-progress-bar mode=\"indeterminate\" style=\"flex: 1;\"></mat-progress-bar>\n </div>\n }\n\n @if (connectionError$ | async; as errorMsg) {\n <div style=\"padding: 0.75rem 1rem; background: #fdecea; color: #b00020; border-left: 4px solid #b00020; border-radius: 2px; margin-bottom: 0.5rem;\">\n {{ errorMsg }}\n </div>\n }\n\n <mat-tab-group animationDuration=\"0ms\" [selectedIndex]=\"1\">\n\n <mat-tab label=\"WS - Data Control\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- DATA CONTROL -->\n <app-ws-data-control\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-data-control>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Messaging\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- MESSAGING -->\n <app-ws-messaging\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n [path]=\"path\"\n ></app-ws-messaging>\n\n </mat-tab>\n\n <mat-tab label=\"WS - Notifications\" [disabled]=\"!(connectionStatus$ | async)\">\n <!-- WS - Notifications -->\n <app-ws-notifications\n [server]=\"server\"\n [wsServer]=\"wsServer\"\n [jwtToken]=\"jwtToken\"\n [user]=\"user\"\n ></app-ws-notifications>\n </mat-tab>\n\n <mat-tab label=\"WS - Chats\" [disabled]=\"true\">\n <!-- WS - Chats -->\n <app-ws-chats></app-ws-chats>\n </mat-tab>\n\n <mat-tab label=\"WS - AI Messaging\" [disabled]=\"true\">\n <!-- WS - AI Messaging -->\n <app-ws-ai-messaging></app-ws-ai-messaging>\n </mat-tab>\n\n </mat-tab-group>\n</div>\n\n</div>\n\n", styles: [""], dependencies: [{ kind: "component", type: i1$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i1$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i3$2.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: WsDataControlComponent, selector: "app-ws-data-control", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsMessagingComponent, selector: "app-ws-messaging", inputs: ["server", "wsServer", "jwtToken", "user", "path"] }, { kind: "component", type: WsNotificationsComponent, selector: "app-ws-notifications", inputs: ["server", "wsServer", "jwtToken", "user"] }, { kind: "component", type: WsAiMessagingComponent, selector: "app-ws-ai-messaging" }, { kind: "component", type: WsChatsComponent, selector: "app-ws-chats" }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] }); }
|
|
12453
12437
|
}
|
|
12454
12438
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, decorators: [{
|
|
12455
12439
|
type: Component,
|
|
@@ -13693,5 +13677,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
13693
13677
|
* Generated bundle index. Do not edit.
|
|
13694
13678
|
*/
|
|
13695
13679
|
|
|
13696
|
-
export { ApiRequest, AppService, AsymmetricalEncryptionService, BatchOptions, BatchResult, CONFIG_SETTINGS_TOKEN, ChannelType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, DexieSqlService, ErrorDisplaySettings, ExecutionPlanType, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, InvalidFileInfoModel, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsDemoComponent, LocalStorageSignalsManagerService, LoggerService,
|
|
13680
|
+
export { ApiRequest, AppService, AsymmetricalEncryptionService, BatchOptions, BatchResult, CONFIG_SETTINGS_TOKEN, ChannelType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, DexieSqlService, ErrorDisplaySettings, ExecutionPlanType, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, InvalidFileInfoModel, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsDemoComponent, LocalStorageSignalsManagerService, LoggerService, NotificationMessage, OperationResultModel, ParsingResultModel, PathQueryService, PublicMessage, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, SqlParseError, SqlValidationError, StateMessage, StateOperationResult, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StoreStateManagerSignalsService, StoreStateSignalsDemoComponent, StreamConfigModel, StreamEventMetadataModel, StreamEventModel, StreamOutputModel, StreamProgressModel, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UploadDemoComponent, UploadValidationErrorModel, UserData, UtilsService, WSOptions, WebSocketMessageService, WithCredentialsInterceptor, calculateBatchProgress, countdown, createChannelName, delayedRetry, isErrorState, isPendingState, isSuccessState, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
|
|
13697
13681
|
//# sourceMappingURL=http-request-manager.mjs.map
|