http-request-manager 18.10.0 → 18.10.1

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, APP_ID, Inject, InjectionToken, Injector, Optional, signal, computed, effect, EventEmitter, Input, Output, ViewEncapsulation, Component, NgModule, ViewChild } from '@angular/core';
2
+ import { inject, Injectable, APP_ID, Inject, InjectionToken, isDevMode, Injector, Optional, signal, computed, effect, EventEmitter, Input, Output, ViewEncapsulation, Component, NgModule, ViewChild } from '@angular/core';
3
3
  import { ComponentStore } from '@ngrx/component-store';
4
4
  import { map, catchError, filter, tap, finalize, takeWhile, retry, startWith, mergeMap, takeUntil, withLatestFrom, switchMap, delay, concatMap, take, scan, distinctUntilChanged } from 'rxjs/operators';
5
5
  import { HttpClient, HttpHeaders, HttpEventType, HttpHeaderResponse, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
@@ -803,6 +803,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
803
803
  }]
804
804
  }], ctorParameters: () => [] });
805
805
 
806
+ /**
807
+ * LoggerService for http-request-manager library
808
+ *
809
+ * Automatically enables debug logging in development mode,
810
+ * disables it in production mode.
811
+ *
812
+ * Usage:
813
+ * ```typescript
814
+ * constructor(private logger: LoggerService) {}
815
+ *
816
+ * this.logger.debug('WebSocket', 'Connected successfully');
817
+ * this.logger.info('HTTP', 'Request completed', { status: 200 });
818
+ * this.logger.warn('State', 'Cache miss for key', { key: 'user' });
819
+ * this.logger.error('Database', 'Connection failed', error);
820
+ * ```
821
+ */
822
+ class LoggerService {
823
+ constructor() {
824
+ // Automatically detect development vs production mode
825
+ this.debugMode = isDevMode();
826
+ }
827
+ /**
828
+ * Debug level logging - only shown in development mode
829
+ * Use for: Detailed diagnostic information, state changes, connection events
830
+ */
831
+ debug(context, message, data) {
832
+ if (this.debugMode) {
833
+ console.log(`[HTTP-MGR DEBUG] ${context}: ${message}`, data ?? '');
834
+ }
835
+ }
836
+ /**
837
+ * Info level logging - only shown in development mode
838
+ * Use for: Important operational messages, successful operations
839
+ */
840
+ info(context, message, data) {
841
+ if (this.debugMode) {
842
+ console.info(`[HTTP-MGR INFO] ${context}: ${message}`, data ?? '');
843
+ }
844
+ }
845
+ /**
846
+ * Warning level logging - always shown
847
+ * Use for: Potential issues, deprecated usage, recoverable errors
848
+ */
849
+ warn(context, message, data) {
850
+ console.warn(`[HTTP-MGR WARN] ${context}: ${message}`, data ?? '');
851
+ }
852
+ /**
853
+ * Error level logging - always shown
854
+ * Use for: Actual errors, failures, exceptions
855
+ */
856
+ error(context, message, data) {
857
+ console.error(`[HTTP-MGR ERROR] ${context}: ${message}`, data ?? '');
858
+ }
859
+ /**
860
+ * Check if debug mode is enabled (development mode)
861
+ */
862
+ isDebugEnabled() {
863
+ return this.debugMode;
864
+ }
865
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
866
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoggerService, providedIn: 'root' }); }
867
+ }
868
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoggerService, decorators: [{
869
+ type: Injectable,
870
+ args: [{
871
+ providedIn: 'root'
872
+ }]
873
+ }], ctorParameters: () => [] });
874
+
806
875
  /**
807
876
  * Stateful processor for managing streaming data and events
808
877
  */
@@ -1202,8 +1271,48 @@ var CommunicationType;
1202
1271
  CommunicationType[CommunicationType["OTHER"] = 2] = "OTHER";
1203
1272
  })(CommunicationType || (CommunicationType = {}));
1204
1273
 
