@xh/hoist 73.0.0-SNAPSHOT.1744065661676 → 73.0.0-SNAPSHOT.1744121102600
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/CHANGELOG.md +21 -0
- package/appcontainer/AppStateModel.ts +6 -1
- package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +4 -1
- package/build/types/appcontainer/AppStateModel.d.ts +5 -1
- package/build/types/security/Types.d.ts +26 -1
- package/build/types/security/msal/MsalClient.d.ts +12 -1
- package/build/types/svc/TrackService.d.ts +31 -1
- package/build/types/utils/js/BrowserUtils.d.ts +38 -1
- package/package.json +2 -2
- package/security/BaseOAuthClient.ts +5 -2
- package/security/Types.ts +29 -2
- package/security/msal/MsalClient.ts +125 -20
- package/svc/FetchService.ts +3 -2
- package/svc/TrackService.ts +94 -8
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/js/BrowserUtils.ts +72 -21
package/svc/TrackService.ts
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {HoistService, PlainObject, TrackOptions, XH} from '@xh/hoist/core';
|
|
8
|
-
import {
|
|
8
|
+
import {Timer} from '@xh/hoist/utils/async';
|
|
9
|
+
import {MINUTES, SECONDS} from '@xh/hoist/utils/datetime';
|
|
9
10
|
import {isOmitted} from '@xh/hoist/utils/impl';
|
|
10
|
-
import {debounced, stripTags, withDefault} from '@xh/hoist/utils/js';
|
|
11
|
-
import {isEmpty, isNil, isString} from 'lodash';
|
|
11
|
+
import {debounced, getClientDeviceInfo, stripTags, withDefault} from '@xh/hoist/utils/js';
|
|
12
|
+
import {isEmpty, isNil, isString, round} from 'lodash';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Primary service for tracking any activity that an application's admins want to track.
|
|
@@ -18,23 +19,38 @@ import {isEmpty, isNil, isString} from 'lodash';
|
|
|
18
19
|
export class TrackService extends HoistService {
|
|
19
20
|
static instance: TrackService;
|
|
20
21
|
|
|
22
|
+
private clientHealthReportSources: Map<string, () => any> = new Map();
|
|
21
23
|
private oncePerSessionSent = new Map();
|
|
22
24
|
private pending: PlainObject[] = [];
|
|
23
25
|
|
|
24
26
|
override async initAsync() {
|
|
27
|
+
const {clientHealthReport} = this.conf;
|
|
28
|
+
if (clientHealthReport?.intervalMins > 0) {
|
|
29
|
+
Timer.create({
|
|
30
|
+
runFn: () => this.sendClientHealthReport(),
|
|
31
|
+
interval: clientHealthReport.intervalMins,
|
|
32
|
+
intervalUnits: MINUTES,
|
|
33
|
+
delay: true
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
window.addEventListener('beforeunload', () => this.pushPendingAsync());
|
|
26
38
|
}
|
|
27
39
|
|
|
28
|
-
get conf() {
|
|
29
|
-
|
|
40
|
+
get conf(): ActivityTrackingConfig {
|
|
41
|
+
const appConfig = XH.getConf('xhActivityTrackingConfig', {});
|
|
42
|
+
return {
|
|
43
|
+
clientHealthReport: {intervalMins: -1},
|
|
30
44
|
enabled: true,
|
|
45
|
+
logData: false,
|
|
31
46
|
maxDataLength: 2000,
|
|
32
47
|
maxRows: {
|
|
33
48
|
default: 10000,
|
|
34
49
|
options: [1000, 5000, 10000, 25000]
|
|
35
50
|
},
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
levels: [{username: '*', category: '*', severity: 'INFO'}],
|
|
52
|
+
...appConfig
|
|
53
|
+
};
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
get enabled(): boolean {
|
|
@@ -79,13 +95,29 @@ export class TrackService extends HoistService {
|
|
|
79
95
|
sent.set(key, true);
|
|
80
96
|
}
|
|
81
97
|
|
|
82
|
-
// Otherwise - log and
|
|
98
|
+
// Otherwise - log and queue to send with next debounced push to server.
|
|
83
99
|
this.logMessage(options);
|
|
84
100
|
|
|
85
101
|
this.pending.push(this.toServerJson(options));
|
|
86
102
|
this.pushPendingBuffered();
|
|
87
103
|
}
|
|
88
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Register a new source for client health report data. No-op if background health report is
|
|
107
|
+
* not generally enabled via `xhActivityTrackingConfig.clientHealthReport.intervalMins`.
|
|
108
|
+
*
|
|
109
|
+
* @param key - key under which to report the data - can be used to remove this source later.
|
|
110
|
+
* @param callback - function returning serializable to include with each report.
|
|
111
|
+
*/
|
|
112
|
+
addClientHealthReportSource(key: string, callback: () => any) {
|
|
113
|
+
this.clientHealthReportSources.set(key, callback);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Unregister a previously-enabled source for client health report data. */
|
|
117
|
+
removeClientHealthReportSource(key: string) {
|
|
118
|
+
this.clientHealthReportSources.delete(key);
|
|
119
|
+
}
|
|
120
|
+
|
|
89
121
|
//------------------
|
|
90
122
|
// Implementation
|
|
91
123
|
//------------------
|
|
@@ -144,4 +176,58 @@ export class TrackService extends HoistService {
|
|
|
144
176
|
|
|
145
177
|
this.logInfo(...consoleMsgs);
|
|
146
178
|
}
|
|
179
|
+
|
|
180
|
+
private sendClientHealthReport() {
|
|
181
|
+
const {
|
|
182
|
+
intervalMins,
|
|
183
|
+
severity: defaultSeverity,
|
|
184
|
+
...rest
|
|
185
|
+
} = this.conf.clientHealthReport ?? {},
|
|
186
|
+
{loadStarted} = XH.appContainerModel.appStateModel;
|
|
187
|
+
|
|
188
|
+
const data = {
|
|
189
|
+
session: {
|
|
190
|
+
started: loadStarted,
|
|
191
|
+
durationMins: round((Date.now() - loadStarted) / 60_000, 1)
|
|
192
|
+
},
|
|
193
|
+
...getClientDeviceInfo()
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
let severity = defaultSeverity ?? 'INFO';
|
|
197
|
+
this.clientHealthReportSources.forEach((cb, k) => {
|
|
198
|
+
try {
|
|
199
|
+
data[k] = cb();
|
|
200
|
+
if (data[k]?.severity === 'WARN') severity = 'WARN';
|
|
201
|
+
} catch (e) {
|
|
202
|
+
data[k] = `Error: ${e.message}`;
|
|
203
|
+
this.logWarn(`Error running client health report callback for [${k}]`, e);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
this.track({
|
|
208
|
+
category: 'App',
|
|
209
|
+
message: 'Submitted health report',
|
|
210
|
+
severity,
|
|
211
|
+
...rest,
|
|
212
|
+
data
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface ActivityTrackingConfig {
|
|
218
|
+
clientHealthReport?: Partial<TrackOptions> & {
|
|
219
|
+
intervalMins: number;
|
|
220
|
+
};
|
|
221
|
+
enabled: boolean;
|
|
222
|
+
logData: boolean;
|
|
223
|
+
maxDataLength: number;
|
|
224
|
+
maxRows?: {
|
|
225
|
+
default: number;
|
|
226
|
+
options: number[];
|
|
227
|
+
};
|
|
228
|
+
levels?: Array<{
|
|
229
|
+
username: string | '*';
|
|
230
|
+
category: string | '*';
|
|
231
|
+
severity: 'DEBUG' | 'INFO' | 'WARN';
|
|
232
|
+
}>;
|
|
147
233
|
}
|