@techextensor/tab-core-utility 2.2.199 → 2.2.201
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 +4 -3
- package/esm2022/lib/tab-core-utility/app/constants/api-constants.mjs +3 -3
- package/esm2022/lib/tab-core-utility/app/constants/common.mjs +2 -1
- package/esm2022/lib/tab-core-utility/app/crud/tab-crud.service.mjs +8 -18
- package/esm2022/lib/tab-core-utility/app/crud/tab-delete.service.mjs +5 -11
- package/esm2022/lib/tab-core-utility/app/crud/tab-get.service.mjs +1 -3
- package/esm2022/lib/tab-core-utility/app/crud/tab-release.service.mjs +3 -3
- package/esm2022/lib/tab-core-utility/app/crud/tab-workflow.service.mjs +3 -22
- package/esm2022/lib/tab-core-utility/app/interfaces/notification.interface.mjs +52 -0
- package/esm2022/lib/tab-core-utility/app/interfaces/release.interface.mjs +1 -1
- package/esm2022/lib/tab-core-utility/core/service/notification/notification-inbox.service.mjs +299 -0
- package/esm2022/lib/tab-core-utility/core/service/notification/notification-websocket.service.mjs +220 -0
- package/esm2022/lib/tab-core-utility/core/service/signalr/operation-tracker.service.mjs +23 -6
- package/esm2022/lib/tab-core-utility/core/service/signalr/signalr-infrastructure.service.mjs +53 -7
- package/esm2022/lib/tab-core-utility/core/service/signalr/signalr.service.mjs +21 -5
- package/index.d.ts +3 -2
- package/lib/tab-core-utility/app/constants/api-constants.d.ts +2 -2
- package/lib/tab-core-utility/app/constants/common.d.ts +2 -0
- package/lib/tab-core-utility/app/crud/tab-crud.service.d.ts +0 -2
- package/lib/tab-core-utility/app/crud/tab-delete.service.d.ts +0 -1
- package/lib/tab-core-utility/app/crud/tab-get.service.d.ts +0 -1
- package/lib/tab-core-utility/app/crud/tab-workflow.service.d.ts +1 -16
- package/lib/tab-core-utility/app/interfaces/notification.interface.d.ts +156 -0
- package/lib/tab-core-utility/app/interfaces/release.interface.d.ts +49 -18
- package/lib/tab-core-utility/core/service/notification/notification-inbox.service.d.ts +87 -0
- package/lib/tab-core-utility/core/service/notification/notification-websocket.service.d.ts +57 -0
- package/lib/tab-core-utility/core/service/signalr/operation-tracker.service.d.ts +9 -1
- package/lib/tab-core-utility/core/service/signalr/signalr-infrastructure.service.d.ts +11 -0
- package/lib/tab-core-utility/core/service/signalr/signalr.service.d.ts +15 -3
- package/package.json +1 -1
- package/esm2022/lib/tab-core-utility/app/helpers/common/dsq.helpers.mjs +0 -67
- package/esm2022/lib/tab-core-utility/app/helpers/common/req-res.helpers.mjs +0 -44
- package/lib/tab-core-utility/app/helpers/common/dsq.helpers.d.ts +0 -35
- package/lib/tab-core-utility/app/helpers/common/req-res.helpers.d.ts +0 -34
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification types & WebSocket protocol constants.
|
|
3
|
+
* Driven by the TAF Notification Service API doc.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Notification status lifecycle (per BE confirmation):
|
|
7
|
+
*
|
|
8
|
+
* Pending — record just created (not yet visible in inbox)
|
|
9
|
+
* Delivered — successfully sent over WebSocket (visible, shown as unread)
|
|
10
|
+
* Read — after mark_notification_read / mark_all_notification_read
|
|
11
|
+
* Done — after clear_notification / clear_all_notifications (soft delete, filtered out)
|
|
12
|
+
* Failed — WebSocket send failed (filtered out)
|
|
13
|
+
*
|
|
14
|
+
* Inbox `get_notifications_response` only returns `Delivered` + `Read`.
|
|
15
|
+
* `isRead` is derived as `status === 'Read'`.
|
|
16
|
+
*/
|
|
17
|
+
export type NotificationStatus = 'Pending' | 'Delivered' | 'Read' | 'Done' | 'Failed';
|
|
18
|
+
export type NotificationPriority = 'Low' | 'Normal' | 'High' | 'Urgent';
|
|
19
|
+
export type WsConnectionState = 'Disconnected' | 'Connecting' | 'Connected' | 'Reconnecting' | 'Failed' | 'Closed';
|
|
20
|
+
export declare const WS_CONNECTION_STATE: {
|
|
21
|
+
readonly DISCONNECTED: "Disconnected";
|
|
22
|
+
readonly CONNECTING: "Connecting";
|
|
23
|
+
readonly CONNECTED: "Connected";
|
|
24
|
+
readonly RECONNECTING: "Reconnecting";
|
|
25
|
+
readonly FAILED: "Failed";
|
|
26
|
+
readonly CLOSED: "Closed";
|
|
27
|
+
};
|
|
28
|
+
export type NotificationActionType = 'Navigate' | 'Dismiss';
|
|
29
|
+
/**
|
|
30
|
+
* WebSocket message types (per BE doc).
|
|
31
|
+
* Outbound: client → server.
|
|
32
|
+
* Inbound: server → client (responses + push events).
|
|
33
|
+
*/
|
|
34
|
+
export declare const WS_MESSAGE_TYPE: {
|
|
35
|
+
readonly PING: "ping";
|
|
36
|
+
readonly HEARTBEAT: "heartbeat";
|
|
37
|
+
readonly GET_NOTIFICATIONS: "get_notifications";
|
|
38
|
+
readonly GET_UNREAD_COUNT: "get_unread_count";
|
|
39
|
+
readonly MARK_NOTIFICATION_READ: "mark_notification_read";
|
|
40
|
+
readonly MARK_ALL_NOTIFICATION_READ: "mark_all_notification_read";
|
|
41
|
+
readonly CLEAR_NOTIFICATION: "clear_notification";
|
|
42
|
+
readonly CLEAR_ALL_NOTIFICATIONS: "clear_all_notifications";
|
|
43
|
+
readonly CONNECTION_ESTABLISHED: "connection_established";
|
|
44
|
+
readonly PONG: "pong";
|
|
45
|
+
readonly HEARTBEAT_ACK: "heartbeat_ack";
|
|
46
|
+
readonly GET_NOTIFICATIONS_RESPONSE: "get_notifications_response";
|
|
47
|
+
readonly GET_UNREAD_COUNT_RESPONSE: "get_unread_count_response";
|
|
48
|
+
readonly MARK_NOTIFICATION_READ_RESPONSE: "mark_notification_read_response";
|
|
49
|
+
readonly MARK_ALL_NOTIFICATION_READ_RESPONSE: "mark_all_notification_read_response";
|
|
50
|
+
readonly CLEAR_NOTIFICATION_RESPONSE: "clear_notification_response";
|
|
51
|
+
readonly CLEAR_ALL_NOTIFICATIONS_RESPONSE: "clear_all_notifications_response";
|
|
52
|
+
readonly NOTIFICATION_MARKED_READ: "notification_marked_read";
|
|
53
|
+
readonly NOTIFICATION_CLEARED: "notification_cleared";
|
|
54
|
+
readonly ALL_NOTIFICATIONS_CLEARED: "all_notifications_cleared";
|
|
55
|
+
readonly NOTIFICATION: "notification";
|
|
56
|
+
readonly ERROR: "error";
|
|
57
|
+
};
|
|
58
|
+
export type WsMessageType = typeof WS_MESSAGE_TYPE[keyof typeof WS_MESSAGE_TYPE];
|
|
59
|
+
export declare const NOTIFICATION_WS_CONFIG: {
|
|
60
|
+
readonly DEFAULT_PAGE_SIZE: 20;
|
|
61
|
+
readonly RECONNECT_DELAYS_MS: readonly [2000, 5000, 10000];
|
|
62
|
+
readonly RECONNECT_MAX_DELAY_MS: 10000;
|
|
63
|
+
readonly LOAD_TIMEOUT_MS: 10000;
|
|
64
|
+
readonly CONNECT_TIMEOUT_MS: 1500;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* One item in `get_notifications_response.notifications[]` per BE doc.
|
|
68
|
+
*/
|
|
69
|
+
export interface NotificationItem {
|
|
70
|
+
id: string;
|
|
71
|
+
status: NotificationStatus;
|
|
72
|
+
data: string;
|
|
73
|
+
priority: NotificationPriority;
|
|
74
|
+
workspaceKey: string;
|
|
75
|
+
provider: string;
|
|
76
|
+
createdAt: string;
|
|
77
|
+
updatedAt: string;
|
|
78
|
+
expiresAt: string | null;
|
|
79
|
+
errorMessage: string | null;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Live-push payload — fields flat at top level (NOT inside `data`).
|
|
83
|
+
*/
|
|
84
|
+
export interface NotificationPushPayload {
|
|
85
|
+
id: string;
|
|
86
|
+
title: string;
|
|
87
|
+
body: string;
|
|
88
|
+
category: string;
|
|
89
|
+
priority: NotificationPriority;
|
|
90
|
+
workspaceKey: string;
|
|
91
|
+
createdAt: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Action object inside the `data` JSON of an inbox notification.
|
|
95
|
+
*/
|
|
96
|
+
export interface NotificationAction {
|
|
97
|
+
label: string;
|
|
98
|
+
url: string;
|
|
99
|
+
type: NotificationActionType;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Parsed contents of an inbox notification's `data` JSON string.
|
|
103
|
+
*/
|
|
104
|
+
export interface ParsedNotificationPayload {
|
|
105
|
+
title?: string;
|
|
106
|
+
body?: string;
|
|
107
|
+
category?: string;
|
|
108
|
+
priority?: NotificationPriority;
|
|
109
|
+
actions?: NotificationAction[];
|
|
110
|
+
[key: string]: unknown;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Canonical UI shape after normalization.
|
|
114
|
+
* Both inbox items and live pushes are normalized into this.
|
|
115
|
+
*/
|
|
116
|
+
export interface UiNotification {
|
|
117
|
+
id: string;
|
|
118
|
+
createdAt: string;
|
|
119
|
+
status: NotificationStatus;
|
|
120
|
+
priority: NotificationPriority;
|
|
121
|
+
parsedPayload: ParsedNotificationPayload;
|
|
122
|
+
isRead: boolean;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Auth identifiers required to open the WebSocket and address messages.
|
|
126
|
+
* The app supplies these at connect time — the core service does not read storage.
|
|
127
|
+
*/
|
|
128
|
+
export interface NotificationConnectParams {
|
|
129
|
+
/** End user — required for the URL. */
|
|
130
|
+
userId: string;
|
|
131
|
+
/** Application — used in URL + workspaceKey. */
|
|
132
|
+
appId: string;
|
|
133
|
+
/** Tenant — used in URL + workspaceKey. */
|
|
134
|
+
tenantId: string;
|
|
135
|
+
/** Environment — used in workspaceKey only. */
|
|
136
|
+
environmentId: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Composed once at the app boundary, passed down to the inbox service.
|
|
140
|
+
* Used as the URL query for the WebSocket and in every outbound message body.
|
|
141
|
+
*/
|
|
142
|
+
export interface NotificationInboxConnectParams {
|
|
143
|
+
userId: string;
|
|
144
|
+
appId: string;
|
|
145
|
+
tenantId: string;
|
|
146
|
+
/** `tenantId.appId.environmentId` — pre-composed by the SDK facade. */
|
|
147
|
+
workspaceKey: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* URL-only params for the low-level transport.
|
|
151
|
+
*/
|
|
152
|
+
export interface NotificationWebSocketConnectParams {
|
|
153
|
+
userId: string;
|
|
154
|
+
appId: string;
|
|
155
|
+
tenantId: string;
|
|
156
|
+
}
|
|
@@ -9,46 +9,77 @@ export declare const ChangeType: {
|
|
|
9
9
|
readonly Deleted: "Deleted";
|
|
10
10
|
};
|
|
11
11
|
export type ChangeTypeValue = typeof ChangeType[keyof typeof ChangeType];
|
|
12
|
+
export interface EnvironmentSnapshot {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
sequence: number;
|
|
16
|
+
releaseVersion: string | null;
|
|
17
|
+
connectionId?: string;
|
|
18
|
+
}
|
|
12
19
|
export interface DiffSection<T> {
|
|
13
20
|
added: T[];
|
|
14
21
|
updated: T[];
|
|
15
22
|
deleted: T[];
|
|
16
23
|
}
|
|
17
|
-
export interface
|
|
24
|
+
export interface FieldDiff {
|
|
18
25
|
id: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
referenceName: string;
|
|
27
|
+
oldValue?: any;
|
|
28
|
+
newValue?: any;
|
|
22
29
|
}
|
|
23
30
|
export interface QueryDiff {
|
|
24
31
|
id: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
referenceName: string;
|
|
33
|
+
oldValue?: any;
|
|
34
|
+
newValue?: any;
|
|
35
|
+
}
|
|
36
|
+
export interface AppObjectDiff {
|
|
37
|
+
id: string;
|
|
38
|
+
referenceName: string;
|
|
39
|
+
properties?: {
|
|
40
|
+
oldValue: any;
|
|
41
|
+
newValue: any;
|
|
42
|
+
};
|
|
43
|
+
fields?: DiffSection<FieldDiff> | null;
|
|
44
|
+
queries?: DiffSection<QueryDiff> | null;
|
|
28
45
|
}
|
|
29
46
|
export interface ScreenDiff {
|
|
30
47
|
id: string;
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
referenceName: string;
|
|
49
|
+
properties?: {
|
|
50
|
+
oldValue: any;
|
|
51
|
+
newValue: any;
|
|
52
|
+
};
|
|
33
53
|
}
|
|
34
54
|
export interface CustomScriptDiff {
|
|
35
55
|
id: string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
referenceName: string;
|
|
57
|
+
properties?: {
|
|
58
|
+
oldValue: any;
|
|
59
|
+
newValue: any;
|
|
60
|
+
};
|
|
39
61
|
}
|
|
40
62
|
export interface RecordDiff {
|
|
41
63
|
id: string;
|
|
42
|
-
|
|
64
|
+
referenceName?: string;
|
|
65
|
+
oldValue?: any;
|
|
66
|
+
newValue?: any;
|
|
43
67
|
}
|
|
44
68
|
export interface MetadataDiffResponse {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
sourceEnvironment: EnvironmentSnapshot;
|
|
70
|
+
targetEnvironment: EnvironmentSnapshot;
|
|
71
|
+
metadataDiff: {
|
|
72
|
+
appObjects: DiffSection<AppObjectDiff>;
|
|
73
|
+
screens: DiffSection<ScreenDiff>;
|
|
74
|
+
customScripts: DiffSection<CustomScriptDiff>;
|
|
75
|
+
};
|
|
49
76
|
}
|
|
50
77
|
export interface DataDiffResponse {
|
|
51
|
-
|
|
78
|
+
sourceEnvironment: EnvironmentSnapshot;
|
|
79
|
+
targetEnvironment: EnvironmentSnapshot;
|
|
80
|
+
dataDiff: {
|
|
81
|
+
tables: Record<string, DiffSection<RecordDiff>>;
|
|
82
|
+
};
|
|
52
83
|
}
|
|
53
84
|
export interface ApplyReleaseRequest {
|
|
54
85
|
releaseId: string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { NotificationInboxConnectParams, UiNotification } from '../../../app/interfaces/notification.interface';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Public notification inbox service.
|
|
6
|
+
*
|
|
7
|
+
* Pure — no storage / auth coupling. The caller (SDK facade) supplies all auth
|
|
8
|
+
* identifiers via `connect(params)`, and they're held for the lifetime of the
|
|
9
|
+
* connection (cleared on disconnect).
|
|
10
|
+
*
|
|
11
|
+
* Subscribes to the WebSocket transport, routes incoming messages by type into
|
|
12
|
+
* dedicated streams, and exposes high-level actions for the UI.
|
|
13
|
+
*
|
|
14
|
+
* Components/extensions consume this via the SDK facade (`TabSdk.notification.*`),
|
|
15
|
+
* not directly.
|
|
16
|
+
*
|
|
17
|
+
* Named `NotificationInboxService` to avoid collision with the existing toastr
|
|
18
|
+
* `NotificationService` in `core/service/notification.service.ts`.
|
|
19
|
+
*/
|
|
20
|
+
export declare class NotificationInboxService {
|
|
21
|
+
private readonly ws;
|
|
22
|
+
private workspaceKey;
|
|
23
|
+
private readonly latestNotifications$;
|
|
24
|
+
private readonly unreadCount$;
|
|
25
|
+
private readonly markAsReadEvent$;
|
|
26
|
+
private readonly clearEvent$;
|
|
27
|
+
private readonly loading$;
|
|
28
|
+
private readonly totalPages$;
|
|
29
|
+
private loadMoreTimer;
|
|
30
|
+
constructor();
|
|
31
|
+
/**
|
|
32
|
+
* Connect to the notification WebSocket. Awaitable, idempotent.
|
|
33
|
+
*
|
|
34
|
+
* If a connection is already active for a *different* workspace (tenant/app/env
|
|
35
|
+
* switch without signOut), we tear it down first so the new connection uses
|
|
36
|
+
* the correct URL and workspaceKey. The underlying `ws.connect` is idempotent
|
|
37
|
+
* by connection state, so it would otherwise keep the stale URL.
|
|
38
|
+
*
|
|
39
|
+
* Once connected, an unread-count fetch is fired automatically so the badge populates.
|
|
40
|
+
*/
|
|
41
|
+
connect(params: NotificationInboxConnectParams): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Tear down the connection. Resets all stream state so the UI clears.
|
|
44
|
+
*/
|
|
45
|
+
disconnect(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Fetch a page of notifications. Server replies via GET_NOTIFICATIONS_RESPONSE.
|
|
48
|
+
*
|
|
49
|
+
* Skips entirely when the socket isn't connected — otherwise we'd set
|
|
50
|
+
* `loading$` true, send into a no-op, and the UI would spin forever.
|
|
51
|
+
*
|
|
52
|
+
* Adds a safety timeout so the spinner clears even if the BE accepts the
|
|
53
|
+
* connection but never replies (broken hub, dropped frame, etc.).
|
|
54
|
+
*/
|
|
55
|
+
loadMore(pageNumber: number, pageSize?: number): void;
|
|
56
|
+
/**
|
|
57
|
+
* Request unread count. Result arrives on `unreadCount$`.
|
|
58
|
+
*/
|
|
59
|
+
requestUnreadCount(): void;
|
|
60
|
+
markAsRead(notificationId: string): void;
|
|
61
|
+
markAllAsRead(): void;
|
|
62
|
+
clearOne(notificationId: string): void;
|
|
63
|
+
clearAll(): void;
|
|
64
|
+
getLatestNotifications(): Observable<UiNotification | UiNotification[]>;
|
|
65
|
+
getUnreadCount(): Observable<number>;
|
|
66
|
+
getMarkAsReadEvents(): Observable<string | null>;
|
|
67
|
+
getClearEvents(): Observable<string[] | null>;
|
|
68
|
+
getLoadingState(): Observable<boolean>;
|
|
69
|
+
getTotalPages(): Observable<number>;
|
|
70
|
+
private handleMessage;
|
|
71
|
+
/**
|
|
72
|
+
* Parse an inbox notification's `data` JSON into a UI-shaped object.
|
|
73
|
+
*
|
|
74
|
+
* Read state is surfaced via `status === 'Read'` (confirmed by BE).
|
|
75
|
+
* Inbox response only contains `Delivered` (unread) + `Read` items;
|
|
76
|
+
* `Pending` / `Done` / `Failed` are filtered out server-side.
|
|
77
|
+
*/
|
|
78
|
+
private parseInboxNotification;
|
|
79
|
+
/**
|
|
80
|
+
* Wrap a server-pushed live notification into the same UI shape as inbox items.
|
|
81
|
+
* The push event has fields flat at the top level (NOT inside `data`) — synthesize
|
|
82
|
+
* `parsedPayload` from those fields so the component sees a uniform shape.
|
|
83
|
+
*/
|
|
84
|
+
private transformPushNotification;
|
|
85
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationInboxService, never>;
|
|
86
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NotificationInboxService>;
|
|
87
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Subject } from 'rxjs';
|
|
2
|
+
import { NotificationWebSocketConnectParams, WsConnectionState } from '../../../app/interfaces/notification.interface';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Low-level Notification WebSocket transport.
|
|
6
|
+
*
|
|
7
|
+
* Pure — no storage / auth coupling. The caller (SDK facade or app layer)
|
|
8
|
+
* supplies all auth identifiers via `connect(params)`.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the SignalR infrastructure pattern:
|
|
11
|
+
* - connect() is idempotent, dedupes concurrent calls, tears down stale sockets
|
|
12
|
+
* - disconnect() flips an explicit-disconnected flag so retries don't revive
|
|
13
|
+
* - state exposed as Angular signal
|
|
14
|
+
* - inbound messages forwarded on `messages$` for higher-level service to route
|
|
15
|
+
*
|
|
16
|
+
* Internal use — consumers should use `NotificationInboxService` instead.
|
|
17
|
+
*/
|
|
18
|
+
export declare class NotificationWebSocketService {
|
|
19
|
+
private socket;
|
|
20
|
+
private socketSub;
|
|
21
|
+
private connectingPromise;
|
|
22
|
+
private explicitlyDisconnected;
|
|
23
|
+
private lastParams;
|
|
24
|
+
private reconnectAttempt;
|
|
25
|
+
private reconnectTimer;
|
|
26
|
+
readonly connectionState: import("@angular/core").WritableSignal<WsConnectionState>;
|
|
27
|
+
readonly messages$: Subject<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Establish the WebSocket connection.
|
|
30
|
+
*
|
|
31
|
+
* Idempotent — if already OPEN, resolves immediately.
|
|
32
|
+
* In-flight calls are de-duplicated.
|
|
33
|
+
* Any stale (non-OPEN) socket is torn down before rebuild.
|
|
34
|
+
*/
|
|
35
|
+
connect(params: NotificationWebSocketConnectParams): Promise<void>;
|
|
36
|
+
private raceWithTimeout;
|
|
37
|
+
private doConnect;
|
|
38
|
+
/**
|
|
39
|
+
* Send a message over the socket. Silently no-ops if not connected.
|
|
40
|
+
*/
|
|
41
|
+
send(message: Record<string, any>): void;
|
|
42
|
+
/**
|
|
43
|
+
* Tear down the socket.
|
|
44
|
+
*
|
|
45
|
+
* Sets explicitlyDisconnected so any pending retry timers become no-ops,
|
|
46
|
+
* then closes the socket and clears state.
|
|
47
|
+
*/
|
|
48
|
+
disconnect(): Promise<void>;
|
|
49
|
+
private handleIncoming;
|
|
50
|
+
private scheduleReconnect;
|
|
51
|
+
/**
|
|
52
|
+
* Snapshot of current connection state — for debugging.
|
|
53
|
+
*/
|
|
54
|
+
isConnected(): boolean;
|
|
55
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationWebSocketService, never>;
|
|
56
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<NotificationWebSocketService>;
|
|
57
|
+
}
|
|
@@ -9,13 +9,15 @@ import * as i0 from "@angular/core";
|
|
|
9
9
|
export declare class OperationTrackerService {
|
|
10
10
|
private pendingOperations;
|
|
11
11
|
private operationCompleted$;
|
|
12
|
+
private cancellation$;
|
|
12
13
|
/**
|
|
13
14
|
* Register an async operation for tracking
|
|
14
15
|
*/
|
|
15
16
|
registerOperation(operation: PendingOperation): void;
|
|
16
17
|
/**
|
|
17
18
|
* Wait for operation to complete via SignalR notification
|
|
18
|
-
* Returns Observable that emits when notification with matching correlationId is received
|
|
19
|
+
* Returns Observable that emits when notification with matching correlationId is received,
|
|
20
|
+
* or errors if cancelAll() is invoked (e.g. on disconnect / signOut).
|
|
19
21
|
*/
|
|
20
22
|
waitForOperation(correlationId: string, timeoutMs?: number): Observable<CrudNotification>;
|
|
21
23
|
/**
|
|
@@ -23,6 +25,12 @@ export declare class OperationTrackerService {
|
|
|
23
25
|
* Called by SignalRService when notification is received
|
|
24
26
|
*/
|
|
25
27
|
handleNotification(notification: CrudNotification): void;
|
|
28
|
+
/**
|
|
29
|
+
* Cancel all pending operations — errors all open waitForOperation() observers.
|
|
30
|
+
* Called by SignalRService.disconnect() so in-flight CRUD UIs resolve fast
|
|
31
|
+
* instead of stranding until the 120s timeout.
|
|
32
|
+
*/
|
|
33
|
+
cancelAll(reason: string): void;
|
|
26
34
|
/**
|
|
27
35
|
* Check if operation is pending
|
|
28
36
|
*/
|
|
@@ -10,6 +10,8 @@ import * as i0 from "@angular/core";
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class SignalRInfrastructure {
|
|
12
12
|
private hubConnection;
|
|
13
|
+
private connectingPromise;
|
|
14
|
+
private explicitlyDisconnected;
|
|
13
15
|
readonly sessionStorageService: SessionStorageService;
|
|
14
16
|
readonly localStorageService: LocalStorageService;
|
|
15
17
|
readonly connectionState: import("@angular/core").WritableSignal<ConnectionState>;
|
|
@@ -28,8 +30,14 @@ export declare class SignalRInfrastructure {
|
|
|
28
30
|
get token(): string | null;
|
|
29
31
|
/**
|
|
30
32
|
* Connect to SignalR hub
|
|
33
|
+
*
|
|
34
|
+
* Idempotent and safe to call from multiple sites:
|
|
35
|
+
* - already CONNECTED → returns immediately
|
|
36
|
+
* - already CONNECTING → returns the in-flight promise
|
|
37
|
+
* - any non-Connected leftover hubConnection → torn down before rebuild
|
|
31
38
|
*/
|
|
32
39
|
connect(): Promise<void>;
|
|
40
|
+
private doConnect;
|
|
33
41
|
/**
|
|
34
42
|
* Register SignalR event handlers for CRUD notifications
|
|
35
43
|
*/
|
|
@@ -62,6 +70,9 @@ export declare class SignalRInfrastructure {
|
|
|
62
70
|
isConnected(): boolean;
|
|
63
71
|
/**
|
|
64
72
|
* Disconnect from SignalR hub (cleanup)
|
|
73
|
+
*
|
|
74
|
+
* Sets explicitlyDisconnected so any pending retry timers from connect()/onclose
|
|
75
|
+
* become no-ops, then stops the hub and clears tracked groups.
|
|
65
76
|
*/
|
|
66
77
|
disconnect(): Promise<void>;
|
|
67
78
|
/**
|
|
@@ -44,12 +44,24 @@ export declare class SignalRService {
|
|
|
44
44
|
readonly isConnected: import("@angular/core").Signal<boolean>;
|
|
45
45
|
constructor();
|
|
46
46
|
/**
|
|
47
|
-
* Establish a connection to the SignalR hub
|
|
47
|
+
* Establish a connection to the SignalR hub.
|
|
48
|
+
*
|
|
49
|
+
* Awaitable — the returned promise resolves when the first connection attempt
|
|
50
|
+
* settles (success or failure). Idempotent: repeated calls are de-duplicated;
|
|
51
|
+
* if already CONNECTED, resolves immediately.
|
|
48
52
|
*
|
|
49
|
-
* This method is idempotent - if the connection is already established, it will not be re-established.
|
|
50
53
|
* Hub URL is read from Common.signalRHubUrl (set during app initialization via Common.init())
|
|
51
54
|
*/
|
|
52
|
-
connect(): void
|
|
55
|
+
connect(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Tear down the connection (call from auth signOut or cross-tab logout).
|
|
58
|
+
*
|
|
59
|
+
* - Stops the hub and clears tracked groups
|
|
60
|
+
* - Drops all component registrations (stale once the socket dies)
|
|
61
|
+
* - Errors any in-flight waitForOperation() observers so the UI doesn't
|
|
62
|
+
* strand until the 120s timeout
|
|
63
|
+
*/
|
|
64
|
+
disconnect(): Promise<void>;
|
|
53
65
|
/**
|
|
54
66
|
* Register component for real-time notifications
|
|
55
67
|
*
|
package/package.json
CHANGED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Injectable, inject } from '@angular/core';
|
|
3
|
-
import { ApiService } from '../../../core/http-client/api.service';
|
|
4
|
-
import { QueryType } from '../../enums/query.enum';
|
|
5
|
-
import { API } from '../../constants/api-constants';
|
|
6
|
-
import { getHeaders } from '../../utils/req-res.util';
|
|
7
|
-
import { MetadataHelper } from './meta-data.helpers';
|
|
8
|
-
import { AccessPermission } from '../../enums/permission.enum';
|
|
9
|
-
import * as i0 from "@angular/core";
|
|
10
|
-
export class DSQHelper {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.apiService = inject(ApiService);
|
|
13
|
-
this.metadataHelper = inject(MetadataHelper);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Executes a query based on the query type
|
|
17
|
-
* NOTE: INSERT, UPDATE, and DELETE now use new /records/* endpoints
|
|
18
|
-
* This helper now only handles legacy endpoints: BulkInsert and Select
|
|
19
|
-
* @param data The data to be executed
|
|
20
|
-
* @param queryType The type of query to be executed
|
|
21
|
-
* @returns The result of the query execution
|
|
22
|
-
*/
|
|
23
|
-
executeQuery(data, queryType, headers) {
|
|
24
|
-
switch (queryType) {
|
|
25
|
-
case QueryType.BulkInsert:
|
|
26
|
-
return this.execution(data, API.bulkInsert, headers);
|
|
27
|
-
case QueryType.Select:
|
|
28
|
-
return this.execution(data, API.select, headers);
|
|
29
|
-
default:
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Executes an HTTP POST request with the provided data and URL
|
|
35
|
-
* @param data The data to be sent in the POST request
|
|
36
|
-
* @param endPointName The URL to send the POST request to
|
|
37
|
-
* @returns The result of the POST request if headers are available, otherwise null
|
|
38
|
-
*/
|
|
39
|
-
execution(data, endPointName, headers) {
|
|
40
|
-
const header = getHeaders(headers);
|
|
41
|
-
return this.apiService.post(endPointName, data, header);
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Checks if the user has access to the specified object based on roles and access type
|
|
45
|
-
* @param dsqId The DataSourceQuery ID to check access for
|
|
46
|
-
* @param accessType The type of access to check (e.g., read, write)
|
|
47
|
-
* @param roles The roles of the user with IDs
|
|
48
|
-
* @returns True if the user has access, false otherwise
|
|
49
|
-
*/
|
|
50
|
-
doesHaveObjectAccess(dsqId, accessType, roles) {
|
|
51
|
-
const dsq = this.metadataHelper.getDataSourceQueryByIdOrName(dsqId);
|
|
52
|
-
const appObject = dsq?.parentAppObject;
|
|
53
|
-
if (appObject) {
|
|
54
|
-
const accessList = appObject.AccessList?.filter((access) => roles.some((role) => access.RoleID.toLowerCase() === role.ID.toLowerCase() &&
|
|
55
|
-
access.IsEnabled)) || [];
|
|
56
|
-
return accessList.some((access) => access[accessType] === AccessPermission.All);
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DSQHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
61
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DSQHelper, providedIn: 'root' }); }
|
|
62
|
-
}
|
|
63
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DSQHelper, decorators: [{
|
|
64
|
-
type: Injectable,
|
|
65
|
-
args: [{ providedIn: 'root' }]
|
|
66
|
-
}] });
|
|
67
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHNxLmhlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2RhdGEtYWNjZXNzL3NyYy9saWIvdGFiLWNvcmUtdXRpbGl0eS9hcHAvaGVscGVycy9jb21tb24vZHNxLmhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBRXZELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUNuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDckQsT0FBTyxFQUFFLGdCQUFnQixFQUFjLE1BQU0sNkJBQTZCLENBQUM7O0FBRzNFLE1BQU0sT0FBTyxTQUFTO0lBRHRCO1FBRW1CLGVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEMsbUJBQWMsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7S0ErRDFEO0lBN0RDOzs7Ozs7O09BT0c7SUFDSCxZQUFZLENBQUMsSUFBUyxFQUFFLFNBQW9CLEVBQUUsT0FBYTtRQUN6RCxRQUFRLFNBQVMsRUFBRSxDQUFDO1lBQ2xCLEtBQUssU0FBUyxDQUFDLFVBQVU7Z0JBQ3ZCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN2RCxLQUFLLFNBQVMsQ0FBQyxNQUFNO2dCQUNuQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDbkQ7Z0JBQ0UsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLFNBQVMsQ0FBQyxJQUFTLEVBQUUsWUFBb0IsRUFBRSxPQUFhO1FBQzlELE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILG9CQUFvQixDQUNsQixLQUFhLEVBQ2IsVUFBc0IsRUFDdEIsS0FBdUI7UUFFdkIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRSxNQUFNLFNBQVMsR0FBRyxHQUFHLEVBQUUsZUFBZSxDQUFDO1FBRXZDLElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxNQUFNLFVBQVUsR0FBVSxTQUFTLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLE1BQVcsRUFBRSxFQUFFLENBQ3JFLEtBQUssQ0FBQyxJQUFJLENBQ1IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNQLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3JELE1BQU0sQ0FBQyxTQUFTLENBQ25CLENBQ0YsSUFBSSxFQUFFLENBQUM7WUFFUixPQUFPLFVBQVUsQ0FBQyxJQUFJLENBQ3BCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQUssZ0JBQWdCLENBQUMsR0FBRyxDQUN4RCxDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzsrR0FoRVUsU0FBUzttSEFBVCxTQUFTLGNBREksTUFBTTs7NEZBQ25CLFNBQVM7a0JBRHJCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xyXG5cclxuaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEFwaVNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9jb3JlL2h0dHAtY2xpZW50L2FwaS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUXVlcnlUeXBlIH0gZnJvbSAnLi4vLi4vZW51bXMvcXVlcnkuZW51bSc7XHJcbmltcG9ydCB7IEFQSSB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy9hcGktY29uc3RhbnRzJztcclxuaW1wb3J0IHsgZ2V0SGVhZGVycyB9IGZyb20gJy4uLy4uL3V0aWxzL3JlcS1yZXMudXRpbCc7XHJcbmltcG9ydCB7IE1ldGFkYXRhSGVscGVyIH0gZnJvbSAnLi9tZXRhLWRhdGEuaGVscGVycyc7XHJcbmltcG9ydCB7IEFjY2Vzc1Blcm1pc3Npb24sIEFjY2Vzc1R5cGUgfSBmcm9tICcuLi8uLi9lbnVtcy9wZXJtaXNzaW9uLmVudW0nO1xyXG5cclxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcclxuZXhwb3J0IGNsYXNzIERTUUhlbHBlciB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBhcGlTZXJ2aWNlID0gaW5qZWN0KEFwaVNlcnZpY2UpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgbWV0YWRhdGFIZWxwZXIgPSBpbmplY3QoTWV0YWRhdGFIZWxwZXIpO1xyXG5cclxuICAvKipcclxuICAgKiBFeGVjdXRlcyBhIHF1ZXJ5IGJhc2VkIG9uIHRoZSBxdWVyeSB0eXBlXHJcbiAgICogTk9URTogSU5TRVJULCBVUERBVEUsIGFuZCBERUxFVEUgbm93IHVzZSBuZXcgL3JlY29yZHMvKiBlbmRwb2ludHNcclxuICAgKiBUaGlzIGhlbHBlciBub3cgb25seSBoYW5kbGVzIGxlZ2FjeSBlbmRwb2ludHM6IEJ1bGtJbnNlcnQgYW5kIFNlbGVjdFxyXG4gICAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGJlIGV4ZWN1dGVkXHJcbiAgICogQHBhcmFtIHF1ZXJ5VHlwZSBUaGUgdHlwZSBvZiBxdWVyeSB0byBiZSBleGVjdXRlZFxyXG4gICAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdGhlIHF1ZXJ5IGV4ZWN1dGlvblxyXG4gICAqL1xyXG4gIGV4ZWN1dGVRdWVyeShkYXRhOiBhbnksIHF1ZXJ5VHlwZTogUXVlcnlUeXBlLCBoZWFkZXJzPzogYW55KSB7XHJcbiAgICBzd2l0Y2ggKHF1ZXJ5VHlwZSkge1xyXG4gICAgICBjYXNlIFF1ZXJ5VHlwZS5CdWxrSW5zZXJ0OlxyXG4gICAgICAgIHJldHVybiB0aGlzLmV4ZWN1dGlvbihkYXRhLCBBUEkuYnVsa0luc2VydCwgaGVhZGVycyk7XHJcbiAgICAgIGNhc2UgUXVlcnlUeXBlLlNlbGVjdDpcclxuICAgICAgICByZXR1cm4gdGhpcy5leGVjdXRpb24oZGF0YSwgQVBJLnNlbGVjdCwgaGVhZGVycyk7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFeGVjdXRlcyBhbiBIVFRQIFBPU1QgcmVxdWVzdCB3aXRoIHRoZSBwcm92aWRlZCBkYXRhIGFuZCBVUkxcclxuICAgKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBiZSBzZW50IGluIHRoZSBQT1NUIHJlcXVlc3RcclxuICAgKiBAcGFyYW0gZW5kUG9pbnROYW1lIFRoZSBVUkwgdG8gc2VuZCB0aGUgUE9TVCByZXF1ZXN0IHRvXHJcbiAgICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiB0aGUgUE9TVCByZXF1ZXN0IGlmIGhlYWRlcnMgYXJlIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIG51bGxcclxuICAgKi9cclxuICBwcml2YXRlIGV4ZWN1dGlvbihkYXRhOiBhbnksIGVuZFBvaW50TmFtZTogc3RyaW5nLCBoZWFkZXJzPzogYW55KSB7XHJcbiAgICBjb25zdCBoZWFkZXIgPSBnZXRIZWFkZXJzKGhlYWRlcnMpO1xyXG4gICAgcmV0dXJuIHRoaXMuYXBpU2VydmljZS5wb3N0KGVuZFBvaW50TmFtZSwgZGF0YSwgaGVhZGVyKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrcyBpZiB0aGUgdXNlciBoYXMgYWNjZXNzIHRvIHRoZSBzcGVjaWZpZWQgb2JqZWN0IGJhc2VkIG9uIHJvbGVzIGFuZCBhY2Nlc3MgdHlwZVxyXG4gICAqIEBwYXJhbSBkc3FJZCBUaGUgRGF0YVNvdXJjZVF1ZXJ5IElEIHRvIGNoZWNrIGFjY2VzcyBmb3JcclxuICAgKiBAcGFyYW0gYWNjZXNzVHlwZSBUaGUgdHlwZSBvZiBhY2Nlc3MgdG8gY2hlY2sgKGUuZy4sIHJlYWQsIHdyaXRlKVxyXG4gICAqIEBwYXJhbSByb2xlcyBUaGUgcm9sZXMgb2YgdGhlIHVzZXIgd2l0aCBJRHNcclxuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSB1c2VyIGhhcyBhY2Nlc3MsIGZhbHNlIG90aGVyd2lzZVxyXG4gICAqL1xyXG4gIGRvZXNIYXZlT2JqZWN0QWNjZXNzKFxyXG4gICAgZHNxSWQ6IHN0cmluZyxcclxuICAgIGFjY2Vzc1R5cGU6IEFjY2Vzc1R5cGUsXHJcbiAgICByb2xlczogW3sgSUQ6IHN0cmluZyB9XVxyXG4gICkge1xyXG4gICAgY29uc3QgZHNxID0gdGhpcy5tZXRhZGF0YUhlbHBlci5nZXREYXRhU291cmNlUXVlcnlCeUlkT3JOYW1lKGRzcUlkKTtcclxuICAgIGNvbnN0IGFwcE9iamVjdCA9IGRzcT8ucGFyZW50QXBwT2JqZWN0O1xyXG5cclxuICAgIGlmIChhcHBPYmplY3QpIHtcclxuICAgICAgY29uc3QgYWNjZXNzTGlzdDogYW55W10gPSBhcHBPYmplY3QuQWNjZXNzTGlzdD8uZmlsdGVyKChhY2Nlc3M6IGFueSkgPT5cclxuICAgICAgICByb2xlcy5zb21lKFxyXG4gICAgICAgICAgKHJvbGUpID0+XHJcbiAgICAgICAgICAgIGFjY2Vzcy5Sb2xlSUQudG9Mb3dlckNhc2UoKSA9PT0gcm9sZS5JRC50b0xvd2VyQ2FzZSgpICYmXHJcbiAgICAgICAgICAgIGFjY2Vzcy5Jc0VuYWJsZWRcclxuICAgICAgICApXHJcbiAgICAgICkgfHwgW107XHJcblxyXG4gICAgICByZXR1cm4gYWNjZXNzTGlzdC5zb21lKFxyXG4gICAgICAgIChhY2Nlc3MpID0+IGFjY2Vzc1thY2Nlc3NUeXBlXSA9PT0gQWNjZXNzUGVybWlzc2lvbi5BbGxcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { QueryType } from '../../enums/query.enum';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export class RequestResponseHelper {
|
|
6
|
-
/**
|
|
7
|
-
* Generates the payload for inserting data into a table in bulk
|
|
8
|
-
* @param table The table name to insert data into
|
|
9
|
-
* @param whereClause The filter criteria for the insert operation
|
|
10
|
-
* @param value The value sets to be inserted
|
|
11
|
-
* @param fields Optional list of fields to include in the insert operation
|
|
12
|
-
* @returns The payload for the bulk insert operation
|
|
13
|
-
*/
|
|
14
|
-
bulkInsertPayload(table, whereClause, value, fields) {
|
|
15
|
-
return {
|
|
16
|
-
QueryObjectID: table,
|
|
17
|
-
QueryType: QueryType.BulkInsert,
|
|
18
|
-
Joins: [],
|
|
19
|
-
WhereClause: whereClause,
|
|
20
|
-
Values: value,
|
|
21
|
-
Fields: fields,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Generates the payload for deleting data from a table
|
|
26
|
-
* NEW: Returns new format for /records/delete endpoint
|
|
27
|
-
* @param tableName The table name (entityName) to delete data from
|
|
28
|
-
* @param whereClause The filter criteria for the delete operation (NEW format with lowercase)
|
|
29
|
-
* @returns The payload for the delete operation in NEW format
|
|
30
|
-
*/
|
|
31
|
-
deletePayload(tableName, whereClause) {
|
|
32
|
-
return {
|
|
33
|
-
entityName: tableName,
|
|
34
|
-
whereClause: whereClause,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: RequestResponseHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: RequestResponseHelper, providedIn: 'root' }); }
|
|
39
|
-
}
|
|
40
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: RequestResponseHelper, decorators: [{
|
|
41
|
-
type: Injectable,
|
|
42
|
-
args: [{ providedIn: 'root' }]
|
|
43
|
-
}] });
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxLXJlcy5oZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9kYXRhLWFjY2Vzcy9zcmMvbGliL3RhYi1jb3JlLXV0aWxpdHkvYXBwL2hlbHBlcnMvY29tbW9uL3JlcS1yZXMuaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1REFBdUQ7QUFFdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7O0FBRW5ELE1BQU0sT0FBTyxxQkFBcUI7SUFDaEM7Ozs7Ozs7T0FPRztJQUNILGlCQUFpQixDQUNmLEtBQWEsRUFDYixXQUE4QixFQUM5QixLQUFxQyxFQUNyQyxNQUFpQjtRQUVqQixPQUFPO1lBQ0wsYUFBYSxFQUFFLEtBQUs7WUFDcEIsU0FBUyxFQUFFLFNBQVMsQ0FBQyxVQUFVO1lBQy9CLEtBQUssRUFBRSxFQUFFO1lBQ1QsV0FBVyxFQUFFLFdBQVc7WUFDeEIsTUFBTSxFQUFFLEtBQUs7WUFDYixNQUFNLEVBQUUsTUFBTTtTQUNmLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsYUFBYSxDQUFDLFNBQWlCLEVBQUUsV0FBOEI7UUFDN0QsT0FBTztZQUNMLFVBQVUsRUFBRSxTQUFTO1lBQ3JCLFdBQVcsRUFBRSxXQUFXO1NBQ3pCLENBQUM7SUFDSixDQUFDOytHQXJDVSxxQkFBcUI7bUhBQXJCLHFCQUFxQixjQURSLE1BQU07OzRGQUNuQixxQkFBcUI7a0JBRGpDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xyXG5cclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBBUElCdWxrSW5zZXJ0RmllbGRzVmFsdWVTZXRzLCBBUElGaWx0ZXJDcml0ZXJpYSB9IGZyb20gJy4uLy4uL21vZGVscy9hcGktcXVlcnkuY2xhc3MnO1xyXG5pbXBvcnQgeyBRdWVyeVR5cGUgfSBmcm9tICcuLi8uLi9lbnVtcy9xdWVyeS5lbnVtJztcclxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcclxuZXhwb3J0IGNsYXNzIFJlcXVlc3RSZXNwb25zZUhlbHBlciB7XHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIHRoZSBwYXlsb2FkIGZvciBpbnNlcnRpbmcgZGF0YSBpbnRvIGEgdGFibGUgaW4gYnVsa1xyXG4gICAqIEBwYXJhbSB0YWJsZSBUaGUgdGFibGUgbmFtZSB0byBpbnNlcnQgZGF0YSBpbnRvXHJcbiAgICogQHBhcmFtIHdoZXJlQ2xhdXNlIFRoZSBmaWx0ZXIgY3JpdGVyaWEgZm9yIHRoZSBpbnNlcnQgb3BlcmF0aW9uXHJcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSBzZXRzIHRvIGJlIGluc2VydGVkXHJcbiAgICogQHBhcmFtIGZpZWxkcyBPcHRpb25hbCBsaXN0IG9mIGZpZWxkcyB0byBpbmNsdWRlIGluIHRoZSBpbnNlcnQgb3BlcmF0aW9uXHJcbiAgICogQHJldHVybnMgVGhlIHBheWxvYWQgZm9yIHRoZSBidWxrIGluc2VydCBvcGVyYXRpb25cclxuICAgKi9cclxuICBidWxrSW5zZXJ0UGF5bG9hZChcclxuICAgIHRhYmxlOiBzdHJpbmcsXHJcbiAgICB3aGVyZUNsYXVzZTogQVBJRmlsdGVyQ3JpdGVyaWEsXHJcbiAgICB2YWx1ZTogQVBJQnVsa0luc2VydEZpZWxkc1ZhbHVlU2V0c1tdLFxyXG4gICAgZmllbGRzPzogc3RyaW5nW11cclxuICApIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIFF1ZXJ5T2JqZWN0SUQ6IHRhYmxlLFxyXG4gICAgICBRdWVyeVR5cGU6IFF1ZXJ5VHlwZS5CdWxrSW5zZXJ0LFxyXG4gICAgICBKb2luczogW10sXHJcbiAgICAgIFdoZXJlQ2xhdXNlOiB3aGVyZUNsYXVzZSxcclxuICAgICAgVmFsdWVzOiB2YWx1ZSxcclxuICAgICAgRmllbGRzOiBmaWVsZHMsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIHRoZSBwYXlsb2FkIGZvciBkZWxldGluZyBkYXRhIGZyb20gYSB0YWJsZVxyXG4gICAqIE5FVzogUmV0dXJucyBuZXcgZm9ybWF0IGZvciAvcmVjb3Jkcy9kZWxldGUgZW5kcG9pbnRcclxuICAgKiBAcGFyYW0gdGFibGVOYW1lIFRoZSB0YWJsZSBuYW1lIChlbnRpdHlOYW1lKSB0byBkZWxldGUgZGF0YSBmcm9tXHJcbiAgICogQHBhcmFtIHdoZXJlQ2xhdXNlIFRoZSBmaWx0ZXIgY3JpdGVyaWEgZm9yIHRoZSBkZWxldGUgb3BlcmF0aW9uIChORVcgZm9ybWF0IHdpdGggbG93ZXJjYXNlKVxyXG4gICAqIEByZXR1cm5zIFRoZSBwYXlsb2FkIGZvciB0aGUgZGVsZXRlIG9wZXJhdGlvbiBpbiBORVcgZm9ybWF0XHJcbiAgICovXHJcbiAgZGVsZXRlUGF5bG9hZCh0YWJsZU5hbWU6IHN0cmluZywgd2hlcmVDbGF1c2U6IEFQSUZpbHRlckNyaXRlcmlhKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBlbnRpdHlOYW1lOiB0YWJsZU5hbWUsXHJcbiAgICAgIHdoZXJlQ2xhdXNlOiB3aGVyZUNsYXVzZSxcclxuICAgIH07XHJcbiAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { QueryType } from '../../enums/query.enum';
|
|
2
|
-
import { AccessType } from '../../enums/permission.enum';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
export declare class DSQHelper {
|
|
5
|
-
private readonly apiService;
|
|
6
|
-
private readonly metadataHelper;
|
|
7
|
-
/**
|
|
8
|
-
* Executes a query based on the query type
|
|
9
|
-
* NOTE: INSERT, UPDATE, and DELETE now use new /records/* endpoints
|
|
10
|
-
* This helper now only handles legacy endpoints: BulkInsert and Select
|
|
11
|
-
* @param data The data to be executed
|
|
12
|
-
* @param queryType The type of query to be executed
|
|
13
|
-
* @returns The result of the query execution
|
|
14
|
-
*/
|
|
15
|
-
executeQuery(data: any, queryType: QueryType, headers?: any): import("rxjs").Observable<any> | null;
|
|
16
|
-
/**
|
|
17
|
-
* Executes an HTTP POST request with the provided data and URL
|
|
18
|
-
* @param data The data to be sent in the POST request
|
|
19
|
-
* @param endPointName The URL to send the POST request to
|
|
20
|
-
* @returns The result of the POST request if headers are available, otherwise null
|
|
21
|
-
*/
|
|
22
|
-
private execution;
|
|
23
|
-
/**
|
|
24
|
-
* Checks if the user has access to the specified object based on roles and access type
|
|
25
|
-
* @param dsqId The DataSourceQuery ID to check access for
|
|
26
|
-
* @param accessType The type of access to check (e.g., read, write)
|
|
27
|
-
* @param roles The roles of the user with IDs
|
|
28
|
-
* @returns True if the user has access, false otherwise
|
|
29
|
-
*/
|
|
30
|
-
doesHaveObjectAccess(dsqId: string, accessType: AccessType, roles: [{
|
|
31
|
-
ID: string;
|
|
32
|
-
}]): boolean;
|
|
33
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<DSQHelper, never>;
|
|
34
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<DSQHelper>;
|
|
35
|
-
}
|