@xh/hoist 64.0.0 → 64.0.3

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 CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 64.0.3 - 2024-05-31
4
+
5
+ ### 🐞 Bug Fixes
6
+
7
+ * Restore disabling of Blueprint animations on popovers and tooltips (corrects regression in v63.0.0)
8
+
9
+ ### ⚙️ Technical
10
+
11
+ * Adjustments to API of (beta) `BaseOAuthClient`, `MsaClient`, and `AuthZeroClient`.
12
+
13
+ ## 64.0.2 - 2024-05-23
14
+
15
+ ### ⚙️ Technical
16
+
17
+ * Adjustments to API of (beta) `BaseOAuthClient`.
18
+ * `FetchService.addDefaultHeaders()` now supports async functions.
19
+
20
+ ## 64.0.1 - 2024-05-19
21
+
22
+ ### ⚙️ Technical
23
+
24
+ * Adjustments to loading of ID Tokens and API of `BaseOAuthClient`. (Note that
25
+ this package remains in Beta for v64 and is subject to change.)
26
+
3
27
  ## 64.0.0 - 2024-05-17
4
28
 
5
29
  ### 💥 Breaking Changes (upgrade difficulty: 🟠 MEDIUM - major Hoist Core = AG Grid updates)
@@ -13,6 +13,7 @@ import {relativeTimestamp} from '@xh/hoist/cmp/relativetimestamp';
13
13
  import {creates, hoistCmp, XH} from '@xh/hoist/core';
14
14
  import {button} from '@xh/hoist/desktop/cmp/button';
15
15
  import {errorMessage} from '@xh/hoist/desktop/cmp/error';
16
+ import {switchInput} from '@xh/hoist/desktop/cmp/input';
16
17
  import {panel} from '@xh/hoist/desktop/cmp/panel';
17
18
  import {toolbar, toolbarSep} from '@xh/hoist/desktop/cmp/toolbar';
18
19
  import {Icon} from '@xh/hoist/icon';
@@ -75,6 +76,11 @@ const tbar = hoistCmp.factory<MonitorTabModel>(({model}) => {
75
76
  icon: Icon.gear(),
76
77
  onClick: () => (model.showEditorDialog = true)
77
78
  }),
