@stytch/nextjs 21.4.3 → 21.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/StytchB2BContext-54aa990c.d.ts +272 -0
  3. package/dist/{StytchB2BContext-a2d58b5b.js → StytchB2BContext-54aa990c.js} +44 -40
  4. package/dist/StytchB2BContext-c5062f9b.d.ts +272 -0
  5. package/dist/{StytchB2BContext-fc9fdcb3.js → StytchB2BContext-c5062f9b.js} +43 -39
  6. package/dist/{StytchSSRProxy-4e34fb34.js → StytchSSRProxy-34c789b5.js} +3 -2
  7. package/dist/{StytchSSRProxy-c9d3bc41.js → StytchSSRProxy-86bc42b3.js} +3 -1
  8. package/dist/adminPortal/index.esm.js +3 -3
  9. package/dist/adminPortal/index.js +3 -3
  10. package/dist/b2b/index.d.ts +19 -23
  11. package/dist/b2b/index.esm.d.ts +19 -23
  12. package/dist/b2b/index.esm.js +19 -24
  13. package/dist/b2b/index.headless.esm.js +1 -1
  14. package/dist/b2b/index.headless.js +1 -1
  15. package/dist/b2b/index.js +18 -23
  16. package/dist/b2b/index.ui.esm.js +1 -1
  17. package/dist/b2b/index.ui.js +1 -1
  18. package/dist/errors-d9d5fbc8.d.ts +5 -0
  19. package/dist/index-b14d4efe.d.ts +1 -1
  20. package/dist/index.d.ts +93 -55
  21. package/dist/index.esm.d.ts +93 -55
  22. package/dist/index.esm.js +55 -66
  23. package/dist/index.headless.esm.js +1 -1
  24. package/dist/index.headless.js +1 -1
  25. package/dist/index.js +54 -65
  26. package/dist/index.ui.esm.js +1 -1
  27. package/dist/index.ui.js +1 -1
  28. package/dist/{useIsomorphicLayoutEffect-2962f7c7.d.ts → useIsomorphicLayoutEffect-1babb81e.d.ts} +3 -3
  29. package/dist/{useIsomorphicLayoutEffect-a2b587d2.d.ts → useIsomorphicLayoutEffect-65746ef3.d.ts} +3 -3
  30. package/package.json +5 -4
  31. package/dist/StytchB2BContext-a2d58b5b.d.ts +0 -177
  32. package/dist/StytchB2BContext-fc9fdcb3.d.ts +0 -177
  33. package/dist/errors-d9d48ed4.d.ts +0 -4
  34. package/dist/{StytchSSRProxy-4e34fb34.d.ts → StytchSSRProxy-34c789b5.d.ts} +0 -0
  35. package/dist/{StytchSSRProxy-c9d3bc41.d.ts → StytchSSRProxy-86bc42b3.d.ts} +0 -0
  36. package/dist/{useIsomorphicLayoutEffect-2962f7c7.js → useIsomorphicLayoutEffect-1babb81e.js} +6 -6
  37. package/dist/{useIsomorphicLayoutEffect-a2b587d2.js → useIsomorphicLayoutEffect-65746ef3.js} +6 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @stytch/nextjs
2
2
 
