http-request-manager 18.7.19 → 18.7.21
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/ARCHITECTURE.md +483 -0
- package/DATABASE_README.md +1176 -0
- package/HTTP_MANAGER_README.md +579 -0
- package/HTTP_SINGNALS_MANAGER_README.md +654 -0
- package/HTTP_STATE_MANAGER_README.md +948 -0
- package/INTERCEPTOR_README.md +549 -0
- package/LOCAL_STORAGE_README.md +1056 -0
- package/STORE_STATE_MANAGER_README.md +1322 -0
- package/UTILS_README.md +1186 -0
- package/WS_MANAGER_README.md +613 -0
- package/ng-package.json +8 -0
- package/package.json +1 -12
- package/src/lib/http-request-manager.module.ts +132 -0
- package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.html +65 -0
- package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.scss +0 -0
- package/src/lib/http-request-services-demo/database-data-demo/database-data-demo.component.ts +224 -0
- package/src/lib/http-request-services-demo/http-request-services-demo.component.html +114 -0
- package/src/lib/http-request-services-demo/http-request-services-demo.component.scss +6 -0
- package/src/lib/http-request-services-demo/http-request-services-demo.component.ts +52 -0
- package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.html +195 -0
- package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.scss +17 -0
- package/src/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.ts +206 -0
- package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.html +200 -0
- package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.scss +17 -0
- package/src/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.ts +212 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.html +53 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.scss +60 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.ts +72 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.ts +28 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.html +10 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.scss +29 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.ts +100 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/models/download-labels-model.ts +22 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.html +8 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.scss +19 -0
- package/src/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.ts +26 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/app-session.model.ts +30 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/app.model.ts +19 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/get-sample.model.ts +25 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/sample-ai-prompt.ts +19 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-details.ts +24 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client-info.ts +30 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/sample-client.model.ts +49 -0
- package/src/lib/http-request-services-demo/request-manager-demo/models/sample-mapper-client-info.ts +33 -0
- package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.html +392 -0
- package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.scss +24 -0
- package/src/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.ts +461 -0
- package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.html +393 -0
- package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.scss +24 -0
- package/src/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.ts +421 -0
- package/src/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.ts +87 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/services/state-data-request.service.ts +120 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.css +0 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.html +3 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-ai-messaging/ws-ai-messaging.component.ts +16 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.css +0 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.html +3 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-chats/ws-chats.component.ts +16 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.css +31 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.html +72 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.scss +41 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.spec.ts +205 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-data-control/ws-data-control.component.ts +77 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.css +11 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.html +96 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.spec.ts +31 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-messaging/ws-messaging.component.ts +229 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.css +30 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.html +172 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.spec.ts +31 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/components/ws-notifications/ws-notifications.component.ts +239 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/models/oidc-client.model.ts +31 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/models/user-data.model.ts +32 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.css +0 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.html +84 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/request-manager-ws-demo.component.ts +41 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/services/index.ts +3 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/services/message-service-demo.service.ts +83 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/services/notification-service-demo.service.ts +147 -0
- package/src/lib/http-request-services-demo/request-manager-ws-demo/services/state-service-demo.service.ts +158 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.html +53 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.scss +60 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/download-file/download-file.component.ts +72 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-download.module.ts +28 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.html +10 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.scss +29 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/file-downloader.component.ts +100 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/models/download-labels-model.ts +22 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.html +8 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.scss +19 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/file-downloader/spinner/spinner.component.ts +26 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/app-session.model.ts +30 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/app.model.ts +19 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/get-sample.model.ts +25 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-ai-prompt.ts +19 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client-details.ts +24 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client-info.ts +30 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-client.model.ts +49 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/models/sample-mapper-client-info.ts +33 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.html +380 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.scss +24 -0
- package/src/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.ts +410 -0
- package/src/lib/http-request-services-demo/store-state-manager-demo/models/settings.model.ts +28 -0
- package/src/lib/http-request-services-demo/store-state-manager-demo/services/settings-state.service.ts +48 -0
- package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.css +0 -0
- package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.html +23 -0
- package/src/lib/http-request-services-demo/store-state-manager-demo/store-state-manager-demo.component.ts +36 -0
- package/src/lib/index.ts +3 -0
- package/src/lib/interceptors/credentials.interceptor.ts +16 -0
- package/src/lib/interceptors/index.ts +6 -0
- package/src/lib/interceptors/models/error-settings.model.ts +22 -0
- package/src/lib/interceptors/models/index.ts +2 -0
- package/src/lib/interceptors/proxy-debugger.interceptor.ts +46 -0
- package/src/lib/interceptors/request-error.interceptor.ts +65 -0
- package/src/lib/interceptors/request-header.interceptor.ts +53 -0
- package/src/lib/models/config-http-options.model.ts +42 -0
- package/src/lib/models/config-local-storage-options.model.ts +27 -0
- package/src/lib/models/config-options.model.ts +27 -0
- package/src/lib/models/config-token.model.ts +9 -0
- package/src/lib/models/data-type.enum.ts +5 -0
- package/src/lib/models/database-storage.model.ts +24 -0
- package/src/lib/models/index.ts +12 -0
- package/src/lib/models/retry-options.model.ts +22 -0
- package/src/lib/services/database-manager-service/database.manager.service.ts +262 -0
- package/src/lib/services/database-manager-service/db.storage.service.ts +207 -0
- package/src/lib/services/database-manager-service/index.ts +4 -0
- package/src/lib/services/database-manager-service/models/index.ts +2 -0
- package/src/lib/services/database-manager-service/models/table-schema.ts +33 -0
- package/src/lib/services/index.ts +12 -0
- package/src/lib/services/local-storage-manager-service/index.ts +4 -0
- package/src/lib/services/local-storage-manager-service/local-storage-manager.service.spec.ts +71 -0
- package/src/lib/services/local-storage-manager-service/local-storage-manager.service.ts +426 -0
- package/src/lib/services/local-storage-manager-service/local-storage-signals-manager.service.spec.ts +67 -0
- package/src/lib/services/local-storage-manager-service/local-storage-signals-manager.service.ts +345 -0
- package/src/lib/services/local-storage-manager-service/models/global-store-options.model.ts +30 -0
- package/src/lib/services/local-storage-manager-service/models/index.ts +6 -0
- package/src/lib/services/local-storage-manager-service/models/setting-options.model.ts +35 -0
- package/src/lib/services/local-storage-manager-service/models/storage-data.model.ts +24 -0
- package/src/lib/services/local-storage-manager-service/models/storage-option.model.ts +32 -0
- package/src/lib/services/local-storage-manager-service/models/storage-type.enum.ts +5 -0
- package/src/lib/services/request-manager-services/README.md +268 -0
- package/src/lib/services/request-manager-services/http-manager-signals.service.ts +246 -0
- package/src/lib/services/request-manager-services/http-manager.service.spec.ts +232 -0
- package/src/lib/services/request-manager-services/http-manager.service.ts +274 -0
- package/src/lib/services/request-manager-services/index.ts +8 -0
- package/src/lib/services/request-manager-services/request-signals.service.ts +214 -0
- package/src/lib/services/request-manager-services/request.service.ts +309 -0
- package/src/lib/services/request-manager-services/rxjs-operators/countdown.ts +17 -0
- package/src/lib/services/request-manager-services/rxjs-operators/delay-retry.ts +16 -0
- package/src/lib/services/request-manager-services/rxjs-operators/index.ts +4 -0
- package/src/lib/services/request-manager-services/rxjs-operators/request-polling.ts +35 -0
- package/src/lib/services/request-manager-services/rxjs-operators/request-streaming.ts +436 -0
- package/src/lib/services/request-manager-state-service/http-manager-state.store.ts +1321 -0
- package/src/lib/services/request-manager-state-service/index.ts +3 -0
- package/src/lib/services/request-manager-state-service/models/api-request.model.ts +61 -0
- package/src/lib/services/request-manager-state-service/models/index.ts +6 -0
- package/src/lib/services/request-manager-state-service/models/request-options.model.ts +22 -0
- package/src/lib/services/request-manager-state-service/models/stream-type.enum.ts +13 -0
- package/src/lib/services/request-manager-state-service/models/ws-options.model.ts +39 -0
- package/src/lib/services/store-state-manager-service/index.ts +3 -0
- package/src/lib/services/store-state-manager-service/models/index.ts +2 -0
- package/src/lib/services/store-state-manager-service/models/state-storage-options.model.ts +24 -0
- package/src/lib/services/store-state-manager-service/store-state-manager.service.ts +88 -0
- package/src/lib/services/utils/app.service.spec.ts +25 -0
- package/src/lib/services/utils/app.service.ts +21 -0
- package/src/lib/services/utils/encryption/README.md +79 -0
- package/src/lib/services/utils/encryption/asymmetrical-encryption.service.ts +282 -0
- package/src/lib/services/utils/encryption/encryption-test.service.ts +39 -0
- package/src/lib/services/utils/encryption/index.ts +5 -0
- package/src/lib/services/utils/encryption/random.ts +81 -0
- package/src/lib/services/utils/encryption/symmetrical-encryption.service.ts +93 -0
- package/src/lib/services/utils/headers.service.spec.ts +80 -0
- package/src/lib/services/utils/headers.service.ts +18 -0
- package/src/lib/services/utils/index.ts +7 -0
- package/src/lib/services/utils/object-merger.service.spec.ts +18 -0
- package/src/lib/services/utils/object-merger.service.ts +78 -0
- package/src/lib/services/utils/path-query.service.spec.ts +117 -0
- package/src/lib/services/utils/path-query.service.ts +69 -0
- package/src/lib/services/utils/random-color.utils.ts +83 -0
- package/src/lib/services/utils/utils.service.spec.ts +165 -0
- package/src/lib/services/utils/utils.service.ts +192 -0
- package/src/lib/services/ws-manager-service/index.ts +4 -0
- package/src/lib/services/ws-manager-service/models/channel-info.model.ts +24 -0
- package/src/lib/services/ws-manager-service/models/channel-message-data.model.ts +24 -0
- package/src/lib/services/ws-manager-service/models/channel-message.model.ts +24 -0
- package/src/lib/services/ws-manager-service/models/communication-type.enum.ts +5 -0
- package/src/lib/services/ws-manager-service/models/index.ts +5 -0
- package/src/lib/services/ws-manager-service/models/ws-user.model.ts +38 -0
- package/src/lib/services/ws-manager-service/services/index.ts +3 -0
- package/src/lib/services/ws-manager-service/services/websocket.service.ts +392 -0
- package/src/public-api.ts +14 -0
- package/tsconfig.lib.json +32 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +14 -0
- package/fesm2022/http-request-manager.mjs +0 -7634
- package/fesm2022/http-request-manager.mjs.map +0 -1
- package/http-request-manager-18.7.19.tgz +0 -0
- package/types/http-request-manager.d.ts +0 -2278
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { OperatorFunction } from 'rxjs';
|
|
2
|
+
import { filter, map } from 'rxjs/operators';
|
|
3
|
+
import { HttpEventType } from '@angular/common/http';
|
|
4
|
+
import { StreamType } from '../../request-manager-state-service/models/stream-type.enum';
|
|
5
|
+
|
|
6
|
+
export interface StreamConfig {
|
|
7
|
+
streamType: StreamType;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// TypeScript interfaces for proper type safety
|
|
11
|
+
export interface StreamEvent<T = any> {
|
|
12
|
+
type: 'progress' | 'complete' | 'data';
|
|
13
|
+
data: T;
|
|
14
|
+
metadata?: {
|
|
15
|
+
timestamp: Date;
|
|
16
|
+
streamType: StreamType;
|
|
17
|
+
contentLength?: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ParsingResult<T = any> {
|
|
22
|
+
success: boolean;
|
|
23
|
+
data?: T[];
|
|
24
|
+
error?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Stateful processor for managing streaming data and events
|
|
29
|
+
*/
|
|
30
|
+
class StreamingProcessor<T = any> {
|
|
31
|
+
private buffer = '';
|
|
32
|
+
private contentType = '';
|
|
33
|
+
private readonly maxBufferSize = 10 * 1024 * 1024; // 10MB limit
|
|
34
|
+
private streamConfig: StreamConfig;
|
|
35
|
+
|
|
36
|
+
constructor(config?: StreamConfig) {
|
|
37
|
+
this.streamConfig = config || { streamType: StreamType.AI_STREAMING };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Process HTTP events and extract streaming data
|
|
42
|
+
*/
|
|
43
|
+
process(event: any): T[] | null {
|
|
44
|
+
switch (event.type) {
|
|
45
|
+
case HttpEventType.ResponseHeader:
|
|
46
|
+
this.contentType = event.headers?.get('content-type') || '';
|
|
47
|
+
return null;
|
|
48
|
+
|
|
49
|
+
case HttpEventType.DownloadProgress:
|
|
50
|
+
if (event.partialText) {
|
|
51
|
+
this.appendToBuffer(event.partialText);
|
|
52
|
+
const parsedData = this.parseBuffer();
|
|
53
|
+
return parsedData.length > 0 ? [parsedData[0]] : null;
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
|
|
57
|
+
case HttpEventType.Response:
|
|
58
|
+
if (event.body) {
|
|
59
|
+
this.appendToBuffer(event.body);
|
|
60
|
+
const parsedData = this.parseBuffer();
|
|
61
|
+
return parsedData.length > 0 ? parsedData : null;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
|
|
65
|
+
default:
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Append data to buffer with size management
|
|
72
|
+
*/
|
|
73
|
+
private appendToBuffer(data: string): void {
|
|
74
|
+
this.buffer += data;
|
|
75
|
+
|
|
76
|
+
// Implement sliding window if buffer gets too large
|
|
77
|
+
if (this.buffer.length > this.maxBufferSize) {
|
|
78
|
+
this.buffer = this.buffer.slice(-this.maxBufferSize / 2);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Parse current buffer content
|
|
84
|
+
*/
|
|
85
|
+
private parseBuffer(): T[] {
|
|
86
|
+
if (!this.buffer.trim()) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const result = parseStreamData(this.buffer, this.contentType, this.streamConfig);
|
|
92
|
+
return result as T[];
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.warn('Failed to parse streaming data:', error);
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reset processor state
|
|
101
|
+
*/
|
|
102
|
+
reset(): void {
|
|
103
|
+
this.buffer = '';
|
|
104
|
+
this.contentType = '';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Update configuration
|
|
109
|
+
*/
|
|
110
|
+
updateConfig(config: StreamConfig): void {
|
|
111
|
+
this.streamConfig = config;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Safe JSON parsing with error handling
|
|
117
|
+
*/
|
|
118
|
+
function safeJsonParse<T>(jsonStr: string, fallback?: T): T | null {
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(jsonStr);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.warn('Failed to parse JSON:', jsonStr.substring(0, 100));
|
|
123
|
+
return fallback || null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Safe JSON array parsing
|
|
129
|
+
*/
|
|
130
|
+
function safeJsonArrayParse<T>(jsonStr: string, fallback: T[] = []): T[] {
|
|
131
|
+
try {
|
|
132
|
+
const parsed = JSON.parse(jsonStr);
|
|
133
|
+
return Array.isArray(parsed) ? parsed : fallback;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.warn('Failed to parse JSON array:', jsonStr.substring(0, 100));
|
|
136
|
+
return fallback;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Enhanced JSON object extraction with better error handling
|
|
142
|
+
*/
|
|
143
|
+
function extractJsonObjects(text: string): string[] {
|
|
144
|
+
const objects: string[] = [];
|
|
145
|
+
let braceCount = 0;
|
|
146
|
+
let currentObject = '';
|
|
147
|
+
let inString = false;
|
|
148
|
+
let escaped = false;
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < text.length; i++) {
|
|
151
|
+
const char = text[i];
|
|
152
|
+
|
|
153
|
+
if (escaped) {
|
|
154
|
+
currentObject += char;
|
|
155
|
+
escaped = false;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (char === '\\') {
|
|
160
|
+
escaped = true;
|
|
161
|
+
currentObject += char;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (char === '"' && !escaped) {
|
|
166
|
+
inString = !inString;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!inString) {
|
|
170
|
+
if (char === '{') braceCount++;
|
|
171
|
+
else if (char === '}') braceCount--;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
currentObject += char;
|
|
175
|
+
|
|
176
|
+
if (braceCount === 0 && currentObject.trim()) {
|
|
177
|
+
objects.push(currentObject.trim());
|
|
178
|
+
currentObject = '';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return objects;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* COMPREHENSIVE REQUEST STREAMING OPERATOR - FULLY ABSTRACTED
|
|
187
|
+
* Refactored for better type safety and memory management
|
|
188
|
+
*
|
|
189
|
+
* Single function that handles ALL streaming formats without hardcoded assumptions:
|
|
190
|
+
* - JSON format (Individual JSON objects)
|
|
191
|
+
* - NDJSON format (Newline delimited JSON)
|
|
192
|
+
* - AI streaming format (Real-time AI responses)
|
|
193
|
+
* - Server-Sent Events format
|
|
194
|
+
* - Auto-detection mode
|
|
195
|
+
*
|
|
196
|
+
* Usage:
|
|
197
|
+
* this.http.get(url, options).pipe(requestStreaming()).subscribe(data => {...})
|
|
198
|
+
* this.http.get(url, options).pipe(requestStreaming({ streamType: StreamType.NDJSON })).subscribe(data => {...})
|
|
199
|
+
*/
|
|
200
|
+
export function requestStreaming<T = any>(config?: StreamConfig): OperatorFunction<any, T[]> {
|
|
201
|
+
const processor = new StreamingProcessor<T>(config);
|
|
202
|
+
|
|
203
|
+
return input$ => input$.pipe(
|
|
204
|
+
// Filter only streaming-related events
|
|
205
|
+
filter((event: any) =>
|
|
206
|
+
event.type === HttpEventType.DownloadProgress ||
|
|
207
|
+
event.type === HttpEventType.Response ||
|
|
208
|
+
event.type === HttpEventType.ResponseHeader
|
|
209
|
+
),
|
|
210
|
+
|
|
211
|
+
// Process events using the streaming processor
|
|
212
|
+
map((event: any) => {
|
|
213
|
+
const result = processor.process(event);
|
|
214
|
+
return result;
|
|
215
|
+
}),
|
|
216
|
+
|
|
217
|
+
// Filter out null results
|
|
218
|
+
filter((result): result is T[] => result !== null)
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Main streaming data parser - handles ALL formats based on streamType
|
|
224
|
+
*/
|
|
225
|
+
function parseStreamData(buffer: string, contentType: string, config: StreamConfig): any[] {
|
|
226
|
+
const results: any[] = [];
|
|
227
|
+
|
|
228
|
+
if (!buffer.trim()) {
|
|
229
|
+
return results;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Determine parsing format based on streamType and content type
|
|
233
|
+
const format = config.streamType === StreamType.AI_STREAMING ? detectFormat(buffer, contentType) : config.streamType;
|
|
234
|
+
|
|
235
|
+
switch (format) {
|
|
236
|
+
case StreamType.NDJSON:
|
|
237
|
+
return parseNdjson(buffer, config);
|
|
238
|
+
|
|
239
|
+
case StreamType.JSON:
|
|
240
|
+
return parseJsonObjects(buffer, config);
|
|
241
|
+
|
|
242
|
+
case StreamType.AI_STREAMING:
|
|
243
|
+
return parseAiStreaming(buffer, config);
|
|
244
|
+
|
|
245
|
+
case StreamType.EVENT_STREAM:
|
|
246
|
+
return parseEventStream(buffer, config);
|
|
247
|
+
|
|
248
|
+
default:
|
|
249
|
+
return autoParse(buffer, contentType, config);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Parse NDJSON format (JSON objects per line)
|
|
255
|
+
*/
|
|
256
|
+
function parseNdjson(buffer: string, config: StreamConfig): any[] {
|
|
257
|
+
const results: any[] = [];
|
|
258
|
+
const lines = buffer.split('\n').filter(line => line.trim());
|
|
259
|
+
|
|
260
|
+
lines.forEach(line => {
|
|
261
|
+
const trimmedLine = line.trim();
|
|
262
|
+
if (trimmedLine && trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
|
|
263
|
+
const parsed = safeJsonParse(trimmedLine);
|
|
264
|
+
if (parsed) results.push(parsed);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
return results;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Parse individual JSON objects
|
|
273
|
+
*/
|
|
274
|
+
function parseJsonObjects(buffer: string, config: StreamConfig): any[] {
|
|
275
|
+
const results: any[] = [];
|
|
276
|
+
const jsonObjects = extractJsonObjects(buffer);
|
|
277
|
+
|
|
278
|
+
jsonObjects.forEach(jsonStr => {
|
|
279
|
+
const parsed = safeJsonParse(jsonStr);
|
|
280
|
+
if (parsed) results.push(parsed);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return results;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Parse AI streaming format
|
|
288
|
+
*/
|
|
289
|
+
function parseAiStreaming(buffer: string, config: StreamConfig): any[] {
|
|
290
|
+
const results: any[] = [];
|
|
291
|
+
const jsonObjects = extractJsonObjects(buffer);
|
|
292
|
+
|
|
293
|
+
jsonObjects.forEach(jsonStr => {
|
|
294
|
+
const parsed = safeJsonParse(jsonStr);
|
|
295
|
+
if (parsed && typeof parsed === 'object' && parsed !== null && 'type' in parsed) {
|
|
296
|
+
const typedParsed = parsed as any;
|
|
297
|
+
if (['ai_thinking', 'ai_response', 'ai_suggestion', 'ai_status'].includes(typedParsed.type)) {
|
|
298
|
+
results.push(typedParsed);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
return results;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Parse Server-Sent Events format
|
|
308
|
+
*/
|
|
309
|
+
function parseEventStream(buffer: string, config: StreamConfig): any[] {
|
|
310
|
+
const results: any[] = [];
|
|
311
|
+
const events = buffer.split('\n\n').filter(event => event.trim());
|
|
312
|
+
|
|
313
|
+
events.forEach(event => {
|
|
314
|
+
const lines = event.split('\n');
|
|
315
|
+
let eventData = '';
|
|
316
|
+
|
|
317
|
+
lines.forEach(line => {
|
|
318
|
+
if (line.startsWith('data: ')) {
|
|
319
|
+
eventData += line.substring(6);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
if (eventData) {
|
|
324
|
+
try {
|
|
325
|
+
const parsed = JSON.parse(eventData);
|
|
326
|
+
if(parsed) results.push(parsed);
|
|
327
|
+
} catch (e) {
|
|
328
|
+
results.push({
|
|
329
|
+
content: eventData,
|
|
330
|
+
_streamType: 'event_stream',
|
|
331
|
+
_format: StreamType.EVENT_STREAM,
|
|
332
|
+
_timestamp: new Date().toISOString()
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
return results;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Auto-detect and parse unknown formats
|
|
343
|
+
*/
|
|
344
|
+
function autoParse(buffer: string, contentType: string, config: StreamConfig): any[] {
|
|
345
|
+
// Check content type hints
|
|
346
|
+
if (contentType.includes('application/x-ndjson') || isNdjsonFormat(buffer)) {
|
|
347
|
+
return parseNdjson(buffer, config);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (contentType.includes('application/json') || buffer.includes('{')) {
|
|
351
|
+
// Check if it looks like AI streaming
|
|
352
|
+
if (buffer.includes('"type":') && buffer.includes('"ai_')) {
|
|
353
|
+
return parseAiStreaming(buffer, config);
|
|
354
|
+
}
|
|
355
|
+
return parseJsonObjects(buffer, config);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (contentType.includes('text/event-stream')) {
|
|
359
|
+
return parseEventStream(buffer, config);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Fallback: try to parse as JSON, otherwise treat as text
|
|
363
|
+
const jsonObjects = extractJsonObjects(buffer);
|
|
364
|
+
if (jsonObjects.length > 0) {
|
|
365
|
+
return parseJsonObjects(buffer, config);
|
|
366
|
+
} else {
|
|
367
|
+
// Return as text chunks
|
|
368
|
+
return buffer.split('\n').filter(line => line.trim()).map(line => ({
|
|
369
|
+
content: line.trim(),
|
|
370
|
+
_streamType: 'text',
|
|
371
|
+
_format: 'plain',
|
|
372
|
+
_timestamp: new Date().toISOString()
|
|
373
|
+
}));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Detect streaming format from content
|
|
379
|
+
*/
|
|
380
|
+
function detectFormat(buffer: string, contentType: string): StreamType {
|
|
381
|
+
if (contentType.includes('application/x-ndjson') || isNdjsonFormat(buffer)) {
|
|
382
|
+
return StreamType.NDJSON;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (contentType.includes('text/event-stream')) {
|
|
386
|
+
return StreamType.EVENT_STREAM;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (contentType.includes('application/json') || buffer.includes('{')) {
|
|
390
|
+
// Check if it looks like AI streaming
|
|
391
|
+
if (buffer.includes('"type":') && buffer.includes('"ai_')) {
|
|
392
|
+
return StreamType.AI_STREAMING;
|
|
393
|
+
}
|
|
394
|
+
return StreamType.JSON;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return StreamType.JSON; // Default
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Check if buffer is NDJSON format
|
|
402
|
+
*/
|
|
403
|
+
function isNdjsonFormat(buffer: string): boolean {
|
|
404
|
+
const lines = buffer.split('\n').filter(line => line.trim());
|
|
405
|
+
const jsonLines = lines.filter(line => line.trim().startsWith('{') && line.trim().endsWith('}'));
|
|
406
|
+
return jsonLines.length > 1 || (lines.length > 1 && jsonLines.length > 0);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Convenience functions for common use cases
|
|
411
|
+
*/
|
|
412
|
+
|
|
413
|
+
// Stream with JSON format
|
|
414
|
+
export function streamJSON<T = any>(): OperatorFunction<any, T[]> {
|
|
415
|
+
return requestStreaming<T>({ streamType: StreamType.JSON });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Stream with NDJSON format
|
|
419
|
+
export function streamNDJSON<T = any>(): OperatorFunction<any, T[]> {
|
|
420
|
+
return requestStreaming<T>({ streamType: StreamType.NDJSON });
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Stream AI responses
|
|
424
|
+
export function streamAI<T = any>(): OperatorFunction<any, T[]> {
|
|
425
|
+
return requestStreaming<T>({ streamType: StreamType.AI_STREAMING });
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Stream Server-Sent Events
|
|
429
|
+
export function streamEvents<T = any>(): OperatorFunction<any, T[]> {
|
|
430
|
+
return requestStreaming<T>({ streamType: StreamType.EVENT_STREAM });
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Auto-detect streaming format
|
|
434
|
+
export function streamAuto<T = any>(): OperatorFunction<any, T[]> {
|
|
435
|
+
return requestStreaming<T>({ streamType: StreamType.AUTO });
|
|
436
|
+
}
|