@xh/hoist 64.0.1 → 64.0.4

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/appcontainer/AppContainerModel.ts +2 -2
  3. package/build/types/core/HoistComponent.d.ts +4 -8
  4. package/build/types/core/HoistProps.d.ts +3 -1
  5. package/build/types/core/elem.d.ts +1 -3
  6. package/build/types/core/types/Types.d.ts +1 -0
  7. package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +1 -0
  8. package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +1 -0
  9. package/build/types/icon/Icon.d.ts +7 -4
  10. package/build/types/security/BaseOAuthClient.d.ts +63 -46
  11. package/build/types/security/{TokenInfo.d.ts → Token.d.ts} +5 -4
  12. package/build/types/security/authzero/AuthZeroClient.d.ts +12 -7
  13. package/build/types/security/authzero/index.d.ts +1 -0
  14. package/build/types/security/msal/MsalClient.d.ts +63 -10
  15. package/build/types/security/msal/index.d.ts +1 -0
  16. package/build/types/svc/FetchService.d.ts +5 -5
  17. package/build/types/utils/react/LayoutPropUtils.d.ts +4 -4
  18. package/core/HoistComponent.ts +4 -8
  19. package/core/HoistProps.ts +4 -1
  20. package/core/elem.ts +0 -4
  21. package/core/types/Types.ts +1 -0
  22. package/desktop/cmp/input/ButtonGroupInput.ts +4 -3
  23. package/icon/Icon.ts +7 -4
  24. package/kit/blueprint/styles.scss +31 -18
  25. package/mobile/appcontainer/ToastSource.ts +2 -1
  26. package/package.json +1 -1
  27. package/security/BaseOAuthClient.ts +148 -165
  28. package/security/{TokenInfo.ts → Token.ts} +12 -9
  29. package/security/authzero/AuthZeroClient.ts +92 -80
  30. package/security/authzero/index.ts +7 -0
  31. package/security/msal/MsalClient.ts +204 -94
  32. package/security/msal/index.ts +7 -0
  33. package/svc/FetchService.ts +14 -11
  34. package/svc/IdentityService.ts +1 -1
  35. package/svc/LocalStorageService.ts +1 -1
  36. package/tsconfig.tsbuildinfo +1 -1
  37. package/utils/react/LayoutPropUtils.ts +4 -4
package/CHANGELOG.md CHANGED
@@ -1,10 +1,32 @@
1
1
  # Changelog
2
2
 
3
- ## 65.0.0-SNAPSHOT - unreleased
3
+ ## 64.0.4 - 2024-06-05
4
+
5
+ ### ⚙️ Technical
6
+
7
+ * Typescript: Improve `ref` typing in JSX.
8
+
9
+ ## 64.0.3 - 2024-05-31
10
+
11
+ ### 🐞 Bug Fixes
12
+
13
+ * Restore disabling of Blueprint animations on popovers and tooltips (corrects regression in v63.0.0)
14
+
15
+ ### ⚙️ Technical
16
+
17
+ * Adjustments to API of (beta) `BaseOAuthClient`, `MsaClient`, and `AuthZeroClient`.
18
+
19
+ ## 64.0.2 - 2024-05-23
20
+
21
+ ### ⚙️ Technical
22
+
23
+ * Adjustments to API of (beta) `BaseOAuthClient`.
24
+ * `FetchService.addDefaultHeaders()` now supports async functions.
4
25
 
5
26
  ## 64.0.1 - 2024-05-19
6
27
 
7
28
  ### ⚙️ Technical
29
+
8
30
  * Adjustments to loading of ID Tokens and API of `BaseOAuthClient`. (Note that
9
31
  this package remains in Beta for v64 and is subject to change.)
10
32
 
@@ -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
 