1274
+ var ChannelType$1;
1275
+ (function (ChannelType) {
1276
+ ChannelType["STATE"] = "SYS";
1277
+ ChannelType["PUBLIC"] = "PUB";
1278
+ ChannelType["NOTIFICATION"] = "MES";
1279
+ ChannelType["CUSTOM"] = ""; // No prefix (raw channel name)
1280
+ })(ChannelType$1 || (ChannelType$1 = {}));
1281
+
1282
+ class StateMessage {
1283
+ constructor(sessionId = { id: '' }, content = {}) {
1284
+ this.sessionId = sessionId;
1285
+ this.content = content;
1286
+ }
1287
+ static adapt(item) {
1288
+ return new StateMessage(item?.sessionId, item?.content);
1289
+ }
1290
+ }
1291
+
1292
+ class PublicMessage {
1293
+ constructor(sessionId = { id: '' }, content = { message: '' }) {
1294
+ this.sessionId = sessionId;
1295
+ this.content = content;
1296
+ }
1297
+ static adapt(item) {
1298
+ return new PublicMessage(item?.sessionId, item?.content);
1299
+ }
1300
+ }
1301
+
1302
+ class NotificationMessage {
1303
+ constructor(sessionId = { id: '' }, message = '', additionalProperties = {}) {
1304
+ this.sessionId = sessionId;
1305
+ this.message = message;
1306
+ Object.assign(this, additionalProperties);
1307
+ }
1308
+ static adapt(item) {
1309
+ return new NotificationMessage(item?.sessionId, item?.message, item);
1310
+ }
1311
+ }
1312
+
1205
1313
  class WebsocketService {
1206
1314
  constructor() {
1315
+ this.logger = new LoggerService();
1207
1316
  this.socket = null;
1208
1317
  this.messages = new BehaviorSubject(null);
1209
1318
  this.messages$ = this.messages.asObservable();
@@ -1241,24 +1350,28 @@ class WebsocketService {
1241
1350
  current.add(channelName);
1242
1351
  this.subscribedChannels.next(current);
1243
1352
  this.isSubscribed = true; // Keep for backward compatibility
1244
- console.log(`[CLIENT] Sent initial subscription to: ${channelName}`);
1353
+ this.logger.debug('WebSocket', `Sent initial subscription to: ${channelName}`);
1245
1354
  }
1246
1355
  else {
1247
- console.warn(`[CLIENT] Subscription prevented. Open: ${this.socket?.readyState === WebSocket.OPEN}, Already subscribed to ${channelName}: ${alreadySubscribed}`);
1356
+ this.logger.warn('WebSocket', `Subscription prevented`, {
1357
+ open: this.socket?.readyState === WebSocket.OPEN,
1358
+ channel: channelName,
1359
+ alreadySubscribed
1360
+ });
1248
1361
  }
1249
1362
  }
1250
1363
  connect(options, jwtToken) {
1251
1364
  if (this.socket) {
1252
1365
  if (this.socket.readyState === WebSocket.OPEN) {
1253
- console.log('WebSocket connection is already OPEN.');
1366
+ this.logger.debug('WebSocket', 'Connection is already OPEN');
1254
1367
  return;
1255
1368
  }
1256
1369
  if (this.socket.readyState === WebSocket.CONNECTING) {
1257
- console.log('WebSocket is already CONNECTING. Waiting for handshake.');
1370
+ this.logger.debug('WebSocket', 'Already CONNECTING. Waiting for handshake');
1258
1371
  return;
1259
1372
  }
1260
1373
  if (this.socket.readyState === WebSocket.CLOSING || this.socket.readyState === WebSocket.CLOSED) {
1261
- console.log(`Cleaning up stale socket (State: ${this.socket.readyState}).`);
1374
+ this.logger.debug('WebSocket', `Cleaning up stale socket`, { state: this.socket.readyState });
1262
1375
  this.socket.close();
1263
1376
  this.socket = null;
1264
1377
  }
@@ -1270,7 +1383,7 @@ class WebsocketService {
1270
1383
  const URL = (jwtToken) ? `${options.wsServer}?token=${jwtToken}&sessionId=${sessionId}` : `${options.wsServer}?sessionId=${sessionId}`;
1271
1384
  this.socket = new WebSocket(URL);
1272
1385
  this.socket.onopen = () => {
1273
- console.log(`📡 Connected to WebSocket`);
1386
+ this.logger.info('WebSocket', '📡 Connected to WebSocket');
1274
1387
  this.connectionStatus.next(true);
1275
1388
  this.lastOptions = options;
1276
1389
  // Subscribe to primary channel
@@ -1308,7 +1421,7 @@ class WebsocketService {
1308
1421
  try {
1309
1422
  const data = JSON.parse(event.data);
1310
1423
  if (data.error && data.error === 'JWT_INVALID') {
1311
- console.error('JWT validation failed. Authentication error!');
1424
+ this.logger.error('WebSocket', 'JWT validation failed. Authentication error!');
1312
1425
  this.messages.next(data);
1313
1426
  this.connectionStatus.next(false);
1314
1427
  this.socket?.close();
@@ -1317,16 +1430,16 @@ class WebsocketService {
1317
1430
  this.messages.next(data);
1318
1431
  }
1319
1432
  catch (error) {
1320
- console.error('Error parsing WebSocket message:', event.data);
1433
+ this.logger.error('WebSocket', 'Error parsing WebSocket message', { data: event.data });
1321
1434
  }
1322
1435
  };
1323
1436
  this.socket.onclose = () => {
1324
- console.log('WebSocket connection closed');
1437
+ this.logger.debug('WebSocket', 'Connection closed');
1325
1438
  this.connectionStatus.next(false);
1326
1439
  this.socket = null;
1327
1440
  };
1328
1441
  this.socket.onerror = (error) => {
1329
- console.error('WebSocket error:', error);
1442
+ this.logger.error('WebSocket', 'WebSocket error', error);
1330
1443
  this.connectionStatus.next(false);
1331
1444
  };
1332
1445
  }
@@ -1349,14 +1462,14 @@ class WebsocketService {
1349
1462
  const current = new Set(this.subscribedChannels.value);
1350
1463
  current.add(channelName);
1351
1464
  this.subscribedChannels.next(current);
1352
- console.log(`📝 Subscribed to channel: ${channelName}`);
1465
+ this.logger.debug('WebSocket', `📝 Subscribed to channel`, { channel: channelName });
1353
1466
  }
1354
1467
  catch (error) {
1355
- console.error(`❌ Failed to subscribe to channel "${channelName}":`, error);
1468
+ this.logger.error('WebSocket', `Failed to subscribe to channel`, { channel: channelName, error });
1356
1469
  }
1357
1470
  }
1358
1471
  else {
1359
- console.warn(`Cannot subscribe to channel "${channelName}": WebSocket not yet open.`);
1472
+ this.logger.warn('WebSocket', `Cannot subscribe to channel - WebSocket not open`, { channel: channelName });
1360
1473
  }
1361
1474
  }
1362
1475
  subscribeToChannels(channelNames) {
@@ -1364,7 +1477,7 @@ class WebsocketService {
1364
1477
  channelNames.forEach(channel => this.subscribeToChannel(channel));
1365
1478
  }
1366
1479
  else {
1367
- console.warn('Cannot subscribe: WebSocket not yet open.');
1480
+ this.logger.warn('WebSocket', 'Cannot subscribe to channels - WebSocket not open');
1368
1481
  }
1369
1482
  }
1370
1483
  unsubscribeFromChannel(channel) {
@@ -1374,10 +1487,10 @@ class WebsocketService {
1374
1487
  const current = new Set(this.subscribedChannels.value);
1375
1488
  current.delete(channel);
1376
1489
  this.subscribedChannels.next(current);
1377
- console.log(`💬 Unsubscribed from channel: ${channel}`);
1490
+ this.logger.debug('WebSocket', `💬 Unsubscribed from channel`, { channel });
1378
1491
  }
1379
1492
  else {
1380
- console.error('WebSocket is not open. Cannot unsubscribe from channel.');
1493
+ this.logger.error('WebSocket', 'Cannot unsubscribe - WebSocket not open');
1381
1494
  }
1382
1495
  }
1383
1496
  unsubscribeToChannel(channel) {
@@ -1390,19 +1503,19 @@ class WebsocketService {
1390
1503
  sendBroadcast(content) {
1391
1504
  if (this.socket?.readyState === WebSocket.OPEN) {
1392
1505
  this.socket.send(JSON.stringify({ type: 'broadcast', content }));
1393
- console.log(`📢 Send broadcast: ${content}`);
1506
+ this.logger.debug('WebSocket', `📢 Send broadcast`, { content });
1394
1507
  }
1395
1508
  else {
1396
- console.error('WebSocket is not open. Cannot send broadcast.');
1509
+ this.logger.error('WebSocket', 'Cannot send broadcast - WebSocket not open');
1397
1510
  }
1398
1511
  }
1399
1512
  sendMessageInChannel(channel, content) {
1400
1513
  if (this.socket?.readyState === WebSocket.OPEN) {
1401
1514
  this.socket.send(JSON.stringify({ type: 'stateMangerMessage', subscribedChannel: channel, content }));
1402
- console.log(`💬 Send message:`, content);
1515
+ this.logger.debug('WebSocket', `💬 Send message`, { channel, content });
1403
1516
  }
1404
1517
  else {
1405
- console.error('WebSocket is not open. Cannot send message.');
1518
+ this.logger.error('WebSocket', 'Cannot send message - WebSocket not open');
1406
1519
  }
1407
1520
  }
1408
1521
  /**
@@ -1412,10 +1525,10 @@ class WebsocketService {
1412
1525
  sendChannelMessage(channel, content) {
1413
1526
  if (this.socket?.readyState === WebSocket.OPEN) {
1414
1527
  this.socket.send(JSON.stringify({ type: 'message', subscribedChannel: channel, content }));
1415
- console.log(`💬 Send channel message to [${channel}]:`, content);
1528
+ this.logger.debug('WebSocket', `💬 Send channel message`, { channel, content });
1416
1529
  }
1417
1530
  else {
1418
- console.error('WebSocket is not open. Cannot send channel message.');
1531
+ this.logger.error('WebSocket', 'Cannot send channel message - WebSocket not open');
1419
1532
  }
1420
1533
  }
1421
1534
  /**
@@ -1431,10 +1544,10 @@ class WebsocketService {
1431
1544
  channels: channels,
1432
1545
  data: content
1433
1546
  }));
1434
- console.log(`💬 Send channel message to channels [${channels.join(', ')}]:`, content);
1547
+ this.logger.debug('WebSocket', `💬 Send channel message to channels`, { channels, content });
1435
1548
  }
1436
1549
  catch (error) {
1437
- console.error(' Failed to send channelMessage batch:', error);
1550
+ this.logger.error('WebSocket', 'Failed to send channelMessage batch', error);
1438
1551
  }
1439
1552
  // Legacy fallback - send individual messages to each channel
1440
1553
  try {
@@ -1443,56 +1556,56 @@ class WebsocketService {
1443
1556
  });
1444
1557
  }
1445
1558
  catch (err) {
1446
- console.warn('⚠️ Legacy fallback failed sending individual messages', err);
1559
+ this.logger.warn('WebSocket', 'Legacy fallback failed sending individual messages', err);
1447
1560
  }
1448
1561
  }
1449
1562
  else {
1450
- console.error('WebSocket is not open. Cannot send message to channels.');
1563
+ this.logger.error('WebSocket', 'Cannot send message to channels - WebSocket not open');
1451
1564
  }
1452
1565
  }
1453
1566
  sendMessageToUser(user, content) {
1454
1567
  if (this.socket?.readyState === WebSocket.OPEN) {
1455
1568
  this.socket.send(JSON.stringify({ type: 'userMessage', subscribedChannel: user, content }));
1456
- console.log(`💬 Send message:`, content);
1569
+ this.logger.debug('WebSocket', `💬 Send message to user`, { user, content });
1457
1570
  }
1458
1571
  else {
1459
- console.error('WebSocket is not open. Cannot send message.');
1572
+ this.logger.error('WebSocket', 'Cannot send message to user - WebSocket not open');
1460
1573
  }
1461
1574
  }
1462
1575
  getAllChannels() {
1463
1576
  if (this.socket?.readyState === WebSocket.OPEN) {
1464
1577
  this.socket.send(JSON.stringify({ type: 'getChannels' }));
1465
- console.log('🗂️ List of all channels');
1578
+ this.logger.debug('WebSocket', '🗂️ Requested list of all channels');
1466
1579
  }
1467
1580
  else {
1468
- console.error('WebSocket is not open. Cannot request channels.');
1581
+ this.logger.error('WebSocket', 'Cannot request channels - WebSocket not open');
1469
1582
  }
1470
1583
  }
1471
1584
  createChannel(channel) {
1472
1585
  if (this.socket?.readyState === WebSocket.OPEN) {
1473
1586
  this.socket.send(JSON.stringify({ type: 'createChannel', content: channel }));
1474
- console.log('🗂️ Created channel:', channel);
1587
+ this.logger.debug('WebSocket', '🗂️ Created channel', { channel });
1475
1588
  }
1476
1589
  else {
1477
- console.error('WebSocket is not open. Cannot request channels.');
1590
+ this.logger.error('WebSocket', 'Cannot create channel - WebSocket not open');
1478
1591
  }
1479
1592
  }
1480
1593
  deleteChannel(channel) {
1481
1594
  if (this.socket?.readyState === WebSocket.OPEN) {
1482
1595
  this.socket.send(JSON.stringify({ type: 'deleteChannel', content: channel }));
1483
- console.log('🗂️ Delete channel:', channel);
1596
+ this.logger.debug('WebSocket', '🗂️ Delete channel', { channel });
1484
1597
  }
1485
1598
  else {
1486
- console.error('WebSocket is not open. Cannot request channels.');
1599
+ this.logger.error('WebSocket', 'Cannot delete channel - WebSocket not open');
1487
1600
  }
1488
1601
  }
1489
1602
  getUsersInChannel(channel) {
1490
1603
  if (this.socket?.readyState === WebSocket.OPEN) {
1491
1604
  this.socket.send(JSON.stringify({ type: 'getUsers', subscribedChannel: channel }));
1492
- console.log(`👥 List all users in channel: ${channel}`);
1605
+ this.logger.debug('WebSocket', `👥 Requested users in channel`, { channel });
1493
1606
  }
1494
1607
  else {
1495
- console.error('WebSocket is not open. Cannot request users.');
1608
+ this.logger.error('WebSocket', 'Cannot request users - WebSocket not open');
1496
1609
  }
1497
1610
  }
1498
1611
  // =====================
@@ -1516,28 +1629,21 @@ class WebsocketService {
1516
1629
  getNotificationChannels() {
1517
1630
  if (this.socket?.readyState === WebSocket.OPEN) {
1518
1631
  this.socket.send(JSON.stringify({ type: 'getNotificationChannels' }));
1519
- console.log('📢 Requested notification channels list');
1632
+ this.logger.debug('WebSocket', '📢 Requested notification channels list');
1520
1633
  }
1521
1634
  else {
1522
- console.error('WebSocket is not open. Cannot request notification channels.');
1635
+ this.logger.error('WebSocket', 'Cannot request notification channels - WebSocket not open');
1523
1636
  }
1524
1637
  }
1525
- /**
1526
- * Get today's notification channels from database
1527
- * Returns unique channels that have notifications posted today
1528
- */
1529
1638
  getTodaysNotificationChannels() {
1530
1639
  if (this.socket?.readyState === WebSocket.OPEN) {
1531
1640
  this.socket.send(JSON.stringify({ type: 'getTodaysNotificationChannels' }));
1532
- console.log('📢 Requested today\'s notification channels from DB');
1641
+ this.logger.debug('WebSocket', "📢 Requested today's notification channels from DB");
1533
1642
  }
1534
1643
  else {
1535
- console.error('WebSocket is not open. Cannot request today\'s notification channels.');
1644
+ this.logger.error('WebSocket', "Cannot request today's notification channels - WebSocket not open");
1536
1645
  }
1537
1646
  }
1538
- /**
1539
- * Subscribe to a notification channel with optional date filters
1540
- */
1541
1647
  subscribeToNotificationChannel(channel, options, user) {
1542
1648
  if (this.socket?.readyState === WebSocket.OPEN) {
1543
1649
  this.socket.send(JSON.stringify({
@@ -1548,30 +1654,24 @@ class WebsocketService {
1548
1654
  ...user
1549
1655
  }
1550
1656
  }));
1551
- console.log(`📢 Subscribed to notification channel: ${channel}`, options);
1657
+ this.logger.debug('WebSocket', `📢 Subscribed to notification channel`, { channel, options });
1552
1658
  }
1553
1659
  else {
1554
- console.error('WebSocket is not open. Cannot subscribe to notification channel.');
1660
+ this.logger.error('WebSocket', 'Cannot subscribe to notification channel - WebSocket not open');
1555
1661
  }
1556
1662
  }
1557
- /**
1558
- * Unsubscribe from a notification channel
1559
- */
1560
1663
  unsubscribeFromNotificationChannel(channel) {
1561
1664
  if (this.socket?.readyState === WebSocket.OPEN) {
1562
1665
  this.socket.send(JSON.stringify({
1563
1666
  type: 'unsubscribeNotifications',
1564
1667
  subscribedChannel: channel
1565
1668
  }));
1566
- console.log(`📢 Unsubscribed from notification channel: ${channel}`);
1669
+ this.logger.debug('WebSocket', `📢 Unsubscribed from notification channel`, { channel });
1567
1670
  }
1568
1671
  else {
1569
- console.error('WebSocket is not open. Cannot unsubscribe from notification channel.');
1672
+ this.logger.error('WebSocket', 'Cannot unsubscribe from notification channel - WebSocket not open');
1570
1673
  }
1571
1674
  }
1572
- /**
1573
- * Send a notification to a channel
1574
- */
1575
1675
  sendNotification(channel, content) {
1576
1676
  if (this.socket?.readyState === WebSocket.OPEN) {
1577
1677
  this.socket.send(JSON.stringify({
@@ -1579,10 +1679,10 @@ class WebsocketService {
1579
1679
  subscribedChannel: channel,
1580
1680
  content
1581
1681
  }));
1582
- console.log(`📢 Sent notification to channel: ${channel}`, content);
1682
+ this.logger.debug('WebSocket', `📢 Sent notification to channel`, { channel, content });
1583
1683
  }
1584
1684
  else {
1585
- console.error('WebSocket is not open. Cannot send notification.');
1685
+ this.logger.error('WebSocket', 'Cannot send notification - WebSocket not open');
1586
1686
  }
1587
1687
  }
1588
1688
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebsocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -2193,6 +2293,124 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2193
2293
  }]
2194
2294
  }] });
2195
2295
 
2296
+ /**
2297
+ * WebSocketMessageService - Unified service for sending WebSocket messages
2298
+ *
2299
+ * Provides type-safe methods for sending messages with automatic prefix management.
2300
+ * Supports three message types: State (SYS-), Public (PUB-), and Notification (MES-).
2301
+ *
2302
+ * Features:
2303
+ * - Type-safe message models
2304
+ * - Automatic prefix management
2305
+ * - Runtime validation
2306
+ * - Boolean return values for success/failure
2307
+ * - Silent failure with console errors
2308
+ */
2309
+ class WebSocketMessageService {
2310
+ constructor() {
2311
+ this.wsManagerService = inject(WebSocketManagerService);
2312
+ this.logger = new LoggerService();
2313
+ }
2314
+ /**
2315
+ * Send state message (SYS- prefix)
2316
+ * Used for CRUD operations and state synchronization
2317
+ *
2318
+ * @param path - Path array (e.g., ['ai', 'tests'])
2319
+ * @param payload - StateMessage with sessionId and content
2320
+ * @returns true if sent successfully, false otherwise
2321
+ */
2322
+ sendStateMessage(path, payload) {
2323
+ // Validate payload
2324
+ if (!payload?.sessionId?.id) {
2325
+ this.logger.error('WebSocketMessageService', 'StateMessage must have sessionId.id');
2326
+ return false;
2327
+ }
2328
+ if (!WebSocketManagerService.isConnected()) {
2329
+ this.logger.error('WebSocketMessageService', 'Cannot send state message - not connected');
2330
+ return false;
2331
+ }
2332
+ const channel = `${ChannelType$1.STATE}-${path.join('/')}`;
2333
+ this.wsManagerService.sendMessageInChannel(channel, payload);
2334
+ return true;
2335
+ }
2336
+ /**
2337
+ * Send public message (PUB- prefix)
2338
+ * Used for chat, broadcast, general messaging
2339
+ *
2340
+ * @param channel - Channel name (without prefix)
2341
+ * @param payload - PublicMessage with sessionId and content.message
2342
+ * @returns true if sent successfully, false otherwise
2343
+ */
2344
+ sendPublicMessage(channel, payload) {
2345
+ // Validate payload
2346
+ if (!payload?.sessionId?.id) {
2347
+ this.logger.error('WebSocketMessageService', 'PublicMessage must have sessionId.id');
2348
+ return false;
2349
+ }
2350
+ if (!payload?.content?.message) {
2351
+ this.logger.error('WebSocketMessageService', 'PublicMessage must have content.message');
2352
+ return false;
2353
+ }
2354
+ if (!WebSocketManagerService.isConnected()) {
2355
+ this.logger.error('WebSocketMessageService', 'Cannot send public message - not connected');
2356
+ return false;
2357
+ }
2358
+ const fullChannel = `${ChannelType$1.PUBLIC}-${channel}`;
2359
+ this.wsManagerService.sendMessageInChannel(fullChannel, payload);
2360
+ return true;
2361
+ }
2362
+ /**
2363
+ * Send notification (MES- prefix)
2364
+ * Used for persistent notifications with history
2365
+ *
2366
+ * @param channel - Channel name (without prefix)
2367
+ * @param payload - NotificationMessage with sessionId and message
2368
+ * @returns true if sent successfully, false otherwise
2369
+ */
2370
+ sendNotification(channel, payload) {
2371
+ // Validate payload
2372
+ if (!payload?.sessionId?.id) {
2373
+ this.logger.error('WebSocketMessageService', 'NotificationMessage must have sessionId.id');
2374
+ return false;
2375
+ }
2376
+ if (!payload?.message) {
2377
+ this.logger.error('WebSocketMessageService', 'NotificationMessage must have message');
2378
+ return false;
2379
+ }
2380
+ if (!WebSocketManagerService.isConnected()) {
2381
+ this.logger.error('WebSocketMessageService', 'Cannot send notification - not connected');
2382
+ return false;
2383
+ }
2384
+ const fullChannel = `${ChannelType$1.NOTIFICATION}-${channel}`;
2385
+ this.wsManagerService.sendMessageInChannel(fullChannel, payload);
2386
+ return true;
2387
+ }
2388
+ /**
2389
+ * Send to custom channel (no prefix)
2390
+ * User provides full channel name
2391
+ *
2392
+ * @param channel - Full channel name
2393
+ * @param payload - Any message payload
2394
+ * @returns true if sent successfully, false otherwise
2395
+ */
2396
+ sendToCustomChannel(channel, payload) {
2397
+ if (!WebSocketManagerService.isConnected()) {
2398
+ this.logger.error('WebSocketMessageService', 'Cannot send custom message - not connected');
2399
+ return false;
2400
+ }
2401
+ this.wsManagerService.sendMessageInChannel(channel, payload);
2402
+ return true;
2403
+ }
2404
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebSocketMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2405
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebSocketMessageService, providedIn: 'root' }); }
2406
+ }
2407
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebSocketMessageService, decorators: [{
2408
+ type: Injectable,
2409
+ args: [{ providedIn: 'root' }]
2410
+ }] });
2411
+
2412
+ // ChannelType is already exported from request-manager-state-service to avoid conflicts
2413
+
2196
2414
  class RequestService extends WebsocketService {
2197
2415
  constructor() {
2198
2416
  super(...arguments);
@@ -4844,6 +5062,7 @@ class HTTPManagerStateService extends ComponentStore {
4844
5062
  this.dbManagerService = inject(DatabaseManagerService);
4845
5063
  this.localStorageManagerService = inject(LocalStorageManagerService);
4846
5064
  this.utils = inject(UtilsService);
5065
+ this.logger = inject(LoggerService);
4847
5066
  this.error$ = this.httpManagerService.error$;
4848
5067
  this.isPending$ = this.httpManagerService.isPending$.pipe(delay(1));
4849
5068
  // PAGINATION
@@ -4926,7 +5145,7 @@ class HTTPManagerStateService extends ComponentStore {
4926
5145
  this.messages.next([...currentMessages, message]);
4927
5146
  console.log('Received:', message);
4928
5147
  // Debug: Log all message types
4929
- console.log('📨 Message type:', message.type);
5148
+ this.logger.debug('StateStore', '📨 Message type', { type: message.type });
4930
5149
  if (message.error === 'JWT_INVALID') {
4931
5150
  this.shouldRetry = false;
4932
5151
  this.httpManagerService.disconnect();
@@ -4939,9 +5158,9 @@ class HTTPManagerStateService extends ComponentStore {
4939
5158
  }
4940
5159
  switch (message.type) {
4941
5160
  case 'channelsList':
4942
- console.log('💬 Channels:', message.channels);
4943
- console.log('🔍 channelsList received, checking connection status...');
4944
- console.log('🔍 WebSocket connected:', WebSocketManagerService.isConnected());
5161
+ this.logger.debug('StateStore', '💬 Channels', { channels: message.channels });
5162
+ this.logger.debug('StateStore', '🔍 channelsList received, checking connection status...');
5163
+ this.logger.debug('StateStore', '🔍 WebSocket connected', { connected: WebSocketManagerService.isConnected() });
4945
5164
  // Extract channel names from metadata objects (new format) or use strings directly (old format)
4946
5165
  const channelNames = message.channels.map((c) => {
4947
5166
  // Handle new format: {name: string, canSubscribe: boolean}
@@ -4953,35 +5172,35 @@ class HTTPManagerStateService extends ComponentStore {
4953
5172
  });
4954
5173
  // Auto-subscribe to all channels from the list
4955
5174
  if (channelNames && channelNames.length > 0) {
4956
- console.log('📥 Auto-subscribing to', channelNames.length, 'channel(s)');
5175
+ this.logger.debug('StateStore', '📥 Auto-subscribing to channels', { count: channelNames.length });
4957
5176
  this.subscribeToChannels(channelNames);
4958
5177
  }
4959
5178
  else {
4960
- console.log('⚠️ No channels to subscribe to');
5179
+ this.logger.warn('StateStore', '⚠️ No channels to subscribe to');
4961
5180
  }
4962
5181
  this.channels.next(channelNames);
4963
5182
  break;
4964
5183
  case 'success':
4965
5184
  // Success messages - check for subscription confirmation
4966
- console.log(`✅ Success: ${message.message}`);
5185
+ this.logger.info('StateStore', `✅ Success`, { message: message.message });
4967
5186
  if (message.message?.includes('Subscribed to channel:')) {
4968
5187
  // Extract channel name from message: "Subscribed to channel: PUB-chat"
4969
5188
  const channelName = message.message.split('Subscribed to channel:')[1]?.trim();
4970
- console.log(`✅ Subscription confirmed for channel: ${channelName}`);
5189
+ this.logger.debug('StateStore', `✅ Subscription confirmed for channel`, { channel: channelName });
4971
5190
  WebSocketManagerService.addSubscribedChannel(channelName);
4972
5191
  }
4973
5192
  break;
4974
5193
  case 'subscribed':
4975
- console.log(`✅ Subscription confirmed: ${message.channel}`);
5194
+ this.logger.debug('StateStore', `✅ Subscription confirmed`, { channel: message.channel });
4976
5195
  // Track as subscribed now that server confirmed
4977
5196
  WebSocketManagerService.addSubscribedChannel(message.channel);
4978
5197
  break;
4979
5198
  case 'unsubscribed':
4980
- console.log(`🔓 Unsubscription confirmed: ${message.channel}`);
5199
+ this.logger.debug('StateStore', `🔓 Unsubscription confirmed`, { channel: message.channel });
4981
5200
  break;
4982
5201
  case 'info':
4983
5202
  // Already subscribed or other info messages
4984
- console.log(`ℹ️ Info: ${message.message}`);
5203
+ this.logger.info('StateStore', `ℹ️ Info`, { message: message.message });
4985
5204
  // If it's an "Already subscribed" message, treat it as subscription confirmation
4986
5205
  if (message.message?.includes('Already subscribed to channel:')) {
4987
5206
  // Extract channel name from message: "Already subscribed to channel: PUB-chat"
@@ -5470,7 +5689,7 @@ class HTTPManagerStateService extends ComponentStore {
5470
5689
  }
5471
5690
  }
5472
5691
  catch (error) {
5473
- console.error('Error initializing HTTPManagerStateService:', error);
5692
+ this.logger.error('HTTPManagerStateService', 'Error initializing', error);
5474
5693
  // Initialize with safe defaults
5475
5694
  this.databaseOptions = undefined;
5476
5695
  this.maxRetries = 3;
@@ -5510,7 +5729,7 @@ class HTTPManagerStateService extends ComponentStore {
5510
5729
  return this.stripChannelPrefix(channel);
5511
5730
  }
5512
5731
  setApiRequestOptions(apiOptions, dataType, database) {
5513
- console.log('🔧 [STATE STORE] setApiRequestOptions called:', {
5732
+ this.logger.debug('StateStore', '🔧 setApiRequestOptions called', {
5514
5733
  hasWs: !!apiOptions?.ws,
5515
5734
  wsId: apiOptions?.ws?.id,
5516
5735
  wsServer: apiOptions?.ws?.wsServer,
@@ -5527,21 +5746,21 @@ class HTTPManagerStateService extends ComponentStore {
5527
5746
  // Auto-prefix channel ID for private state manager channels
5528
5747
  // This ensures state manager channels are separate from user-defined channels
5529
5748
  this.apiOptions.ws.id = this.prefixChannel(this.apiOptions.ws.id, ChannelType.STATE);
5530
- console.log(`🔒 Private state channel configured: ${this.apiOptions.ws.id}`);
5749
+ this.logger.debug('StateStore', `🔒 Private state channel configured`, { channelId: this.apiOptions.ws.id });
5531
5750
  // Store our own sessionId for filtering incoming messages
5532
5751
  this.ownSessionId = sessionStorage.getItem('WSID') || null;
5533
- console.log(`🆔 Stored own sessionId for message filtering: ${this.ownSessionId}`);
5534
- console.log(`🔍 [STATE STORE] WebSocket configuration:`, {
5752
+ this.logger.debug('StateStore', `🆔 Stored own sessionId for message filtering`, { sessionId: this.ownSessionId });
5753
+ this.logger.debug('StateStore', `🔍 WebSocket configuration`, {
5535
5754
  channelId: this.apiOptions.ws.id,
5536
5755
  wsServer: this.apiOptions.ws.wsServer,
5537
5756
  sessionId: this.ownSessionId,
5538
5757
  path: this.apiOptions.path
5539
5758
  });
5540
5759
  // Initialize WebSocket connection if not already connected
5541
- console.log('🔌 [STATE STORE] Checking WebSocket connection status...');
5542
- console.log('🔌 [STATE STORE] Is connected?', WebSocketManagerService.isConnected());
5760
+ this.logger.debug('StateStore', '🔌 Checking WebSocket connection status...');
5761
+ this.logger.debug('StateStore', '🔌 Is connected?', { connected: WebSocketManagerService.isConnected() });
5543
5762
  if (!WebSocketManagerService.isConnected()) {
5544
- console.log('🔌 [STATE STORE] WebSocket not connected, will initialize via effect');
5763
+ this.logger.debug('StateStore', '🔌 WebSocket not connected, will initialize via effect');
5545
5764
  // initWS is an effect that triggers when setApiRequestOptions is called with ws config
5546
5765
  // The effect is already triggered by calling setApiRequestOptions above
5547
5766
  }
@@ -5552,7 +5771,7 @@ class HTTPManagerStateService extends ComponentStore {
5552
5771
  }
5553
5772
  // Validate wsServer before attempting connection
5554
5773
  if (!this.apiOptions.ws.wsServer || this.apiOptions.ws.wsServer === '') {
5555
- console.error('WSOptions invalid: wsServer is missing or empty');
5774
+ this.logger.error('StateStore', 'WSOptions invalid: wsServer is missing or empty');
5556
5775
  return;
5557
5776
  }
5558
5777
  // Clean up previous subscription to prevent duplicate handlers
@@ -5563,23 +5782,23 @@ class HTTPManagerStateService extends ComponentStore {
5563
5782
  // Setup connection status monitoring (internal subscription to drive retry counters)
5564
5783
  this.connectionStatusSubscription = this.setupConnectionStatus().subscribe();
5565
5784
  // Make initial connection attempt
5566
- console.log('🔄 Initial WebSocket connection attempt...');
5785
+ this.logger.debug('StateStore', '🔄 Initial WebSocket connection attempt...');
5567
5786
  this.httpManagerService.connect(this.apiOptions.ws, this.apiOptions.ws.jwtToken || '');
5568
5787
  // Initialize WS effect to handle messages
5569
5788
  this.initWS(this.apiOptions.ws);
5570
5789
  }
5571
5790
  else {
5572
- console.warn('WSOptions invalid Id: empty');
5791
+ this.logger.warn('StateStore', 'WSOptions invalid Id: empty');
5573
5792
  }
5574
5793
  }
5575
5794
  // WebSocket
5576
5795
  setupConnectionStatus() {
5577
5796
  return this.httpManagerService.connectionStatus$.pipe(distinctUntilChanged(), tap(status => {
5578
5797
  if (status === true) {
5579
- console.log('🟢 WebSocket connection is open.');
5798
+ this.logger.debug('StateStore', '🟢 WebSocket connection is open');
5580
5799
  }
5581
5800
  else {
5582
- console.log('🔴 WebSocket connection is closed.');
5801
+ this.logger.debug('StateStore', '🔴 WebSocket connection is closed');
5583
5802
  }
5584
5803
  }), switchMap(status => {
5585
5804
  if (status === true) {
@@ -6467,6 +6686,212 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6467
6686
  }]
6468
6687
  }] });
6469
6688
 
6689
+ class DisplayConfig {
6690
+ constructor(type = 'snackbar', supportsMarkdown, stackable, queueBehavior, autoDismiss, width, height) {
6691
+ this.type = type;
6692
+ this.supportsMarkdown = supportsMarkdown;
6693
+ this.stackable = stackable;
6694
+ this.queueBehavior = queueBehavior;
6695
+ this.autoDismiss = autoDismiss;
6696
+ this.width = width;
6697
+ this.height = height;
6698
+ }
6699
+ static adapt(item) {
6700
+ return new DisplayConfig(item?.type, item?.supportsMarkdown, item?.stackable, item?.queueBehavior, item?.autoDismiss, item?.width, item?.height);
6701
+ }
6702
+ }
6703
+
6704
+ class DisplayRule {
6705
+ constructor(id = '', name, match = () => false, display = DisplayConfig.adapt()) {
6706
+ this.id = id;
6707
+ this.name = name;
6708
+ this.match = match;
6709
+ this.display = display;
6710
+ }
6711
+ static adapt(item) {
6712
+ return new DisplayRule(item?.id, item?.name, item?.match, item?.display ? DisplayConfig.adapt(item.display) : DisplayConfig.adapt());
6713
+ }
6714
+ }
6715
+
6716
+ class Slide {
6717
+ constructor(title = '', message = '', image, icon) {
6718
+ this.title = title;
6719
+ this.message = message;
6720
+ this.image = image;
6721
+ this.icon = icon;
6722
+ }
6723
+ static adapt(item) {
6724
+ return new Slide(item?.title, item?.message, item?.image, item?.icon);
6725
+ }
6726
+ }
6727
+
6728
+ class Action {
6729
+ constructor(label = '', action = 'close', target, callback, primary) {
6730
+ this.label = label;
6731
+ this.action = action;
6732
+ this.target = target;
6733
+ this.callback = callback;
6734
+ this.primary = primary;
6735
+ }
6736
+ static adapt(item) {
6737
+ return new Action(item?.label, item?.action, item?.target, item?.callback, item?.primary);
6738
+ }
6739
+ }
6740
+
6741
+ class MessageContent {
6742
+ constructor(displayConfig, title, message = '', slides, image, images, actions, messageType, icon, data) {
6743
+ this.displayConfig = displayConfig;
6744
+ this.title = title;
6745
+ this.message = message;
6746
+ this.slides = slides;
6747
+ this.image = image;
6748
+ this.images = images;
6749
+ this.actions = actions;
6750
+ this.messageType = messageType;
6751
+ this.icon = icon;
6752
+ this.data = data;
6753
+ }
6754
+ static adapt(item) {
6755
+ return new MessageContent(item?.displayConfig ? DisplayConfig.adapt(item.displayConfig) : undefined, item?.title, item?.message, item?.slides ? item.slides.map((slideItem) => Slide.adapt(slideItem)) : [], item?.image, item?.images, item?.actions ? item.actions.map((actionItem) => Action.adapt(actionItem)) : [], item?.messageType, item?.icon, item?.data);
6756
+ }
6757
+ }
6758
+ class CommunicationMessage {
6759
+ constructor(type = '', messageId, channel, sessionId, timestamp, content = MessageContent.adapt()) {
6760
+ this.type = type;
6761
+ this.messageId = messageId;
6762
+ this.channel = channel;
6763
+ this.sessionId = sessionId;
6764
+ this.timestamp = timestamp;
6765
+ this.content = content;
6766
+ }
6767
+ static adapt(item) {
6768
+ return new CommunicationMessage(item?.type, item?.messageId, item?.channel, item?.sessionId, item?.timestamp, item?.content ? MessageContent.adapt(item.content) : MessageContent.adapt());
6769
+ }
6770
+ }
6771
+
6772
+ const defaultDisplayRules = [
6773
+ {
6774
+ id: 'carousel',
6775
+ name: 'Carousel',
6776
+ match: (message) => message.content?.displayConfig?.type === 'carousel',
6777
+ display: {
6778
+ type: 'carousel',
6779
+ supportsMarkdown: true,
6780
+ stackable: false
6781
+ }
6782
+ },
6783
+ {
6784
+ id: 'dialog',
6785
+ name: 'Dialog',
6786
+ match: (message) => message.content?.displayConfig?.type === 'dialog',
6787
+ display: {
6788
+ type: 'dialog',
6789
+ supportsMarkdown: true,
6790
+ stackable: true
6791
+ }
6792
+ },
6793
+ {
6794
+ id: 'default',
6795
+ name: 'Snackbar',
6796
+ match: () => true,
6797
+ display: {
6798
+ type: 'snackbar',
6799
+ supportsMarkdown: false,
6800
+ stackable: true,
6801
+ autoDismiss: 3000
6802
+ }
6803
+ }
6804
+ ];
6805
+
6806
+ class SnackbarStrategy {
6807
+ constructor() {
6808
+ this.name = 'snackbar';
6809
+ this.toastService = inject(ToastMessageDisplayService);
6810
+ }
6811
+ canHandle(message) {
6812
+ return true; // Always can handle (fallback strategy)
6813
+ }
6814
+ display(message, config) {
6815
+ const messageText = this.extractMessage(message.content);
6816
+ this.toastService.toastMessage({
6817
+ message: messageText,
6818
+ color: ToastColors.INFO,
6819
+ icon: 'info',
6820
+ action: 'DONE'
6821
+ }, config.autoDismiss ?? 3000);
6822
+ }
6823
+ extractMessage(content) {
6824
+ if (!content)
6825
+ return '';
6826
+ // Try nested content structure (backward compatibility)
6827
+ if (content.content?.message) {
6828
+ return content.content.message;
6829
+ }
6830
+ // Try direct message
6831
+ if (content.message) {
6832
+ return content.message;
6833
+ }
6834
+ return '';
6835
+ }
6836
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SnackbarStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6837
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SnackbarStrategy }); }
6838
+ }
6839
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SnackbarStrategy, decorators: [{
6840
+ type: Injectable
6841
+ }] });
6842
+
6843
+ class MessageDisplayRouterService {
6844
+ constructor() {
6845
+ this.snackbarStrategy = inject(SnackbarStrategy);
6846
+ // All available strategies
6847
+ this.strategies = [
6848
+ this.snackbarStrategy
6849
+ // DialogStrategy will be added in Phase 2
6850
+ // CarouselStrategy will be added in Phase 3
6851
+ ];
6852
+ // Rules are evaluated in order - first match wins
6853
+ this.rules = defaultDisplayRules;
6854
+ }
6855
+ display(message) {
6856
+ console.log('📨 MessageDisplayRouterService: Processing message:', message);
6857
+ // Find FIRST matching rule (order matters!)
6858
+ const matchingRule = this.rules.find(rule => rule.match(message));
6859
+ // Get the rule (will be 'default' if nothing else matches)
6860
+ const rule = matchingRule || this.rules[this.rules.length - 1];
6861
+ console.log(`🎯 MessageDisplayRouterService: Matched rule '${rule.id}' (${rule.name})`);
6862
+ console.log(` → Display type: ${rule.display.type}`);
6863
+ // Get strategy for the display type
6864
+ const strategy = this.strategies.find(s => s.name === rule.display.type);
6865
+ if (!strategy) {
6866
+ console.warn(`⚠️ MessageDisplayRouterService: No strategy found for type '${rule.display.type}', falling back to snackbar`);
6867
+ // Fallback to snackbar if strategy not found
6868
+ this.snackbarStrategy.display(message, rule.display);
6869
+ return;
6870
+ }
6871
+ // Execute display
6872
+ console.log(`🚀 MessageDisplayRouterService: Executing ${strategy.name} strategy`);
6873
+ strategy.display(message, rule.display);
6874
+ }
6875
+ registerStrategies(strategies) {
6876
+ strategies.forEach(strategy => {
6877
+ if (!this.strategies.find(s => s.name === strategy.name)) {
6878
+ this.strategies.push(strategy);
6879
+ console.log(`✅ Registered strategy: ${strategy.name}`);
6880
+ }
6881
+ });
6882
+ }
6883
+ setRules(rules) {
6884
+ this.rules = rules;
6885
+ console.log(`📋 MessageDisplayRouterService: Rules updated (${rules.length} rules)`);
6886
+ }
6887
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageDisplayRouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6888
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageDisplayRouterService, providedIn: 'root' }); }
6889
+ }
6890
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageDisplayRouterService, decorators: [{
6891
+ type: Injectable,
6892
+ args: [{ providedIn: 'root' }]
6893
+ }] });
6894
+
6470
6895
  let ClientInfo$2 = class ClientInfo {
6471
6896
  constructor(domain = '', service = '', id = 0, name = '') {
6472
6897
  this.domain = domain;
@@ -6566,7 +6991,7 @@ class RequestManagerBasicDemoComponent {
6566
6991
  this.streamType = 'Auto';
6567
6992
  this.downloadRequest = ApiRequest.adapt({
6568
6993
  server: 'assets/images',
6569
- path: ['me.jpg'],
6994
+ path: ['lego.png'],
6570
6995
  saveAs: 'john.jpg', // Optional
6571
6996
  headers: { 'Authorization': 'Bearer Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InJ0c0ZULWItN0x1WTdEVlllU05LY0lKN1ZuYyJ9.eyJhdWQiOiI4ODhhMzFjZS01OWQzLTRhMTItYTU5Ni04ZDYyZjY0MWI1MDUiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNmY0MTE5ODItY2YyMy00ZTQ1LTk0NDktNGI2MDdiN2E4OGVjL3YyLjAiLCJpYXQiOjE3NjU4MzQxNDksIm5iZiI6MTc2NTgzNDE0OSwiZXhwIjoxNzY1ODM5NzQ2LCJhY2N0IjowLCJhaW8iOiJBV1FBbS84YUFBQUFVUEZOYUhSZkZ4ZVkwRWthcFBzdWZaNG1QYXV6YVRoODRRZUtQRzkrbEFIVE5XanVwQy9ZSjEwK2IrMktWVlJSSXZRNFpwS2xyWTFGd0xRZmtXOTNLbkRNckxSeEMzWTVOOGlQREZ4b1liZExucW1QL1N1ZE1pRW1Va05tTklSWSIsImF6cCI6Ijg4OGEzMWNlLTU5ZDMtNGExMi1hNTk2LThkNjJmNjQxYjUwNSIsImF6cGFjciI6IjAiLCJncm91cHMiOlsiZWE2ZDk5YjAtNDgyNC00MDU0LTk0MTQtZDNhOTZkZDA3MjRiIl0sIm5hbWUiOiJHVExDIEFwcCBTdXBlciBBZG1pbiIsIm9pZCI6IjI2NzUxY2I2LWNlMDEtNDMzMC05OTc0LWZjMzgxMjQ3YTEzYyIsInByZWZlcnJlZF91c2VybmFtZSI6Imd0bGMwMDNAZ3RsYy5jYSIsInJoIjoiMS5BUzRBZ2hsQmJ5UFBSVTZVU1V0Z2UzcUk3TTR4aW9qVFdSSktwWmFOWXZaQnRRVm1BYTR1QUEuIiwicm9sZXMiOlsiZ3RsYy5hY2wuc3VwZXJhZG1pbiJdLCJzY3AiOiJHVExDX0FwcGxpY2F0aW9uIiwic2lkIjoiMDAzZjVhZDktZmJmNi1jZTkyLTg3MjItMWEzNDExYjMzMDJiIiwic3ViIjoiS0RYQ3drVlhUbTRUUmcwaTkxbXZDZzgtQ29uLXpWbk5FQ2Y5LVg0dkpzUSIsInRpZCI6IjZmNDExOTgyLWNmMjMtNGU0NS05NDQ5LTRiNjA3YjdhODhlYyIsInVwbiI6Imd0bGMwMDNAZ3RsYy5jYSIsInV0aSI6InpBaTJoMmpVUUVHbVY0RTJXMWxqQUEiLCJ2ZXIiOiIyLjAiLCJ3aWRzIjpbImI3OWZiZjRkLTNlZjktNDY4OS04MTQzLTc2YjE5NGU4NTUwOSJdLCJ4bXNfZnRkIjoiUDJraW1ZM0tqc1BTRndxNHlZdmJ0bGhrSUk3d2tXNmFpcW1FQ1BaNEdja0JkWE5sWVhOMExXUnpiWE0ifQ.LzppoggMm27smSAy9SamtPN95vCzdELCAfhtOj5n_T_H6g9xCmNRLS9FaUFQMau6Qvl0lROKl7WDklTswLFkfxbIxCBWtXdL-LTqT5cDURSJAll8vC3zlN3Hg9pAFBUVZFRolt6Z7LvPdI3pvUOQs0yFwVzp9k6cLF8aemKdwKQrMX3XXua1MfBWZcqQ4WiBVNmKh8w6yQB35I4u5WqdFnu33nUGb-kvc18SOpoUfiJnlV-PudaEzFXdU3CjAaMEcuPFv5xLwWJKuhU73dNH4EyQDFMVGtcIHNnieOfiY_nK2_0-5DM6aI40UIRK6Bt-HmMQpnbhLps5y3ep6Z7RNw' } // Optional
6572
6997
  });
@@ -7305,7 +7730,7 @@ class RequestManagerDemoComponent {
7305
7730
  this.streamType = 'Auto';
7306
7731
  this.downloadRequest = ApiRequest.adapt({
7307
7732
  server: 'assets/images',
7308
- path: ['me.jpg'],
7733
+ path: ['lego.png'],
7309
7734
  saveAs: 'john.jpg', // Optional
7310
7735
  headers: { 'Authorization': 'Bearer Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InJ0c0ZULWItN0x1WTdEVlllU05LY0lKN1ZuYyJ9.eyJhdWQiOiI4ODhhMzFjZS01OWQzLTRhMTItYTU5Ni04ZDYyZjY0MWI1MDUiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNmY0MTE5ODItY2YyMy00ZTQ1LTk0NDktNGI2MDdiN2E4OGVjL3YyLjAiLCJpYXQiOjE3NjU4MzQxNDksIm5iZiI6MTc2NTgzNDE0OSwiZXhwIjoxNzY1ODM5NzQ2LCJhY2N0IjowLCJhaW8iOiJBV1FBbS84YUFBQUFVUEZOYUhSZkZ4ZVkwRWthcFBzdWZaNG1QYXV6YVRoODRRZUtQRzkrbEFIVE5XanVwQy9ZSjEwK2IrMktWVlJSSXZRNFpwS2xyWTFGd0xRZmtXOTNLbkRNckxSeEMzWTVOOGlQREZ4b1liZExucW1QL1N1ZE1pRW1Va05tTklSWSIsImF6cCI6Ijg4OGEzMWNlLTU5ZDMtNGExMi1hNTk2LThkNjJmNjQxYjUwNSIsImF6cGFjciI6IjAiLCJncm91cHMiOlsiZWE2ZDk5YjAtNDgyNC00MDU0LTk0MTQtZDNhOTZkZDA3MjRiIl0sIm5hbWUiOiJHVExDIEFwcCBTdXBlciBBZG1pbiIsIm9pZCI6IjI2NzUxY2I2LWNlMDEtNDMzMC05OTc0LWZjMzgxMjQ3YTEzYyIsInByZWZlcnJlZF91c2VybmFtZSI6Imd0bGMwMDNAZ3RsYy5jYSIsInJoIjoiMS5BUzRBZ2hsQmJ5UFBSVTZVU1V0Z2UzcUk3TTR4aW9qVFdSSktwWmFOWXZaQnRRVm1BYTR1QUEuIiwicm9sZXMiOlsiZ3RsYy5hY2wuc3VwZXJhZG1pbiJdLCJzY3AiOiJHVExDX0FwcGxpY2F0aW9uIiwic2lkIjoiMDAzZjVhZDktZmJmNi1jZTkyLTg3MjItMWEzNDExYjMzMDJiIiwic3ViIjoiS0RYQ3drVlhUbTRUUmcwaTkxbXZDZzgtQ29uLXpWbk5FQ2Y5LVg0dkpzUSIsInRpZCI6IjZmNDExOTgyLWNmMjMtNGU0NS05NDQ5LTRiNjA3YjdhODhlYyIsInVwbiI6Imd0bGMwMDNAZ3RsYy5jYSIsInV0aSI6InpBaTJoMmpVUUVHbVY0RTJXMWxqQUEiLCJ2ZXIiOiIyLjAiLCJ3aWRzIjpbImI3OWZiZjRkLTNlZjktNDY4OS04MTQzLTc2YjE5NGU4NTUwOSJdLCJ4bXNfZnRkIjoiUDJraW1ZM0tqc1BTRndxNHlZdmJ0bGhrSUk3d2tXNmFpcW1FQ1BaNEdja0JkWE5sWVhOMExXUnpiWE0ifQ.LzppoggMm27smSAy9SamtPN95vCzdELCAfhtOj5n_T_H6g9xCmNRLS9FaUFQMau6Qvl0lROKl7WDklTswLFkfxbIxCBWtXdL-LTqT5cDURSJAll8vC3zlN3Hg9pAFBUVZFRolt6Z7LvPdI3pvUOQs0yFwVzp9k6cLF8aemKdwKQrMX3XXua1MfBWZcqQ4WiBVNmKh8w6yQB35I4u5WqdFnu33nUGb-kvc18SOpoUfiJnlV-PudaEzFXdU3CjAaMEcuPFv5xLwWJKuhU73dNH4EyQDFMVGtcIHNnieOfiY_nK2_0-5DM6aI40UIRK6Bt-HmMQpnbhLps5y3ep6Z7RNw' } // Optional
7311
7736
  });
@@ -8234,7 +8659,7 @@ class WsMessagingComponent {
8234
8659
  this.fb = inject(FormBuilder);
8235
8660
  this.messageService = inject(MessageServiceDemo);
8236
8661
  this.stateService = inject(StateServiceDemo);
8237
- this.toastService = inject(ToastMessageDisplayService);
8662
+ this.messageDisplayService = inject(MessageDisplayRouterService);
8238
8663
  // Only show public channels (starting with "PUB-"), strip prefix for display
8239
8664
  // SYS- channels are private/internal and hidden from users
8240
8665
  this.channels$ = this.messageService.channels$.pipe(map$1(channels => channels
@@ -8283,20 +8708,15 @@ class WsMessagingComponent {
8283
8708
  this.messageService.getAllChannels();
8284
8709
  }, 500); // 500ms delay to ensure subscription is processed
8285
8710
  });
8286
- // Subscribe to latest messages and show toast notification
8711
+ // Subscribe to latest messages and display using rule-based routing
8287
8712
  this.latestCommunicationMessages$.pipe(filter$1(message => !!message), takeUntil$1(this.destroy$)).subscribe((message) => {
8288
- console.log('🔔 Toast notification triggered:', message);
8289
- console.log(' message.content:', message.content);
8290
- // Message structure has nested content: message.content.content.message
8291
- const messageContent = message.content?.content?.message || message.content?.message || '';
8292
- console.log(' Extracted messageContent:', messageContent);
8293
- this.toastService.toastMessage(ToastDisplay.adapt({
8294
- message: messageContent,
8295
- color: ToastColors.INFO,
8296
- icon: 'chat',
8297
- action: 'DONE'
8298
- }), -1 // Stay until dismissed
8299
- );
8713
+ console.log('🔔 Message received, routing to display:', message);
8714
+ // NEW: Delegate to MessageDisplayRouterService
8715
+ // The message payload determines the display type via rules
8716
+ this.messageDisplayService.display(message);
8717
+ // OLD: Hardcoded snackbar (removed)
8718
+ // const messageContent = message.content?.content?.message || message.content?.message || '';
8719
+ // this.toastService.toastMessage(...);
8300
8720
  });
8301
8721
  }
8302
8722
  ngOnDestroy() {
@@ -9163,7 +9583,7 @@ class RequestSignalsManagerDemoComponent {
9163
9583
  this.questionControl = this.fb.control("", [Validators.required]);
9164
9584
  this.downloadRequest = ApiRequest.adapt({
9165
9585
  server: 'assets/images',
9166
- path: ['me.jpg'],
9586
+ path: ['lego.png'],
9167
9587
  // saveAs: 'john.jpg' // Optional
9168
9588
  });
9169
9589
  // downloadRequest = ApiRequest.adapt({
@@ -9491,7 +9911,9 @@ class HttpRequestManagerModule {
9491
9911
  { provide: HTTP_INTERCEPTORS, useClass: ProxyDebuggerInterceptor, multi: true },
9492
9912
  { provide: CONFIG_SETTINGS_TOKEN, useValue: ConfigOptions.adapt() },
9493
9913
  HTTPManagerService, LocalStorageManagerService,
9494
- ToastMessageDisplayService
9914
+ ToastMessageDisplayService,
9915
+ MessageDisplayRouterService,
9916
+ SnackbarStrategy
9495
9917
  ], imports: [CommonModule,
9496
9918
  ToastMessageDisplayModule,
9497
9919
  FormsModule,
@@ -9576,7 +9998,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9576
9998
  { provide: HTTP_INTERCEPTORS, useClass: ProxyDebuggerInterceptor, multi: true },
9577
9999
  { provide: CONFIG_SETTINGS_TOKEN, useValue: ConfigOptions.adapt() },
9578
10000
  HTTPManagerService, LocalStorageManagerService,
9579
- ToastMessageDisplayService
10001
+ ToastMessageDisplayService,
10002
+ MessageDisplayRouterService,
10003
+ SnackbarStrategy
9580
10004
  ],
9581
10005
  }]
9582
10006
  }] });
@@ -9589,5 +10013,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9589
10013
  * Generated bundle index. Do not edit.
9590
10014
  */
9591
10015
 
9592
- export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelInfo, ChannelType, CommunicationType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UserData, UtilsService, WSOptions, WSUser, WebSocketManagerService, WebsocketService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
10016
+ export { ApiRequest, AppService, AsymmetricalEncryptionService, CONFIG_SETTINGS_TOKEN, ChannelType, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseManagerService, DatabaseStorage, DbService, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerSignalsService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, LoggerService, NotificationMessage, PathQueryService, PublicMessage, Random, RandomHSLColor, RandomHexColor, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomPaletteColor, RandomSignature, RandomStr, RandomVisibleColor, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RequestService, RequestSignalsService, RetryOptions, SettingOptions, StateMessage, StateStorageOptions, StorageData, StorageOption, StorageType, StoreStateManagerService, StreamType, SymmetricalEncryptionService, TableSchemaDef, UUID, UUID_STR, UserData, UtilsService, WSOptions, WebSocketMessageService, WithCredentialsInterceptor, countdown, createChannelName, delayedRetry, requestPolling, requestStreaming, streamAI, streamAuto, streamEvents, streamJSON, streamNDJSON };
9593
10017
  //# sourceMappingURL=http-request-manager.mjs.map