http-request-manager 18.16.3 → 18.16.4
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.
|
@@ -1868,6 +1868,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
1868
1868
|
*/
|
|
1869
1869
|
class WebSocketManagerService {
|
|
1870
1870
|
constructor() {
|
|
1871
|
+
this.isConnecting$ = WebSocketManagerService.isConnectingSubject.asObservable();
|
|
1871
1872
|
this.retryCount$ = WebSocketManagerService.retryCountSubject.asObservable();
|
|
1872
1873
|
this.maxRetries$ = WebSocketManagerService.maxRetriesSubject.asObservable();
|
|
1873
1874
|
this.messages$ = WebSocketManagerService.messages.asObservable();
|
|
@@ -1880,8 +1881,9 @@ class WebSocketManagerService {
|
|
|
1880
1881
|
// STATIC SINGLETON STATE (Shared across ALL instances)
|
|
1881
1882
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1882
1883
|
static { this.socket = null; }
|
|
1883
|
-
static { this.
|
|
1884
|
+
static { this.isConnectingSubject = new BehaviorSubject(false); }
|
|
1884
1885
|
static { this.connectionInitialized = false; }
|
|
1886
|
+
static { this.shouldRetry = true; }
|
|
1885
1887
|
// Store last options for reconnection
|
|
1886
1888
|
static { this.lastOptions = null; }
|
|
1887
1889
|
static { this.lastJwtToken = ''; }
|
|
@@ -1961,7 +1963,7 @@ class WebSocketManagerService {
|
|
|
1961
1963
|
}
|
|
1962
1964
|
}
|
|
1963
1965
|
// Prevent duplicate connection attempts
|
|
1964
|
-
if (WebSocketManagerService.
|
|
1966
|
+
if (WebSocketManagerService.isConnectingSubject.value) {
|
|
1965
1967
|
console.log('⏳ Connection already in progress...');
|
|
1966
1968
|
return;
|
|
1967
1969
|
}
|
|
@@ -1983,12 +1985,15 @@ class WebSocketManagerService {
|
|
|
1983
1985
|
else {
|
|
1984
1986
|
WebSocketManagerService.retryDelay = 5000;
|
|
1985
1987
|
}
|
|
1986
|
-
//
|
|
1987
|
-
WebSocketManagerService.
|
|
1988
|
+
// Reset shouldRetry flag for new connection attempts
|
|
1989
|
+
WebSocketManagerService.shouldRetry = true;
|
|
1990
|
+
// Mark as connecting — connectionStatus false while connecting, true only when connected
|
|
1991
|
+
WebSocketManagerService.isConnectingSubject.next(true);
|
|
1988
1992
|
WebSocketManagerService.isSubscribed = false;
|
|
1989
1993
|
WebSocketManagerService.connectionReadyNotified = false;
|
|
1990
1994
|
WebSocketManagerService.subscribedChannels.next(new Set());
|
|
1991
|
-
|
|
1995
|
+
// Don't set connectionStatus to true here - only set to true when connection is actually established
|
|
1996
|
+
// WebSocketManagerService.connectionStatus.next(true);
|
|
1992
1997
|
const sessionId = this.getSessionId();
|
|
1993
1998
|
const URL = (jwtToken) ? `${options.wsServer}?token=${jwtToken}&sessionId=${sessionId}` : `${options.wsServer}?sessionId=${sessionId}`;
|
|
1994
1999
|
console.log(`🔌 Initiating WebSocket connection to: ${options.wsServer}`);
|
|
@@ -2002,8 +2007,9 @@ class WebSocketManagerService {
|
|
|
2002
2007
|
// Do NOT reset retryCount here — reset happens only on confirmed stable connection
|
|
2003
2008
|
// (onmessage first valid response). Resetting here would cause the counter to always
|
|
2004
2009
|
// show 1/N because onopen fires before onclose increments the counter.
|
|
2005
|
-
WebSocketManagerService.
|
|
2010
|
+
WebSocketManagerService.isConnectingSubject.next(false);
|
|
2006
2011
|
WebSocketManagerService.connectionInitialized = true;
|
|
2012
|
+
// Do NOT set connectionStatus to true here - wait for server to confirm authentication via onmessage
|
|
2007
2013
|
};
|
|
2008
2014
|
WebSocketManagerService.socket.onmessage = (event) => {
|
|
2009
2015
|
try {
|
|
@@ -2015,6 +2021,8 @@ class WebSocketManagerService {
|
|
|
2015
2021
|
WebSocketManagerService.lastOptions = null;
|
|
2016
2022
|
WebSocketManagerService.connectionError.next('Invalid or Expired JWT');
|
|
2017
2023
|
WebSocketManagerService.connectionStatus.next(false);
|
|
2024
|
+
// Stop retrying for authentication errors
|
|
2025
|
+
WebSocketManagerService.shouldRetry = false;
|
|
2018
2026
|
}
|
|
2019
2027
|
else {
|
|
2020
2028
|
console.error(`❌ Server error: ${data.error} — will retry`);
|
|
@@ -2032,6 +2040,8 @@ class WebSocketManagerService {
|
|
|
2032
2040
|
WebSocketManagerService.retryCountSubject.next(0);
|
|
2033
2041
|
}
|
|
2034
2042
|
WebSocketManagerService.connectionReadyNotified = true;
|
|
2043
|
+
// Set connection status to true only when server confirms authentication
|
|
2044
|
+
WebSocketManagerService.connectionStatus.next(true);
|
|
2035
2045
|
console.log(`🔄 Emitting reconnect event for MessageTrackerService`);
|
|
2036
2046
|
WebSocketManagerService.onReconnect.next();
|
|
2037
2047
|
}
|
|
@@ -2043,18 +2053,21 @@ class WebSocketManagerService {
|
|
|
2043
2053
|
};
|
|
2044
2054
|
WebSocketManagerService.socket.onclose = (event) => {
|
|
2045
2055
|
console.log(`🔴 WebSocket closed (code: ${event.code})`);
|
|
2046
|
-
WebSocketManagerService.
|
|
2056
|
+
WebSocketManagerService.isConnectingSubject.next(false);
|
|
2047
2057
|
WebSocketManagerService.connectionReadyNotified = false;
|
|
2048
2058
|
WebSocketManagerService.socket = null;
|
|
2049
2059
|
WebSocketManagerService.subscribedChannels.next(new Set());
|
|
2050
2060
|
if (event.code === 4000 || event.code === 4001 || event.code === 4003) {
|
|
2051
2061
|
WebSocketManagerService.connectionError.next('Invalid or Expired JWT');
|
|
2052
2062
|
WebSocketManagerService.connectionStatus.next(false);
|
|
2063
|
+
// Stop retrying for authentication errors
|
|
2064
|
+
WebSocketManagerService.shouldRetry = false;
|
|
2053
2065
|
return;
|
|
2054
2066
|
}
|
|
2055
2067
|
const maxRetries = WebSocketManagerService.maxRetries;
|
|
2056
2068
|
const retryDelay = WebSocketManagerService.retryDelay;
|
|
2057
|
-
if
|
|
2069
|
+
// Only retry if shouldRetry is true and we haven't exceeded max retries
|
|
2070
|
+
if (WebSocketManagerService.shouldRetry && WebSocketManagerService.lastOptions && WebSocketManagerService.retryCount < maxRetries) {
|
|
2058
2071
|
WebSocketManagerService.retryCount++;
|
|
2059
2072
|
WebSocketManagerService.retryCountSubject.next(WebSocketManagerService.retryCount);
|
|
2060
2073
|
console.log(`🔄 Reconnect attempt ${WebSocketManagerService.retryCount}/${maxRetries}...`);
|
|
@@ -2064,13 +2077,19 @@ class WebSocketManagerService {
|
|
|
2064
2077
|
else {
|
|
2065
2078
|
console.error(`❌ WebSocket failed after ${maxRetries} retries. Giving up.`);
|
|
2066
2079
|
WebSocketManagerService.connectionStatus.next(false);
|
|
2080
|
+
// Set error message if not already set
|
|
2081
|
+
if (!WebSocketManagerService.connectionError.value) {
|
|
2082
|
+
WebSocketManagerService.connectionError.next('Connection failed after maximum retries');
|
|
2083
|
+
}
|
|
2067
2084
|
WebSocketManagerService.retryCount = maxRetries;
|
|
2068
2085
|
WebSocketManagerService.retryCountSubject.next(maxRetries);
|
|
2086
|
+
// Reset shouldRetry flag for future connection attempts
|
|
2087
|
+
WebSocketManagerService.shouldRetry = true;
|
|
2069
2088
|
}
|
|
2070
2089
|
};
|
|
2071
2090
|
WebSocketManagerService.socket.onerror = (error) => {
|
|
2072
2091
|
console.error('❌ WebSocket error:', error);
|
|
2073
|
-
WebSocketManagerService.
|
|
2092
|
+
WebSocketManagerService.isConnectingSubject.next(false);
|
|
2074
2093
|
// onclose will fire after onerror and drive retry/give-up logic
|
|
2075
2094
|
};
|
|
2076
2095
|
}
|
|
@@ -3794,6 +3813,7 @@ class HTTPManagerService extends RequestService {
|
|
|
3794
3813
|
this.connectionStatus$ = this.wsManager.connectionStatus$;
|
|
3795
3814
|
this.messages$ = this.messageTracker.messages$; // Messages flow through MessageTrackerService
|
|
3796
3815
|
this.subscribedChannels$ = this.wsManager.subscribedChannels$;
|
|
3816
|
+
this.isConnecting$ = this.wsManager.isConnecting$;
|
|
3797
3817
|
this.retryCount$ = this.wsManager.retryCount$;
|
|
3798
3818
|
this.maxRetries$ = this.wsManager.maxRetries$;
|
|
3799
3819
|
this.connectionError$ = this.wsManager.connectionError$;
|
|
@@ -6658,6 +6678,7 @@ class HTTPManagerStateService extends ComponentStore {
|
|
|
6658
6678
|
this.wsOptions = WSOptions.adapt();
|
|
6659
6679
|
// Expose raw WS connection status directly to UI (from singleton WebSocketManagerService)
|
|
6660
6680
|
this.connectionStatus$ = this.httpManagerService.connectionStatus$;
|
|
6681
|
+
this.isConnecting$ = this.httpManagerService.isConnecting$;
|
|
6661
6682
|
this.wsRetryCount$ = this.httpManagerService.retryCount$;
|
|
6662
6683
|
this.wsMaxRetries$ = this.httpManagerService.maxRetries$;
|
|
6663
6684
|
this.connectionError$ = this.httpManagerService.connectionError$;
|
|
@@ -12419,6 +12440,7 @@ class RequestManagerWsDemoComponent {
|
|
|
12419
12440
|
this.retryCount$ = this.stateService.wsRetryCount$;
|
|
12420
12441
|
this.maxRetries$ = this.stateService.wsMaxRetries$;
|
|
12421
12442
|
this.connectionStatus$ = this.stateService.connectionStatus$;
|
|
12443
|
+
this.isConnecting$ = this.stateService.isConnecting$;
|
|
12422
12444
|
this.connectionError$ = this.stateService.connectionError$;
|
|
12423
12445
|
this.data$ = this.stateService.data$;
|
|
12424
12446
|
this.isPending$ = this.stateService.isPending$;
|
|
@@ -12427,11 +12449,11 @@ class RequestManagerWsDemoComponent {
|
|
|
12427
12449
|
this.stateService.updateConnection(this.server, this.wsServer, this.jwtToken, this.user, this.path);
|
|
12428
12450
|
}
|
|
12429
12451
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
12430
|
-
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 {\n <span style=\"color: red;\">
|
|
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" }] }); }
|
|
12431
12453
|
}
|
|
12432
12454
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RequestManagerWsDemoComponent, decorators: [{
|
|
12433
12455
|
type: Component,
|
|
12434
|
-
args: [{ selector: 'app-request-manager-ws-demo', standalone: false, 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 {\n <span style=\"color: red;\">
|
|
12456
|
+
args: [{ selector: 'app-request-manager-ws-demo', standalone: false, 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" }]
|
|
12435
12457
|
}], propDecorators: { server: [{
|
|
12436
12458
|
type: Input
|
|
12437
12459
|
}], wsServer: [{
|