@@ -4,15 +4,11 @@ import { ForwardedRef, FC, ReactNode } from 'react';
4
4
  /**
5
5
  * Type representing props passed to a HoistComponent's render function.
6
6
  *
7
- * This type removes from its base type several props that are used by HoistComponent itself and
8
- * not provided to the render function.
7
+ * This type removes from its base type several properties that are pulled out by the HoistComponent itself and
8
+ * not provided to the render function. `modelConfig` and `modelRef` are resolved into the `model` property.
9
+ * `ref` is passed as the second argument to the render function.
9
10
  */
10
- export type RenderPropsOf<P extends HoistProps> = P & {
11
- /** Pre-processed by HoistComponent internals into a mounted model. Never passed to render. */
12
- modelConfig: never;
13
- /** Pre-processed by HoistComponent internals and attached to model. Never passed to render. */
14
- modelRef: never;
15
- };
11
+ export type RenderPropsOf<P extends HoistProps> = Omit<P, 'modelConfig' | 'modelRef' | 'ref'>;
16
12
  /**
17
13
  * Configuration for creating a Component. May be specified either as a render function,
18
14
  * or an object containing a render function and associated metadata.
@@ -1,6 +1,6 @@
1
1
  import { HoistModel } from '@xh/hoist/core';
2
2
  import { Property } from 'csstype';
3
- import { CSSProperties, HTMLAttributes, ReactNode, Ref } from 'react';
3
+ import { CSSProperties, HTMLAttributes, LegacyRef, ReactNode, Ref } from 'react';
4
4
  /**
5
5
  * Props interface for Hoist Components.
6
6
  *
@@ -32,6 +32,8 @@ export interface HoistProps<M extends HoistModel = HoistModel> {
32
32
  className?: string;
33
33
  /** React children. */
34
34
  children?: ReactNode;
35
+ /** React Ref for this component. */
36
+ ref?: LegacyRef<any>;
35
37
  }
36
38
  /**
37
39
  * A version of Hoist props that allows dynamic keys/properties. This is the interface that
@@ -1,5 +1,5 @@
1
1
  import { TEST_ID } from '@xh/hoist/utils/js';
2
- import { ForwardedRef, Key, ReactElement, ReactNode } from 'react';
2
+ import { Key, ReactElement, ReactNode } from 'react';
3
3
  import { Some, Thunkable } from './types/Types';
4
4
  /**
5
5
  * Alternative format for specifying React Elements in render functions. This type is designed to
@@ -31,8 +31,6 @@ export type ElementSpec<P> = P & {
31
31
  item?: Some<ReactNode>;
32
32
  /** True to exclude the Element. */
33
33
  omit?: Thunkable<boolean>;
34
- /** React Ref for this component. */
35
- ref?: ForwardedRef<any>;
36
34
  /** React key for this component. */
37
35
  key?: Key;
