@stytch/nextjs 19.0.0 → 20.1.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 +19 -0
- package/README.md +1 -1
- package/b2b/adminPortal/package.json +6 -0
- package/dist/StytchB2BContext-162fadb4.d.ts +177 -0
- package/dist/StytchB2BContext-162fadb4.js +258 -0
- package/dist/StytchB2BContext-82437b10.d.ts +177 -0
- package/dist/StytchB2BContext-82437b10.js +276 -0
- package/dist/StytchSSRProxy-14916009.d.ts +3 -0
- package/dist/StytchSSRProxy-14916009.js +47 -0
- package/dist/StytchSSRProxy-63bc6323.d.ts +3 -0
- package/dist/StytchSSRProxy-63bc6323.js +52 -0
- package/dist/adminPortal/index.d.ts +34 -0
- package/dist/adminPortal/index.esm.d.ts +34 -0
- package/dist/adminPortal/index.esm.js +9519 -0
- package/dist/adminPortal/index.js +9527 -0
- package/dist/async-86a7f0d6.d.ts +18 -0
- package/dist/async-86a7f0d6.js +81 -0
- package/dist/async-b1e10055.d.ts +18 -0
- package/dist/async-b1e10055.js +77 -0
- package/dist/b2b/index.d.ts +3 -174
- package/dist/b2b/index.esm.d.ts +3 -174
- package/dist/b2b/index.esm.js +6 -340
- package/dist/b2b/index.headless.esm.js +1 -38
- package/dist/b2b/index.headless.js +2 -39
- package/dist/b2b/index.js +18 -353
- package/dist/b2b/index.ui.esm.js +1 -38
- package/dist/b2b/index.ui.js +2 -39
- package/dist/createDeepEqual-5555f2e1.d.ts +5 -0
- package/dist/errors-d9d48ed4.d.ts +4 -0
- package/dist/index-b14d4efe.d.ts +2 -0
- package/dist/index.esm.js +3 -86
- package/dist/index.headless.esm.js +1 -38
- package/dist/index.headless.js +2 -39
- package/dist/index.js +17 -100
- package/dist/index.ui.esm.js +1 -38
- package/dist/index.ui.js +2 -39
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @stytch/nextjs
|
|
2
2
|
|
|
3
|
+
## 20.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a99f21b8: Add `AdminPortalSSO` component to `@stytch/nextjs/b2b/adminPortal`
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [0f448e7e]
|
|
12
|
+
- Updated dependencies [a99f21b8]
|
|
13
|
+
- @stytch/vanilla-js@4.13.0
|
|
14
|
+
|
|
15
|
+
## 20.0.0
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [cbab0c30]
|
|
20
|
+
- @stytch/vanilla-js@4.12.0
|
|
21
|
+
|
|
3
22
|
## 19.0.0
|
|
4
23
|
|
|
5
24
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ import { createStytchB2BUIClient } from '@stytch/nextjs/b2b/ui';
|
|
|
25
25
|
import { createStytchB2BHeadlessClient } from '@stytch/nextjs/b2b/headless';
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
For full documentation please refer to Stytch's javascript SDK documentation on https://stytch.com/docs/sdks.
|
|
28
|
+
For full documentation please refer to Stytch's javascript SDK documentation on https://stytch.com/docs/sdks/javascript-sdk.
|
|
29
29
|
|
|
30
30
|
## Example Usage
|
|
31
31
|
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
import { Member, MemberSession, Organization, StytchB2BUIClient } from '@stytch/vanilla-js/b2b';
|
|
5
|
+
import { StytchB2BHeadlessClient } from '@stytch/vanilla-js/b2b/headless';
|
|
6
|
+
import { PermissionsMap } from '@stytch/core/public';
|
|
7
|
+
/**
|
|
8
|
+
* The Stytch Client object passed in to <StytchProvider /> in your `_app.js`.
|
|
9
|
+
* Either a StytchUIClient or StytchHeadlessClient.
|
|
10
|
+
*/
|
|
11
|
+
type StytchB2BClient = StytchB2BHeadlessClient | StytchB2BUIClient;
|
|
12
|
+
type SWRMember = {
|
|
13
|
+
member: null;
|
|
14
|
+
fromCache: false;
|
|
15
|
+
isInitialized: false;
|
|
16
|
+
} | {
|
|
17
|
+
member: Member | null;
|
|
18
|
+
fromCache: boolean;
|
|
19
|
+
isInitialized: true;
|
|
20
|
+
};
|
|
21
|
+
type SWRMemberSession = {
|
|
22
|
+
session: null;
|
|
23
|
+
fromCache: false;
|
|
24
|
+
isInitialized: false;
|
|
25
|
+
} | {
|
|
26
|
+
session: MemberSession | null;
|
|
27
|
+
fromCache: boolean;
|
|
28
|
+
isInitialized: true;
|
|
29
|
+
};
|
|
30
|
+
type SWROrganization = {
|
|
31
|
+
organization: null;
|
|
32
|
+
fromCache: false;
|
|
33
|
+
isInitialized: false;
|
|
34
|
+
} | {
|
|
35
|
+
organization: Organization | null;
|
|
36
|
+
fromCache: boolean;
|
|
37
|
+
isInitialized: true;
|
|
38
|
+
};
|
|
39
|
+
declare const useIsMounted__INTERNAL: () => boolean;
|
|
40
|
+
declare const isUIClient: (client: StytchB2BClient) => client is StytchB2BUIClient;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the active member.
|
|
43
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
44
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
45
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
46
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
47
|
+
* @example
|
|
48
|
+
* const {member, isInitialized, fromCache} = useStytchMember();
|
|
49
|
+
* if (!isInitialized) {
|
|
50
|
+
* return <p>Loading...</p>;
|
|
51
|
+
* }
|
|
52
|
+
* return (<h1>Welcome, {member.name}</h1>);
|
|
53
|
+
*/
|
|
54
|
+
declare const useStytchMember: () => SWRMember;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the member's active Stytch member session.
|
|
57
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
58
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
59
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
60
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
61
|
+
* @example
|
|
62
|
+
* const {session, isInitialized, fromCache} = useStytchMemberSession();
|
|
63
|
+
* useEffect(() => {
|
|
64
|
+
* if (!isInitialized) {
|
|
65
|
+
* return;
|
|
66
|
+
* }
|
|
67
|
+
* if (!session) {
|
|
68
|
+
* router.replace('/login')
|
|
69
|
+
* }
|
|
70
|
+
* }, [session, isInitialized]);
|
|
71
|
+
*/
|
|
72
|
+
declare const useStytchMemberSession: () => SWRMemberSession;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the active Stytch organization.
|
|
75
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
76
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
77
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
78
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
79
|
+
* @example
|
|
80
|
+
* const {organization, isInitialized, fromCache} = useStytchOrganization();
|
|
81
|
+
* if (!isInitialized) {
|
|
82
|
+
* return <p>Loading...</p>;
|
|
83
|
+
* }
|
|
84
|
+
* return (<p>Welcome to {organization.organization_name}</p>);
|
|
85
|
+
*/
|
|
86
|
+
declare const useStytchOrganization: () => SWROrganization;
|
|
87
|
+
type SWRIsAuthorized = {
|
|
88
|
+
isAuthorized: boolean;
|
|
89
|
+
fromCache: boolean;
|
|
90
|
+
isInitialized: boolean;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
94
|
+
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
95
|
+
*
|
|
96
|
+
* If the member is not logged in, this method will always return false.
|
|
97
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
98
|
+
*
|
|
99
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
100
|
+
* @example
|
|
101
|
+
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
102
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
103
|
+
*/
|
|
104
|
+
declare const useStytchIsAuthorized: (resourceId: string, action: string) => SWRIsAuthorized;
|
|
105
|
+
/**
|
|
106
|
+
* Returns the Stytch client stored in the Stytch context.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const stytch = useStytch();
|
|
110
|
+
* useEffect(() => {
|
|
111
|
+
* stytch.magicLinks.authenticate('...')
|
|
112
|
+
* }, [stytch]);
|
|
113
|
+
*/
|
|
114
|
+
declare const useStytchB2BClient: () => StytchB2BHeadlessClient;
|
|
115
|
+
declare const withStytchB2BClient: <T extends object>(Component: React.ComponentType<T & {
|
|
116
|
+
stytch: StytchB2BHeadlessClient;
|
|
117
|
+
}>) => React.ComponentType<T>;
|
|
118
|
+
declare const withStytchMember: <T extends object>(Component: React.ComponentType<T & {
|
|
119
|
+
stytchMember: Member | null;
|
|
120
|
+
stytchMemberIsInitialized: boolean;
|
|
121
|
+
stytchMemberIsFromCache: boolean;
|
|
122
|
+
}>) => React.ComponentType<T>;
|
|
123
|
+
declare const withStytchMemberSession: <T extends object>(Component: React.ComponentType<T & {
|
|
124
|
+
stytchMemberSession: MemberSession | null;
|
|
125
|
+
stytchMemberSessionIsInitialized: boolean;
|
|
126
|
+
stytchMemberSessionIsFromCache: boolean;
|
|
127
|
+
}>) => React.ComponentType<T>;
|
|
128
|
+
declare const withStytchOrganization: <T extends object>(Component: React.ComponentType<T & {
|
|
129
|
+
stytchOrganization: Organization | null;
|
|
130
|
+
stytchOrganizationIsInitialized: boolean;
|
|
131
|
+
stytchOrganizationIsFromCache: boolean;
|
|
132
|
+
}>) => React.ComponentType<T>;
|
|
133
|
+
/**
|
|
134
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in member.
|
|
135
|
+
* Evaluates all permissions granted to the logged-in member.
|
|
136
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
|
|
137
|
+
* Each boolean will be `true` if the member can perform the action, `false` otherwise.
|
|
138
|
+
*
|
|
139
|
+
* If the member is not logged in, all values will be false.
|
|
140
|
+
*
|
|
141
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
142
|
+
* @example
|
|
143
|
+
* type Permissions = {
|
|
144
|
+
* document: 'create' | 'read' | 'write
|
|
145
|
+
* image: 'create' | 'read'
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* const MyComponent = (props) => {
|
|
149
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
150
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
151
|
+
* }
|
|
152
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
153
|
+
*/
|
|
154
|
+
declare const withStytchPermissions: <Permissions_1 extends Record<string, string>, T extends object>(Component: React.ComponentType<T & {
|
|
155
|
+
stytchPermissions: PermissionsMap<Permissions_1>;
|
|
156
|
+
}>) => React.ComponentType<T>;
|
|
157
|
+
interface StytchB2BProviderProps {
|
|
158
|
+
/**
|
|
159
|
+
* A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
|
|
160
|
+
*/
|
|
161
|
+
stytch: StytchB2BClient;
|
|
162
|
+
children?: ReactNode;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The Stytch Context Provider.
|
|
166
|
+
* Wrap your application with this component in `_app.js` in order to use Stytch everywhere in your app.
|
|
167
|
+
* @example
|
|
168
|
+
* const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
169
|
+
*
|
|
170
|
+
* return (
|
|
171
|
+
* <StytchB2BProvider stytch={stytch}>
|
|
172
|
+
* <App />
|
|
173
|
+
* </StytchB2BProvider>
|
|
174
|
+
* )
|
|
175
|
+
*/
|
|
176
|
+
declare const StytchB2BProvider: ({ stytch, children }: StytchB2BProviderProps) => JSX.Element;
|
|
177
|
+
export { useIsMounted__INTERNAL, isUIClient, useStytchMember, useStytchMemberSession, useStytchOrganization, useStytchIsAuthorized, useStytchB2BClient, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions, StytchB2BProviderProps, StytchB2BProvider };
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo } from 'react';
|
|
2
|
+
import { i as isStytchSSRProxy, n as noProviderError } from './StytchSSRProxy-14916009.js';
|
|
3
|
+
import { i as invariant, u as useAsyncState, m as mergeWithStableProps } from './async-b1e10055.js';
|
|
4
|
+
|
|
5
|
+
const initialMember = {
|
|
6
|
+
member: null,
|
|
7
|
+
fromCache: false,
|
|
8
|
+
isInitialized: false,
|
|
9
|
+
};
|
|
10
|
+
const initialMemberSession = {
|
|
11
|
+
session: null,
|
|
12
|
+
fromCache: false,
|
|
13
|
+
isInitialized: false,
|
|
14
|
+
};
|
|
15
|
+
const initialOrganization = {
|
|
16
|
+
organization: null,
|
|
17
|
+
fromCache: false,
|
|
18
|
+
isInitialized: false,
|
|
19
|
+
};
|
|
20
|
+
const StytchContext = createContext({ isMounted: false });
|
|
21
|
+
const StytchMemberContext = createContext(initialMember);
|
|
22
|
+
const StytchMemberSessionContext = createContext(initialMemberSession);
|
|
23
|
+
const StytchOrganizationContext = createContext(initialOrganization);
|
|
24
|
+
const useIsMounted__INTERNAL = () => useContext(StytchContext).isMounted;
|
|
25
|
+
const isUIClient = (client) => {
|
|
26
|
+
return client.mount !== undefined;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Returns the active member.
|
|
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.
|
|
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.
|
|
34
|
+
* @example
|
|
35
|
+
* const {member, isInitialized, fromCache} = useStytchMember();
|
|
36
|
+
* if (!isInitialized) {
|
|
37
|
+
* return <p>Loading...</p>;
|
|
38
|
+
* }
|
|
39
|
+
* return (<h1>Welcome, {member.name}</h1>);
|
|
40
|
+
*/
|
|
41
|
+
const useStytchMember = () => {
|
|
42
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMember', 'StytchB2BProvider'));
|
|
43
|
+
return useContext(StytchMemberContext);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Returns the member's active Stytch member session.
|
|
47
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
48
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
49
|
+
* 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
|
+
* @example
|
|
52
|
+
* const {session, isInitialized, fromCache} = useStytchMemberSession();
|
|
53
|
+
* useEffect(() => {
|
|
54
|
+
* if (!isInitialized) {
|
|
55
|
+
* return;
|
|
56
|
+
* }
|
|
57
|
+
* if (!session) {
|
|
58
|
+
* router.replace('/login')
|
|
59
|
+
* }
|
|
60
|
+
* }, [session, isInitialized]);
|
|
61
|
+
*/
|
|
62
|
+
const useStytchMemberSession = () => {
|
|
63
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
|
|
64
|
+
return useContext(StytchMemberSessionContext);
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Returns the active Stytch organization.
|
|
68
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
69
|
+
* 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.
|
|
72
|
+
* @example
|
|
73
|
+
* const {organization, isInitialized, fromCache} = useStytchOrganization();
|
|
74
|
+
* if (!isInitialized) {
|
|
75
|
+
* return <p>Loading...</p>;
|
|
76
|
+
* }
|
|
77
|
+
* return (<p>Welcome to {organization.organization_name}</p>);
|
|
78
|
+
*/
|
|
79
|
+
const useStytchOrganization = () => {
|
|
80
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchOrganization', 'StytchB2BProvider'));
|
|
81
|
+
return useContext(StytchOrganizationContext);
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
85
|
+
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
86
|
+
*
|
|
87
|
+
* If the member is not logged in, this method will always return false.
|
|
88
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
89
|
+
*
|
|
90
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
91
|
+
* @example
|
|
92
|
+
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
93
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
94
|
+
*/
|
|
95
|
+
const useStytchIsAuthorized = (resourceId, action) => {
|
|
96
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchIsAuthorized', 'StytchB2BProvider'));
|
|
97
|
+
const client = useStytchB2BClient();
|
|
98
|
+
const { session } = useStytchMemberSession();
|
|
99
|
+
const [isAuthorized, setIsAuthorized] = useAsyncState({
|
|
100
|
+
isInitialized: false,
|
|
101
|
+
fromCache: false,
|
|
102
|
+
isAuthorized: false,
|
|
103
|
+
});
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (isStytchSSRProxy(client)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
setIsAuthorized({
|
|
109
|
+
isInitialized: true,
|
|
110
|
+
fromCache: true,
|
|
111
|
+
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
112
|
+
});
|
|
113
|
+
}, [action, client, resourceId, setIsAuthorized]);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (isStytchSSRProxy(client)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
|
|
119
|
+
setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
|
|
120
|
+
});
|
|
121
|
+
}, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
|
|
122
|
+
return isAuthorized;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Returns the Stytch client stored in the Stytch context.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* const stytch = useStytch();
|
|
129
|
+
* useEffect(() => {
|
|
130
|
+
* stytch.magicLinks.authenticate('...')
|
|
131
|
+
* }, [stytch]);
|
|
132
|
+
*/
|
|
133
|
+
const useStytchB2BClient = () => {
|
|
134
|
+
const ctx = useContext(StytchContext);
|
|
135
|
+
invariant(ctx.isMounted, noProviderError('useStytchB2BClient', 'StytchB2BProvider'));
|
|
136
|
+
return ctx.client;
|
|
137
|
+
};
|
|
138
|
+
const withStytchB2BClient = (Component) => {
|
|
139
|
+
const WithStytch = (props) => {
|
|
140
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchB2BClient', 'StytchB2BProvider'));
|
|
141
|
+
return React.createElement(Component, Object.assign({}, props, { stytch: useStytchB2BClient() }));
|
|
142
|
+
};
|
|
143
|
+
WithStytch.displayName = `withStytch(${Component.displayName || Component.name || 'Component'})`;
|
|
144
|
+
return WithStytch;
|
|
145
|
+
};
|
|
146
|
+
const withStytchMember = (Component) => {
|
|
147
|
+
const WithStytchUser = (props) => {
|
|
148
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMember', 'StytchB2BProvider'));
|
|
149
|
+
const { member, isInitialized, fromCache } = useStytchMember();
|
|
150
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsInitialized: isInitialized, stytchMemberIsFromCache: fromCache })));
|
|
151
|
+
};
|
|
152
|
+
WithStytchUser.displayName = `withStytchMember(${Component.displayName || Component.name || 'Component'})`;
|
|
153
|
+
return WithStytchUser;
|
|
154
|
+
};
|
|
155
|
+
const withStytchMemberSession = (Component) => {
|
|
156
|
+
const WithStytchSession = (props) => {
|
|
157
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMemberSession', 'StytchB2BProvider'));
|
|
158
|
+
const { session, isInitialized, fromCache } = useStytchMemberSession();
|
|
159
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsInitialized: isInitialized, stytchMemberSessionIsFromCache: fromCache })));
|
|
160
|
+
};
|
|
161
|
+
WithStytchSession.displayName = `withStytchMemberSession(${Component.displayName || Component.name || 'Component'})`;
|
|
162
|
+
return WithStytchSession;
|
|
163
|
+
};
|
|
164
|
+
const withStytchOrganization = (Component) => {
|
|
165
|
+
const WithStytchOrganization = (props) => {
|
|
166
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchOrganization', 'StytchB2BProvider'));
|
|
167
|
+
const { organization, isInitialized, fromCache } = useStytchOrganization();
|
|
168
|
+
return (React.createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsInitialized: isInitialized, stytchOrganizationIsFromCache: fromCache })));
|
|
169
|
+
};
|
|
170
|
+
WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
|
|
171
|
+
return WithStytchOrganization;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in member.
|
|
175
|
+
* Evaluates all permissions granted to the logged-in member.
|
|
176
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
|
|
177
|
+
* Each boolean will be `true` if the member can perform the action, `false` otherwise.
|
|
178
|
+
*
|
|
179
|
+
* If the member is not logged in, all values will be false.
|
|
180
|
+
*
|
|
181
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
182
|
+
* @example
|
|
183
|
+
* type Permissions = {
|
|
184
|
+
* document: 'create' | 'read' | 'write
|
|
185
|
+
* image: 'create' | 'read'
|
|
186
|
+
* }
|
|
187
|
+
*
|
|
188
|
+
* const MyComponent = (props) => {
|
|
189
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
190
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
191
|
+
* }
|
|
192
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
193
|
+
*/
|
|
194
|
+
const withStytchPermissions = (Component) => {
|
|
195
|
+
const WithStytchPermissions = (props) => {
|
|
196
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useRBACPermissions', 'StytchB2BProvider'));
|
|
197
|
+
const client = useStytchB2BClient();
|
|
198
|
+
const { session } = useStytchMemberSession();
|
|
199
|
+
const [permissions, setPermissions] = useAsyncState({ loaded: false, value: null });
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
client.rbac
|
|
202
|
+
.allPermissions()
|
|
203
|
+
.then((permissions) => setPermissions({ loaded: true, value: permissions }));
|
|
204
|
+
}, [client, session === null || session === void 0 ? void 0 : session.roles, setPermissions]);
|
|
205
|
+
if (!permissions.loaded) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
return React.createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
|
|
209
|
+
};
|
|
210
|
+
WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
|
|
211
|
+
return WithStytchPermissions;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* The Stytch Context Provider.
|
|
215
|
+
* Wrap your application with this component in `_app.js` in order to use Stytch everywhere in your app.
|
|
216
|
+
* @example
|
|
217
|
+
* const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
218
|
+
*
|
|
219
|
+
* return (
|
|
220
|
+
* <StytchB2BProvider stytch={stytch}>
|
|
221
|
+
* <App />
|
|
222
|
+
* </StytchB2BProvider>
|
|
223
|
+
* )
|
|
224
|
+
*/
|
|
225
|
+
const StytchB2BProvider = ({ stytch, children }) => {
|
|
226
|
+
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
|
+
});
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
if (isStytchSSRProxy(stytch)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
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 },
|
|
253
|
+
React.createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
254
|
+
React.createElement(StytchMemberContext.Provider, { value: member },
|
|
255
|
+
React.createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export { StytchB2BProvider as S, useStytchB2BClient as a, useStytchMemberSession as b, useStytchMember as c, useStytchIsAuthorized as d, useStytchOrganization as e, withStytchMemberSession as f, withStytchMember as g, withStytchOrganization as h, isUIClient as i, withStytchPermissions as j, useIsMounted__INTERNAL as u, withStytchB2BClient as w };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
import { Member, MemberSession, Organization, StytchB2BUIClient } from '@stytch/vanilla-js/b2b';
|
|
5
|
+
import { StytchB2BHeadlessClient } from '@stytch/vanilla-js/b2b/headless';
|
|
6
|
+
import { PermissionsMap } from '@stytch/core/public';
|
|
7
|
+
/**
|
|
8
|
+
* The Stytch Client object passed in to <StytchProvider /> in your `_app.js`.
|
|
9
|
+
* Either a StytchUIClient or StytchHeadlessClient.
|
|
10
|
+
*/
|
|
11
|
+
type StytchB2BClient = StytchB2BHeadlessClient | StytchB2BUIClient;
|
|
12
|
+
type SWRMember = {
|
|
13
|
+
member: null;
|
|
14
|
+
fromCache: false;
|
|
15
|
+
isInitialized: false;
|
|
16
|
+
} | {
|
|
17
|
+
member: Member | null;
|
|
18
|
+
fromCache: boolean;
|
|
19
|
+
isInitialized: true;
|
|
20
|
+
};
|
|
21
|
+
type SWRMemberSession = {
|
|
22
|
+
session: null;
|
|
23
|
+
fromCache: false;
|
|
24
|
+
isInitialized: false;
|
|
25
|
+
} | {
|
|
26
|
+
session: MemberSession | null;
|
|
27
|
+
fromCache: boolean;
|
|
28
|
+
isInitialized: true;
|
|
29
|
+
};
|
|
30
|
+
type SWROrganization = {
|
|
31
|
+
organization: null;
|
|
32
|
+
fromCache: false;
|
|
33
|
+
isInitialized: false;
|
|
34
|
+
} | {
|
|
35
|
+
organization: Organization | null;
|
|
36
|
+
fromCache: boolean;
|
|
37
|
+
isInitialized: true;
|
|
38
|
+
};
|
|
39
|
+
declare const useIsMounted__INTERNAL: () => boolean;
|
|
40
|
+
declare const isUIClient: (client: StytchB2BClient) => client is StytchB2BUIClient;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the active member.
|
|
43
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
44
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
45
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
46
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
47
|
+
* @example
|
|
48
|
+
* const {member, isInitialized, fromCache} = useStytchMember();
|
|
49
|
+
* if (!isInitialized) {
|
|
50
|
+
* return <p>Loading...</p>;
|
|
51
|
+
* }
|
|
52
|
+
* return (<h1>Welcome, {member.name}</h1>);
|
|
53
|
+
*/
|
|
54
|
+
declare const useStytchMember: () => SWRMember;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the member's active Stytch member session.
|
|
57
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
58
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
59
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
60
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
61
|
+
* @example
|
|
62
|
+
* const {session, isInitialized, fromCache} = useStytchMemberSession();
|
|
63
|
+
* useEffect(() => {
|
|
64
|
+
* if (!isInitialized) {
|
|
65
|
+
* return;
|
|
66
|
+
* }
|
|
67
|
+
* if (!session) {
|
|
68
|
+
* router.replace('/login')
|
|
69
|
+
* }
|
|
70
|
+
* }, [session, isInitialized]);
|
|
71
|
+
*/
|
|
72
|
+
declare const useStytchMemberSession: () => SWRMemberSession;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the active Stytch organization.
|
|
75
|
+
* The Stytch SDKs are used for client-side authentication and session management.
|
|
76
|
+
* Check the isInitialized property to determine if the SDK has completed initialization.
|
|
77
|
+
* Check the fromCache property to determine if the session data is from persistent storage.
|
|
78
|
+
* See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
|
|
79
|
+
* @example
|
|
80
|
+
* const {organization, isInitialized, fromCache} = useStytchOrganization();
|
|
81
|
+
* if (!isInitialized) {
|
|
82
|
+
* return <p>Loading...</p>;
|
|
83
|
+
* }
|
|
84
|
+
* return (<p>Welcome to {organization.organization_name}</p>);
|
|
85
|
+
*/
|
|
86
|
+
declare const useStytchOrganization: () => SWROrganization;
|
|
87
|
+
type SWRIsAuthorized = {
|
|
88
|
+
isAuthorized: boolean;
|
|
89
|
+
fromCache: boolean;
|
|
90
|
+
isInitialized: boolean;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
94
|
+
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
95
|
+
*
|
|
96
|
+
* If the member is not logged in, this method will always return false.
|
|
97
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
98
|
+
*
|
|
99
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
100
|
+
* @example
|
|
101
|
+
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
102
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
103
|
+
*/
|
|
104
|
+
declare const useStytchIsAuthorized: (resourceId: string, action: string) => SWRIsAuthorized;
|
|
105
|
+
/**
|
|
106
|
+
* Returns the Stytch client stored in the Stytch context.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const stytch = useStytch();
|
|
110
|
+
* useEffect(() => {
|
|
111
|
+
* stytch.magicLinks.authenticate('...')
|
|
112
|
+
* }, [stytch]);
|
|
113
|
+
*/
|
|
114
|
+
declare const useStytchB2BClient: () => StytchB2BHeadlessClient;
|
|
115
|
+
declare const withStytchB2BClient: <T extends object>(Component: React.ComponentType<T & {
|
|
116
|
+
stytch: StytchB2BHeadlessClient;
|
|
117
|
+
}>) => React.ComponentType<T>;
|
|
118
|
+
declare const withStytchMember: <T extends object>(Component: React.ComponentType<T & {
|
|
119
|
+
stytchMember: Member | null;
|
|
120
|
+
stytchMemberIsInitialized: boolean;
|
|
121
|
+
stytchMemberIsFromCache: boolean;
|
|
122
|
+
}>) => React.ComponentType<T>;
|
|
123
|
+
declare const withStytchMemberSession: <T extends object>(Component: React.ComponentType<T & {
|
|
124
|
+
stytchMemberSession: MemberSession | null;
|
|
125
|
+
stytchMemberSessionIsInitialized: boolean;
|
|
126
|
+
stytchMemberSessionIsFromCache: boolean;
|
|
127
|
+
}>) => React.ComponentType<T>;
|
|
128
|
+
declare const withStytchOrganization: <T extends object>(Component: React.ComponentType<T & {
|
|
129
|
+
stytchOrganization: Organization | null;
|
|
130
|
+
stytchOrganizationIsInitialized: boolean;
|
|
131
|
+
stytchOrganizationIsFromCache: boolean;
|
|
132
|
+
}>) => React.ComponentType<T>;
|
|
133
|
+
/**
|
|
134
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in member.
|
|
135
|
+
* Evaluates all permissions granted to the logged-in member.
|
|
136
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
|
|
137
|
+
* Each boolean will be `true` if the member can perform the action, `false` otherwise.
|
|
138
|
+
*
|
|
139
|
+
* If the member is not logged in, all values will be false.
|
|
140
|
+
*
|
|
141
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
142
|
+
* @example
|
|
143
|
+
* type Permissions = {
|
|
144
|
+
* document: 'create' | 'read' | 'write
|
|
145
|
+
* image: 'create' | 'read'
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* const MyComponent = (props) => {
|
|
149
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
150
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
151
|
+
* }
|
|
152
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
153
|
+
*/
|
|
154
|
+
declare const withStytchPermissions: <Permissions_1 extends Record<string, string>, T extends object>(Component: React.ComponentType<T & {
|
|
155
|
+
stytchPermissions: PermissionsMap<Permissions_1>;
|
|
156
|
+
}>) => React.ComponentType<T>;
|
|
157
|
+
interface StytchB2BProviderProps {
|
|
158
|
+
/**
|
|
159
|
+
* A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
|
|
160
|
+
*/
|
|
161
|
+
stytch: StytchB2BClient;
|
|
162
|
+
children?: ReactNode;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The Stytch Context Provider.
|
|
166
|
+
* Wrap your application with this component in `_app.js` in order to use Stytch everywhere in your app.
|
|
167
|
+
* @example
|
|
168
|
+
* const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
169
|
+
*
|
|
170
|
+
* return (
|
|
171
|
+
* <StytchB2BProvider stytch={stytch}>
|
|
172
|
+
* <App />
|
|
173
|
+
* </StytchB2BProvider>
|
|
174
|
+
* )
|
|
175
|
+
*/
|
|
176
|
+
declare const StytchB2BProvider: ({ stytch, children }: StytchB2BProviderProps) => JSX.Element;
|
|
177
|
+
export { useIsMounted__INTERNAL, isUIClient, useStytchMember, useStytchMemberSession, useStytchOrganization, useStytchIsAuthorized, useStytchB2BClient, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions, StytchB2BProviderProps, StytchB2BProvider };
|