79
+ '-',
80
+ switchInput({
81
+ label: 'Show inactive',
82
+ bind: 'showInactive'
83
+ }),
78
84
  hbox({
79
85
  className: getClassName(!failed),
80
86
  items: [
@@ -5,7 +5,7 @@
5
5
  * Copyright © 2024 Extremely Heavy Industries Inc.
6
6
  */
7
7
  import {MonitorResults, MonitorStatus} from '@xh/hoist/admin/tabs/monitor/Types';
8
- import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
8
+ import {HoistModel, LoadSpec, managed, persist, XH} from '@xh/hoist/core';
9
9
  import {Icon} from '@xh/hoist/icon';
10
10
  import {action, bindable, computed, makeObservable, observable} from '@xh/hoist/mobx';
11
11
  import {Timer} from '@xh/hoist/utils/async';
@@ -14,10 +14,13 @@ import {pluralize} from '@xh/hoist/utils/js';
14
14
  import {filter, isEqual, minBy, sortBy} from 'lodash';
15
15
 
16
16
  export class MonitorTabModel extends HoistModel {
17
+ override persistWith = {localStorageKey: 'xhAdminClientMonitorState'};
18
+
17
19
  @observable.ref results: MonitorResults[] = [];
18
20
  @observable lastRun: number = null;
19
21
  @managed timer: Timer = null;
20
22
 
23
+ @bindable @persist showInactive = false;
21
24
  @bindable showEditorDialog = false;
22
25
 
23
26
  @computed
@@ -55,11 +58,17 @@ export class MonitorTabModel extends HoistModel {
55
58
  constructor() {
56
59
  super();
57
60
  makeObservable(this);
61
+
58
62
  this.timer = Timer.create({
59
63
  runFn: () => this.autoRefreshAsync(),
60
64
  interval: 5 * SECONDS,
61
65
  delay: true
62
66
  });
67
+
68
+ this.addReaction({
69
+ track: () => this.showInactive,
70
+ run: () => this.refreshAsync()
71
+ });
63
72
  }
64
73
 
65
74
  override async doLoadAsync(loadSpec: LoadSpec) {
@@ -88,6 +97,10 @@ export class MonitorTabModel extends HoistModel {
88
97
  //-------------------
89
98
  @action
90
99
  private installResults(results: MonitorResults[]) {
100
+ if (!this.showInactive) {
101
+ results = results.filter(it => it.status !== 'INACTIVE');
102
+ }
103
+
91
104
  const prevCounts = this.countsByStatus;
92
105
  this.results = sortBy(results, 'sortOrder');
93
106
  this.lastRun = minBy(results, 'dateComputed')?.dateComputed ?? null;
@@ -161,7 +161,7 @@ export class AppContainerModel extends HoistModel {
161
161
  }
162
162
 
163
163
  try {
164
- await installServicesAsync([FetchService, LocalStorageService]);
164
+ await installServicesAsync([FetchService]);
165
165
 
166
166
  // consult (optional) pre-auth init for app
167
167
  const modelClass: any = this.appSpec.modelClass;
@@ -205,7 +205,7 @@ export class AppContainerModel extends HoistModel {
205
205
 
206
206
  // Complete initialization process
207
207
  this.setAppState('INITIALIZING');
208
- await installServicesAsync([ConfigService]);
208
+ await installServicesAsync([ConfigService, LocalStorageService]);
209
209
  await installServicesAsync(TrackService);
210
210
  await installServicesAsync([EnvironmentService, PrefService, JsonBlobService]);
211
211
 
@@ -2,9 +2,13 @@ import { MonitorResults, MonitorStatus } from '@xh/hoist/admin/tabs/monitor/Type
2
2
  import { HoistModel, LoadSpec } from '@xh/hoist/core';
3
3
  import { Timer } from '@xh/hoist/utils/async';
4
4
  export declare class MonitorTabModel extends HoistModel {
5
+ persistWith: {
6
+ localStorageKey: string;
7
+ };
5
8
  results: MonitorResults[];
6
9
  lastRun: number;
7
10
  timer: Timer;
11
+ showInactive: boolean;
8
12
  showEditorDialog: boolean;
9
13
  get passed(): number;
10
14
  get warned(): number;
@@ -15,6 +15,7 @@ export type HAlign = 'left' | 'right' | 'center';
15
15
  export type VAlign = 'top' | 'bottom' | 'center';
16
16
  /** Convenience type for common pattern of accepting a single T, or an array of Ts. */
17
17
  export type Some<T> = T | T[];
18
+ export type NonEmptyArray<T> = [T, ...T[]];
18
19
  export type Thunkable<T> = T | (() => T);
19
20
  export type Awaitable<T> = Promise<T> | T;
20
21
  /** Convenience type for a "plain", string-keyed object holding any kind of values. */
@@ -1,6 +1,7 @@
1
- import { BannerSpec, HoistBase, PlainObject } from '@xh/hoist/core';
2
- import { TokenInfo } from '@xh/hoist/security/TokenInfo';
3
- export interface BaseOAuthClientConfig {
1
+ import { HoistBase } from '@xh/hoist/core';
2
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
3
+ export type LoginMethod = 'REDIRECT' | 'POPUP';
4
+ export interface BaseOAuthClientConfig<S> {
4
5
  /** Client ID (GUID) of your app registered with your Oauth provider. */
5
6
  clientId: string;
6
7
  /**
@@ -15,20 +16,31 @@ export interface BaseOAuthClientConfig {
15
16
  */
16
17
  postLogoutRedirectUrl?: 'APP_BASE_URL' | string;
17
18
  /** The method used for logging in on desktop. Default is 'REDIRECT'. */
18
- loginMethodDesktop?: 'REDIRECT' | 'POPUP';
19
+ loginMethodDesktop?: LoginMethod;
19
20
  /** The method used for logging in on mobile. Default is 'REDIRECT'. */
20
- loginMethodMobile?: 'REDIRECT' | 'POPUP';
21
+ loginMethodMobile?: LoginMethod;
21
22
  /**
22
- * When the remaining token lifetime is below this threshold, try to refresh the token.
23
- * Should be substantially shorter than the lifetime of the tokens, but long enough so that
24
- * there is ample time to complete the refresh, including retries. Default is 10 minutes.
23
+ * Governs an optional refresh timer that will work to keep the tokens fresh.
24
+ *
25
+ * A typical refresh will use the underlying provider cache, and should not result in
26
+ * network activity. However, if any token lifetime falls below`autoRefreshSkipCacheSecs`,
27
+ * this client will force a call to the underlying provider to get the token.
28
+ *
29
+ * In order to allow aging tokens to be replaced in a timely manner, this value should be
30
+ * significantly shorter than both the minimum token lifetime that will be
31
+ * returned by the underlying API and `autoRefreshSkipCacheSecs`.
32
+ *
33
+ * Default is -1, disabling this behavior.
25
34
  */
26
- tokenRefreshThresholdMins?: number;
35
+ autoRefreshSecs?: number;
27
36
  /**
28
- * Governs how frequently we attempt to refresh aging tokens. Should be short enough to allow
29
- * multiple attempts during `tokenRefreshThresholdMins`. Default is 30 seconds.
37
+ * During auto-refresh, if the remaining lifetime for any token is below this threshold,
38
+ * force the provider to skip the local cache and go directly to the underlying provider for
39
+ * new tokens and refresh tokens.
40
+ *
41
+ * Default is -1, disabling this behavior.
30
42
  */
31
- tokenRefreshCheckSecs?: number;
43
+ autoRefreshSkipCacheSecs?: number;
32
44
  /**
33
45
  * Scopes to request - if any - beyond the core `['openid', 'email']` scopes, which
34
46
  * this client will always request.
@@ -44,17 +56,12 @@ export interface BaseOAuthClientConfig {
44
56
  *
45
57
  * Use this map to gain targeted access tokens for different back-end resources.
46
58
  */
47
- accessTokens?: Record<string, PlainObject>;
48
- /**
49
- * True to display a warning banner to the user if tokens expire. May be specified as a boolean
50
- * or a partial banner spec. Defaults to false.
51
- */
52
- expiryWarning?: boolean | Partial<BannerSpec>;
59
+ accessTokens?: Record<string, S>;
53
60
  }
54
61
  /**
55
62
  * Implementations of this class coordinate OAuth-based login and token provision. Apps can use a
56
- * suitable concrete implementation to power a client-side OauthService - see Toolbox for an
57
- * example using `Auth0Client`.
63
+ * suitable concrete implementation to power a client-side OauthService. See `MsalClient` and
64
+ * `AuthZeroClient`
58
65
  *
59
66
  * Initialize such a service and this client within the `preAuthInitAsync()` lifecycle method of
60
67
  * `AppModel` to use the tokens it acquires to authenticate with the Hoist server. (Note this
@@ -62,42 +69,62 @@ export interface BaseOAuthClientConfig {
62
69
  * actually resolve the user.) On init, the client implementation will initiate a pop-up or redirect
63
70
  * flow as necessary.
64
71
  */
65
- export declare abstract class BaseOAuthClient<T extends BaseOAuthClientConfig> extends HoistBase {
72
+ export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>, S> extends HoistBase {
66
73
  /** Config loaded from UI server + init method. */
67
- protected config: T;
68
- /** Scopes */
74
+ protected config: C;
75
+ /** Id Scopes */
69
76
  protected idScopes: string[];
70
- protected _idToken: TokenInfo;
71
- protected _accessTokens: Record<string, TokenInfo>;
77
+ /** Specification for Access Tokens **/
78
+ protected accessSpecs: Record<string, S>;
72
79
  private timer;
73
- private expiryWarningDisplayed;
74
80
  private lastRefreshAttempt;
75
81
  private TIMER_INTERVAL;
76
- /**
77
- * ID token in JWT format. Observable.
78
- */
79
- get idToken(): string;
80
- /**
81
- * Get a configured Access token in JWT format. Observable.
82
- */
83
- getAccessToken(key: string): string;
84
- constructor(config: T);
82
+ constructor(config: C);
85
83
  /**
86
84
  * Main entry point for this object.
87
85
  */
88
86
  initAsync(): Promise<void>;
87
+ /**
88
+ * Request an interactive login with the underlying OAuth provider.
89
+ */
90
+ loginAsync(method?: LoginMethod): Promise<void>;
89
91
  /**
90
92
  * Request a full logout from the underlying OAuth provider.
91
93
  */
92
94
  logoutAsync(): Promise<void>;
93
- protected abstract doInitAsync(): Promise<void>;
95
+ /**
96
+ * Get an ID token.
97
+ */
98
+ getIdTokenAsync(): Promise<Token>;
99
+ /**
100
+ * Get a Access token.
101
+ */
102
+ getAccessTokenAsync(key: string): Promise<Token>;
103
+ /**
104
+ * Get all available tokens.
105
+ */
106
+ getAllTokensAsync(): Promise<TokenMap>;
107
+ /**
108
+ * The last authenticated OAuth username.
109
+ *
110
+ * Provided to facilitate more efficient re-login via SSO or otherwise. Cleared on logout.
111
+ * Note: not necessarily a currently authenticated user, and not necessarily the Hoist username.
112
+ */
113
+ getSelectedUsername(): string;
114
+ /**
115
+ * Set the last authenticated OAuth username.
116
+ * See `getSelectedUsername()`.
117
+ */
118
+ setSelectedUsername(username: string): void;
119
+ protected abstract doInitAsync(): Promise<TokenMap>;
120
+ protected abstract doLoginPopupAsync(): Promise<void>;
121
+ protected abstract doLoginRedirectAsync(): Promise<void>;
122
+ protected abstract fetchIdTokenAsync(useCache: boolean): Promise<Token>;
123
+ protected abstract fetchAccessTokenAsync(spec: S, useCache: boolean): Promise<Token>;
94
124
  protected abstract doLogoutAsync(): Promise<void>;
95
- protected abstract getIdTokenAsync(useCache: boolean): Promise<string>;
96
- protected abstract getAccessTokenAsync(spec: PlainObject, useCache: boolean): Promise<string>;
97
125
  protected get redirectUrl(): string;
98
126
  protected get postLogoutRedirectUrl(): string;
99
- protected get loginMethod(): 'REDIRECT' | 'POPUP';
100
- protected get usesRedirect(): boolean;
127
+ protected get loginMethod(): LoginMethod;
101
128
  protected get baseUrl(): string;
102
129
  protected popupBlockerErrorMessage: String;
103
130
  protected defaultErrorMsg: String;
@@ -114,13 +141,10 @@ export declare abstract class BaseOAuthClient<T extends BaseOAuthClientConfig> e
114
141
  * @param key - key for re-accessing this state, as round-tripped with redirect.
115
142
  */
116
143
  protected restoreRedirectState(key: string): void;
117
- /**
118
- * Load tokens from provider.
119
- *
120
- * @param useCache - true (default) to use local cache if available, or false to force a
121
- * network request to fetch a fresh token.
122
- */
123
- protected loadTokensAsync(useCache?: boolean): Promise<void>;
144
+ protected fetchAllTokensAsync(useCache?: boolean): Promise<TokenMap>;
145
+ protected getLocalStorage(key: string, defaultValue?: any): any;
146
+ protected setLocalStorage(key: string, value: any): void;
147
+ private fetchIdTokenSafeAsync;
124
148
  private onTimerAsync;
125
- private updateWarning;
149
+ private logTokensDebug;
126
150
  }
@@ -0,0 +1,12 @@
1
+ import { PlainObject } from '@xh/hoist/core';
2
+ export type TokenMap = Record<string, Token>;
3
+ export declare class Token {
4
+ readonly value: string;
5
+ readonly decoded: PlainObject;
6
+ readonly expiry: number;
7
+ constructor(value: string);
8
+ expiresWithin(interval: number): boolean;
9
+ get formattedExpiry(): string;
10
+ get forLog(): PlainObject;
11
+ equals(other: Token): boolean;
12
+ }
@@ -1,9 +1,18 @@
1
- import { PlainObject } from '@xh/hoist/core';
1
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
2
2
  import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
3
- export interface AuthZeroClientConfig extends BaseOAuthClientConfig {
3
+ export interface AuthZeroClientConfig extends BaseOAuthClientConfig<AuthZeroTokenSpec> {
4
4
  /** Domain of your app registered with Auth0 */
5
5
  domain: string;
6
- /** Audience (i.e. API) identifier for AccessToken. Must be registered with Auth0*/
6
+ }
7
+ export interface AuthZeroTokenSpec {
8
+ /** Scopes for the desired access token.*/
9
+ scopes: string[];
10
+ /**
11
+ * Audience (i.e. API) identifier for AccessToken. Must be registered with Auth0.
12
+ *
13
+ * Note that this is required to ensure that issued token is a JWT and not
14
+ * an opaque string.
15
+ */
7
16
  audience: string;
8
17
  }
9
18
  /**
@@ -11,15 +20,20 @@ export interface AuthZeroClientConfig extends BaseOAuthClientConfig {
11
20
  * via Google, GitHub, Microsoft, and various other OAuth providers *or* via a username/password
12
21
  * combo stored and managed within Auth0's own database. Supported options will depend on the
13
22
  * configuration of your Auth0 app.
23
+ *
24
+ * Note: If developing on localhost and using Access Tokens will need to configure your browser to
25
+ * allow third-party cookies.
14
26
  */
15
- export declare class AuthZeroClient extends BaseOAuthClient<AuthZeroClientConfig> {
27
+ export declare class AuthZeroClient extends BaseOAuthClient<AuthZeroClientConfig, AuthZeroTokenSpec> {
16
28
  private client;
17
- doInitAsync(): Promise<void>;
18
- getIdTokenAsync(useCache?: boolean): Promise<string>;
19
- getAccessTokenAsync(spec: PlainObject, useCache?: boolean): Promise<string>;
20
- doLogoutAsync(): Promise<void>;
29
+ protected doInitAsync(): Promise<TokenMap>;
30
+ protected doLoginRedirectAsync(): Promise<void>;
31
+ protected doLoginPopupAsync(): Promise<void>;
32
+ protected fetchIdTokenAsync(useCache?: boolean): Promise<Token>;
33
+ protected fetchAccessTokenAsync(spec: AuthZeroTokenSpec, useCache?: boolean): Promise<Token>;
34
+ protected doLogoutAsync(): Promise<void>;
21
35
  private createClient;
22
- private completeViaRedirectAsync;
23
- private completeViaPopupAsync;
24
36
  private get loginScope();
37
+ private returningFromRedirect;
38
+ private noteUserAuthenticatedAsync;
25
39
  }
@@ -0,0 +1 @@
1
+ export * from './AuthZeroClient';
@@ -1,7 +1,7 @@
1
- import { LogLevel } from '@azure/msal-common';
2
- import { PlainObject } from '@xh/hoist/core';
1
+ import { LogLevel } from '@azure/msal-browser';
2
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
3
3
  import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
4
- export interface MsalClientConfig extends BaseOAuthClientConfig {
4
+ export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
5
5
  /** Tenant ID (GUID) of your organization */
6
6
  tenantId: string;
7
7
  /**
@@ -10,23 +10,80 @@ export interface MsalClientConfig extends BaseOAuthClientConfig {
10
10
  * MSAL Browser Lib defaults authority to "https://login.microsoftonline.com/common"
11
11
  */
12
12
  authority?: string;
13
- /** The log level of MSAL. Default is LogLevel.Info (2). */
13
+ /**
14
+ * A hint about the tenant or domain that the user should use to sign in.
15
+ * The value of the domain hint is a registered domain for the tenant.
16
+ */
17
+ domainHint?: string;
18
+ /**
19
+ * If specified, the client will use this value when initializing the app to enforce a minimum
20
+ * amount of time during which no further auth flow with the provider should be necessary.
21
+ *
22
+ * Use this argument to front-load any necessary auth flow to the apps initialization stage
23
+ * thereby minimizing disruption to user activity during application use.
24
+ *
25
+ * This value may be set to anything up to 86400 (24 hours), the maximum lifetime
26
+ * of an Azure refresh token. Set to -1 to disable (default).
27
+ *
28
+ * Note that setting to *any* non-disabled amount will require the app to do *some* communication
29
+ * with the login provider at *every* app load. This may just involve loading new tokens via
30
+ * fetch, however, setting to higher values will increase the frequency with which
31
+ * a new refresh token will also need to be requested via a hidden iframe/redirect/popup. This
32
+ * can be time-consuming and potentially disruptive and applications should therefore use with
33
+ * care and typically set to some value significantly less than the max.
34
+ *
35
+ * See https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/token-lifetimes.md
36
+ */
37
+ initRefreshTokenExpirationOffsetSecs?: number;
38
+ /** The log level of MSAL. Default is LogLevel.Warning. */
14
39
  msalLogLevel?: LogLevel;
15
40
  }
41
+ export interface MsalTokenSpec {
42
+ /** Scopes for the desired access token. */
43
+ scopes: string[];
44
+ /**
45
+ * Scopes to be added to the scopes requested during interactive and SSO logins.
46
+ * See the `scopes` property on `PopupRequest`, `RedirectRequest`, and `SSORequest`
47
+ * for more info.
48
+ */
49
+ loginScopes?: string[];
50
+ /**
51
+ * Scopes to be added to the scopes requested during interactive and SSO login.
52
+ *
53
+ * See the `extraScopesToConsent` property on `PopupRequest`, `RedirectRequest`, and
54
+ * `SSORequest` for more info.
55
+ */
56
+ extraScopesToConsent?: string[];
57
+ }
16
58
  /**
17
59
  * Service to implement OAuth authentication via MSAL.
60
+ *
61
+ * See the following helpful information relevant to our use of this tricky API --
62
+ * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/
63
+ * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/token-lifetimes.md
64
+ * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/login-user.md
65
+ *
66
+ * TODO: The handling of `ssoSilent` and `initRefreshTokenExpirationOffsetSecs` in this library
67
+ * require 3rd party cookies to be enabled in the browser so that MSAL can load contact in a
68
+ * hidden iFrame If its *not* enabled, we may be doing extra work. Consider checking 3rd party
69
+ * cookie support and adding conditional behavior?
18
70
  */
19
- export declare class MsalClient extends BaseOAuthClient<MsalClientConfig> {
71
+ export declare class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec> {
20
72
  private client;
21
73
  private account;
22
- doInitAsync(): Promise<void>;
23
- getIdTokenAsync(useCache?: boolean): Promise<string>;
24
- getAccessTokenAsync(spec: PlainObject, useCache?: boolean): Promise<string>;
25
- doLogoutAsync(): Promise<void>;
74
+ private initialTokenLoad;
75
+ constructor(config: MsalClientConfig);
76
+ protected doInitAsync(): Promise<TokenMap>;
77
+ protected doLoginPopupAsync(): Promise<void>;
78
+ protected doLoginRedirectAsync(): Promise<void>;
79
+ protected fetchIdTokenAsync(useCache?: boolean): Promise<Token>;
80
+ protected fetchAccessTokenAsync(spec: MsalTokenSpec, useCache?: boolean): Promise<Token>;
81
+ protected doLogoutAsync(): Promise<void>;
82
+ private loginSsoAsync;
26
83
  private createClientAsync;
27
- private completeViaRedirectAsync;
28
- private completeViaPopupAsync;
29
84
  private logFromMsal;
30
85
  private get loginScopes();
31
- private get loginExtraScopes();
86
+ private get loginExtraScopesToConsent();
87
+ private get refreshOffsetArgs();
88
+ private noteUserAuthenticated;
32
89
  }
@@ -0,0 +1 @@
1
+ export * from './MsalClient';
@@ -1,4 +1,4 @@
1
- import { FetchResponse, HoistService, LoadSpec, PlainObject } from '@xh/hoist/core';
1
+ import { Awaitable, FetchResponse, HoistService, LoadSpec, PlainObject } from '@xh/hoist/core';
2
2
  import { PromiseTimeoutSpec } from '@xh/hoist/promise';
3
3
  import { StatusCodes } from 'http-status-codes';
4
4
  import { IStringifyOptions } from 'qs';
@@ -26,19 +26,19 @@ export declare class FetchService extends HoistService {
26
26
  static instance: FetchService;
27
27
  NO_JSON_RESPONSES: StatusCodes[];
28
28
  private autoAborters;
29
- defaultHeaders: (PlainObject | ((arg: FetchOptions) => PlainObject))[];
29
+ defaultHeaders: (PlainObject | ((arg: FetchOptions) => Awaitable<PlainObject>))[];
30
30
  defaultTimeout: any;
31
31
  /**
32
32
  * Set default headers to be sent with all subsequent requests.
33
33
  * @param headers - to be sent with all fetch requests, or a function to generate.
34
34
  * @deprecated use addDefaultHeaders instead.
35
35
  */
36
- setDefaultHeaders(headers: PlainObject | ((arg: FetchOptions) => PlainObject)): void;
36
+ setDefaultHeaders(headers: PlainObject | ((arg: FetchOptions) => Awaitable<PlainObject>)): void;
37
37
  /**
38
38
  * Add default headers to be sent with all subsequent requests.
39
39
  * @param headers - to be sent with all fetch requests, or a function to generate.
40
40
  */
41
- addDefaultHeaders(headers: PlainObject | ((arg: FetchOptions) => PlainObject)): void;
41
+ addDefaultHeaders(headers: PlainObject | ((arg: FetchOptions) => Awaitable<PlainObject>)): void;
42
42
  /**
43
43
  * Set the timeout (default 30 seconds) to be used for all requests made via this service that
44
44
  * do not themselves spec a custom timeout.
@@ -84,7 +84,7 @@ export declare class FetchService extends HoistService {
84
84
  * @returns false if no request pending for the given key.
85
85
  */
86
86
  abort(autoAbortKey: string): boolean;
87
- private withDefaults;
87
+ private withDefaultsAsync;
88
88
  private managedFetchAsync;
89
89
  private fetchInternalAsync;
90
90
  private sendJsonInternalAsync;
@@ -26,6 +26,7 @@ export type VAlign = 'top' | 'bottom' | 'center';
26
26
 
27
27
  /** Convenience type for common pattern of accepting a single T, or an array of Ts. */
28
28
  export type Some<T> = T | T[];
29
+ export type NonEmptyArray<T> = [T, ...T[]];
29
30
 
30
31
  export type Thunkable<T> = T | (() => T);
31
32
  export type Awaitable<T> = Promise<T> | T;
@@ -57,24 +57,37 @@
57
57
  background-color: var(--xh-backdrop-bg);
58
58
  }
59
59
 
60
- // Squelch popover scale transition - unlike Dialog with its `transitionName` prop, Popover
61
- // does not appear to provide a way to turn off its transition without also losing the (often
62
- // desirable) arrow pointing to its target. Variables below required for the include to function.
63
- $pt-transition-ease: cubic-bezier(0.4, 1, 0.75, 0.9) !default;
64
- $pt-transition-ease-bounce: cubic-bezier(0.54, 1.12, 0.38, 1.11) !default;
65
- $pt-transition-duration: 100ms !default;
66
-
67
- .bp5-popover {
68
- // This override is taken from the popover source SCSS - there it is scoped under the minimal class.
69
- // https://github.com/palantir/blueprint/blob/1bfd1e42303d2626bfc3923eec2195ab4dc696d2/packages/core/src/components/popover/_popover.scss#L54
70
- @include react-transition(
71
- 'bp5-popover',
72
- (
73
- transform: scale(1) scale(1)
74
- ),
75
- $duration: 0,
76
- $after: '> &'
77
- );
60
+ // On Popover and Tooltip components, squelch scale & opacity transition - unlike Dialog with its `transitionName` prop,
61
+ // Popover, and consequently Tooltip, do not appear to provide a way to turn off
62
+ // their transitions without also losing the (often desirable) arrow pointing to their targets.
63
+ // These rules override the scale and opacity starting values of enter and exit classes by setting them to
64
+ // their final 'end of transition' values, which has the effect of preventing/short circuiting transitions.
65
+ // BlueprintJs' own Popover.minimal uses this same approach to disable its transitions.
66
+ // (it appears from testing that overriding these rules with any value will squelch the transition, but
67
+ // we might as well use the final values to be explicit.)
68
+ .bp5-popover-transition-container {
69
+ &.bp5-popover-enter,
70
+ &.bp5-popover-appear {
71
+ opacity: 1;
72
+ }
73
+
74
+ &.bp5-popover-exit {
75
+ opacity: 0;
76
+ }
77
+
78
+ &.bp5-popover-enter,
79
+ &.bp5-popover-appear {
80
+ > .bp5-popover {
81
+ transform: scale(1);
82
+ }
83
+ }
84
+
85
+ &.bp5-popover-exit-active,
86
+ &.bp5-popover-exit {
87
+ > .bp5-popover {
88
+ transform: scale(0);
89
+ }
90
+ }
78
91
  }
79
92
 
80
93
  //------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "64.0.0",
3
+ "version": "64.0.3",
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",