@xh/hoist 79.0.0-SNAPSHOT.1766259546947 → 79.0.0-SNAPSHOT.1766275267656
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 +13 -6
- package/appcontainer/AppContainerModel.ts +1 -1
- package/appcontainer/AppStateModel.ts +5 -3
- package/build/types/appcontainer/AppStateModel.d.ts +1 -1
- package/build/types/core/types/Types.d.ts +2 -0
- package/build/types/utils/datetime/LocalDate.d.ts +13 -17
- package/core/types/Types.ts +13 -0
- package/package.json +1 -1
- package/security/msal/MsalClient.ts +10 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/datetime/LocalDate.ts +28 -26
package/CHANGELOG.md
CHANGED
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
Some apps may need to update their imports.
|
|
25
25
|
* `TabContainerConfig.switcher` has been repurposed to accept a `TabSwitcherConfig`. To pass
|
|
26
26
|
`TabSwitcherProps` via a parent `TabContainer`, use `TabContainerProps.switcher`.
|
|
27
|
+
* Tightened the typing of `LocalDate` adjustment methods with new `LocalDateUnit` type. Some less
|
|
28
|
+
common or ambiguous units (e.g. `date` or `d`) are no longer supported. Also typed the adjustment
|
|
29
|
+
`value` args to `number` where applicable.
|
|
27
30
|
|
|
28
31
|
### 🐞 Bug Fixes
|
|
29
32
|
|
|
@@ -40,6 +43,8 @@
|
|
|
40
43
|
* `GroupingChooserProps.popoverTitle` - use `editorTitle`
|
|
41
44
|
* `RelativeTimestampProps.options` - provide directly as top-level props
|
|
42
45
|
|
|
46
|
+
* Improved the efficiency and logging of MsalClient.
|
|
47
|
+
*
|
|
43
48
|
## 78.1.4 - 2025-12-05
|
|
44
49
|
|
|
45
50
|
### 🐞 Bug Fixes
|
|
@@ -50,7 +55,7 @@
|
|
|
50
55
|
|
|
51
56
|
### 🐞 Bug Fixes
|
|
52
57
|
|
|
53
|
-
* Fix to Highchart timezone handling regression from version 77.
|
|
58
|
+
* Fix to Highchart timezone handling regression from version 77. Applications should note that
|
|
54
59
|
Highcharts has deprecated the `time.useUTC` option and its functioning seem suspect. Apps
|
|
55
60
|
should set `time.timezone` instead. See https://api.highcharts.com/highcharts/time.useUTC.
|
|
56
61
|
|
|
@@ -61,14 +66,15 @@
|
|
|
61
66
|
## 78.1.0 - 2025-12-02
|
|
62
67
|
|
|
63
68
|
### ⚙️ Technical
|
|
69
|
+
|
|
64
70
|
* New property `MsalClientConfig.enableSsoSilent` to govern use of MSAL SSO api.
|
|
65
71
|
|
|
66
72
|
* Existing property `MsalClientConfig.enableTelemetry` now defaults to `true`.
|
|
67
73
|
|
|
68
|
-
* Improved use of MSAL client API, to maximize effectiveness of SSO.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
* Improved use of MSAL client API, to maximize effectiveness of SSO. Improved documentation
|
|
75
|
+
and logging. Iframe attempts will now time out by default after 3 seconds vs. 10 seconds.
|
|
76
|
+
This can be further modified by apps via the option
|
|
77
|
+
`MsalClientConfig.msalClientOptions.system.iFrameHashTimeout`
|
|
72
78
|
|
|
73
79
|
### 📚 Libraries
|
|
74
80
|
|
|
@@ -110,7 +116,8 @@
|
|
|
110
116
|
|
|
111
117
|
### 💥 Breaking Changes (upgrade difficulty: 🟢 LOW)
|
|
112
118
|
|
|
113
|
-
* Apps that use and provide the `highcharts` library should be sure to update the version to
|
|
119
|
+
* Apps that use and provide the `highcharts` library should be sure to update the version to
|
|
120
|
+
v12.4.0.
|
|
114
121
|
Refer to `Bootstrap.js` in Toolbox for required import changes.
|
|
115
122
|
* Visit https://www.highcharts.com/blog/changelog/ for specific changes.
|
|
116
123
|
|
|
@@ -197,7 +197,7 @@ export class AppContainerModel extends HoistModel {
|
|
|
197
197
|
|
|
198
198
|
// Check auth, locking out, or showing login if possible
|
|
199
199
|
this.setAppState('AUTHENTICATING');
|
|
200
|
-
XH.authModel = createSingleton(
|
|
200
|
+
XH.authModel = createSingleton(appSpec.authModelClass);
|
|
201
201
|
const isAuthenticated = await XH.authModel.completeAuthAsync();
|
|
202
202
|
if (!isAuthenticated) {
|
|
203
203
|
throwIf(
|
|
@@ -28,8 +28,8 @@ export class AppStateModel extends HoistModel {
|
|
|
28
28
|
* Read from timestamp set on window within index.html.
|
|
29
29
|
*/
|
|
30
30
|
readonly loadStarted: number = window['_xhLoadTimestamp'];
|
|
31
|
+
readonly timings: Record<AppState, number> = {} as Record<AppState, number>;
|
|
31
32
|
|
|
32
|
-
private timings: Record<AppState, number> = {} as Record<AppState, number>;
|
|
33
33
|
private lastStateChangeTime: number = this.loadStarted;
|
|
34
34
|
|
|
35
35
|
constructor() {
|
|
@@ -85,7 +85,7 @@ export class AppStateModel extends HoistModel {
|
|
|
85
85
|
const {timings, loadStarted} = this;
|
|
86
86
|
this.addReaction({
|
|
87
87
|
when: () => this.state === 'RUNNING',
|
|
88
|
-
run: () =>
|
|
88
|
+
run: () => {
|
|
89
89
|
XH.track({
|
|
90
90
|
category: 'App',
|
|
91
91
|
message: `Loaded ${XH.clientAppCode}`,
|
|
@@ -98,7 +98,9 @@ export class AppStateModel extends HoistModel {
|
|
|
98
98
|
screen: this.getScreenData()
|
|
99
99
|
},
|
|
100
100
|
omit: !XH.appSpec.trackAppLoad
|
|
101
|
-
})
|
|
101
|
+
});
|
|
102
|
+
this.logDebug('Load timings', this.timings);
|
|
103
|
+
}
|
|
102
104
|
});
|
|
103
105
|
}
|
|
104
106
|
|
|
@@ -15,7 +15,7 @@ export declare class AppStateModel extends HoistModel {
|
|
|
15
15
|
* Read from timestamp set on window within index.html.
|
|
16
16
|
*/
|
|
17
17
|
readonly loadStarted: number;
|
|
18
|
-
|
|
18
|
+
readonly timings: Record<AppState, number>;
|
|
19
19
|
private lastStateChangeTime;
|
|
20
20
|
constructor();
|
|
21
21
|
setAppState(nextState: AppState): void;
|
|
@@ -42,6 +42,8 @@ export type DebounceSpec = number | (DebounceSettings & {
|
|
|
42
42
|
*/
|
|
43
43
|
export type Content = ReactElement | FunctionComponent | Component | ElementFactory | (() => ReactElement);
|
|
44
44
|
export type DateLike = Date | LocalDate | MomentInput;
|
|
45
|
+
/** Valid units for the {@link LocalDate} adjustment methods. */
|
|
46
|
+
export type LocalDateUnit = 'year' | 'years' | 'quarter' | 'quarters' | 'month' | 'months' | 'week' | 'weeks' | 'day' | 'days';
|
|
45
47
|
export type PageState =
|
|
46
48
|
/**
|
|
47
49
|
* Window/tab is visible and focused.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { LocalDateUnit } from '@xh/hoist/core';
|
|
2
|
+
import { Moment, MomentInput } from 'moment';
|
|
2
3
|
/**
|
|
3
4
|
* A Date representation that does not contain time information. Useful for business day or calendar
|
|
4
5
|
* day data where time and time zone should be explicitly ignored. Client-side equivalent of the
|
|
@@ -8,15 +9,13 @@ import moment, { Moment, MomentInput } from 'moment';
|
|
|
8
9
|
* For efficiency and to enable strict equality checks, instances of this class are memoized:
|
|
9
10
|
* only a single version of the object will be created and returned for each calendar day,
|
|
10
11
|
* as long as the caller uses one of the *public factory methods*, which they always should!
|
|
11
|
-
*
|
|
12
|
-
* Unit accepted by manipulation methods are ['year', 'quarter', 'month', 'week', 'day', 'date'].
|
|
13
12
|
*/
|
|
14
13
|
export declare class LocalDate {
|
|
14
|
+
static readonly VALID_UNITS: Set<LocalDateUnit>;
|
|
15
15
|
private static _instances;
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
private
|
|
19
|
-
private _date;
|
|
16
|
+
private readonly _isoString;
|
|
17
|
+
private readonly _moment;
|
|
18
|
+
private readonly _date;
|
|
20
19
|
/**
|
|
21
20
|
* Get an instance of this class.
|
|
22
21
|
* This is the standard way to get an instance of this object from serialized server-side data.
|
|
@@ -64,11 +63,11 @@ export declare class LocalDate {
|
|
|
64
63
|
toJSON(): string;
|
|
65
64
|
valueOf(): string;
|
|
66
65
|
get isLocalDate(): boolean;
|
|
67
|
-
add(value:
|
|
68
|
-
subtract(value:
|
|
69
|
-
addWeekdays(value:
|
|
70
|
-
subtractWeekdays(value:
|
|
71
|
-
startOf(unit:
|
|
66
|
+
add(value: number, unit?: LocalDateUnit): LocalDate;
|
|
67
|
+
subtract(value: number, unit?: LocalDateUnit): LocalDate;
|
|
68
|
+
addWeekdays(value: number): LocalDate;
|
|
69
|
+
subtractWeekdays(value: number): LocalDate;
|
|
70
|
+
startOf(unit: LocalDateUnit): LocalDate;
|
|
72
71
|
startOfMonth(): LocalDate;
|
|
73
72
|
startOfQuarter(): LocalDate;
|
|
74
73
|
startOfYear(): LocalDate;
|
|
@@ -84,13 +83,10 @@ export declare class LocalDate {
|
|
|
84
83
|
currentOrNextWeekday(): LocalDate;
|
|
85
84
|
/** The same date if already a weekday, or the previous weekday. */
|
|
86
85
|
currentOrPreviousWeekday(): LocalDate;
|
|
87
|
-
diff(other: LocalDate, unit?:
|
|
86
|
+
diff(other: LocalDate, unit?: LocalDateUnit): number;
|
|
88
87
|
/** @internal - use one of the static factory methods instead. */
|
|
89
88
|
private constructor();
|
|
90
89
|
private ensureUnitValid;
|
|
91
90
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Is the input value a local Date?
|
|
94
|
-
* Convenience alias for LocalDate.isLocalDate()
|
|
95
|
-
*/
|
|
91
|
+
/** @returns true if the input value is a `LocalDate` instance. */
|
|
96
92
|
export declare function isLocalDate(val: any): val is LocalDate;
|
package/core/types/Types.ts
CHANGED
|
@@ -63,6 +63,19 @@ export type Content =
|
|
|
63
63
|
|
|
64
64
|
export type DateLike = Date | LocalDate | MomentInput;
|
|
65
65
|
|
|
66
|
+
/** Valid units for the {@link LocalDate} adjustment methods. */
|
|
67
|
+
export type LocalDateUnit =
|
|
68
|
+
| 'year'
|
|
69
|
+
| 'years'
|
|
70
|
+
| 'quarter'
|
|
71
|
+
| 'quarters'
|
|
72
|
+
| 'month'
|
|
73
|
+
| 'months'
|
|
74
|
+
| 'week'
|
|
75
|
+
| 'weeks'
|
|
76
|
+
| 'day'
|
|
77
|
+
| 'days';
|
|
78
|
+
|
|
66
79
|
export type PageState =
|
|
67
80
|
/**
|
|
68
81
|
* Window/tab is visible and focused.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "79.0.0-SNAPSHOT.
|
|
3
|
+
"version": "79.0.0-SNAPSHOT.1766275267656",
|
|
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",
|
|
@@ -170,17 +170,19 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
170
170
|
const account =
|
|
171
171
|
accounts.length == 1
|
|
172
172
|
? accounts[0]
|
|
173
|
-
: accounts.find(a =>
|
|
173
|
+
: accounts.find(a => a.username == this.getSelectedUsername());
|
|
174
|
+
let trySsoSilent = enableSsoSilent;
|
|
174
175
|
if (account) {
|
|
175
176
|
this.setAccount(account);
|
|
176
177
|
try {
|
|
177
|
-
this.initialTokenLoad = true;
|
|
178
178
|
this.logDebug('Attempting silent token load.');
|
|
179
|
+
this.initialTokenLoad = true;
|
|
179
180
|
const ret = await this.fetchAllTokensAsync({eagerOnly: true});
|
|
180
181
|
this.noteAuthComplete('acquireSilent');
|
|
181
182
|
return ret;
|
|
182
183
|
} catch (e) {
|
|
183
|
-
|
|
184
|
+
if (e instanceof InteractionRequiredAuthError) trySsoSilent = false;
|
|
185
|
+
this.logDebug('AcquireSilent failed', e.message ?? e);
|
|
184
186
|
} finally {
|
|
185
187
|
this.initialTokenLoad = false;
|
|
186
188
|
}
|
|
@@ -189,15 +191,18 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
189
191
|
// 2) Try `ssoSilent` API to potentially reuse logged-in user on other apps
|
|
190
192
|
// in same domain without interaction. This should never trigger popup/redirect, and will
|
|
191
193
|
// use an iFrame (3rd party cookies required). Must fail gently.
|
|
192
|
-
if (
|
|
194
|
+
if (trySsoSilent) {
|
|
193
195
|
try {
|
|
194
196
|
this.logDebug('Attempting SSO');
|
|
195
197
|
await this.loginSsoAsync();
|
|
198
|
+
this.initialTokenLoad = true;
|
|
196
199
|
const ret = await this.fetchAllTokensAsync({eagerOnly: true});
|
|
197
200
|
this.noteAuthComplete('ssoSilent');
|
|
198
201
|
return ret;
|
|
199
202
|
} catch (e) {
|
|
200
203
|
this.logDebug('SSO failed', e.message ?? e);
|
|
204
|
+
} finally {
|
|
205
|
+
this.initialTokenLoad = false;
|
|
201
206
|
}
|
|
202
207
|
}
|
|
203
208
|
|
|
@@ -453,7 +458,7 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
453
458
|
|
|
454
459
|
private noteAuthComplete(authMethod: AuthMethod) {
|
|
455
460
|
if (this.telemetry) this.telemetry.authMethod = authMethod;
|
|
456
|
-
this.logInfo(`Authenticated user ${this.account.username} via ${authMethod}`);
|
|
461
|
+
this.logInfo(`Authenticated user '${this.account.username}' via ${authMethod}`);
|
|
457
462
|
}
|
|
458
463
|
|
|
459
464
|
private authRequestCore(): AuthRequestCore {
|