38
36
  /**
@@ -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. */
@@ -36,6 +36,7 @@ export declare const autoRefreshAppOption: ({ formFieldProps, inputProps }?: Aut
36
36
  modelRef?: import("react").Ref<import("../../../cmp/form").FieldModel>;
37
37
  className?: string;
38
38
  children?: import("react").ReactNode;
39
+ ref?: import("react").LegacyRef<any>;
39
40
  margin?: string | number;
40
41
  marginTop?: string | number;
41
42
  marginRight?: string | number;
@@ -34,6 +34,7 @@ export declare const themeAppOption: ({ formFieldProps, inputProps }?: ThemeAppO
34
34
  modelRef?: import("react").Ref<import("../../../cmp/form").FieldModel>;
35
35
  className?: string;
36
36
  children?: import("react").ReactNode;
37
+ ref?: import("react").LegacyRef<any>;
37
38
  margin?: string | number;
38
39
  marginTop?: string | number;
39
40
  marginRight?: string | number;
@@ -5,11 +5,14 @@ export interface IconProps extends HoistProps, Partial<Omit<FontAwesomeIconProps
5
5
  /** Name of the icon in FontAwesome. */
6
6
  iconName?: string;
7
7
  /**
8
- * Prefix or weight of the icon. By default, 'far' for the standard
9
- * variant of each icon. Pass a value of either 'fas' for a heavier-weight/solid variant
10
- * or 'fal' for a lighter-weight variant.
8
+ * Prefix / weight of the icon (or "fab" if your app has imported the free-brand-icons pkg).
9
+ * - far - Regular
10
+ * - fas - Solid
11
+ * - fal - Light
12
+ * - fat - Thin (yes, unfortunate)
13
+ * - fab - Brand (requires optional import, see Toolbox)
11
14
  */
12
- prefix?: 'far' | 'fas' | 'fal' | 'fab';
15
+ prefix?: 'far' | 'fas' | 'fal' | 'fat' | 'fab';
13
16
  intent?: Intent;
14
17
  /** Optional tooltip string. */
15
18
  title?: string;
@@ -1,5 +1,6 @@
1
- import { BannerSpec, HoistBase } from '@xh/hoist/core';
2
- import { TokenInfo } from '@xh/hoist/security/TokenInfo';
1
+ import { HoistBase } from '@xh/hoist/core';
2
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
3
+ export type LoginMethod = 'REDIRECT' | 'POPUP';
3
4
  export interface BaseOAuthClientConfig<S> {
4
5
  /** Client ID (GUID) of your app registered with your Oauth provider. */
5
6
  clientId: string;
@@ -15,26 +16,31 @@ export interface BaseOAuthClientConfig<S> {
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
- * Governs how frequently we attempt to refresh tokens with the API.
23
+ * Governs an optional refresh timer that will work to keep the tokens fresh.
23
24
  *
24
- * A typical refresh will use the underlying provider cache, and should not result in network
25
- * activity. However, if the token lifetime falls below`tokenSkipCacheSecs`, this client
26
- * will force a call to the underlying provider to get the token.
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.
27
28
  *
28
29
  * In order to allow aging tokens to be replaced in a timely manner, this value should be
29
30
  * significantly shorter than both the minimum token lifetime that will be
30
- * returned by the underlying API and `tokenSkipCacheSecs`. Default is 30 secs.
31
+ * returned by the underlying API and `autoRefreshSkipCacheSecs`.
32
+ *
33
+ * Default is -1, disabling this behavior.
31
34
  */
32
- tokenRefreshSecs?: number;
35
+ autoRefreshSecs?: number;
33
36
  /**
34
- * When the remaining token lifetime is below this threshold, force the provider to skip the
35
- * local cache and go directly to the underlying provider for a new token. Default is 180 secs.
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.
36
42
  */
37
- tokenSkipCacheSecs?: number;
43
+ autoRefreshSkipCacheSecs?: number;
38
44
  /**
39
45
  * Scopes to request - if any - beyond the core `['openid', 'email']` scopes, which
40
46
  * this client will always request.
@@ -51,16 +57,11 @@ export interface BaseOAuthClientConfig<S> {
51
57
  * Use this map to gain targeted access tokens for different back-end resources.
52
58
  */
53
59
  accessTokens?: Record<string, S>;
54
- /**
55
- * True to display a warning banner to the user if tokens expire. May be specified as a boolean
56
- * or a partial banner spec. Defaults to false.
57
- */
58
- expiryWarning?: boolean | Partial<BannerSpec>;
59
60
  }
60
61
  /**
61
62
  * Implementations of this class coordinate OAuth-based login and token provision. Apps can use a
62
- * suitable concrete implementation to power a client-side OauthService - see Toolbox for an
63
- * example using `Auth0Client`.
63
+ * suitable concrete implementation to power a client-side OauthService. See `MsalClient` and
64
+ * `AuthZeroClient`
64
65
  *
65
66
  * Initialize such a service and this client within the `preAuthInitAsync()` lifecycle method of
66
67
  * `AppModel` to use the tokens it acquires to authenticate with the Hoist server. (Note this
@@ -71,39 +72,59 @@ export interface BaseOAuthClientConfig<S> {
71
72
  export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>, S> extends HoistBase {
72
73
  /** Config loaded from UI server + init method. */
73
74
  protected config: C;
74
- /** Scopes */
75
+ /** Id Scopes */
75
76
  protected idScopes: string[];
76
- protected _idToken: TokenInfo;
77
- protected _accessTokens: Record<string, TokenInfo>;
77
+ /** Specification for Access Tokens **/
78
+ protected accessSpecs: Record<string, S>;
78
79
  private timer;
79
- private expiryWarningDisplayed;
80
80
  private lastRefreshAttempt;
81
81
  private TIMER_INTERVAL;
82
- /**
83
- * ID token in JWT format. Observable.
84
- */
85
- get idToken(): string;
86
- /**
87
- * Get a configured Access token in JWT format. Observable.
88
- */
89
- getAccessToken(key: string): string;
90
82
  constructor(config: C);
91
83
  /**
92
84
  * Main entry point for this object.
93
85
  */
94
86
  initAsync(): Promise<void>;
87
+ /**
88
+ * Request an interactive login with the underlying OAuth provider.
89
+ */
90
+ loginAsync(method?: LoginMethod): Promise<void>;
95
91
  /**
96
92
  * Request a full logout from the underlying OAuth provider.
97
93
  */
98
94
  logoutAsync(): Promise<void>;
99
- 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>;
100
124
  protected abstract doLogoutAsync(): Promise<void>;
101
- protected abstract getIdTokenAsync(useCache: boolean): Promise<TokenInfo>;
102
- protected abstract getAccessTokenAsync(spec: S, useCache: boolean): Promise<TokenInfo>;
103
125
  protected get redirectUrl(): string;
104
126
  protected get postLogoutRedirectUrl(): string;
105
- protected get loginMethod(): 'REDIRECT' | 'POPUP';
106
- protected get usesRedirect(): boolean;
127
+ protected get loginMethod(): LoginMethod;
107
128
  protected get baseUrl(): string;
108
129
  protected popupBlockerErrorMessage: String;
109
130
  protected defaultErrorMsg: String;
@@ -120,14 +141,10 @@ export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>
120
141
  * @param key - key for re-accessing this state, as round-tripped with redirect.
121
142
  */
122
143
  protected restoreRedirectState(key: string): void;
123
- /**
124
- * Load tokens from provider.
125
- *
126
- * @param useCache - true (default) to use local cache if available, or false to force a
127
- * network request to fetch a fresh token.
128
- */
129
- protected loadTokensAsync(useCache?: boolean): Promise<void>;
130
- private getIdTokenSafeAsync;
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;
131
148
  private onTimerAsync;
132
- private updateWarning;
149
+ private logTokensDebug;
133
150
  }
@@ -1,11 +1,12 @@
1
1
  import { PlainObject } from '@xh/hoist/core';
2
- export declare class TokenInfo {
3
- readonly token: string;
2
+ export type TokenMap = Record<string, Token>;
3
+ export declare class Token {
4
+ readonly value: string;
4
5
  readonly decoded: PlainObject;
5
6
  readonly expiry: number;
6
- constructor(token: string);
7
+ constructor(value: string);
7
8
  expiresWithin(interval: number): boolean;
8
9
  get formattedExpiry(): string;
9
10
  get forLog(): PlainObject;
10
- equals(other: TokenInfo): boolean;
11
+ equals(other: Token): boolean;
11
12
  }
@@ -1,4 +1,4 @@
1
- import { TokenInfo } from '@xh/hoist/security/TokenInfo';
1
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
2
2
  import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
3
3
  export interface AuthZeroClientConfig extends BaseOAuthClientConfig<AuthZeroTokenSpec> {
4
4
  /** Domain of your app registered with Auth0 */
@@ -20,15 +20,20 @@ export interface AuthZeroTokenSpec {
20
20
  * via Google, GitHub, Microsoft, and various other OAuth providers *or* via a username/password
21
21
  * combo stored and managed within Auth0's own database. Supported options will depend on the
22
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.
23
26
  */
24
27
  export declare class AuthZeroClient extends BaseOAuthClient<AuthZeroClientConfig, AuthZeroTokenSpec> {
25
28
  private client;
26
- doInitAsync(): Promise<void>;
27
- getIdTokenAsync(useCache?: boolean): Promise<TokenInfo>;
28
- getAccessTokenAsync(spec: AuthZeroTokenSpec, useCache?: boolean): Promise<TokenInfo>;
29
- 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>;
30
35
  private createClient;
31
- private completeViaRedirectAsync;
32
- private completeViaPopupAsync;
33
36
  private get loginScope();
37
+ private returningFromRedirect;
38
+ private noteUserAuthenticatedAsync;
34
39
  }
@@ -0,0 +1 @@
1
+ export * from './AuthZeroClient';
@@ -1,5 +1,5 @@
1
- import { LogLevel } from '@azure/msal-common';
2
- import { TokenInfo } from '@xh/hoist/security/TokenInfo';
1
+ import { LogLevel } from '@azure/msal-browser';
2
+ import { Token, TokenMap } from '@xh/hoist/security/Token';
3
3
  import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
4
4
  export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
5
5
  /** Tenant ID (GUID) of your organization */
@@ -10,27 +10,80 @@ export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
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
  }
16
41
  export interface MsalTokenSpec {
17
42
  /** Scopes for the desired access token. */
18
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[];
19
57
  }
20
58
  /**
21
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?
22
70
  */
23
71
  export declare class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec> {
24
72
  private client;
25
73
  private account;
26
- doInitAsync(): Promise<void>;
27
- getIdTokenAsync(useCache?: boolean): Promise<TokenInfo>;
28
- getAccessTokenAsync(spec: MsalTokenSpec, useCache?: boolean): Promise<TokenInfo>;
29
- 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;
30
83
  private createClientAsync;
31
- private completeViaRedirectAsync;
32
- private completeViaPopupAsync;
33
84
  private logFromMsal;
34
85
  private get loginScopes();
35
- private get loginExtraScopes();
86
+ private get loginExtraScopesToConsent();
87
+ private get refreshOffsetArgs();
88
+ private noteUserAuthenticated;
36
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;
@@ -1,4 +1,4 @@
1
- import { HoistProps, LayoutProps } from '@xh/hoist/core';
1
+ import { LayoutProps, PlainObject } from '@xh/hoist/core';
2
2
  /**
3
3
  * These utils support accepting the CSS styles enumerated below as top-level props of a Component,
4
4
  * and are typically accessed via the `@LayoutSupport` mixin (for class-based components) or the
@@ -31,12 +31,12 @@ import { HoistProps, LayoutProps } from '@xh/hoist/core';
31
31
  * that afforded by the underlying flexbox styles. In particular, it accepts flex and sizing props
32
32
  * as raw numbers rather than strings.
33
33
  */
34
- export declare function getLayoutProps(props: HoistProps): LayoutProps;
34
+ export declare function getLayoutProps(props: PlainObject): LayoutProps;
35
35
  /**
36
36
  * Return all non-layout related props found in props.
37
37
  */
38
- export declare function getNonLayoutProps<T extends HoistProps>(props: T): T;
38
+ export declare function getNonLayoutProps<T extends PlainObject>(props: T): T;
39
39
  /**
40
40
  * Split a set of props into layout and non-layout props.
41
41
  */
42
- export declare function splitLayoutProps<T extends HoistProps>(props: T): [LayoutProps, T];
42
+ export declare function splitLayoutProps<T extends PlainObject>(props: T): [LayoutProps, T];
@@ -47,16 +47,12 @@ import {
47
47
  /**
48
48
  * Type representing props passed to a HoistComponent's render function.
49
49
  *
50
- * This type removes from its base type several props that are used by HoistComponent itself and
51
- * not provided to the render function.
50
+ * This type removes from its base type several properties that are pulled out by the HoistComponent itself and
51
+ * not provided to the render function. `modelConfig` and `modelRef` are resolved into the `model` property.
52
+ * `ref` is passed as the second argument to the render function.
52
53
  */
53
- export type RenderPropsOf<P extends HoistProps> = P & {
54
- /** Pre-processed by HoistComponent internals into a mounted model. Never passed to render. */
55
- modelConfig: never;
56
54
 
57
- /** Pre-processed by HoistComponent internals and attached to model. Never passed to render. */
58
- modelRef: never;
59
- };
55
+ export type RenderPropsOf<P extends HoistProps> = Omit<P, 'modelConfig' | 'modelRef' | 'ref'>;
60
56
 
61
57
  /**
62
58
  * Configuration for creating a Component. May be specified either as a render function,
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import {HoistModel} from '@xh/hoist/core';
8
8
  import {Property} from 'csstype';
9
- import {CSSProperties, HTMLAttributes, ReactNode, Ref} from 'react';
9
+ import {CSSProperties, HTMLAttributes, LegacyRef, ReactNode, Ref} from 'react';
10
10
 
11
11
  /**
12
12
  * Props interface for Hoist Components.
@@ -43,6 +43,9 @@ export interface HoistProps<M extends HoistModel = HoistModel> {
43
43
 
44
44
  /** React children. */
45
45
  children?: ReactNode;
46
+
47
+ /** React Ref for this component. */
48
+ ref?: LegacyRef<any>;
46
49
  }
47
50
 
48
51
  /**
package/core/elem.ts CHANGED
@@ -8,7 +8,6 @@ import {TEST_ID} from '@xh/hoist/utils/js';
8
8
  import {castArray, isFunction, isNil, isPlainObject} from 'lodash';
9
9
  import {
10
10
  createElement as reactCreateElement,
11
- ForwardedRef,
12
11
  isValidElement,
13
12
  Key,
14
13
  ReactElement,
@@ -55,9 +54,6 @@ export type ElementSpec<P> = P & {
55
54
  //-----------------------------------
56
55
  // Core React attributes
57
56
  //-----------------------------------
58
- /** React Ref for this component. */
59
- ref?: ForwardedRef<any>;
60
-
61
57
  /** React key for this component. */
62
58
  key?: Key;
63
59
 
@@ -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;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import {HoistInputModel, HoistInputProps, useHoistInputModel} from '@xh/hoist/cmp/input';
8
8
  import {hoistCmp, HoistModel, Intent, XH} from '@xh/hoist/core';
9
- import {Button, buttonGroup, ButtonGroupProps} from '@xh/hoist/desktop/cmp/button';
9
+ import {Button, buttonGroup, ButtonGroupProps, ButtonProps} from '@xh/hoist/desktop/cmp/button';
10
10
  import '@xh/hoist/desktop/register';
11
11
  import {throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
12
12
  import {getLayoutProps, getNonLayoutProps} from '@xh/hoist/utils/react';
@@ -130,8 +130,9 @@ const cmp = hoistCmp.factory<ButtonGroupInputModel>(({model, className, ...props
130
130
  throw XH.exception('ButtonGroupInput child must be a Button.');
131
131
  }
132
132
 
133
- const {value, intent: btnIntent} = button.props,
134
- btnDisabled = disabled || button.props.disabled;
133
+ const props = button.props as ButtonProps,
134
+ {value, intent: btnIntent} = props,
135
+ btnDisabled = disabled || props.disabled;
135
136
 
136
137
  throwIf(
137
138
  (enableClear || enableMulti) && value == null,