@xh/hoist 67.0.0-SNAPSHOT.1725151485260 → 67.0.0-SNAPSHOT.1725400144289
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/build/types/core/XH.d.ts +1 -2
- package/build/types/svc/EnvironmentService.d.ts +10 -3
- package/core/XH.ts +1 -10
- package/package.json +1 -1
- package/svc/EnvironmentService.ts +84 -63
- package/tsconfig.tsbuildinfo +1 -1
package/build/types/core/XH.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ToastModel } from '../appcontainer/ToastModel';
|
|
|
11
11
|
import '../styles/XH.scss';
|
|
12
12
|
import { AppSpec, AppState, AppSuspendData, BannerSpec, ExceptionHandler, ExceptionHandlerOptions, HoistAppModel, HoistException, HoistService, HoistServiceClass, HoistUser, MessageSpec, PageState, PlainObject, SizingMode, TaskObserver, Theme, ToastSpec, TrackOptions } from './';
|
|
13
13
|
import { HoistModel, ModelSelector, RefreshContextModel } from './model';
|
|
14
|
-
export declare const MIN_HOIST_CORE_VERSION = "
|
|
14
|
+
export declare const MIN_HOIST_CORE_VERSION = "21.0";
|
|
15
15
|
/**
|
|
16
16
|
* Top-level Singleton model for Hoist. This is the main entry point for the API.
|
|
17
17
|
*
|
|
@@ -321,7 +321,6 @@ export declare class XHApi {
|
|
|
321
321
|
* @param options - provides further control over how the exception is shown and/or logged.
|
|
322
322
|
*/
|
|
323
323
|
handleException(exception: unknown, options?: ExceptionHandlerOptions): void;
|
|
324
|
-
showException(exception: unknown, options?: ExceptionHandlerOptions): void;
|
|
325
324
|
/**
|
|
326
325
|
* Create a new exception - See {@link Exception}.
|
|
327
326
|
*
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { HoistService } from '@xh/hoist/core';
|
|
2
|
+
/**
|
|
3
|
+
* Load and report on the client and server environment, including software versions, timezones, and
|
|
4
|
+
* and other technical information.
|
|
5
|
+
*/
|
|
2
6
|
export declare class EnvironmentService extends HoistService {
|
|
3
7
|
static instance: EnvironmentService;
|
|
4
8
|
/**
|
|
@@ -16,7 +20,9 @@ export declare class EnvironmentService extends HoistService {
|
|
|
16
20
|
* Unlike most other EnvironmentService state, this is refreshed on a timer and observable.
|
|
17
21
|
*/
|
|
18
22
|
serverInstance: string;
|
|
19
|
-
private
|
|
23
|
+
private data;
|
|
24
|
+
private pollConfig;
|
|
25
|
+
private pollTimer;
|
|
20
26
|
initAsync(): Promise<void>;
|
|
21
27
|
get(key: string): any;
|
|
22
28
|
get appEnvironment(): AppEnvironment;
|
|
@@ -25,9 +31,10 @@ export declare class EnvironmentService extends HoistService {
|
|
|
25
31
|
isMinHoistCoreVersion(version: string): boolean;
|
|
26
32
|
isMaxHoistCoreVersion(version: string): boolean;
|
|
27
33
|
constructor();
|
|
28
|
-
private
|
|
29
|
-
private
|
|
34
|
+
private startPolling;
|
|
35
|
+
private pollServerAsync;
|
|
30
36
|
private setServerInfo;
|
|
37
|
+
private get pollIntervalMs();
|
|
31
38
|
}
|
|
32
39
|
/**
|
|
33
40
|
* Available application deployment environments, as defined by Hoist Core `AppEnvironment.groovy`.
|
package/core/XH.ts
CHANGED
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
TrackService,
|
|
30
30
|
WebSocketService
|
|
31
31
|
} from '@xh/hoist/svc';
|
|
32
|
-
import {apiDeprecated} from '@xh/hoist/utils/js';
|
|
33
32
|
import {camelCase, flatten, isString, uniqueId} from 'lodash';
|
|
34
33
|
import {Router, State} from 'router5';
|
|
35
34
|
import {CancelFn} from 'router5/types/types/base';
|
|
@@ -64,7 +63,7 @@ import {installServicesAsync} from './impl/InstallServices';
|
|
|
64
63
|
import {instanceManager} from './impl/InstanceManager';
|
|
65
64
|
import {HoistModel, ModelSelector, RefreshContextModel} from './model';
|
|
66
65
|
|
|
67
|
-
export const MIN_HOIST_CORE_VERSION = '
|
|
66
|
+
export const MIN_HOIST_CORE_VERSION = '21.0';
|
|
68
67
|
|
|
69
68
|
declare const xhAppCode: string;
|
|
70
69
|
declare const xhAppName: string;
|
|
@@ -628,14 +627,6 @@ export class XHApi {
|
|
|
628
627
|
this.exceptionHandler.handleException(exception, options);
|
|
629
628
|
}
|
|
630
629
|
|
|
631
|
-
showException(exception: unknown, options?: ExceptionHandlerOptions) {
|
|
632
|
-
apiDeprecated('showException', {
|
|
633
|
-
msg: 'Use XH.exceptionHandler.showException instead',
|
|
634
|
-
v: '62'
|
|
635
|
-
});
|
|
636
|
-
this.exceptionHandler.showException(exception, options);
|
|
637
|
-
}
|
|
638
|
-
|
|
639
630
|
/**
|
|
640
631
|
* Create a new exception - See {@link Exception}.
|
|
641
632
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "67.0.0-SNAPSHOT.
|
|
3
|
+
"version": "67.0.0-SNAPSHOT.1725400144289",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": "github:xh/hoist-react",
|
|
6
6
|
"homepage": "https://xh.io",
|
|
@@ -7,15 +7,19 @@
|
|
|
7
7
|
import bpPkg from '@blueprintjs/core/package.json';
|
|
8
8
|
import {HoistService, XH} from '@xh/hoist/core';
|
|
9
9
|
import {agGridVersion} from '@xh/hoist/kit/ag-grid';
|
|
10
|
-
import {
|
|
10
|
+
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
11
11
|
import hoistPkg from '@xh/hoist/package.json';
|
|
12
12
|
import {Timer} from '@xh/hoist/utils/async';
|
|
13
13
|
import {MINUTES, SECONDS} from '@xh/hoist/utils/datetime';
|
|
14
14
|
import {checkMaxVersion, checkMinVersion, deepFreeze} from '@xh/hoist/utils/js';
|
|
15
|
-
import {defaults} from 'lodash';
|
|
15
|
+
import {defaults, isFinite} from 'lodash';
|
|
16
16
|
import mobxPkg from 'mobx/package.json';
|
|
17
17
|
import {version as reactVersion} from 'react';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Load and report on the client and server environment, including software versions, timezones, and
|
|
21
|
+
* and other technical information.
|
|
22
|
+
*/
|
|
19
23
|
export class EnvironmentService extends HoistService {
|
|
20
24
|
static instance: EnvironmentService;
|
|
21
25
|
|
|
@@ -40,47 +44,49 @@ export class EnvironmentService extends HoistService {
|
|
|
40
44
|
@observable
|
|
41
45
|
serverInstance: string;
|
|
42
46
|
|
|
43
|
-
private
|
|
47
|
+
private data = {};
|
|
48
|
+
private pollConfig: PollConfig;
|
|
49
|
+
private pollTimer: Timer;
|
|
44
50
|
|
|
45
51
|
override async initAsync() {
|
|
46
|
-
const serverEnv = await XH.fetchJson({
|
|
52
|
+
const {pollConfig, instanceName, ...serverEnv} = await XH.fetchJson({
|
|
53
|
+
url: 'xh/environment'
|
|
54
|
+
}),
|
|
47
55
|
clientTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'Unknown',
|
|
48
56
|
clientTimeZoneOffset = new Date().getTimezoneOffset() * -1 * MINUTES;
|
|
49
57
|
|
|
50
58
|
// Favor client-side data injected via Webpack build or otherwise determined locally,
|
|
51
59
|
// then apply all other env data sourced from the server.
|
|
52
|
-
this.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
this.data = deepFreeze(
|
|
61
|
+
defaults(
|
|
62
|
+
{
|
|
63
|
+
appCode: XH.appCode,
|
|
64
|
+
appName: XH.appName,
|
|
65
|
+
clientVersion: XH.appVersion,
|
|
66
|
+
clientBuild: XH.appBuild,
|
|
67
|
+
reactVersion,
|
|
68
|
+
hoistReactVersion: hoistPkg.version,
|
|
69
|
+
agGridVersion,
|
|
70
|
+
mobxVersion: mobxPkg.version,
|
|
71
|
+
blueprintCoreVersion: bpPkg.version,
|
|
72
|
+
clientTimeZone,
|
|
73
|
+
clientTimeZoneOffset
|
|
74
|
+
},
|
|
75
|
+
serverEnv
|
|
76
|
+
)
|
|
67
77
|
);
|
|
68
78
|
|
|
69
|
-
|
|
70
|
-
delete this._data['instanceName'];
|
|
71
|
-
|
|
72
|
-
deepFreeze(this._data);
|
|
73
|
-
|
|
74
|
-
this.setServerInfo(serverEnv.instanceName, serverEnv.appVersion, serverEnv.appBuild);
|
|
79
|
+
this.setServerInfo(instanceName, serverEnv.appVersion, serverEnv.appBuild);
|
|
75
80
|
|
|
81
|
+
this.pollConfig = pollConfig;
|
|
76
82
|
this.addReaction({
|
|
77
83
|
when: () => XH.appIsRunning,
|
|
78
|
-
run: this.
|
|
84
|
+
run: this.startPolling
|
|
79
85
|
});
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
get(key: string): any {
|
|
83
|
-
return this.
|
|
89
|
+
return this.data[key];
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
get appEnvironment(): AppEnvironment {
|
|
@@ -111,54 +117,64 @@ export class EnvironmentService extends HoistService {
|
|
|
111
117
|
makeObservable(this);
|
|
112
118
|
}
|
|
113
119
|
|
|
114
|
-
private
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
private startPolling() {
|
|
121
|
+
this.pollTimer = Timer.create({
|
|
122
|
+
runFn: () => this.pollServerAsync(),
|
|
123
|
+
interval: this.pollIntervalMs,
|
|
124
|
+
delay: true
|
|
119
125
|
});
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
private
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// `mode` set in `xhAppVersionCheck`. Builds are checked here to trigger refresh prompts
|
|
130
|
-
// across SNAPSHOT updates for projects with active dev/QA users.
|
|
131
|
-
if (appVersion !== this.get('appVersion') || appBuild !== this.get('appBuild')) {
|
|
132
|
-
if (mode === 'promptReload') {
|
|
133
|
-
XH.appContainerModel.showUpdateBanner(appVersion, appBuild);
|
|
134
|
-
} else if (mode === 'forceReload') {
|
|
135
|
-
XH.suspendApp({
|
|
136
|
-
reason: 'APP_UPDATE',
|
|
137
|
-
message: `A new version of ${XH.clientAppName} is now available (${appVersion}) and requires an immediate update.`
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Note that the case of version mismatches across the client and server we do *not* show
|
|
143
|
-
// the update bar to the user - that would indicate a deployment issue that a client reload
|
|
144
|
-
// is unlikely to resolve, leaving the user in a frustrating state where they are endlessly
|
|
145
|
-
// prompted to refresh.
|
|
146
|
-
const clientVersion = this.get('clientVersion');
|
|
147
|
-
if (appVersion !== clientVersion) {
|
|
148
|
-
this.logWarn(
|
|
149
|
-
`Version mismatch detected between client and server - ${clientVersion} vs ${appVersion}`
|
|
150
|
-
);
|
|
128
|
+
private async pollServerAsync() {
|
|
129
|
+
let data;
|
|
130
|
+
try {
|
|
131
|
+
data = await XH.fetchJson({url: 'xh/environmentPoll'});
|
|
132
|
+
} catch (e) {
|
|
133
|
+
this.logError('Error polling server environment', e);
|
|
134
|
+
return;
|
|
151
135
|
}
|
|
152
136
|
|
|
137
|
+
// Update config/interval, and server info
|
|
138
|
+
const {pollConfig, instanceName, appVersion, appBuild} = data;
|
|
139
|
+
this.pollConfig = pollConfig;
|
|
140
|
+
this.pollTimer.setInterval(this.pollIntervalMs);
|
|
153
141
|
this.setServerInfo(instanceName, appVersion, appBuild);
|
|
154
|
-
|
|
142
|
+
|
|
143
|
+
// Handle version change
|
|
144
|
+
if (appVersion != XH.getEnv('appVersion') || appBuild != XH.getEnv('appBuild')) {
|
|
145
|
+
// force the user to refresh or prompt the user to refresh via the banner according to config
|
|
146
|
+
// build checked to trigger refresh across SNAPSHOT updates in lower environments
|
|
147
|
+
const {onVersionChange} = pollConfig;
|
|
148
|
+
switch (onVersionChange) {
|
|
149
|
+
case 'promptReload':
|
|
150
|
+
XH.appContainerModel.showUpdateBanner(appVersion, appBuild);
|
|
151
|
+
return;
|
|
152
|
+
case 'forceReload':
|
|
153
|
+
XH.suspendApp({
|
|
154
|
+
reason: 'APP_UPDATE',
|
|
155
|
+
message: `A new version of ${XH.clientAppName} is now available (${appVersion}) and requires an immediate update.`
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
default:
|
|
159
|
+
this.logWarn(
|
|
160
|
+
`New version ${appVersion} reported by server, onVersionChange is ${onVersionChange} - ignoring.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
155
165
|
|
|
156
166
|
@action
|
|
157
|
-
private setServerInfo(serverInstance, serverVersion, serverBuild) {
|
|
167
|
+
private setServerInfo(serverInstance: string, serverVersion: string, serverBuild: string) {
|
|
158
168
|
this.serverInstance = serverInstance;
|
|
159
169
|
this.serverVersion = serverVersion;
|
|
160
170
|
this.serverBuild = serverBuild;
|
|
161
171
|
}
|
|
172
|
+
|
|
173
|
+
private get pollIntervalMs(): number {
|
|
174
|
+
// Throttle to 5secs, disable if set to 0 or less.
|
|
175
|
+
const {interval} = this.pollConfig;
|
|
176
|
+
return isFinite(interval) && interval > 0 ? Math.max(interval, 5) * SECONDS : -1;
|
|
177
|
+
}
|
|
162
178
|
}
|
|
163
179
|
|
|
164
180
|
/**
|
|
@@ -175,3 +191,8 @@ export type AppEnvironment =
|
|
|
175
191
|
| 'Test'
|
|
176
192
|
| 'UAT'
|
|
177
193
|
| 'BCP';
|
|
194
|
+
|
|
195
|
+
interface PollConfig {
|
|
196
|
+
interval: number;
|
|
197
|
+
onVersionChange: 'forceReload' | 'promptReload' | 'silent';
|
|
198
|
+
}
|