3
+ ## 21.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 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 `false` in `@stytch/nextjs`, which preserves the behavior from previous versions.
8
+
9
+ 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}`.
10
+
11
+ Unless you set `assumeHydrated={true}`, you should continue to check the initialized state of the provider by checking the `isInitialized` value (returned from hooks like `useStytchUser`, `useStytchSession`, `useStytchMember`, `useStytchMemberSession`, `useStytchOrganization`, and `useStytchIsAuthorized`) or `*IsInitialized` prop (injected by HOCs like `withStytchUser`, `withStytchSession`, `withStytchMember`, `withStytchMemberSession`, and `withStytchOrganization`) before relying on any other values.
12
+
13
+ ## 21.4.4
14
+
15
+ ### Patch Changes
16
+
17
+ - 54275c2: Make some minor improvements to JSDoc comments
18
+ - 54275c2: Add missing default generic type parameters
19
+
3
20
  ## 21.4.3
4
21
 
5
22
  ### Patch Changes
@@ -0,0 +1,272 @@
1
+ /// <reference types="react" />
2
+ import React from 'react';
3
+ import { ReactNode } from "react";
4
+ import { PermissionsMap } from '@stytch/core/public';
5
+ import { Member, MemberSession, Organization, StytchB2BUIClient } from '@stytch/vanilla-js/b2b';
6
+ import { StytchB2BHeadlessClient, StytchProjectConfigurationInput } from '@stytch/vanilla-js/b2b/headless';
7
+ /**
8
+ * The Stytch Client object passed in to <StytchB2BProvider /> in your application root.
9
+ * Either a StytchB2BUIClient or StytchB2BHeadlessClient.
10
+ */
11
+ type StytchB2BClient<TProjectConfiguration extends StytchProjectConfigurationInput> = StytchB2BHeadlessClient<TProjectConfiguration> | StytchB2BUIClient<TProjectConfiguration>;
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 = {
27
+ /**
28
+ * Either the active {@link Member} object, or null if the member is not logged in.
29
+ */
30
+ member: Member | null;
31
+ /**
32
+ * If true, indicates that the value returned is from the application cache and a state refresh is in progress.
33
+ */
34
+ fromCache: boolean;
35
+ /**
36
+ * If true, indicates that the SDK has completed initialization.
37
+ */
38
+ isInitialized: true;
39
+ };
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 = {
56
+ /**
57
+ * Either the active {@link MemberSession} object, or null if the member is not logged in.
58
+ */
59
+ session: MemberSession | null;
60
+ /**
61
+ * If true, indicates that the value returned is from the application cache and a state refresh is in progress.
62
+ */
63
+ fromCache: boolean;
64
+ /**
65
+ * If true, indicates that the SDK has completed initialization.
66
+ */
67
+ isInitialized: true;
68
+ };
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 = {
85
+ /**
86
+ * Either the active {@link Organization} object, or null if the member is not logged in.
87
+ */
88
+ organization: Organization | null;
89
+ /**
90
+ * If true, indicates that the value returned is from the application cache and a state refresh is in progress.
91
+ */
92
+ fromCache: boolean;
93
+ /**
94
+ * If true, indicates that the SDK has completed initialization.
95
+ */
96
+ isInitialized: true;
97
+ };
98
+ type SWROrganization<TAlwaysInitialized extends boolean = boolean> = TAlwaysInitialized extends true ? SWROrganizationInitialized : SWROrganizationInitialized | SWROrganizationUninitialized;
99
+ declare const useIsMounted__INTERNAL: () => boolean;
100
+ declare const isUIClient: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration>>(client: StytchB2BClient<TProjectConfiguration>) => client is StytchB2BUIClient<TProjectConfiguration>;
101
+ /**
102
+ * Returns the active Member.
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.
105
+ * Check the fromCache property to determine if the member data is from persistent storage.
106
+ * @example
107
+ * const {member, isInitialized, fromCache} = useStytchMember();
108
+ * if (!isInitialized) {
109
+ * return <p>Loading...</p>;
110
+ * }
111
+ * return (<h1>Welcome, {member.name}</h1>);
112
+ */
113
+ declare const useStytchMember: <TAssumeHydrated extends boolean = false>() => SWRMember<TAssumeHydrated>;
114
+ /**
115
+ * Returns the active member's Stytch member session.
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.
118
+ * Check the fromCache property to determine if the session data is from persistent storage.
119
+ * @example
120
+ * const {session, isInitialized, fromCache} = useStytchMemberSession();
121
+ * useEffect(() => {
122
+ * if (!isInitialized) {
123
+ * return;
124
+ * }
125
+ * if (!session) {
126
+ * router.replace('/login')
127
+ * }
128
+ * }, [session, isInitialized]);
129
+ */
130
+ declare const useStytchMemberSession: <TAssumeHydrated extends boolean = false>() => SWRMemberSession<TAssumeHydrated>;
131
+ /**
132
+ * Returns the active Stytch organization.
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.
135
+ * Check the fromCache property to determine if the organization data is from persistent storage.
136
+ * @example
137
+ * const {organization, isInitialized, fromCache} = useStytchOrganization();
138
+ * if (!isInitialized) {
139
+ * return <p>Loading...</p>;
140
+ * }
141
+ * return (<p>Welcome to {organization.organization_name}</p>);
142
+ */
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 = {
159
+ /**
160
+ * Whether the logged-in member is allowed to perform the specified action on the specified resource.
161
+ */
162
+ isAuthorized: boolean;
163
+ /**
164
+ * If true, indicates that the value returned is from the application cache and a state refresh is in progress.
165
+ */
166
+ fromCache: boolean;
167
+ /**
168
+ * If true, indicates that the SDK has completed initialization.
169
+ */
170
+ isInitialized: boolean;
171
+ };
172
+ type SWRIsAuthorized<TAlwaysInitialized extends boolean> = TAlwaysInitialized extends true ? SWRIsAuthorizedInitialized : SWRIsAuthorizedInitialized | SWRIsAuthorizedUninitialized;
173
+ /**
174
+ * Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
175
+ * Returns `true` if the member can perform the action, `false` otherwise.
176
+ *
177
+ * If the member is not logged in, this method will always return false.
178
+ * If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
179
+ *
180
+ * Remember - authorization checks for sensitive actions should always occur on the backend as well.
181
+ * @example
182
+ * const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
183
+ * return <button disabled={!isAuthorized}>Edit</button>
184
+ */
185
+ declare const useStytchIsAuthorized: <TAssumeHydrated extends boolean = false>(resourceId: string, action: string) => SWRIsAuthorized<TAssumeHydrated>;
186
+ /**
187
+ * Returns the Stytch B2B client stored in the Stytch context.
188
+ *
189
+ * @example
190
+ * const stytch = useStytchB2BClient();
191
+ * useEffect(() => {
192
+ * stytch.magicLinks.authenticate('...')
193
+ * }, [stytch]);
194
+ */
195
+ declare const useStytchB2BClient: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration> = Stytch.DefaultProjectConfiguration>() => StytchB2BHeadlessClient<TProjectConfiguration>;
196
+ declare const withStytchB2BClient: <T extends object, TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration>>(Component: React.ComponentType<T & {
197
+ stytch: StytchB2BHeadlessClient<TProjectConfiguration>;
198
+ }>) => React.ComponentType<T>;
199
+ declare const withStytchMember: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
200
+ stytchMember: Member | null;
201
+ stytchMemberIsInitialized: boolean;
202
+ stytchMemberIsFromCache: boolean;
203
+ }>) => React.ComponentType<T>;
204
+ declare const withStytchMemberSession: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
205
+ stytchMemberSession: MemberSession | null;
206
+ stytchMemberSessionIsInitialized: boolean;
207
+ stytchMemberSessionIsFromCache: boolean;
208
+ }>) => React.ComponentType<T>;
209
+ declare const withStytchOrganization: <T extends object, TAssumeHydrated extends boolean = false>(Component: React.ComponentType<T & {
210
+ stytchOrganization: Organization | null;
211
+ stytchOrganizationIsInitialized: boolean;
212
+ stytchOrganizationIsFromCache: boolean;
213
+ }>) => React.ComponentType<T>;
214
+ /**
215
+ * Wrap your component with this HOC in order to receive the permissions for the logged-in member.
216
+ * Evaluates all permissions granted to the logged-in member.
217
+ * Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
218
+ * Each boolean will be `true` if the member can perform the action, `false` otherwise.
219
+ *
220
+ * If the member is not logged in, all values will be false.
221
+ *
222
+ * Remember - authorization checks for sensitive actions should always occur on the backend as well.
223
+ * @example
224
+ * type Permissions = {
225
+ * document: 'create' | 'read' | 'write
226
+ * image: 'create' | 'read'
227
+ * }
228
+ *
229
+ * const MyComponent = (props) => {
230
+ * const canEditDocuments = props.stytchPermissions.document.edit;
231
+ * const canReadImages = props.stytchPermissions.image.read;
232
+ * }
233
+ * return withStytchPermissions<Permissions>(MyComponent)
234
+ */
235
+ declare const withStytchPermissions: <Permissions_1 extends Record<string, string>, T extends object>(Component: React.ComponentType<T & {
236
+ stytchPermissions: PermissionsMap<Permissions_1>;
237
+ }>) => React.ComponentType<T>;
238
+ interface StytchB2BProviderProps<TProjectConfiguration extends StytchProjectConfigurationInput = Stytch.DefaultProjectConfiguration> {
239
+ /**
240
+ * A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
241
+ */
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;
257
+ children?: ReactNode;
258
+ }
259
+ /**
260
+ * The Stytch Context Provider.
261
+ * Wrap your application with this component in order to use Stytch everywhere in your app.
262
+ * @example
263
+ * const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
264
+ *
265
+ * return (
266
+ * <StytchB2BProvider stytch={stytch}>
267
+ * <App />
268
+ * </StytchB2BProvider>
269
+ * )
270
+ */
271
+ declare const StytchB2BProvider: <TProjectConfiguration extends Partial<import("@stytch/core/public").StytchProjectConfiguration> = Stytch.DefaultProjectConfiguration>({ stytch, children, assumeHydrated, }: StytchB2BProviderProps<TProjectConfiguration>) => JSX.Element;
272
+ export { useIsMounted__INTERNAL, isUIClient, useStytchMember, useStytchMemberSession, useStytchOrganization, useStytchIsAuthorized, useStytchB2BClient, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions, StytchB2BProviderProps, StytchB2BProvider };
@@ -1,6 +1,6 @@
1
- import React, { createContext, useContext, useEffect, useMemo } from 'react';
2
- import { i as invariant, u as useAsyncState, m as mergeWithStableProps } from './useIsomorphicLayoutEffect-2962f7c7.js';
3
- import { i as isStytchSSRProxy, n as noProviderError } from './StytchSSRProxy-4e34fb34.js';
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 { i as isStytchSSRProxy, n as noProviderError } from './StytchSSRProxy-34c789b5.js';
4
4
 
5
5
  const initialMember = {
6
6
  member: null,
@@ -17,20 +17,19 @@ const initialOrganization = {
17
17
  fromCache: false,
18
18
  isInitialized: false,
19
19
  };
20
- const StytchContext = createContext({ isMounted: false });
20
+ const StytchB2BContext = createContext({ isMounted: false });
21
21
  const StytchMemberContext = createContext(initialMember);
22
22
  const StytchMemberSessionContext = createContext(initialMemberSession);
23
23
  const StytchOrganizationContext = createContext(initialOrganization);
24
- const useIsMounted__INTERNAL = () => useContext(StytchContext).isMounted;
24
+ const useIsMounted__INTERNAL = () => useContext(StytchB2BContext).isMounted;
25
25
  const isUIClient = (client) => {
26
26
  return client.mount !== undefined;
27
27
  };
28
28
  /**
29
- * Returns the active member.
29
+ * Returns the active Member.
30
30
  * The Stytch SDKs are used for client-side authentication and session management.
31
31
  * Check the isInitialized property to determine if the SDK has completed initialization.
32
- * Check the fromCache property to determine if the session data is from persistent storage.
33
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
32
+ * Check the fromCache property to determine if the member data is from persistent storage.
34
33
  * @example
35
34
  * const {member, isInitialized, fromCache} = useStytchMember();
36
35
  * if (!isInitialized) {
@@ -43,11 +42,10 @@ const useStytchMember = () => {
43
42
  return useContext(StytchMemberContext);
44
43
  };
45
44
  /**
46
- * Returns the member's active Stytch member session.
45
+ * Returns the active member's Stytch member session.
47
46
  * The Stytch SDKs are used for client-side authentication and session management.
48
47
  * Check the isInitialized property to determine if the SDK has completed initialization.
49
48
  * Check the fromCache property to determine if the session data is from persistent storage.
50
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
51
49
  * @example
52
50
  * const {session, isInitialized, fromCache} = useStytchMemberSession();
53
51
  * useEffect(() => {
@@ -67,8 +65,7 @@ const useStytchMemberSession = () => {
67
65
  * Returns the active Stytch organization.
68
66
  * The Stytch SDKs are used for client-side authentication and session management.
69
67
  * Check the isInitialized property to determine if the SDK has completed initialization.
70
- * Check the fromCache property to determine if the session data is from persistent storage.
71
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
68
+ * Check the fromCache property to determine if the organization data is from persistent storage.
72
69
  * @example
73
70
  * const {organization, isInitialized, fromCache} = useStytchOrganization();
74
71
  * if (!isInitialized) {
@@ -89,7 +86,7 @@ const useStytchOrganization = () => {
89
86
  *
90
87
  * Remember - authorization checks for sensitive actions should always occur on the backend as well.
91
88
  * @example
92
- * const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
89
+ * const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
93
90
  * return <button disabled={!isAuthorized}>Edit</button>
94
91
  */
95
92
  const useStytchIsAuthorized = (resourceId, action) => {
@@ -122,16 +119,16 @@ const useStytchIsAuthorized = (resourceId, action) => {
122
119
  return isAuthorized;
123
120
  };
124
121
  /**
125
- * Returns the Stytch client stored in the Stytch context.
122
+ * Returns the Stytch B2B client stored in the Stytch context.
126
123
  *
127
124
  * @example
128
- * const stytch = useStytch();
125
+ * const stytch = useStytchB2BClient();
129
126
  * useEffect(() => {
130
127
  * stytch.magicLinks.authenticate('...')
131
128
  * }, [stytch]);
132
129
  */
133
130
  const useStytchB2BClient = () => {
134
- const ctx = useContext(StytchContext);
131
+ const ctx = useContext(StytchB2BContext);
135
132
  invariant(ctx.isMounted, noProviderError('useStytchB2BClient', 'StytchB2BProvider'));
136
133
  return ctx.client;
137
134
  };
@@ -212,7 +209,7 @@ const withStytchPermissions = (Component) => {
212
209
  };
213
210
  /**
214
211
  * The Stytch Context Provider.
215
- * Wrap your application with this component in `_app.js` in order to use Stytch everywhere in your app.
212
+ * Wrap your application with this component in order to use Stytch everywhere in your app.
216
213
  * @example
217
214
  * const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
218
215
  *
@@ -222,34 +219,41 @@ const withStytchPermissions = (Component) => {
222
219
  * </StytchB2BProvider>
223
220
  * )
224
221
  */
225
- const StytchB2BProvider = ({ stytch, children, }) => {
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.');
226
225
  const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
227
- const [{ member, session, organization }, setClientState] = useAsyncState({
228
- member: initialMember,
229
- session: initialMemberSession,
230
- organization: initialOrganization,
231
- });
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);
232
244
  useEffect(() => {
233
245
  if (isStytchSSRProxy(stytch)) {
234
246
  return;
235
247
  }
236
- setClientState({
237
- member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
238
- session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
239
- organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
240
- });
241
- return stytch.onStateChange(() => {
242
- setClientState((oldState) => {
243
- const newState = {
244
- member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
245
- session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
246
- organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
247
- };
248
- return mergeWithStableProps(oldState, newState);
249
- });
250
- });
251
- }, [setClientState, stytch]);
252
- return (React.createElement(StytchContext.Provider, { value: ctx },
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]);
256
+ return (React.createElement(StytchB2BContext.Provider, { value: ctx },
253
257
  React.createElement(StytchOrganizationContext.Provider, { value: organization },
254
258
  React.createElement(StytchMemberContext.Provider, { value: member },
255
259
  React.createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));