@stytch/nextjs 16.0.1 → 17.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @stytch/nextjs
2
2
 
3
+ ## 17.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 50de202: Fix B2B headless entrypoint to import `@stytch/vanilla-js` rather than bundle it
8
+ - @stytch/vanilla-js@4.4.3
9
+
10
+ ## 17.0.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 223e30e: Add `useStytchOrganization` hook for B2B
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [223e30e]
19
+ - @stytch/vanilla-js@4.2.0
20
+
3
21
  ## 16.0.1
4
22
 
5
23
  ### Patch Changes
@@ -1,7 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  import React from "react";
3
3
  import { ReactNode } from "react";
4
- import { Member, MemberSession, StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
4
+ import { Member, MemberSession, Organization, StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
5
5
  import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
6
6
  import { PermissionsMap } from "@stytch/core/public";
7
7
  import { Callbacks, StyleConfig, StytchB2BUIConfig } from "@stytch/vanilla-js";
@@ -28,6 +28,15 @@ type SWRMemberSession = {
28
28
  fromCache: boolean;
29
29
  isInitialized: true;
30
30
  };
31
+ type SWROrganization = {
32
+ organization: null;
33
+ fromCache: false;
34
+ isInitialized: false;
35
+ } | {
36
+ organization: Organization | null;
37
+ fromCache: boolean;
38
+ isInitialized: true;
39
+ };
31
40
  /**
32
41
  * Returns the active member.
33
42
  * The Stytch SDKs are used for client-side authentication and session management.
@@ -60,6 +69,20 @@ declare const useStytchMember: () => SWRMember;
60
69
  * }, [session, isInitialized]);
61
70
  */
62
71
  declare const useStytchMemberSession: () => SWRMemberSession;
72
+ /**
73
+ * Returns the active Stytch organization.
74
+ * The Stytch SDKs are used for client-side authentication and session management.
75
+ * Check the isInitialized property to determine if the SDK has completed initialization.
76
+ * Check the fromCache property to determine if the session data is from persistent storage.
77
+ * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
78
+ * @example
79
+ * const {organization, isInitialized, fromCache} = useStytchOrganization();
80
+ * if (!isInitialized) {
81
+ * return <p>Loading...</p>;
82
+ * }
83
+ * return (<p>Welcome to {organization.organization_name}</p>);
84
+ */
85
+ declare const useStytchOrganization: () => SWROrganization;
63
86
  type SWRIsAuthorized = {
64
87
  isAuthorized: boolean;
65
88
  fromCache: boolean;
@@ -101,6 +124,11 @@ declare const withStytchMemberSession: <T extends object>(Component: React.Compo
101
124
  stytchMemberSessionIsInitialized: boolean;
102
125
  stytchMemberSessionIsFromCache: boolean;
103
126
  }>) => React.ComponentType<T>;
127
+ declare const withStytchOrganization: <T extends object>(Component: React.ComponentType<T & {
128
+ stytchOrganization: Organization | null;
129
+ stytchOrganizationIsInitialized: boolean;
130
+ stytchOrganizationIsFromCache: boolean;
131
+ }>) => React.ComponentType<T>;
104
132
  /**
105
133
  * Wrap your component with this HOC in order to receive the permissions for the logged-in member.
106
134
  * Evaluates all permissions granted to the logged-in member.
@@ -247,5 +275,5 @@ interface StytchB2BProps {
247
275
  * @param props {@link StytchB2BProps}
248
276
  */
249
277
  declare const StytchB2B: ({ styles, callbacks, config }: StytchB2BProps) => React.JSX.Element;
250
- export { StytchB2BProvider, useStytchB2BClient, useStytchMemberSession, useStytchMember, useStytchIsAuthorized, withStytchB2BClient, withStytchMemberSession, withStytchMember, withStytchPermissions, StytchB2B };
278
+ export { StytchB2BProvider, useStytchB2BClient, useStytchMemberSession, useStytchMember, useStytchIsAuthorized, useStytchOrganization, withStytchB2BClient, withStytchMemberSession, withStytchMember, withStytchOrganization, withStytchPermissions, StytchB2B };
251
279
  export type { StytchB2BProviderProps };
@@ -1,7 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  import React from "react";
3
3
  import { ReactNode } from "react";
4
- import { Member, MemberSession, StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
4
+ import { Member, MemberSession, Organization, StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
5
5
  import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
6
6
  import { PermissionsMap } from "@stytch/core/public";
7
7
  import { Callbacks, StyleConfig, StytchB2BUIConfig } from "@stytch/vanilla-js";
@@ -28,6 +28,15 @@ type SWRMemberSession = {
28
28
  fromCache: boolean;
29
29
  isInitialized: true;
30
30
  };
31
+ type SWROrganization = {
32
+ organization: null;
33
+ fromCache: false;
34
+ isInitialized: false;
35
+ } | {
36
+ organization: Organization | null;
37
+ fromCache: boolean;
38
+ isInitialized: true;
39
+ };
31
40
  /**
32
41
  * Returns the active member.
33
42
  * The Stytch SDKs are used for client-side authentication and session management.
@@ -60,6 +69,20 @@ declare const useStytchMember: () => SWRMember;
60
69
  * }, [session, isInitialized]);
61
70
  */
62
71
  declare const useStytchMemberSession: () => SWRMemberSession;
72
+ /**
73
+ * Returns the active Stytch organization.
74
+ * The Stytch SDKs are used for client-side authentication and session management.
75
+ * Check the isInitialized property to determine if the SDK has completed initialization.
76
+ * Check the fromCache property to determine if the session data is from persistent storage.
77
+ * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
78
+ * @example
79
+ * const {organization, isInitialized, fromCache} = useStytchOrganization();
80
+ * if (!isInitialized) {
81
+ * return <p>Loading...</p>;
82
+ * }
83
+ * return (<p>Welcome to {organization.organization_name}</p>);
84
+ */
85
+ declare const useStytchOrganization: () => SWROrganization;
63
86
  type SWRIsAuthorized = {
64
87
  isAuthorized: boolean;
65
88
  fromCache: boolean;
@@ -101,6 +124,11 @@ declare const withStytchMemberSession: <T extends object>(Component: React.Compo
101
124
  stytchMemberSessionIsInitialized: boolean;
102
125
  stytchMemberSessionIsFromCache: boolean;
103
126
  }>) => React.ComponentType<T>;
127
+ declare const withStytchOrganization: <T extends object>(Component: React.ComponentType<T & {
128
+ stytchOrganization: Organization | null;
129
+ stytchOrganizationIsInitialized: boolean;
130
+ stytchOrganizationIsFromCache: boolean;
131
+ }>) => React.ComponentType<T>;
104
132
  /**
105
133
  * Wrap your component with this HOC in order to receive the permissions for the logged-in member.
106
134
  * Evaluates all permissions granted to the logged-in member.
@@ -247,5 +275,5 @@ interface StytchB2BProps {
247
275
  * @param props {@link StytchB2BProps}
248
276
  */
249
277
  declare const StytchB2B: ({ styles, callbacks, config }: StytchB2BProps) => React.JSX.Element;
250
- export { StytchB2BProvider, useStytchB2BClient, useStytchMemberSession, useStytchMember, useStytchIsAuthorized, withStytchB2BClient, withStytchMemberSession, withStytchMember, withStytchPermissions, StytchB2B };
278
+ export { StytchB2BProvider, useStytchB2BClient, useStytchMemberSession, useStytchMember, useStytchIsAuthorized, useStytchOrganization, withStytchB2BClient, withStytchMemberSession, withStytchMember, withStytchOrganization, withStytchPermissions, StytchB2B };
251
279
  export type { StytchB2BProviderProps };
@@ -44,9 +44,15 @@ const initialMemberSession = {
44
44
  fromCache: false,
45
45
  isInitialized: false,
46
46
  };
47
+ const initialOrganization = {
48
+ organization: null,
49
+ fromCache: false,
50
+ isInitialized: false,
51
+ };
47
52
  const StytchContext = createContext({ isMounted: false });
48
53
  const StytchMemberContext = createContext(initialMember);
49
54
  const StytchMemberSessionContext = createContext(initialMemberSession);
55
+ const StytchOrganizationContext = createContext(initialOrganization);
50
56
  const useIsMounted__INTERNAL = () => useContext(StytchContext).isMounted;
51
57
  const isUIClient = (client) => {
52
58
  return client.mount !== undefined;
@@ -89,6 +95,23 @@ const useStytchMemberSession = () => {
89
95
  invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
90
96
  return useContext(StytchMemberSessionContext);
91
97
  };
98
+ /**
99
+ * Returns the active Stytch organization.
100
+ * The Stytch SDKs are used for client-side authentication and session management.
101
+ * Check the isInitialized property to determine if the SDK has completed initialization.
102
+ * Check the fromCache property to determine if the session data is from persistent storage.
103
+ * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
104
+ * @example
105
+ * const {organization, isInitialized, fromCache} = useStytchOrganization();
106
+ * if (!isInitialized) {
107
+ * return <p>Loading...</p>;
108
+ * }
109
+ * return (<p>Welcome to {organization.organization_name}</p>);
110
+ */
111
+ const useStytchOrganization = () => {
112
+ invariant(useIsMounted__INTERNAL(), noProviderError('useStytchOrganization', 'StytchB2BProvider'));
113
+ return useContext(StytchOrganizationContext);
114
+ };
92
115
  /**
93
116
  * Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
94
117
  * Returns `true` if the member can perform the action, `false` otherwise.
@@ -119,7 +142,7 @@ const useStytchIsAuthorized = (resourceId, action) => {
119
142
  fromCache: true,
120
143
  isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
121
144
  });
122
- }, []);
145
+ }, [action, client, resourceId, setIsAuthorized]);
123
146
  useEffect(() => {
124
147
  if (isStytchSSRProxy(client)) {
125
148
  return;
@@ -127,7 +150,7 @@ const useStytchIsAuthorized = (resourceId, action) => {
127
150
  client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
128
151
  setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
129
152
  });
130
- }, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action]);
153
+ }, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
131
154
  return isAuthorized;
132
155
  };
133
156
  /**
@@ -170,6 +193,15 @@ const withStytchMemberSession = (Component) => {
170
193
  WithStytchSession.displayName = `withStytchMemberSession(${Component.displayName || Component.name || 'Component'})`;
171
194
  return WithStytchSession;
172
195
  };
196
+ const withStytchOrganization = (Component) => {
197
+ const WithStytchOrganization = (props) => {
198
+ invariant(useIsMounted__INTERNAL(), noProviderError('withStytchOrganization', 'StytchB2BProvider'));
199
+ const { organization, isInitialized, fromCache } = useStytchOrganization();
200
+ return (React.createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsInitialized: isInitialized, stytchOrganizationIsFromCache: fromCache })));
201
+ };
202
+ WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
203
+ return WithStytchOrganization;
204
+ };
173
205
  /**
174
206
  * Wrap your component with this HOC in order to receive the permissions for the logged-in member.
175
207
  * Evaluates all permissions granted to the logged-in member.
@@ -201,7 +233,7 @@ const withStytchPermissions = (Component) => {
201
233
  client.rbac
202
234
  .allPermissions()
203
235
  .then((permissions) => setPermissions({ loaded: true, value: permissions }));
204
- }, [client, session === null || session === void 0 ? void 0 : session.roles]);
236
+ }, [client, session === null || session === void 0 ? void 0 : session.roles, setPermissions]);
205
237
  if (!permissions.loaded) {
206
238
  return null;
207
239
  }
@@ -226,6 +258,7 @@ const StytchB2BProvider = ({ stytch, children }) => {
226
258
  const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
227
259
  const [member, setMember] = useAsyncState(initialMember);
228
260
  const [session, setMemberSession] = useAsyncState(initialMemberSession);
261
+ const [organization, setOrganization] = useAsyncState(initialOrganization);
229
262
  useEffect(() => {
230
263
  if (isStytchSSRProxy(stytch)) {
231
264
  return;
@@ -240,18 +273,36 @@ const StytchB2BProvider = ({ stytch, children }) => {
240
273
  fromCache: true,
241
274
  isInitialized: true,
242
275
  });
276
+ setOrganization({
277
+ organization: stytch.organization.getSync(),
278
+ fromCache: true,
279
+ isInitialized: true,
280
+ });
243
281
  const unsubscribeMember = stytch.self.onChange((member) => setMember({ member, fromCache: false, isInitialized: true }));
244
282
  const unsubscribeMemberSession = stytch.session.onChange((session) => setMemberSession({ session, fromCache: false, isInitialized: true }));
283
+ const unsubscribeOrganization = stytch.organization.onChange((organization) => setOrganization({ organization, fromCache: false, isInitialized: true }));
245
284
  return () => {
246
285
  unsubscribeMember();
247
286
  unsubscribeMemberSession();
287
+ unsubscribeOrganization();
288
+ };
289
+ }, [stytch, setMember, setMemberSession, setOrganization]);
290
+ const allValuesReady = !!member.member === !!session.session && !!session.session === !!organization.organization;
291
+ const finalValues = allValuesReady
292
+ ? {
293
+ member,
294
+ session,
295
+ organization,
296
+ }
297
+ : {
298
+ member: initialMember,
299
+ session: initialMemberSession,
300
+ organization: initialOrganization,
248
301
  };
249
- }, [stytch, setMember, setMemberSession]);
250
- const finalMemberSession = !!session.session === !!member.member ? session : initialMemberSession;
251
- const finalMember = !!session.session === !!member.member ? member : initialMember;
252
302
  return (React.createElement(StytchContext.Provider, { value: ctx },
253
- React.createElement(StytchMemberContext.Provider, { value: finalMember },
254
- React.createElement(StytchMemberSessionContext.Provider, { value: finalMemberSession }, children))));
303
+ React.createElement(StytchOrganizationContext.Provider, { value: finalValues.organization },
304
+ React.createElement(StytchMemberContext.Provider, { value: finalValues.member },
305
+ React.createElement(StytchMemberSessionContext.Provider, { value: finalValues.session }, children)))));
255
306
  };
256
307
 
257
308
  /**
@@ -309,8 +360,9 @@ const StytchB2B = ({ styles, callbacks, config }) => {
309
360
  elementId: `#${containerEl.current.id}`,
310
361
  styles,
311
362
  });
363
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- SDK-1354
312
364
  }, [stytchClient, styles, callbacks]);
313
365
  return React.createElement("div", { ref: containerEl });
314
366
  };
315
367
 
316
- export { StytchB2B, StytchB2BProvider, useStytchB2BClient, useStytchIsAuthorized, useStytchMember, useStytchMemberSession, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchPermissions };
368
+ export { StytchB2B, StytchB2BProvider, useStytchB2BClient, useStytchIsAuthorized, useStytchMember, useStytchMemberSession, useStytchOrganization, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions };
@@ -12,5 +12,5 @@ import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
12
12
  * )
13
13
  * @returns A {@link StytchB2BHeadlessClient}
14
14
  */
15
- declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
15
+ declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("@stytch/core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
16
16
  export { createStytchB2BHeadlessClient };
@@ -12,5 +12,5 @@ import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
12
12
  * )
13
13
  * @returns A {@link StytchB2BHeadlessClient}
14
14
  */
15
- declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
15
+ declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("@stytch/core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
16
16
  export { createStytchB2BHeadlessClient };