@stytch/react 19.4.4 → 19.5.0
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 +25 -0
- package/README.md +7 -7
- package/b2b/headless/package.json +6 -0
- package/b2b/ui/package.json +6 -0
- package/dist/{StytchB2BContext-09d376ba.d.ts → StytchB2BContext-9c062712.d.ts} +127 -23
- package/dist/{StytchB2BContext-09d376ba.js → StytchB2BContext-9c062712.js} +85 -42
- package/dist/{StytchB2BContext-a8d57249.d.ts → StytchB2BContext-c5062f9b.d.ts} +127 -23
- package/dist/{StytchB2BContext-a8d57249.js → StytchB2BContext-c5062f9b.js} +95 -52
- package/dist/StytchSSRProxy-34c789b5.d.ts +3 -0
- package/dist/StytchSSRProxy-34c789b5.js +48 -0
- package/dist/StytchSSRProxy-86bc42b3.d.ts +3 -0
- package/dist/StytchSSRProxy-86bc42b3.js +54 -0
- package/dist/adminPortal/index.d.ts +1 -1
- package/dist/adminPortal/index.esm.d.ts +1 -1
- package/dist/adminPortal/index.esm.js +5 -4
- package/dist/adminPortal/index.js +5 -4
- package/dist/b2b/index.d.ts +170 -6
- package/dist/b2b/index.esm.d.ts +170 -6
- package/dist/b2b/index.esm.js +85 -8
- package/dist/b2b/index.headless.d.ts +16 -0
- package/dist/b2b/index.headless.esm.d.ts +16 -0
- package/dist/b2b/index.headless.esm.js +24 -0
- package/dist/b2b/index.headless.js +28 -0
- package/dist/b2b/index.js +93 -16
- package/dist/b2b/index.ui.d.ts +17 -0
- package/dist/b2b/index.ui.esm.d.ts +17 -0
- package/dist/b2b/index.ui.esm.js +25 -0
- package/dist/b2b/index.ui.js +29 -0
- package/dist/errors-d9d5fbc8.d.ts +5 -0
- package/dist/index-b14d4efe.d.ts +1 -1
- package/dist/index.d.ts +92 -54
- package/dist/index.esm.d.ts +92 -54
- package/dist/index.esm.js +112 -38
- package/dist/index.headless.d.ts +16 -0
- package/dist/index.headless.esm.d.ts +16 -0
- package/dist/index.headless.esm.js +24 -0
- package/dist/index.headless.js +28 -0
- package/dist/index.js +126 -52
- package/dist/index.ui.d.ts +17 -0
- package/dist/index.ui.esm.d.ts +17 -0
- package/dist/index.ui.esm.js +25 -0
- package/dist/index.ui.js +29 -0
- package/dist/useIsomorphicLayoutEffect-1babb81e.d.ts +24 -0
- package/dist/{invariant-568a7633.js → useIsomorphicLayoutEffect-1babb81e.js} +5 -13
- package/dist/useIsomorphicLayoutEffect-65746ef3.d.ts +24 -0
- package/dist/{invariant-ae5a5bce.js → useIsomorphicLayoutEffect-65746ef3.js} +4 -16
- package/package.json +4 -3
- package/dist/invariant-568a7633.d.ts +0 -27
- package/dist/invariant-ae5a5bce.d.ts +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @stytch/react
|
|
2
2
|
|
|
3
|
+
## 19.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1e9ab0e: Add `createStytch*Client` helper functions:
|
|
8
|
+
|
|
9
|
+
- `import { createStytchHeadlessClient } from '@stytch/react/headless';`
|
|
10
|
+
- `import { createStytchUIClient } from '@stytch/react/ui';`
|
|
11
|
+
- `import { createStytchB2BHeadlessClient } from '@stytch/react/b2b/headless';`
|
|
12
|
+
- `import { createStytchB2BUIClient } from '@stytch/react/b2b/ui';`
|
|
13
|
+
|
|
14
|
+
These are equivalent to the same functions in `@stytch/nextjs` and may be used instead of constructing clients directly (e.g., `new StytchUIClient()`).
|
|
15
|
+
|
|
16
|
+
- 1e9ab0e: Add `isInitialized` as a returned value from `useStytchUser`, `useStytchSession`, `useStytchMember`, `useStytchMemberSession`, `useStytchOrganization`, and `useStytchIsAuthorized` hooks; add `*IsInitialized` as an injected prop to the `withStytchUser`, `withStytchSession`, `withStytchMember`, `withStytchMemberSession`, and `withStytchOrganization` HOCs. This provides parity with the same APIs in `@stytch/nextjs`.
|
|
17
|
+
|
|
18
|
+
If you set `assumeHydrated={false}` in your `StytchProvider` or `StytchB2BProvider`, `isInitialized` will initially be `false` and should be checked before accessing the other values returned by these hooks (or props injected by these HOCs). If you set `assumeHydrated={true}` (the default in `@stytch/react`), `isInitialized` will always be `true`, and it is always safe to access the other values, as in previous versions of `@stytch/react`.
|
|
19
|
+
|
|
20
|
+
- 1e9ab0e: Add a new `assumeHydrated` prop to the `StytchProvider` and `StytchB2BProvider` components. This prop allows the provider to assume whether or not the app might be hydrated in a browser environment after initially being rendered in a server environment. When `true`, the provider eagerly reads from the browser's local cache to retrieve cached session and related data. When `false`, the provider defers this initialization until after the first render, to avoid hydration errors. This prop defaults to `true` in `@stytch/react`, which preserves the behavior from previous versions.
|
|
21
|
+
|
|
22
|
+
We recommend setting `assumeHydrated={false}` if your app hydrates server-rendered content on the client. Otherwise, it is safe to set `assumeHydrated={true}`. If you're unsure or notice hydration errors in your app, set `assumeHydrated={false}`.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- 1e9ab0e: Remove errors when attempting to use StytchProvider or StytchB2BProvider in a server environment
|
|
27
|
+
|
|
3
28
|
## 19.4.4
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ For full documentation please refer to Stytch's javascript SDK documentation at
|
|
|
18
18
|
|
|
19
19
|
```javascript
|
|
20
20
|
import { StytchProvider } from '@stytch/react';
|
|
21
|
-
import {
|
|
21
|
+
import { createStytchUIClient } from '@stytch/react/ui';
|
|
22
22
|
|
|
23
|
-
const stytch =
|
|
23
|
+
const stytch = createStytchUIClient('public-token-<find yours in the stytch dashboard>');
|
|
24
24
|
|
|
25
25
|
// Wrap your App in the StytchProvider
|
|
26
26
|
const Root = () => (
|
|
@@ -96,18 +96,18 @@ yarn remove @stytch/stytch-react
|
|
|
96
96
|
### Step 3: Initialize the client in your Application Root
|
|
97
97
|
|
|
98
98
|
- Determine if you need the Headless or UI client. If you plan to use the `<StytchLogin />` component in your application then you should use the the UI client. Otherwise use the Headless client to minimize application bundle size.
|
|
99
|
-
- To create the Stytch Headless client, use `
|
|
100
|
-
- To create the Stytch UI client, use `
|
|
99
|
+
- To create the Stytch Headless client, use `createStytchHeadlessClient` from `@stytch/react/headless`
|
|
100
|
+
- To create the Stytch UI client, use `createStytchUIClient` from `@stytch/react/ui`
|
|
101
101
|
- Pass it into `<StytchProvider />` component from `@stytch/react`
|
|
102
102
|
|
|
103
103
|
```jsx
|
|
104
104
|
import React from 'react';
|
|
105
105
|
import { StytchProvider } from '@stytch/react';
|
|
106
|
-
import {
|
|
106
|
+
import { createStytchHeadlessClient } from '@stytch/react/headless';
|
|
107
107
|
// Or alternately
|
|
108
|
-
// import {
|
|
108
|
+
// import { createStytchUIClient } from '@stytch/react/ui';
|
|
109
109
|
|
|
110
|
-
const stytch =
|
|
110
|
+
const stytch = createStytchHeadlessClient(process.env.REACT_APP_STYTCH_PUBLIC_TOKEN);
|
|
111
111
|
|
|
112
112
|
function WrappedApp() {
|
|
113
113
|
return (
|
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
|
+
import { PermissionsMap } from '@stytch/core/public';
|
|
4
5
|
import { Member, MemberSession, Organization, StytchB2BUIClient } from '@stytch/vanilla-js/b2b';
|
|
5
6
|
import { StytchB2BHeadlessClient, StytchProjectConfigurationInput } from '@stytch/vanilla-js/b2b/headless';
|
|
6
|
-
import { PermissionsMap } from '@stytch/core/public';
|
|
7
7
|
/**
|
|
8
8
|
* The Stytch Client object passed in to <StytchB2BProvider /> in your application root.
|
|
9
9
|
* Either a StytchB2BUIClient or StytchB2BHeadlessClient.
|
|
10
10
|
*/
|
|
11
11
|
type StytchB2BClient<TProjectConfiguration extends StytchProjectConfigurationInput> = StytchB2BHeadlessClient<TProjectConfiguration> | StytchB2BUIClient<TProjectConfiguration>;
|
|
12
|
-
type
|
|
12
|
+
type SWRMemberUninitialized = {
|
|
13
|
+
/**
|
|
14
|
+
* Either the active {@link Member} object, or null if the member is not logged in.
|
|
15
|
+
*/
|
|
16
|
+
member: null;
|
|
17
|
+
/**
|
|
18
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
19
|
+
*/
|
|
20
|
+
fromCache: false;
|
|
21
|
+
/**
|
|
22
|
+
* If true, indicates that the SDK has completed initialization.
|
|
23
|
+
*/
|
|
24
|
+
isInitialized: false;
|
|
25
|
+
};
|
|
26
|
+
type SWRMemberInitialized = {
|
|
13
27
|
/**
|
|
14
28
|
* Either the active {@link Member} object, or null if the member is not logged in.
|
|
15
29
|
*/
|
|
@@ -18,8 +32,27 @@ type SWRMember = {
|
|
|
18
32
|
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
19
33
|
*/
|
|
20
34
|
fromCache: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* If true, indicates that the SDK has completed initialization.
|
|
37
|
+
*/
|
|
38
|
+
isInitialized: true;
|
|
21
39
|
};
|
|
22
|
-
type
|
|
40
|
+
type SWRMember<TAlwaysInitialized extends boolean = boolean> = TAlwaysInitialized extends true ? SWRMemberInitialized : SWRMemberInitialized | SWRMemberUninitialized;
|
|
41
|
+
type SWRMemberSessionUninitialized = {
|
|
42
|
+
/**
|
|
43
|
+
* Either the active {@link MemberSession} object, or null if the member is not logged in.
|
|
44
|
+
*/
|
|
45
|
+
session: null;
|
|
46
|
+
/**
|
|
47
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
48
|
+
*/
|
|
49
|
+
fromCache: false;
|
|
50
|
+
/**
|
|
51
|
+
* If true, indicates that the SDK has completed initialization.
|
|
52
|
+
*/
|
|
53
|
+
isInitialized: false;
|
|
54
|
+
};
|
|
55
|
+
type SWRMemberSessionInitialized = {
|
|
23
56
|
/**
|
|
24
57
|
* Either the active {@link MemberSession} object, or null if the member is not logged in.
|
|
25
58
|
*/
|
|
@@ -28,8 +61,27 @@ type SWRMemberSession = {
|
|
|
28
61
|
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
29
62
|
*/
|
|
30
63
|
fromCache: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* If true, indicates that the SDK has completed initialization.
|
|
66
|
+
*/
|
|
67
|
+
isInitialized: true;
|
|
31
68
|
};
|
|
32
|
-
type
|
|
69
|
+
type SWRMemberSession<TAlwaysInitialized extends boolean = boolean> = TAlwaysInitialized extends true ? SWRMemberSessionInitialized : SWRMemberSessionInitialized | SWRMemberSessionUninitialized;
|
|
70
|
+
type SWROrganizationUninitialized = {
|
|
71
|
+
/**
|
|
72
|
+
* Either the active {@link Organization} object, or null if the member is not logged in.
|
|
73
|
+
*/
|
|
74
|
+
organization: null;
|
|
75
|
+
/**
|
|
76
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
77
|
+
*/
|
|
78
|
+
fromCache: false;
|
|
79
|
+
/**
|
|
80
|
+
* If true, indicates that the SDK has completed initialization.
|
|
81
|
+
*/
|
|
82
|
+
isInitialized: false;
|
|
83
|
+
};
|
|
84
|
+
type SWROrganizationInitialized = {
|
|
33
85
|
/**
|
|
34
86
|
* Either the active {@link Organization} object, or null if the member is not logged in.
|
|
35
87
|
*/
|
|
@@ -38,41 +90,72 @@ type SWROrganization = {
|
|
|
38
90
|
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
39
91
|
*/
|
|
40
92
|
fromCache: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* If true, indicates that the SDK has completed initialization.
|
|
95
|
+
*/
|
|
96
|
+
isInitialized: true;
|
|
41
97
|
};
|
|
98
|
+
type SWROrganization<TAlwaysInitialized extends boolean = boolean> = TAlwaysInitialized extends true ? SWROrganizationInitialized : SWROrganizationInitialized | SWROrganizationUninitialized;
|
|
42
99
|
declare const useIsMounted__INTERNAL: () => boolean;
|
|
43
100
|
declare const isUIClient: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration>>(client: StytchB2BClient<TProjectConfiguration>) => client is StytchB2BUIClient<TProjectConfiguration>;
|
|
44
101
|
/**
|
|
45
102
|
* Returns the active Member.
|
|
46
103
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
104
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
47
105
|
* Check the fromCache property to determine if the member data is from persistent storage.
|
|
48
106
|
* @example
|
|
49
|
-
* const {member} = useStytchMember();
|
|
107
|
+
* const {member, isInitialized, fromCache} = useStytchMember();
|
|
108
|
+
* if (!isInitialized) {
|
|
109
|
+
* return <p>Loading...</p>;
|
|
110
|
+
* }
|
|
50
111
|
* return (<h1>Welcome, {member.name}</h1>);
|
|
51
112
|
*/
|
|
52
|
-
declare const useStytchMember: () => SWRMember
|
|
113
|
+
declare const useStytchMember: <TAssumeHydrated extends boolean = false>() => SWRMember<TAssumeHydrated>;
|
|
53
114
|
/**
|
|
54
115
|
* Returns the active member's Stytch member session.
|
|
55
116
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
117
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
56
118
|
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
57
119
|
* @example
|
|
58
|
-
* const {
|
|
120
|
+
* const {session, isInitialized, fromCache} = useStytchMemberSession();
|
|
59
121
|
* useEffect(() => {
|
|
122
|
+
* if (!isInitialized) {
|
|
123
|
+
* return;
|
|
124
|
+
* }
|
|
60
125
|
* if (!session) {
|
|
61
126
|
* router.replace('/login')
|
|
62
127
|
* }
|
|
63
|
-
* }, [session]);
|
|
128
|
+
* }, [session, isInitialized]);
|
|
64
129
|
*/
|
|
65
|
-
declare const useStytchMemberSession: () => SWRMemberSession
|
|
130
|
+
declare const useStytchMemberSession: <TAssumeHydrated extends boolean = false>() => SWRMemberSession<TAssumeHydrated>;
|
|
66
131
|
/**
|
|
67
132
|
* Returns the active Stytch organization.
|
|
68
133
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
134
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
69
135
|
* Check the fromCache property to determine if the organization data is from persistent storage.
|
|
70
136
|
* @example
|
|
71
|
-
* const {
|
|
137
|
+
* const {organization, isInitialized, fromCache} = useStytchOrganization();
|
|
138
|
+
* if (!isInitialized) {
|
|
139
|
+
* return <p>Loading...</p>;
|
|
140
|
+
* }
|
|
72
141
|
* return (<p>Welcome to {organization.organization_name}</p>);
|
|
73
142
|
*/
|
|
74
|
-
declare const useStytchOrganization: () => SWROrganization
|
|
75
|
-
type
|
|
143
|
+
declare const useStytchOrganization: <TAssumeHydrated extends boolean = false>() => SWROrganization<TAssumeHydrated>;
|
|
144
|
+
type SWRIsAuthorizedUninitialized = {
|
|
145
|
+
/**
|
|
146
|
+
* Whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
147
|
+
*/
|
|
148
|
+
isAuthorized: false;
|
|
149
|
+
/**
|
|
150
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
151
|
+
*/
|
|
152
|
+
fromCache: false;
|
|
153
|
+
/**
|
|
154
|
+
* If true, indicates that the SDK has completed initialization.
|
|
155
|
+
*/
|
|
156
|
+
isInitialized: false;
|
|
157
|
+
};
|
|
158
|
+
type SWRIsAuthorizedInitialized = {
|
|
76
159
|
/**
|
|
77
160
|
* Whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
78
161
|
*/
|
|
@@ -81,7 +164,12 @@ type SWRIsAuthorized = {
|
|
|
81
164
|
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
82
165
|
*/
|
|
83
166
|
fromCache: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* If true, indicates that the SDK has completed initialization.
|
|
169
|
+
*/
|
|
170
|
+
isInitialized: boolean;
|
|
84
171
|
};
|
|
172
|
+
type SWRIsAuthorized<TAlwaysInitialized extends boolean> = TAlwaysInitialized extends true ? SWRIsAuthorizedInitialized : SWRIsAuthorizedInitialized | SWRIsAuthorizedUninitialized;
|
|
85
173
|
/**
|
|
86
174
|
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
87
175
|
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
@@ -91,10 +179,10 @@ type SWRIsAuthorized = {
|
|
|
91
179
|
*
|
|
92
180
|
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
93
181
|
* @example
|
|
94
|
-
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
182
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
95
183
|
* return <button disabled={!isAuthorized}>Edit</button>
|
|
96
184
|
*/
|
|
97
|
-
declare const useStytchIsAuthorized: (resourceId: string, action: string) => SWRIsAuthorized
|
|
185
|
+
declare const useStytchIsAuthorized: <TAssumeHydrated extends boolean = false>(resourceId: string, action: string) => SWRIsAuthorized<TAssumeHydrated>;
|
|
98
186
|
/**
|
|
99
187
|
* Returns the Stytch B2B client stored in the Stytch context.
|
|
100
188
|
*
|
|
@@ -108,16 +196,19 @@ declare const useStytchB2BClient: <TProjectConfiguration extends Partial<import(
|
|
|
108
196
|
declare const withStytchB2BClient: <T extends object, TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration>>(Component: React.ComponentType<T & {
|
|
109
197
|
stytch: StytchB2BHeadlessClient<TProjectConfiguration>;
|
|
110
198
|
}>) => React.ComponentType<T>;
|
|
111
|
-
declare const withStytchMember: <T extends object>(Component: React.ComponentType<T & {
|
|
199
|
+
declare const withStytchMember: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
|
|
112
200
|
stytchMember: Member | null;
|
|
201
|
+
stytchMemberIsInitialized: boolean;
|
|
113
202
|
stytchMemberIsFromCache: boolean;
|
|
114
203
|
}>) => React.ComponentType<T>;
|
|
115
|
-
declare const withStytchMemberSession: <T extends object>(Component: React.ComponentType<T & {
|
|
204
|
+
declare const withStytchMemberSession: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
|
|
116
205
|
stytchMemberSession: MemberSession | null;
|
|
206
|
+
stytchMemberSessionIsInitialized: boolean;
|
|
117
207
|
stytchMemberSessionIsFromCache: boolean;
|
|
118
208
|
}>) => React.ComponentType<T>;
|
|
119
|
-
declare const withStytchOrganization: <T extends object>(Component: React.ComponentType<T & {
|
|
209
|
+
declare const withStytchOrganization: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
|
|
120
210
|
stytchOrganization: Organization | null;
|
|
211
|
+
stytchOrganizationIsInitialized: boolean;
|
|
121
212
|
stytchOrganizationIsFromCache: boolean;
|
|
122
213
|
}>) => React.ComponentType<T>;
|
|
123
214
|
/**
|
|
@@ -146,23 +237,36 @@ declare const withStytchPermissions: <Permissions_1 extends Record<string, strin
|
|
|
146
237
|
}>) => React.ComponentType<T>;
|
|
147
238
|
interface StytchB2BProviderProps<TProjectConfiguration extends StytchProjectConfigurationInput = Stytch.DefaultProjectConfiguration> {
|
|
148
239
|
/**
|
|
149
|
-
* A Stytch client instance, either
|
|
240
|
+
* A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
|
|
150
241
|
*/
|
|
151
242
|
stytch: StytchB2BClient<TProjectConfiguration>;
|
|
243
|
+
/**
|
|
244
|
+
* When true, the provider will assume that the component will only be
|
|
245
|
+
* rendered in a browser environment, either in a single-page application or
|
|
246
|
+
* after completing hydration of a server-rendered application. This allows
|
|
247
|
+
* cached values to be retrieved from the browser on the first render, meaning
|
|
248
|
+
* that the `isInitialized` value returned from Stytch hooks will be `true`
|
|
249
|
+
* starting from the first render.
|
|
250
|
+
*
|
|
251
|
+
* When `false`, the provider will defer initialization until after the first
|
|
252
|
+
* render, and `isInitialized` will initially be `false`.
|
|
253
|
+
*
|
|
254
|
+
* This value defaults to `false` in `@stytch/nextjs`.
|
|
255
|
+
*/
|
|
256
|
+
assumeHydrated?: boolean;
|
|
152
257
|
children?: ReactNode;
|
|
153
258
|
}
|
|
154
259
|
/**
|
|
155
260
|
* The Stytch Context Provider.
|
|
156
261
|
* Wrap your application with this component in order to use Stytch everywhere in your app.
|
|
157
262
|
* @example
|
|
158
|
-
* const stytch =
|
|
263
|
+
* const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
159
264
|
*
|
|
160
|
-
*
|
|
265
|
+
* return (
|
|
161
266
|
* <StytchB2BProvider stytch={stytch}>
|
|
162
267
|
* <App />
|
|
163
|
-
* </
|
|
164
|
-
* document.getElementById('root'),
|
|
268
|
+
* </StytchB2BProvider>
|
|
165
269
|
* )
|
|
166
270
|
*/
|
|
167
|
-
declare const StytchB2BProvider: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration> = Stytch.DefaultProjectConfiguration>({ stytch, children, }: StytchB2BProviderProps<TProjectConfiguration>) => JSX.Element;
|
|
271
|
+
declare const StytchB2BProvider: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration> = Stytch.DefaultProjectConfiguration>({ stytch, children, assumeHydrated, }: StytchB2BProviderProps<TProjectConfiguration>) => JSX.Element;
|
|
168
272
|
export { useIsMounted__INTERNAL, isUIClient, useStytchMember, useStytchMemberSession, useStytchOrganization, useStytchIsAuthorized, useStytchB2BClient, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions, StytchB2BProviderProps, StytchB2BProvider };
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useMemo } from 'react';
|
|
2
|
-
import { i as invariant, u as useAsyncState, m as mergeWithStableProps
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useCallback, useRef } from 'react';
|
|
2
|
+
import { i as invariant, u as useAsyncState, m as mergeWithStableProps } from './useIsomorphicLayoutEffect-1babb81e.js';
|
|
3
|
+
import { n as noProviderError, i as isStytchSSRProxy } from './StytchSSRProxy-34c789b5.js';
|
|
3
4
|
|
|
4
5
|
const initialMember = {
|
|
5
6
|
member: null,
|
|
6
7
|
fromCache: false,
|
|
8
|
+
isInitialized: false,
|
|
7
9
|
};
|
|
8
10
|
const initialMemberSession = {
|
|
9
11
|
session: null,
|
|
10
12
|
fromCache: false,
|
|
13
|
+
isInitialized: false,
|
|
11
14
|
};
|
|
12
15
|
const initialOrganization = {
|
|
13
16
|
organization: null,
|
|
14
17
|
fromCache: false,
|
|
18
|
+
isInitialized: false,
|
|
15
19
|
};
|
|
16
20
|
const StytchB2BContext = createContext({ isMounted: false });
|
|
17
21
|
const StytchMemberContext = createContext(initialMember);
|
|
@@ -24,9 +28,13 @@ const isUIClient = (client) => {
|
|
|
24
28
|
/**
|
|
25
29
|
* Returns the active Member.
|
|
26
30
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
31
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
27
32
|
* Check the fromCache property to determine if the member data is from persistent storage.
|
|
28
33
|
* @example
|
|
29
|
-
* const {member} = useStytchMember();
|
|
34
|
+
* const {member, isInitialized, fromCache} = useStytchMember();
|
|
35
|
+
* if (!isInitialized) {
|
|
36
|
+
* return <p>Loading...</p>;
|
|
37
|
+
* }
|
|
30
38
|
* return (<h1>Welcome, {member.name}</h1>);
|
|
31
39
|
*/
|
|
32
40
|
const useStytchMember = () => {
|
|
@@ -36,14 +44,18 @@ const useStytchMember = () => {
|
|
|
36
44
|
/**
|
|
37
45
|
* Returns the active member's Stytch member session.
|
|
38
46
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
47
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
39
48
|
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
40
49
|
* @example
|
|
41
|
-
* const {
|
|
50
|
+
* const {session, isInitialized, fromCache} = useStytchMemberSession();
|
|
42
51
|
* useEffect(() => {
|
|
52
|
+
* if (!isInitialized) {
|
|
53
|
+
* return;
|
|
54
|
+
* }
|
|
43
55
|
* if (!session) {
|
|
44
56
|
* router.replace('/login')
|
|
45
57
|
* }
|
|
46
|
-
* }, [session]);
|
|
58
|
+
* }, [session, isInitialized]);
|
|
47
59
|
*/
|
|
48
60
|
const useStytchMemberSession = () => {
|
|
49
61
|
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
|
|
@@ -52,9 +64,13 @@ const useStytchMemberSession = () => {
|
|
|
52
64
|
/**
|
|
53
65
|
* Returns the active Stytch organization.
|
|
54
66
|
* The Stytch SDKs are used for client-side authentication and session management.
|
|
67
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
55
68
|
* Check the fromCache property to determine if the organization data is from persistent storage.
|
|
56
69
|
* @example
|
|
57
|
-
* const {
|
|
70
|
+
* const {organization, isInitialized, fromCache} = useStytchOrganization();
|
|
71
|
+
* if (!isInitialized) {
|
|
72
|
+
* return <p>Loading...</p>;
|
|
73
|
+
* }
|
|
58
74
|
* return (<p>Welcome to {organization.organization_name}</p>);
|
|
59
75
|
*/
|
|
60
76
|
const useStytchOrganization = () => {
|
|
@@ -70,7 +86,7 @@ const useStytchOrganization = () => {
|
|
|
70
86
|
*
|
|
71
87
|
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
72
88
|
* @example
|
|
73
|
-
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
89
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
74
90
|
* return <button disabled={!isAuthorized}>Edit</button>
|
|
75
91
|
*/
|
|
76
92
|
const useStytchIsAuthorized = (resourceId, action) => {
|
|
@@ -78,14 +94,27 @@ const useStytchIsAuthorized = (resourceId, action) => {
|
|
|
78
94
|
const client = useStytchB2BClient();
|
|
79
95
|
const { session } = useStytchMemberSession();
|
|
80
96
|
const [isAuthorized, setIsAuthorized] = useAsyncState({
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
isInitialized: false,
|
|
98
|
+
fromCache: false,
|
|
99
|
+
isAuthorized: false,
|
|
83
100
|
});
|
|
84
101
|
useEffect(() => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
if (isStytchSSRProxy(client)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
setIsAuthorized({
|
|
106
|
+
isInitialized: true,
|
|
107
|
+
fromCache: true,
|
|
108
|
+
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
109
|
+
});
|
|
110
|
+
}, [action, client, resourceId, setIsAuthorized]);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (isStytchSSRProxy(client)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
|
|
116
|
+
setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
|
|
117
|
+
});
|
|
89
118
|
}, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
|
|
90
119
|
return isAuthorized;
|
|
91
120
|
};
|
|
@@ -114,8 +143,8 @@ const withStytchB2BClient = (Component) => {
|
|
|
114
143
|
const withStytchMember = (Component) => {
|
|
115
144
|
const WithStytchUser = (props) => {
|
|
116
145
|
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMember', 'StytchB2BProvider'));
|
|
117
|
-
const { member, fromCache } = useStytchMember();
|
|
118
|
-
return React.createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsFromCache: fromCache }));
|
|
146
|
+
const { member, isInitialized, fromCache } = useStytchMember();
|
|
147
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsInitialized: isInitialized, stytchMemberIsFromCache: fromCache })));
|
|
119
148
|
};
|
|
120
149
|
WithStytchUser.displayName = `withStytchMember(${Component.displayName || Component.name || 'Component'})`;
|
|
121
150
|
return WithStytchUser;
|
|
@@ -123,8 +152,8 @@ const withStytchMember = (Component) => {
|
|
|
123
152
|
const withStytchMemberSession = (Component) => {
|
|
124
153
|
const WithStytchSession = (props) => {
|
|
125
154
|
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMemberSession', 'StytchB2BProvider'));
|
|
126
|
-
const { session, fromCache } = useStytchMemberSession();
|
|
127
|
-
return React.createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsFromCache: fromCache }));
|
|
155
|
+
const { session, isInitialized, fromCache } = useStytchMemberSession();
|
|
156
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsInitialized: isInitialized, stytchMemberSessionIsFromCache: fromCache })));
|
|
128
157
|
};
|
|
129
158
|
WithStytchSession.displayName = `withStytchMemberSession(${Component.displayName || Component.name || 'Component'})`;
|
|
130
159
|
return WithStytchSession;
|
|
@@ -132,8 +161,8 @@ const withStytchMemberSession = (Component) => {
|
|
|
132
161
|
const withStytchOrganization = (Component) => {
|
|
133
162
|
const WithStytchOrganization = (props) => {
|
|
134
163
|
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchOrganization', 'StytchB2BProvider'));
|
|
135
|
-
const { organization, fromCache } = useStytchOrganization();
|
|
136
|
-
return React.createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsFromCache: fromCache }));
|
|
164
|
+
const { organization, isInitialized, fromCache } = useStytchOrganization();
|
|
165
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsInitialized: isInitialized, stytchOrganizationIsFromCache: fromCache })));
|
|
137
166
|
};
|
|
138
167
|
WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
|
|
139
168
|
return WithStytchOrganization;
|
|
@@ -182,38 +211,52 @@ const withStytchPermissions = (Component) => {
|
|
|
182
211
|
* The Stytch Context Provider.
|
|
183
212
|
* Wrap your application with this component in order to use Stytch everywhere in your app.
|
|
184
213
|
* @example
|
|
185
|
-
* const stytch =
|
|
214
|
+
* const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
186
215
|
*
|
|
187
|
-
*
|
|
216
|
+
* return (
|
|
188
217
|
* <StytchB2BProvider stytch={stytch}>
|
|
189
218
|
* <App />
|
|
190
|
-
* </
|
|
191
|
-
* document.getElementById('root'),
|
|
219
|
+
* </StytchB2BProvider>
|
|
192
220
|
* )
|
|
193
221
|
*/
|
|
194
|
-
const StytchB2BProvider = ({ stytch, children, }) => {
|
|
195
|
-
invariant(!useIsMounted__INTERNAL(),
|
|
196
|
-
invariant(typeof window !== 'undefined',
|
|
222
|
+
const StytchB2BProvider = ({ stytch, children, assumeHydrated = false, }) => {
|
|
223
|
+
invariant(!useIsMounted__INTERNAL(), 'You cannot render a <StytchB2BProvider> inside another <StytchB2BProvider>.');
|
|
224
|
+
invariant(!assumeHydrated || typeof window !== 'undefined', 'The `assumeHydrated` prop must be set to `false` when using StytchB2BProvider in a server environment.');
|
|
197
225
|
const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
226
|
+
const getHydratedState = useCallback(() => {
|
|
227
|
+
return {
|
|
228
|
+
member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
|
|
229
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
230
|
+
organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
|
|
231
|
+
};
|
|
232
|
+
}, [stytch]);
|
|
233
|
+
const getInitialState = () => {
|
|
234
|
+
return {
|
|
235
|
+
member: initialMember,
|
|
236
|
+
session: initialMemberSession,
|
|
237
|
+
organization: initialOrganization,
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
const [{ member, session, organization }, setClientState] = useAsyncState(() => assumeHydrated ? getHydratedState() : getInitialState());
|
|
241
|
+
// Store the initial value of `assumeHydrated` in a ref, because it is
|
|
242
|
+
// logically only relevant for the first render
|
|
243
|
+
const assumeHydratedRef = useRef(assumeHydrated);
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
if (isStytchSSRProxy(stytch)) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const updateState = () => {
|
|
249
|
+
setClientState((oldState) => mergeWithStableProps(oldState, getHydratedState()));
|
|
250
|
+
};
|
|
251
|
+
if (!assumeHydratedRef.current) {
|
|
252
|
+
updateState();
|
|
253
|
+
}
|
|
254
|
+
return stytch.onStateChange(updateState);
|
|
255
|
+
}, [getHydratedState, setClientState, stytch]);
|
|
213
256
|
return (React.createElement(StytchB2BContext.Provider, { value: ctx },
|
|
214
257
|
React.createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
215
258
|
React.createElement(StytchMemberContext.Provider, { value: member },
|
|
216
259
|
React.createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
217
260
|
};
|
|
218
261
|
|
|
219
|
-
export { StytchB2BProvider as S, useStytchB2BClient as a, useStytchMember as b, useStytchMemberSession as c,
|
|
262
|
+
export { StytchB2BProvider as S, useStytchB2BClient as a, useStytchMember as b, useStytchMemberSession as c, useStytchOrganization as d, useStytchIsAuthorized as e, withStytchMemberSession as f, withStytchOrganization as g, withStytchB2BClient as h, isUIClient as i, withStytchPermissions as j, useIsMounted__INTERNAL as u, withStytchMember as w };
|