@techextensor/tab-core-utility 2.2.184 → 2.2.187
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/esm2022/index.mjs +1 -5
- package/esm2022/lib/tab-core-utility/app/constants/api-constants.mjs +13 -24
- package/esm2022/lib/tab-core-utility/app/constants/common.mjs +50 -14
- package/esm2022/lib/tab-core-utility/app/constants/storage-constants.mjs +2 -2
- package/esm2022/lib/tab-core-utility/app/crud/tab-crud.service.mjs +49 -38
- package/esm2022/lib/tab-core-utility/app/crud/tab-delete.service.mjs +30 -81
- package/esm2022/lib/tab-core-utility/app/crud/tab-formio.service.mjs +12 -141
- package/esm2022/lib/tab-core-utility/app/crud/tab-get.service.mjs +35 -136
- package/esm2022/lib/tab-core-utility/app/crud/tab-insert.service.mjs +38 -89
- package/esm2022/lib/tab-core-utility/app/crud/tab-update.service.mjs +131 -152
- package/esm2022/lib/tab-core-utility/app/enums/query.enum.mjs +7 -7
- package/esm2022/lib/tab-core-utility/app/helpers/common/app.helpers.mjs +17 -6
- package/esm2022/lib/tab-core-utility/app/helpers/common/dsq.helpers.mjs +11 -9
- package/esm2022/lib/tab-core-utility/app/helpers/common/meta-data.helpers.mjs +13 -13
- package/esm2022/lib/tab-core-utility/app/helpers/common/req-res.helpers.mjs +45 -7
- package/esm2022/lib/tab-core-utility/app/helpers/common/where-clause.helpers.mjs +76 -79
- package/esm2022/lib/tab-core-utility/app/helpers/screen/grid.helpers.mjs +4 -8
- package/esm2022/lib/tab-core-utility/app/helpers/screen/screen.helpers.mjs +33 -8
- package/esm2022/lib/tab-core-utility/app/interfaces/common.interface.mjs +1 -1
- package/esm2022/lib/tab-core-utility/app/models/api-query.class.mjs +1 -39
- package/esm2022/lib/tab-core-utility/app/models/app-field.model.mjs +7 -36
- package/esm2022/lib/tab-core-utility/app/models/app-object.model.mjs +47 -84
- package/esm2022/lib/tab-core-utility/app/models/app-screen.model.mjs +13 -24
- package/esm2022/lib/tab-core-utility/app/models/data-source-query.model.mjs +23 -57
- package/esm2022/lib/tab-core-utility/app/models/filter.model.mjs +10 -21
- package/esm2022/lib/tab-core-utility/app/models/parameter.model.mjs +6 -12
- package/esm2022/lib/tab-core-utility/app/models/sort.model.mjs +4 -11
- package/esm2022/lib/tab-core-utility/app/utils/json.util.mjs +16 -17
- package/esm2022/lib/tab-core-utility/app/utils/req-res.util.mjs +55 -1
- package/esm2022/lib/tab-core-utility/app/utils/tab-app.util.mjs +164 -1
- package/esm2022/lib/tab-core-utility/core/http-client/api.service.mjs +1 -63
- package/index.d.ts +0 -4
- package/lib/tab-core-utility/app/constants/api-constants.d.ts +10 -13
- package/lib/tab-core-utility/app/constants/common.d.ts +0 -9
- package/lib/tab-core-utility/app/constants/storage-constants.d.ts +1 -1
- package/lib/tab-core-utility/app/crud/tab-crud.service.d.ts +1 -8
- package/lib/tab-core-utility/app/crud/tab-delete.service.d.ts +10 -20
- package/lib/tab-core-utility/app/crud/tab-formio.service.d.ts +6 -33
- package/lib/tab-core-utility/app/crud/tab-get.service.d.ts +3 -45
- package/lib/tab-core-utility/app/crud/tab-insert.service.d.ts +21 -16
- package/lib/tab-core-utility/app/crud/tab-update.service.d.ts +19 -34
- package/lib/tab-core-utility/app/enums/query.enum.d.ts +6 -3
- package/lib/tab-core-utility/app/helpers/common/app.helpers.d.ts +8 -3
- package/lib/tab-core-utility/app/helpers/common/dsq.helpers.d.ts +0 -3
- package/lib/tab-core-utility/app/helpers/common/meta-data.helpers.d.ts +3 -3
- package/lib/tab-core-utility/app/helpers/common/req-res.helpers.d.ts +51 -7
- package/lib/tab-core-utility/app/helpers/common/where-clause.helpers.d.ts +0 -1
- package/lib/tab-core-utility/app/helpers/screen/grid.helpers.d.ts +1 -2
- package/lib/tab-core-utility/app/helpers/screen/screen.helpers.d.ts +0 -1
- package/lib/tab-core-utility/app/interfaces/common.interface.d.ts +2 -50
- package/lib/tab-core-utility/app/models/api-query.class.d.ts +9 -54
- package/lib/tab-core-utility/app/models/app-field.model.d.ts +2 -4
- package/lib/tab-core-utility/app/models/app-object.model.d.ts +3 -5
- package/lib/tab-core-utility/app/models/app-screen.model.d.ts +2 -2
- package/lib/tab-core-utility/app/models/data-source-query.model.d.ts +2 -7
- package/lib/tab-core-utility/app/models/filter.model.d.ts +2 -2
- package/lib/tab-core-utility/app/models/parameter.model.d.ts +2 -2
- package/lib/tab-core-utility/app/models/sort.model.d.ts +1 -1
- package/lib/tab-core-utility/app/utils/json.util.d.ts +2 -3
- package/lib/tab-core-utility/app/utils/req-res.util.d.ts +9 -1
- package/lib/tab-core-utility/app/utils/tab-app.util.d.ts +61 -0
- package/lib/tab-core-utility/core/http-client/api.service.d.ts +0 -37
- package/package.json +2 -3
- package/esm2022/lib/tab-core-utility/app/helpers/response.adapter.mjs +0 -38
- package/esm2022/lib/tab-core-utility/app/interfaces/signalr.interface.mjs +0 -42
- package/esm2022/lib/tab-core-utility/core/service/signalr/operation-tracker.service.mjs +0 -82
- package/esm2022/lib/tab-core-utility/core/service/signalr/signalr-infrastructure.service.mjs +0 -252
- package/esm2022/lib/tab-core-utility/core/service/signalr/signalr.service.mjs +0 -207
- package/lib/tab-core-utility/app/helpers/response.adapter.d.ts +0 -22
- package/lib/tab-core-utility/app/interfaces/signalr.interface.d.ts +0 -80
- package/lib/tab-core-utility/core/service/signalr/operation-tracker.service.d.ts +0 -40
- package/lib/tab-core-utility/core/service/signalr/signalr-infrastructure.service.d.ts +0 -68
- package/lib/tab-core-utility/core/service/signalr/signalr.service.d.ts +0 -122
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { Injectable, inject, computed } from '@angular/core';
|
|
2
|
-
import { SignalRInfrastructure } from './signalr-infrastructure.service';
|
|
3
|
-
import { OperationTrackerService } from './operation-tracker.service';
|
|
4
|
-
import { CONNECTION_STATE, } from '../../../app/interfaces/signalr.interface';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
/**
|
|
7
|
-
* SignalR Service
|
|
8
|
-
* Public API for:
|
|
9
|
-
* 1. Components to register for real-time CRUD notifications
|
|
10
|
-
* 2. Services (TabFormioService) to track async operations
|
|
11
|
-
*
|
|
12
|
-
* Usage in components:
|
|
13
|
-
* ```typescript
|
|
14
|
-
* ngOnInit() {
|
|
15
|
-
* this.signalRService.register(
|
|
16
|
-
* this.componentId,
|
|
17
|
-
* this.appObjectId,
|
|
18
|
-
* (notification) => this.handleNotification(notification)
|
|
19
|
-
* );
|
|
20
|
-
* }
|
|
21
|
-
*
|
|
22
|
-
* ngOnDestroy() {
|
|
23
|
-
* this.signalRService.unregister(this.componentId, this.appObjectId);
|
|
24
|
-
* }
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* Usage in services (TabFormioService):
|
|
28
|
-
* ```typescript
|
|
29
|
-
* const correlationId = response.correlationId;
|
|
30
|
-
* this.signalRService.waitForOperation(correlationId).subscribe(notification => {
|
|
31
|
-
* // Handle completed operation
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export class SignalRService {
|
|
36
|
-
constructor() {
|
|
37
|
-
this.infrastructure = inject(SignalRInfrastructure);
|
|
38
|
-
this.operationTracker = inject(OperationTrackerService);
|
|
39
|
-
// Registry: Map<appObjectId, Map<componentId, callback>>
|
|
40
|
-
this.componentRegistry = new Map();
|
|
41
|
-
/**
|
|
42
|
-
* Get connection state (for UI indicators)
|
|
43
|
-
*/
|
|
44
|
-
this.connectionState = this.infrastructure.connectionState;
|
|
45
|
-
/**
|
|
46
|
-
* Check if currently connected
|
|
47
|
-
*/
|
|
48
|
-
this.isConnected = computed(() => this.connectionState() === CONNECTION_STATE.CONNECTED);
|
|
49
|
-
// Listen to notifications from infrastructure and route them
|
|
50
|
-
this.infrastructure.notifications$.subscribe((notification) => {
|
|
51
|
-
// 1. Check if this is a tracked async operation (processRequest)
|
|
52
|
-
this.operationTracker.handleNotification(notification);
|
|
53
|
-
// 2. Also notify components subscribed to this appObjectId (Grid, etc.)
|
|
54
|
-
this.notifyComponents(notification);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Establish a connection to the SignalR hub
|
|
59
|
-
*
|
|
60
|
-
* This method is idempotent - if the connection is already established, it will not be re-established.
|
|
61
|
-
* Hub URL is read from Common.signalRHubUrl (set during app initialization via Common.init())
|
|
62
|
-
*/
|
|
63
|
-
connect() {
|
|
64
|
-
this.infrastructure.connect();
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Register component for real-time notifications
|
|
68
|
-
*
|
|
69
|
-
* @param componentId - Unique component identifier (generated by component)
|
|
70
|
-
* @param appObjectId - AppObject ID to subscribe to
|
|
71
|
-
* @param callback - Function to call when notification received
|
|
72
|
-
*/
|
|
73
|
-
register(componentId, appObjectId, callback) {
|
|
74
|
-
// Initialize map for this AppObject if doesn't exist
|
|
75
|
-
if (!this.componentRegistry.has(appObjectId)) {
|
|
76
|
-
this.componentRegistry.set(appObjectId, new Map());
|
|
77
|
-
}
|
|
78
|
-
const components = this.componentRegistry.get(appObjectId);
|
|
79
|
-
// First component for this AppObject? Join SignalR group
|
|
80
|
-
if (components.size === 0) {
|
|
81
|
-
this.infrastructure.joinGroup(appObjectId);
|
|
82
|
-
}
|
|
83
|
-
// Add component to registry
|
|
84
|
-
components.set(componentId, callback);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Unregister component (cleanup on component destroy)
|
|
88
|
-
*
|
|
89
|
-
* @param componentId - Component identifier to remove
|
|
90
|
-
* @param appObjectId - AppObject ID to unsubscribe from
|
|
91
|
-
*/
|
|
92
|
-
unregister(componentId, appObjectId) {
|
|
93
|
-
const components = this.componentRegistry.get(appObjectId);
|
|
94
|
-
if (!components) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
// Remove component from registry
|
|
98
|
-
components.delete(componentId);
|
|
99
|
-
// Last component for this AppObject? Leave SignalR group
|
|
100
|
-
if (components.size === 0) {
|
|
101
|
-
this.infrastructure.leaveGroup(appObjectId);
|
|
102
|
-
this.componentRegistry.delete(appObjectId);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Wait for specific async operation to complete
|
|
107
|
-
* Used by TabFormioService for async processRequest operations
|
|
108
|
-
*
|
|
109
|
-
* @param correlationId - Correlation ID from backend response
|
|
110
|
-
* @param timeout - Optional timeout in milliseconds
|
|
111
|
-
* @returns Observable that emits when operation completes
|
|
112
|
-
*/
|
|
113
|
-
waitForOperation(correlationId, timeout) {
|
|
114
|
-
return this.operationTracker.waitForOperation(correlationId, timeout);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Register async operation for tracking
|
|
118
|
-
* Optional - waitForOperation handles registration automatically
|
|
119
|
-
*
|
|
120
|
-
* @param operation - Pending operation details
|
|
121
|
-
*/
|
|
122
|
-
registerOperation(operation) {
|
|
123
|
-
this.operationTracker.registerOperation(operation);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Check if operation is pending
|
|
127
|
-
*/
|
|
128
|
-
isOperationPending(correlationId) {
|
|
129
|
-
return this.operationTracker.isPending(correlationId);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Notify all registered components for an AppObject
|
|
133
|
-
* Called when notification received from SignalR hub
|
|
134
|
-
*/
|
|
135
|
-
notifyComponents(notification) {
|
|
136
|
-
const components = this.componentRegistry.get(notification.appObjectId);
|
|
137
|
-
if (!components || components.size === 0) {
|
|
138
|
-
// No components registered for this AppObject - ignore notification
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
// Call each component's callback
|
|
142
|
-
components.forEach((callback, componentId) => {
|
|
143
|
-
try {
|
|
144
|
-
callback(notification);
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
console.error(`[SignalR Service] Callback failed for component ${componentId}:`, error);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Get active AppObject groups (for debugging)
|
|
153
|
-
*/
|
|
154
|
-
getActiveGroups() {
|
|
155
|
-
return Array.from(this.componentRegistry.keys());
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Get component count for an AppObject (for debugging)
|
|
159
|
-
*/
|
|
160
|
-
getComponentCount(appObjectId) {
|
|
161
|
-
return this.componentRegistry.get(appObjectId)?.size || 0;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Get total registered components across all AppObjects (for debugging)
|
|
165
|
-
*/
|
|
166
|
-
getTotalComponentCount() {
|
|
167
|
-
let total = 0;
|
|
168
|
-
this.componentRegistry.forEach((components) => {
|
|
169
|
-
total += components.size;
|
|
170
|
-
});
|
|
171
|
-
return total;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Get registry state (for debugging)
|
|
175
|
-
*/
|
|
176
|
-
getRegistryState() {
|
|
177
|
-
const state = [];
|
|
178
|
-
this.componentRegistry.forEach((components, appObjectId) => {
|
|
179
|
-
state.push({
|
|
180
|
-
appObjectId,
|
|
181
|
-
componentCount: components.size,
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
return state;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Get pending operations count (for debugging)
|
|
188
|
-
*/
|
|
189
|
-
getPendingOperationsCount() {
|
|
190
|
-
return this.operationTracker.getPendingCount();
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Get all pending operations (for debugging)
|
|
194
|
-
*/
|
|
195
|
-
getPendingOperations() {
|
|
196
|
-
return this.operationTracker.getAllPending();
|
|
197
|
-
}
|
|
198
|
-
static { this.ɵfac = function SignalRService_Factory(t) { return new (t || SignalRService)(); }; }
|
|
199
|
-
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: SignalRService, factory: SignalRService.ɵfac, providedIn: 'root' }); }
|
|
200
|
-
}
|
|
201
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SignalRService, [{
|
|
202
|
-
type: Injectable,
|
|
203
|
-
args: [{
|
|
204
|
-
providedIn: 'root',
|
|
205
|
-
}]
|
|
206
|
-
}], () => [], null); })();
|
|
207
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmFsci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9kYXRhLWFjY2Vzcy9zcmMvbGliL3RhYi1jb3JlLXV0aWxpdHkvY29yZS9zZXJ2aWNlL3NpZ25hbHIvc2lnbmFsci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU3RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUN6RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN0RSxPQUFPLEVBSUwsZ0JBQWdCLEdBQ2pCLE1BQU0sMkNBQTJDLENBQUM7O0FBRW5EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBSUgsTUFBTSxPQUFPLGNBQWM7SUFpQnpCO1FBaEJRLG1CQUFjLEdBQUcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDL0MscUJBQWdCLEdBQUcsTUFBTSxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFFM0QseURBQXlEO1FBQ2pELHNCQUFpQixHQUFHLElBQUksR0FBRyxFQUE2QyxDQUFDO1FBRWpGOztXQUVHO1FBQ00sb0JBQWUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQztRQUUvRDs7V0FFRztRQUNNLGdCQUFXLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsS0FBSyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUczRiw2REFBNkQ7UUFDN0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDNUQsaUVBQWlFO1lBQ2pFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FB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O0lBQy9DLENBQUM7K0VBNUxVLGNBQWM7dUVBQWQsY0FBYyxXQUFkLGNBQWMsbUJBRmIsTUFBTTs7aUZBRVAsY0FBYztjQUgxQixVQUFVO2VBQUM7Z0JBQ1YsVUFBVSxFQUFFLE1BQU07YUFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QsIGNvbXB1dGVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgU2lnbmFsUkluZnJhc3RydWN0dXJlIH0gZnJvbSAnLi9zaWduYWxyLWluZnJhc3RydWN0dXJlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBPcGVyYXRpb25UcmFja2VyU2VydmljZSB9IGZyb20gJy4vb3BlcmF0aW9uLXRyYWNrZXIuc2VydmljZSc7XHJcbmltcG9ydCB7XHJcbiAgQ3J1ZE5vdGlmaWNhdGlvbixcclxuICBOb3RpZmljYXRpb25DYWxsYmFjayxcclxuICBQZW5kaW5nT3BlcmF0aW9uLFxyXG4gIENPTk5FQ1RJT05fU1RBVEUsXHJcbn0gZnJvbSAnLi4vLi4vLi4vYXBwL2ludGVyZmFjZXMvc2lnbmFsci5pbnRlcmZhY2UnO1xyXG5cclxuLyoqXHJcbiAqIFNpZ25hbFIgU2VydmljZVxyXG4gKiBQdWJsaWMgQVBJIGZvcjpcclxuICogMS4gQ29tcG9uZW50cyB0byByZWdpc3RlciBmb3IgcmVhbC10aW1lIENSVUQgbm90aWZpY2F0aW9uc1xyXG4gKiAyLiBTZXJ2aWNlcyAoVGFiRm9ybWlvU2VydmljZSkgdG8gdHJhY2sgYXN5bmMgb3BlcmF0aW9uc1xyXG4gKlxyXG4gKiBVc2FnZSBpbiBjb21wb25lbnRzOlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIG5nT25Jbml0KCkge1xyXG4gKiAgIHRoaXMuc2lnbmFsUlNlcnZpY2UucmVnaXN0ZXIoXHJcbiAqICAgICB0aGlzLmNvbXBvbmVudElkLFxyXG4gKiAgICAgdGhpcy5hcHBPYmplY3RJZCxcclxuICogICAgIChub3RpZmljYXRpb24pID0+IHRoaXMuaGFuZGxlTm90aWZpY2F0aW9uKG5vdGlmaWNhdGlvbilcclxuICogICApO1xyXG4gKiB9XHJcbiAqXHJcbiAqIG5nT25EZXN0cm95KCkge1xyXG4gKiAgIHRoaXMuc2lnbmFsUlNlcnZpY2UudW5yZWdpc3Rlcih0aGlzLmNvbXBvbmVudElkLCB0aGlzLmFwcE9iamVjdElkKTtcclxuICogfVxyXG4gKiBgYGBcclxuICpcclxuICogVXNhZ2UgaW4gc2VydmljZXMgKFRhYkZvcm1pb1NlcnZpY2UpOlxyXG4gKiBgYGB0eXBlc2NyaXB0XHJcbiAqIGNvbnN0IGNvcnJlbGF0aW9uSWQgPSByZXNwb25zZS5jb3JyZWxhdGlvbklkO1xyXG4gKiB0aGlzLnNpZ25hbFJTZXJ2aWNlLndhaXRGb3JPcGVyYXRpb24oY29ycmVsYXRpb25JZCkuc3Vic2NyaWJlKG5vdGlmaWNhdGlvbiA9PiB7XHJcbiAqICAgLy8gSGFuZGxlIGNvbXBsZXRlZCBvcGVyYXRpb25cclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290JyxcclxufSlcclxuZXhwb3J0IGNsYXNzIFNpZ25hbFJTZXJ2aWNlIHtcclxuICBwcml2YXRlIGluZnJhc3RydWN0dXJlID0gaW5qZWN0KFNpZ25hbFJJbmZyYXN0cnVjdHVyZSk7XHJcbiAgcHJpdmF0ZSBvcGVyYXRpb25UcmFja2VyID0gaW5qZWN0KE9wZXJhdGlvblRyYWNrZXJTZXJ2aWNlKTtcclxuXHJcbiAgLy8gUmVnaXN0cnk6IE1hcDxhcHBPYmplY3RJZCwgTWFwPGNvbXBvbmVudElkLCBjYWxsYmFjaz4+XHJcbiAgcHJpdmF0ZSBjb21wb25lbnRSZWdpc3RyeSA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBOb3RpZmljYXRpb25DYWxsYmFjaz4+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBjb25uZWN0aW9uIHN0YXRlIChmb3IgVUkgaW5kaWNhdG9ycylcclxuICAgKi9cclxuICByZWFkb25seSBjb25uZWN0aW9uU3RhdGUgPSB0aGlzLmluZnJhc3RydWN0dXJlLmNvbm5lY3Rpb25TdGF0ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgY3VycmVudGx5IGNvbm5lY3RlZFxyXG4gICAqL1xyXG4gIHJlYWRvbmx5IGlzQ29ubmVjdGVkID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5jb25uZWN0aW9uU3RhdGUoKSA9PT0gQ09OTkVDVElPTl9TVEFURS5DT05ORUNURUQpO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIC8vIExpc3RlbiB0byBub3RpZmljYXRpb25zIGZyb20gaW5mcmFzdHJ1Y3R1cmUgYW5kIHJvdXRlIHRoZW1cclxuICAgIHRoaXMuaW5mcmFzdHJ1Y3R1cmUubm90aWZpY2F0aW9ucyQuc3Vic2NyaWJlKChub3RpZmljYXRpb24pID0+IHtcclxuICAgICAgLy8gMS4gQ2hlY2sgaWYgdGhpcyBpcyBhIHRyYWNrZWQgYXN5bmMgb3BlcmF0aW9uIChwcm9jZXNzUmVxdWVzdClcclxuICAgICAgdGhpcy5vcGVyYXRpb25UcmFja2VyLmhhbmRsZU5vdGlmaWNhdGlvbihub3RpZmljYXRpb24pO1xyXG5cclxuICAgICAgLy8gMi4gQWxzbyBub3RpZnkgY29tcG9uZW50cyBzdWJzY3JpYmVkIHRvIHRoaXMgYXBwT2JqZWN0SWQgKEdyaWQsIGV0Yy4pXHJcbiAgICAgIHRoaXMubm90aWZ5Q29tcG9uZW50cyhub3RpZmljYXRpb24pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFc3RhYmxpc2ggYSBjb25uZWN0aW9uIHRvIHRoZSBTaWduYWxSIGh1YlxyXG4gICAqXHJcbiAgICogVGhpcyBtZXRob2QgaXMgaWRlbXBvdGVudCAtIGlmIHRoZSBjb25uZWN0aW9uIGlzIGFscmVhZHkgZXN0YWJsaXNoZWQsIGl0IHdpbGwgbm90IGJlIHJlLWVzdGFibGlzaGVkLlxyXG4gICAqIEh1YiBVUkwgaXMgcmVhZCBmcm9tIENvbW1vbi5zaWduYWxSSHViVXJsIChzZXQgZHVyaW5nIGFwcCBpbml0aWFsaXphdGlvbiB2aWEgQ29tbW9uLmluaXQoKSlcclxuICAgKi9cclxuICBjb25uZWN0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbmZyYXN0cnVjdHVyZS5jb25uZWN0KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWdpc3RlciBjb21wb25lbnQgZm9yIHJlYWwtdGltZSBub3RpZmljYXRpb25zXHJcbiAgICpcclxuICAgKiBAcGFyYW0gY29tcG9uZW50SWQgLSBVbmlxdWUgY29tcG9uZW50IGlkZW50aWZpZXIgKGdlbmVyYXRlZCBieSBjb21wb25lbnQpXHJcbiAgICogQHBhcmFtIGFwcE9iamVjdElkIC0gQXBwT2JqZWN0IElEIHRvIHN1YnNjcmliZSB0b1xyXG4gICAqIEBwYXJhbSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgd2hlbiBub3RpZmljYXRpb24gcmVjZWl2ZWRcclxuICAgKi9cclxuICByZWdpc3Rlcihjb21wb25lbnRJZDogc3RyaW5nLCBhcHBPYmplY3RJZDogc3RyaW5nLCBjYWxsYmFjazogTm90aWZpY2F0aW9uQ2FsbGJhY2spOiB2b2lkIHtcclxuICAgIC8vIEluaXRpYWxpemUgbWFwIGZvciB0aGlzIEFwcE9iamVjdCBpZiBkb2Vzbid0IGV4aXN0XHJcbiAgICBpZiAoIXRoaXMuY29tcG9uZW50UmVnaXN0cnkuaGFzKGFwcE9iamVjdElkKSkge1xyXG4gICAgICB0aGlzLmNvbXBvbmVudFJlZ2lzdHJ5LnNldChhcHBPYmplY3RJZCwgbmV3IE1hcCgpKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjb21wb25lbnRzID0gdGhpcy5jb21wb25lbnRSZWdpc3RyeS5nZXQoYXBwT2JqZWN0SWQpITtcclxuXHJcbiAgICAvLyBGaXJzdCBjb21wb25lbnQgZm9yIHRoaXMgQXBwT2JqZWN0PyBKb2luIFNpZ25hbFIgZ3JvdXBcclxuICAgIGlmIChjb21wb25lbnRzLnNpemUgPT09IDApIHtcclxuICAgICAgdGhpcy5pbmZyYXN0cnVjdHVyZS5qb2luR3JvdXAoYXBwT2JqZWN0SWQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEFkZCBjb21wb25lbnQgdG8gcmVnaXN0cnlcclxuICAgIGNvbXBvbmVudHMuc2V0KGNvbXBvbmVudElkLCBjYWxsYmFjayk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVbnJlZ2lzdGVyIGNvbXBvbmVudCAoY2xlYW51cCBvbiBjb21wb25lbnQgZGVzdHJveSlcclxuICAgKlxyXG4gICAqIEBwYXJhbSBjb21wb25lbnRJZCAtIENvbXBvbmVudCBpZGVudGlmaWVyIHRvIHJlbW92ZVxyXG4gICAqIEBwYXJhbSBhcHBPYmplY3RJZCAtIEFwcE9iamVjdCBJRCB0byB1bnN1YnNjcmliZSBmcm9tXHJcbiAgICovXHJcbiAgdW5yZWdpc3Rlcihjb21wb25lbnRJZDogc3RyaW5nLCBhcHBPYmplY3RJZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBjb21wb25lbnRzID0gdGhpcy5jb21wb25lbnRSZWdpc3RyeS5nZXQoYXBwT2JqZWN0SWQpO1xyXG4gICAgaWYgKCFjb21wb25lbnRzKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZW1vdmUgY29tcG9uZW50IGZyb20gcmVnaXN0cnlcclxuICAgIGNvbXBvbmVudHMuZGVsZXRlKGNvbXBvbmVudElkKTtcclxuXHJcbiAgICAvLyBMYXN0IGNvbXBvbmVudCBmb3IgdGhpcyBBcHBPYmplY3Q/IExlYXZlIFNpZ25hbFIgZ3JvdXBcclxuICAgIGlmIChjb21wb25lbnRzLnNpemUgPT09IDApIHtcclxuICAgICAgdGhpcy5pbmZyYXN0cnVjdHVyZS5sZWF2ZUdyb3VwKGFwcE9iamVjdElkKTtcclxuICAgICAgdGhpcy5jb21wb25lbnRSZWdpc3RyeS5kZWxldGUoYXBwT2JqZWN0SWQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogV2FpdCBmb3Igc3BlY2lmaWMgYXN5bmMgb3BlcmF0aW9uIHRvIGNvbXBsZXRlXHJcbiAgICogVXNlZCBieSBUYWJGb3JtaW9TZXJ2aWNlIGZvciBhc3luYyBwcm9jZXNzUmVxdWVzdCBvcGVyYXRpb25zXHJcbiAgICpcclxuICAgKiBAcGFyYW0gY29ycmVsYXRpb25JZCAtIENvcnJlbGF0aW9uIElEIGZyb20gYmFja2VuZCByZXNwb25zZVxyXG4gICAqIEBwYXJhbSB0aW1lb3V0IC0gT3B0aW9uYWwgdGltZW91dCBpbiBtaWxsaXNlY29uZHNcclxuICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIHRoYXQgZW1pdHMgd2hlbiBvcGVyYXRpb24gY29tcGxldGVzXHJcbiAgICovXHJcbiAgd2FpdEZvck9wZXJhdGlvbihjb3JyZWxhdGlvbklkOiBzdHJpbmcsIHRpbWVvdXQ/OiBudW1iZXIpOiBPYnNlcnZhYmxlPENydWROb3RpZmljYXRpb24+IHtcclxuICAgIHJldHVybiB0aGlzLm9wZXJhdGlvblRyYWNrZXIud2FpdEZvck9wZXJhdGlvbihjb3JyZWxhdGlvbklkLCB0aW1lb3V0KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdGVyIGFzeW5jIG9wZXJhdGlvbiBmb3IgdHJhY2tpbmdcclxuICAgKiBPcHRpb25hbCAtIHdhaXRGb3JPcGVyYXRpb24gaGFuZGxlcyByZWdpc3RyYXRpb24gYXV0b21hdGljYWxseVxyXG4gICAqXHJcbiAgICogQHBhcmFtIG9wZXJhdGlvbiAtIFBlbmRpbmcgb3BlcmF0aW9uIGRldGFpbHNcclxuICAgKi9cclxuICByZWdpc3Rlck9wZXJhdGlvbihvcGVyYXRpb246IFBlbmRpbmdPcGVyYXRpb24pOiB2b2lkIHtcclxuICAgIHRoaXMub3BlcmF0aW9uVHJhY2tlci5yZWdpc3Rlck9wZXJhdGlvbihvcGVyYXRpb24pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgb3BlcmF0aW9uIGlzIHBlbmRpbmdcclxuICAgKi9cclxuICBpc09wZXJhdGlvblBlbmRpbmcoY29ycmVsYXRpb25JZDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25UcmFja2VyLmlzUGVuZGluZyhjb3JyZWxhdGlvbklkKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE5vdGlmeSBhbGwgcmVnaXN0ZXJlZCBjb21wb25lbnRzIGZvciBhbiBBcHBPYmplY3RcclxuICAgKiBDYWxsZWQgd2hlbiBub3RpZmljYXRpb24gcmVjZWl2ZWQgZnJvbSBTaWduYWxSIGh1YlxyXG4gICAqL1xyXG4gIHByaXZhdGUgbm90aWZ5Q29tcG9uZW50cyhub3RpZmljYXRpb246IENydWROb3RpZmljYXRpb24pOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbXBvbmVudHMgPSB0aGlzLmNvbXBvbmVudFJlZ2lzdHJ5LmdldChub3RpZmljYXRpb24uYXBwT2JqZWN0SWQpO1xyXG5cclxuICAgIGlmICghY29tcG9uZW50cyB8fCBjb21wb25lbnRzLnNpemUgPT09IDApIHtcclxuICAgICAgLy8gTm8gY29tcG9uZW50cyByZWdpc3RlcmVkIGZvciB0aGlzIEFwcE9iamVjdCAtIGlnbm9yZSBub3RpZmljYXRpb25cclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENhbGwgZWFjaCBjb21wb25lbnQncyBjYWxsYmFja1xyXG4gICAgY29tcG9uZW50cy5mb3JFYWNoKChjYWxsYmFjaywgY29tcG9uZW50SWQpID0+IHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjYWxsYmFjayhub3RpZmljYXRpb24pO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYFtTaWduYWxSIFNlcnZpY2VdIENhbGxiYWNrIGZhaWxlZCBmb3IgY29tcG9uZW50ICR7Y29tcG9uZW50SWR9OmAsIGVycm9yKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgYWN0aXZlIEFwcE9iamVjdCBncm91cHMgKGZvciBkZWJ1Z2dpbmcpXHJcbiAgICovXHJcbiAgZ2V0QWN0aXZlR3JvdXBzKCk6IHN0cmluZ1tdIHtcclxuICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMuY29tcG9uZW50UmVnaXN0cnkua2V5cygpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBjb21wb25lbnQgY291bnQgZm9yIGFuIEFwcE9iamVjdCAoZm9yIGRlYnVnZ2luZylcclxuICAgKi9cclxuICBnZXRDb21wb25lbnRDb3VudChhcHBPYmplY3RJZDogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudFJlZ2lzdHJ5LmdldChhcHBPYmplY3RJZCk/LnNpemUgfHwgMDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0b3RhbCByZWdpc3RlcmVkIGNvbXBvbmVudHMgYWNyb3NzIGFsbCBBcHBPYmplY3RzIChmb3IgZGVidWdnaW5nKVxyXG4gICAqL1xyXG4gIGdldFRvdGFsQ29tcG9uZW50Q291bnQoKTogbnVtYmVyIHtcclxuICAgIGxldCB0b3RhbCA9IDA7XHJcbiAgICB0aGlzLmNvbXBvbmVudFJlZ2lzdHJ5LmZvckVhY2goKGNvbXBvbmVudHMpID0+IHtcclxuICAgICAgdG90YWwgKz0gY29tcG9uZW50cy5zaXplO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gdG90YWw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgcmVnaXN0cnkgc3RhdGUgKGZvciBkZWJ1Z2dpbmcpXHJcbiAgICovXHJcbiAgZ2V0UmVnaXN0cnlTdGF0ZSgpOiB7IGFwcE9iamVjdElkOiBzdHJpbmc7IGNvbXBvbmVudENvdW50OiBudW1iZXIgfVtdIHtcclxuICAgIGNvbnN0IHN0YXRlOiB7IGFwcE9iamVjdElkOiBzdHJpbmc7IGNvbXBvbmVudENvdW50OiBudW1iZXIgfVtdID0gW107XHJcblxyXG4gICAgdGhpcy5jb21wb25lbnRSZWdpc3RyeS5mb3JFYWNoKChjb21wb25lbnRzLCBhcHBPYmplY3RJZCkgPT4ge1xyXG4gICAgICBzdGF0ZS5wdXNoKHtcclxuICAgICAgICBhcHBPYmplY3RJZCxcclxuICAgICAgICBjb21wb25lbnRDb3VudDogY29tcG9uZW50cy5zaXplLFxyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG5cclxuICAgIHJldHVybiBzdGF0ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBwZW5kaW5nIG9wZXJhdGlvbnMgY291bnQgKGZvciBkZWJ1Z2dpbmcpXHJcbiAgICovXHJcbiAgZ2V0UGVuZGluZ09wZXJhdGlvbnNDb3VudCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMub3BlcmF0aW9uVHJhY2tlci5nZXRQZW5kaW5nQ291bnQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChmb3IgZGVidWdnaW5nKVxyXG4gICAqL1xyXG4gIGdldFBlbmRpbmdPcGVyYXRpb25zKCk6IFBlbmRpbmdPcGVyYXRpb25bXSB7XHJcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25UcmFja2VyLmdldEFsbFBlbmRpbmcoKTtcclxuICB9XHJcbn0iXX0=
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { CommonApiResponse, StandardApiResponse } from '../interfaces/common.interface';
|
|
2
|
-
/**
|
|
3
|
-
* ResponseAdapter - Transforms new API response format to legacy format
|
|
4
|
-
*
|
|
5
|
-
* This adapter maintains backward compatibility by converting the new camelCase
|
|
6
|
-
* response format from the backend to the old PascalCase format expected by
|
|
7
|
-
* existing application code.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* // Auto-detect and normalize response
|
|
11
|
-
* return this.apiService.postToService(...).pipe(
|
|
12
|
-
* map(response => ResponseAdapter.normalize(response))
|
|
13
|
-
* );
|
|
14
|
-
*/
|
|
15
|
-
export declare class ResponseAdapter {
|
|
16
|
-
/**
|
|
17
|
-
* Normalizes a StandardApiResponse to CommonApiResponse format.
|
|
18
|
-
* @param newResponse The response object in the new API format.
|
|
19
|
-
* @returns The normalized response in the legacy format.
|
|
20
|
-
*/
|
|
21
|
-
static normalize(newResponse: StandardApiResponse): CommonApiResponse;
|
|
22
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CRUD notification payload received from SignalR hub
|
|
3
|
-
*/
|
|
4
|
-
export interface CrudNotification {
|
|
5
|
-
isSuccess: boolean;
|
|
6
|
-
correlationId: string;
|
|
7
|
-
recordId: string;
|
|
8
|
-
entityName: string;
|
|
9
|
-
appObjectId: string;
|
|
10
|
-
executionTimeMs: number;
|
|
11
|
-
affectedRecords: number;
|
|
12
|
-
errorMessage?: string;
|
|
13
|
-
errorCode?: string;
|
|
14
|
-
operation?: CrudOperation;
|
|
15
|
-
receivedAt?: Date;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Pending async operation tracked by OperationTrackerService
|
|
19
|
-
*/
|
|
20
|
-
export interface PendingOperation {
|
|
21
|
-
requestId: string;
|
|
22
|
-
correlationId: string;
|
|
23
|
-
operation: CrudOperation;
|
|
24
|
-
appObjectId?: string;
|
|
25
|
-
payload?: any;
|
|
26
|
-
timestamp: Date;
|
|
27
|
-
timeout: number;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Callback function type for component notifications
|
|
31
|
-
*/
|
|
32
|
-
export type NotificationCallback = (notification: CrudNotification) => void;
|
|
33
|
-
/**
|
|
34
|
-
* CRUD operation types
|
|
35
|
-
*/
|
|
36
|
-
export type CrudOperation = typeof CRUD_OPERATION[keyof typeof CRUD_OPERATION];
|
|
37
|
-
/**
|
|
38
|
-
* SignalR connection state types
|
|
39
|
-
*/
|
|
40
|
-
export type ConnectionState = typeof CONNECTION_STATE[keyof typeof CONNECTION_STATE];
|
|
41
|
-
/**
|
|
42
|
-
* SignalR hub method names
|
|
43
|
-
*/
|
|
44
|
-
export declare const SIGNALR_HUB_METHODS: {
|
|
45
|
-
readonly JOIN_GROUP: "JoinGroupAsync";
|
|
46
|
-
readonly LEAVE_GROUP: "LeaveGroupAsync";
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* SignalR event names from backend
|
|
50
|
-
*/
|
|
51
|
-
export declare const SIGNALR_EVENTS: {
|
|
52
|
-
readonly INSERT_COMPLETED: "InsertOperationCompleted";
|
|
53
|
-
readonly UPDATE_COMPLETED: "UpdateOperationCompleted";
|
|
54
|
-
readonly DELETE_COMPLETED: "DeleteOperationCompleted";
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* CRUD operation types
|
|
58
|
-
*/
|
|
59
|
-
export declare const CRUD_OPERATION: {
|
|
60
|
-
readonly INSERT: "INSERT";
|
|
61
|
-
readonly UPDATE: "UPDATE";
|
|
62
|
-
readonly DELETE: "DELETE";
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* SignalR connection states
|
|
66
|
-
*/
|
|
67
|
-
export declare const CONNECTION_STATE: {
|
|
68
|
-
readonly DISCONNECTED: "Disconnected";
|
|
69
|
-
readonly CONNECTING: "Connecting";
|
|
70
|
-
readonly CONNECTED: "Connected";
|
|
71
|
-
readonly RECONNECTING: "Reconnecting";
|
|
72
|
-
readonly FAILED: "Failed";
|
|
73
|
-
};
|
|
74
|
-
/**
|
|
75
|
-
* SignalR configuration constants
|
|
76
|
-
*/
|
|
77
|
-
export declare const SIGNALR_CONFIG: {
|
|
78
|
-
readonly DEFAULT_TIMEOUT: 120000;
|
|
79
|
-
readonly RECONNECT_DELAYS: readonly [0, 2000, 10000, 30000, 60000];
|
|
80
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { CrudNotification, PendingOperation } from '../../../app/interfaces/signalr.interface';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
/**
|
|
5
|
-
* Operation Tracker Service
|
|
6
|
-
* Tracks async operations by correlationId and matches them with SignalR notifications
|
|
7
|
-
* Used by TabFormioService for handling async processRequest operations
|
|
8
|
-
*/
|
|
9
|
-
export declare class OperationTrackerService {
|
|
10
|
-
private pendingOperations;
|
|
11
|
-
private operationCompleted$;
|
|
12
|
-
/**
|
|
13
|
-
* Register an async operation for tracking
|
|
14
|
-
*/
|
|
15
|
-
registerOperation(operation: PendingOperation): void;
|
|
16
|
-
/**
|
|
17
|
-
* Wait for operation to complete via SignalR notification
|
|
18
|
-
* Returns Observable that emits when notification with matching correlationId is received
|
|
19
|
-
*/
|
|
20
|
-
waitForOperation(correlationId: string, timeoutMs?: number): Observable<CrudNotification>;
|
|
21
|
-
/**
|
|
22
|
-
* Handle incoming SignalR notification
|
|
23
|
-
* Called by SignalRService when notification is received
|
|
24
|
-
*/
|
|
25
|
-
handleNotification(notification: CrudNotification): void;
|
|
26
|
-
/**
|
|
27
|
-
* Check if operation is pending
|
|
28
|
-
*/
|
|
29
|
-
isPending(correlationId: string): boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Get pending operations count (for debugging)
|
|
32
|
-
*/
|
|
33
|
-
getPendingCount(): number;
|
|
34
|
-
/**
|
|
35
|
-
* Get all pending operations (for debugging)
|
|
36
|
-
*/
|
|
37
|
-
getAllPending(): PendingOperation[];
|
|
38
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<OperationTrackerService, never>;
|
|
39
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<OperationTrackerService>;
|
|
40
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Subject } from 'rxjs';
|
|
2
|
-
import { ConnectionState, CrudNotification } from '../../../app/interfaces/signalr.interface';
|
|
3
|
-
import { SessionStorageService } from '../../../auth/session-storage.service';
|
|
4
|
-
import { LocalStorageService } from '../../../auth/local-storage.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
/**
|
|
7
|
-
* SignalR Infrastructure Service
|
|
8
|
-
* Handles low-level WebSocket connection, group management, and reconnection
|
|
9
|
-
* Internal use only - components should use SignalRService instead
|
|
10
|
-
*/
|
|
11
|
-
export declare class SignalRInfrastructure {
|
|
12
|
-
private hubConnection;
|
|
13
|
-
readonly sessionStorageService: SessionStorageService;
|
|
14
|
-
readonly localStorageService: LocalStorageService;
|
|
15
|
-
readonly connectionState: import("@angular/core").WritableSignal<ConnectionState>;
|
|
16
|
-
readonly notifications$: Subject<CrudNotification>;
|
|
17
|
-
private activeGroups;
|
|
18
|
-
/**
|
|
19
|
-
* Helper method to get value from storage
|
|
20
|
-
* @param type The type of storage, 'Session' or 'Local'
|
|
21
|
-
* @param key The key to retrieve the value for
|
|
22
|
-
* @returns The value from storage, or null if not available
|
|
23
|
-
*/
|
|
24
|
-
private getFromStorage;
|
|
25
|
-
get appId(): string | null;
|
|
26
|
-
get environmentId(): string | null;
|
|
27
|
-
get tenantId(): string | null;
|
|
28
|
-
get token(): string | null;
|
|
29
|
-
/**
|
|
30
|
-
* Connect to SignalR hub
|
|
31
|
-
*/
|
|
32
|
-
connect(): Promise<void>;
|
|
33
|
-
/**
|
|
34
|
-
* Register SignalR event handlers for CRUD notifications
|
|
35
|
-
*/
|
|
36
|
-
private registerEventHandlers;
|
|
37
|
-
/**
|
|
38
|
-
* Register connection lifecycle handlers
|
|
39
|
-
*/
|
|
40
|
-
private registerConnectionLifecycle;
|
|
41
|
-
/**
|
|
42
|
-
* Join SignalR group for an AppObject
|
|
43
|
-
*/
|
|
44
|
-
joinGroup(appObjectId: string): Promise<void>;
|
|
45
|
-
/**
|
|
46
|
-
* Leave SignalR group
|
|
47
|
-
*/
|
|
48
|
-
leaveGroup(appObjectId: string): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Rejoin all active groups after reconnection
|
|
51
|
-
* This ensures components continue receiving notifications after network interruption
|
|
52
|
-
*/
|
|
53
|
-
private rejoinGroups;
|
|
54
|
-
/**
|
|
55
|
-
* Check if connected
|
|
56
|
-
*/
|
|
57
|
-
isConnected(): boolean;
|
|
58
|
-
/**
|
|
59
|
-
* Disconnect from SignalR hub (cleanup)
|
|
60
|
-
*/
|
|
61
|
-
disconnect(): Promise<void>;
|
|
62
|
-
/**
|
|
63
|
-
* Get active groups (for debugging)
|
|
64
|
-
*/
|
|
65
|
-
getActiveGroups(): string[];
|
|
66
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SignalRInfrastructure, never>;
|
|
67
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<SignalRInfrastructure>;
|
|
68
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import { CrudNotification, NotificationCallback, PendingOperation } from '../../../app/interfaces/signalr.interface';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
/**
|
|
5
|
-
* SignalR Service
|
|
6
|
-
* Public API for:
|
|
7
|
-
* 1. Components to register for real-time CRUD notifications
|
|
8
|
-
* 2. Services (TabFormioService) to track async operations
|
|
9
|
-
*
|
|
10
|
-
* Usage in components:
|
|
11
|
-
* ```typescript
|
|
12
|
-
* ngOnInit() {
|
|
13
|
-
* this.signalRService.register(
|
|
14
|
-
* this.componentId,
|
|
15
|
-
* this.appObjectId,
|
|
16
|
-
* (notification) => this.handleNotification(notification)
|
|
17
|
-
* );
|
|
18
|
-
* }
|
|
19
|
-
*
|
|
20
|
-
* ngOnDestroy() {
|
|
21
|
-
* this.signalRService.unregister(this.componentId, this.appObjectId);
|
|
22
|
-
* }
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* Usage in services (TabFormioService):
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const correlationId = response.correlationId;
|
|
28
|
-
* this.signalRService.waitForOperation(correlationId).subscribe(notification => {
|
|
29
|
-
* // Handle completed operation
|
|
30
|
-
* });
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export declare class SignalRService {
|
|
34
|
-
private infrastructure;
|
|
35
|
-
private operationTracker;
|
|
36
|
-
private componentRegistry;
|
|
37
|
-
/**
|
|
38
|
-
* Get connection state (for UI indicators)
|
|
39
|
-
*/
|
|
40
|
-
readonly connectionState: import("@angular/core").WritableSignal<import("../../../app/interfaces/signalr.interface").ConnectionState>;
|
|
41
|
-
/**
|
|
42
|
-
* Check if currently connected
|
|
43
|
-
*/
|
|
44
|
-
readonly isConnected: import("@angular/core").Signal<boolean>;
|
|
45
|
-
constructor();
|
|
46
|
-
/**
|
|
47
|
-
* Establish a connection to the SignalR hub
|
|
48
|
-
*
|
|
49
|
-
* This method is idempotent - if the connection is already established, it will not be re-established.
|
|
50
|
-
* Hub URL is read from Common.signalRHubUrl (set during app initialization via Common.init())
|
|
51
|
-
*/
|
|
52
|
-
connect(): void;
|
|
53
|
-
/**
|
|
54
|
-
* Register component for real-time notifications
|
|
55
|
-
*
|
|
56
|
-
* @param componentId - Unique component identifier (generated by component)
|
|
57
|
-
* @param appObjectId - AppObject ID to subscribe to
|
|
58
|
-
* @param callback - Function to call when notification received
|
|
59
|
-
*/
|
|
60
|
-
register(componentId: string, appObjectId: string, callback: NotificationCallback): void;
|
|
61
|
-
/**
|
|
62
|
-
* Unregister component (cleanup on component destroy)
|
|
63
|
-
*
|
|
64
|
-
* @param componentId - Component identifier to remove
|
|
65
|
-
* @param appObjectId - AppObject ID to unsubscribe from
|
|
66
|
-
*/
|
|
67
|
-
unregister(componentId: string, appObjectId: string): void;
|
|
68
|
-
/**
|
|
69
|
-
* Wait for specific async operation to complete
|
|
70
|
-
* Used by TabFormioService for async processRequest operations
|
|
71
|
-
*
|
|
72
|
-
* @param correlationId - Correlation ID from backend response
|
|
73
|
-
* @param timeout - Optional timeout in milliseconds
|
|
74
|
-
* @returns Observable that emits when operation completes
|
|
75
|
-
*/
|
|
76
|
-
waitForOperation(correlationId: string, timeout?: number): Observable<CrudNotification>;
|
|
77
|
-
/**
|
|
78
|
-
* Register async operation for tracking
|
|
79
|
-
* Optional - waitForOperation handles registration automatically
|
|
80
|
-
*
|
|
81
|
-
* @param operation - Pending operation details
|
|
82
|
-
*/
|
|
83
|
-
registerOperation(operation: PendingOperation): void;
|
|
84
|
-
/**
|
|
85
|
-
* Check if operation is pending
|
|
86
|
-
*/
|
|
87
|
-
isOperationPending(correlationId: string): boolean;
|
|
88
|
-
/**
|
|
89
|
-
* Notify all registered components for an AppObject
|
|
90
|
-
* Called when notification received from SignalR hub
|
|
91
|
-
*/
|
|
92
|
-
private notifyComponents;
|
|
93
|
-
/**
|
|
94
|
-
* Get active AppObject groups (for debugging)
|
|
95
|
-
*/
|
|
96
|
-
getActiveGroups(): string[];
|
|
97
|
-
/**
|
|
98
|
-
* Get component count for an AppObject (for debugging)
|
|
99
|
-
*/
|
|
100
|
-
getComponentCount(appObjectId: string): number;
|
|
101
|
-
/**
|
|
102
|
-
* Get total registered components across all AppObjects (for debugging)
|
|
103
|
-
*/
|
|
104
|
-
getTotalComponentCount(): number;
|
|
105
|
-
/**
|
|
106
|
-
* Get registry state (for debugging)
|
|
107
|
-
*/
|
|
108
|
-
getRegistryState(): {
|
|
109
|
-
appObjectId: string;
|
|
110
|
-
componentCount: number;
|
|
111
|
-
}[];
|
|
112
|
-
/**
|
|
113
|
-
* Get pending operations count (for debugging)
|
|
114
|
-
*/
|
|
115
|
-
getPendingOperationsCount(): number;
|
|
116
|
-
/**
|
|
117
|
-
* Get all pending operations (for debugging)
|
|
118
|
-
*/
|
|
119
|
-
getPendingOperations(): PendingOperation[];
|
|
120
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SignalRService, never>;
|
|
121
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<SignalRService>;
|
|
122
|
-
}
|