@stytch/react 17.0.0 → 18.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-8acafb28.d.ts +165 -0
- package/dist/StytchB2BContext-8acafb28.js +217 -0
- package/dist/StytchB2BContext-ce9e254c.d.ts +165 -0
- package/dist/StytchB2BContext-ce9e254c.js +235 -0
- package/dist/adminPortal/index.d.ts +34 -0
- package/dist/adminPortal/index.esm.d.ts +34 -0
- package/dist/adminPortal/index.esm.js +9518 -0
- package/dist/adminPortal/index.js +9526 -0
- package/dist/b2b/index.d.ts +3 -162
- package/dist/b2b/index.esm.d.ts +3 -162
- package/dist/b2b/index.esm.js +5 -299
- package/dist/b2b/index.js +17 -312
- package/dist/createDeepEqual-5555f2e1.d.ts +5 -0
- package/dist/index-b14d4efe.d.ts +2 -0
- package/dist/index.esm.js +2 -85
- package/dist/index.js +17 -100
- package/dist/invariant-568a7633.d.ts +27 -0
- package/dist/invariant-568a7633.js +88 -0
- package/dist/invariant-ae5a5bce.d.ts +27 -0
- package/dist/invariant-ae5a5bce.js +97 -0
- package/package.json +3 -3
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var invariant = require('./invariant-ae5a5bce.js');
|
|
5
|
+
|
|
6
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
7
|
+
|
|
8
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
9
|
+
|
|
10
|
+
const initialMember = {
|
|
11
|
+
member: null,
|
|
12
|
+
fromCache: false,
|
|
13
|
+
};
|
|
14
|
+
const initialMemberSession = {
|
|
15
|
+
session: null,
|
|
16
|
+
fromCache: false,
|
|
17
|
+
};
|
|
18
|
+
const initialOrganization = {
|
|
19
|
+
organization: null,
|
|
20
|
+
fromCache: false,
|
|
21
|
+
};
|
|
22
|
+
const StytchB2BContext = React.createContext({ isMounted: false });
|
|
23
|
+
const StytchMemberContext = React.createContext(initialMember);
|
|
24
|
+
const StytchMemberSessionContext = React.createContext(initialMemberSession);
|
|
25
|
+
const StytchOrganizationContext = React.createContext(initialOrganization);
|
|
26
|
+
const useIsMounted__INTERNAL = () => React.useContext(StytchB2BContext).isMounted;
|
|
27
|
+
const isUIClient = (client) => {
|
|
28
|
+
return client.mount !== undefined;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns the active Member.
|
|
32
|
+
* Check the fromCache property to determine if the member data is from persistent storage.
|
|
33
|
+
* @example
|
|
34
|
+
* const {member} = useStytchMember();
|
|
35
|
+
* return (<h1>Welcome, {member.name}</h1>);
|
|
36
|
+
* @returns A {@link SWRUser}
|
|
37
|
+
*/
|
|
38
|
+
const useStytchMember = () => {
|
|
39
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchMember', 'StytchB2BProvider'));
|
|
40
|
+
return React.useContext(StytchMemberContext);
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Returns the active member's Stytch member session.
|
|
44
|
+
* @example
|
|
45
|
+
* const { session } = useStytchMemberSession();
|
|
46
|
+
* useEffect(() => {
|
|
47
|
+
* if (!session) {
|
|
48
|
+
* router.replace('/login')
|
|
49
|
+
* }
|
|
50
|
+
* }, [session]);
|
|
51
|
+
* @returns A {@link SWRMemberSession}
|
|
52
|
+
*/
|
|
53
|
+
const useStytchMemberSession = () => {
|
|
54
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
|
|
55
|
+
return React.useContext(StytchMemberSessionContext);
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Returns the active Stytch organization.
|
|
59
|
+
* @example
|
|
60
|
+
* const { organization } = useStytchOrganization();
|
|
61
|
+
* return organization ? <p>Welcome to {organization.organization_name}</p> : <p>Log in to continue!</p>;
|
|
62
|
+
* @returns A {@link SWROrganization}
|
|
63
|
+
*/
|
|
64
|
+
const useStytchOrganization = () => {
|
|
65
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchOrganization', 'StytchB2BProvider'));
|
|
66
|
+
return React.useContext(StytchOrganizationContext);
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
70
|
+
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
71
|
+
*
|
|
72
|
+
* If the member is not logged in, this method will always return false.
|
|
73
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
74
|
+
*
|
|
75
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
76
|
+
* @example
|
|
77
|
+
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
78
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
79
|
+
*/
|
|
80
|
+
const useStytchIsAuthorized = (resourceId, action) => {
|
|
81
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchIsAuthorized', 'StytchB2BProvider'));
|
|
82
|
+
const client = useStytchB2BClient();
|
|
83
|
+
const { session } = useStytchMemberSession();
|
|
84
|
+
const [isAuthorized, setIsAuthorized] = invariant.useAsyncState({
|
|
85
|
+
fromCache: true,
|
|
86
|
+
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
87
|
+
});
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => setIsAuthorized({
|
|
90
|
+
fromCache: false,
|
|
91
|
+
isAuthorized,
|
|
92
|
+
}));
|
|
93
|
+
}, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
|
|
94
|
+
return isAuthorized;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Returns the Stytch B2B client stored in the Stytch context.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const stytch = useStytchB2BClient();
|
|
101
|
+
* useEffect(() => {
|
|
102
|
+
* stytch.magicLinks.authenticate('...')
|
|
103
|
+
* }, [stytch]);
|
|
104
|
+
*/
|
|
105
|
+
const useStytchB2BClient = () => {
|
|
106
|
+
const ctx = React.useContext(StytchB2BContext);
|
|
107
|
+
invariant.invariant(ctx.isMounted, invariant.noProviderError('useStytchB2BClient', 'StytchB2BProvider'));
|
|
108
|
+
return ctx.client;
|
|
109
|
+
};
|
|
110
|
+
const withStytchB2BClient = (Component) => {
|
|
111
|
+
const WithStytch = (props) => {
|
|
112
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchB2BClient', 'StytchB2BProvider'));
|
|
113
|
+
return React__default['default'].createElement(Component, Object.assign({}, props, { stytch: useStytchB2BClient() }));
|
|
114
|
+
};
|
|
115
|
+
WithStytch.displayName = `withStytch(${Component.displayName || Component.name || 'Component'})`;
|
|
116
|
+
return WithStytch;
|
|
117
|
+
};
|
|
118
|
+
const withStytchMember = (Component) => {
|
|
119
|
+
const WithStytchUser = (props) => {
|
|
120
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchMember', 'StytchB2BProvider'));
|
|
121
|
+
const { member, fromCache } = useStytchMember();
|
|
122
|
+
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsFromCache: fromCache }));
|
|
123
|
+
};
|
|
124
|
+
WithStytchUser.displayName = `withStytchUser(${Component.displayName || Component.name || 'Component'})`;
|
|
125
|
+
return WithStytchUser;
|
|
126
|
+
};
|
|
127
|
+
const withStytchMemberSession = (Component) => {
|
|
128
|
+
const WithStytchSession = (props) => {
|
|
129
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchMemberSession', 'StytchB2BProvider'));
|
|
130
|
+
const { session, fromCache } = useStytchMemberSession();
|
|
131
|
+
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsFromCache: fromCache }));
|
|
132
|
+
};
|
|
133
|
+
WithStytchSession.displayName = `withStytchSession(${Component.displayName || Component.name || 'Component'})`;
|
|
134
|
+
return WithStytchSession;
|
|
135
|
+
};
|
|
136
|
+
const withStytchOrganization = (Component) => {
|
|
137
|
+
const WithStytchOrganization = (props) => {
|
|
138
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchOrganization', 'StytchB2BProvider'));
|
|
139
|
+
const { organization, fromCache } = useStytchOrganization();
|
|
140
|
+
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsFromCache: fromCache }));
|
|
141
|
+
};
|
|
142
|
+
WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
|
|
143
|
+
return WithStytchOrganization;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in member.
|
|
147
|
+
* Evaluates all permissions granted to the logged-in member.
|
|
148
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
|
|
149
|
+
* Each boolean will be `true` if the member can perform the action, `false` otherwise.
|
|
150
|
+
*
|
|
151
|
+
* If the member is not logged in, all values will be false.
|
|
152
|
+
*
|
|
153
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
154
|
+
* @example
|
|
155
|
+
* type Permissions = {
|
|
156
|
+
* document: 'create' | 'read' | 'write
|
|
157
|
+
* image: 'create' | 'read'
|
|
158
|
+
* }
|
|
159
|
+
*
|
|
160
|
+
* const MyComponent = (props) => {
|
|
161
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
162
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
163
|
+
* }
|
|
164
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
165
|
+
*/
|
|
166
|
+
const withStytchPermissions = (Component) => {
|
|
167
|
+
const WithStytchPermissions = (props) => {
|
|
168
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useRBACPermissions', 'StytchB2BProvider'));
|
|
169
|
+
const client = useStytchB2BClient();
|
|
170
|
+
const { session } = useStytchMemberSession();
|
|
171
|
+
const [permissions, setPermissions] = invariant.useAsyncState({ loaded: false, value: null });
|
|
172
|
+
React.useEffect(() => {
|
|
173
|
+
client.rbac
|
|
174
|
+
.allPermissions()
|
|
175
|
+
.then((permissions) => setPermissions({ loaded: true, value: permissions }));
|
|
176
|
+
}, [client, session === null || session === void 0 ? void 0 : session.roles, setPermissions]);
|
|
177
|
+
if (!permissions.loaded) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
|
|
181
|
+
};
|
|
182
|
+
WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
|
|
183
|
+
return WithStytchPermissions;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The Stytch Context Provider.
|
|
187
|
+
* Wrap your application with this component in the root file in order to use Stytch everywhere in your app.
|
|
188
|
+
* @example
|
|
189
|
+
* const stytch = new StytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
190
|
+
*
|
|
191
|
+
* ReactDOM.render(
|
|
192
|
+
* <StytchB2BProvider stytch={stytch}>
|
|
193
|
+
* <App />
|
|
194
|
+
* </StytchProvider>,
|
|
195
|
+
* document.getElementById('root'),
|
|
196
|
+
* )
|
|
197
|
+
*/
|
|
198
|
+
const StytchB2BProvider = ({ stytch, children }) => {
|
|
199
|
+
invariant.invariant(!useIsMounted__INTERNAL(), invariant.B2BProviderMustBeUniqueError);
|
|
200
|
+
invariant.invariant(typeof window !== 'undefined', invariant.noSSRError);
|
|
201
|
+
const ctx = React.useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
202
|
+
const [{ member, session, organization }, setClientState] = invariant.useAsyncState({
|
|
203
|
+
session: stytch.session.getInfo(),
|
|
204
|
+
member: stytch.self.getInfo(),
|
|
205
|
+
organization: stytch.organization.getInfo(),
|
|
206
|
+
});
|
|
207
|
+
React.useEffect(() => stytch.onStateChange(() => {
|
|
208
|
+
setClientState((oldState) => {
|
|
209
|
+
const newState = {
|
|
210
|
+
session: stytch.session.getInfo(),
|
|
211
|
+
member: stytch.self.getInfo(),
|
|
212
|
+
organization: stytch.organization.getInfo(),
|
|
213
|
+
};
|
|
214
|
+
return invariant.mergeWithStableProps(oldState, newState);
|
|
215
|
+
});
|
|
216
|
+
}), [setClientState, stytch]);
|
|
217
|
+
return (React__default['default'].createElement(StytchB2BContext.Provider, { value: ctx },
|
|
218
|
+
React__default['default'].createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
219
|
+
React__default['default'].createElement(StytchMemberContext.Provider, { value: member },
|
|
220
|
+
React__default['default'].createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
exports.StytchB2BProvider = StytchB2BProvider;
|
|
224
|
+
exports.isUIClient = isUIClient;
|
|
225
|
+
exports.useIsMounted__INTERNAL = useIsMounted__INTERNAL;
|
|
226
|
+
exports.useStytchB2BClient = useStytchB2BClient;
|
|
227
|
+
exports.useStytchIsAuthorized = useStytchIsAuthorized;
|
|
228
|
+
exports.useStytchMember = useStytchMember;
|
|
229
|
+
exports.useStytchMemberSession = useStytchMemberSession;
|
|
230
|
+
exports.useStytchOrganization = useStytchOrganization;
|
|
231
|
+
exports.withStytchB2BClient = withStytchB2BClient;
|
|
232
|
+
exports.withStytchMember = withStytchMember;
|
|
233
|
+
exports.withStytchMemberSession = withStytchMemberSession;
|
|
234
|
+
exports.withStytchOrganization = withStytchOrganization;
|
|
235
|
+
exports.withStytchPermissions = withStytchPermissions;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { AdminPortalStyleConfig } from "@stytch/vanilla-js/b2b/adminPortal";
|
|
3
|
+
import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
|
|
4
|
+
import { PartialDeep } from "type-fest";
|
|
5
|
+
interface AdminPortalComponentProps {
|
|
6
|
+
/**
|
|
7
|
+
* The Stytch B2B client to use.
|
|
8
|
+
*/
|
|
9
|
+
client: StytchB2BHeadlessClient;
|
|
10
|
+
/**
|
|
11
|
+
* An HTML element or query selector string for the element that should contain the UI.
|
|
12
|
+
* @example '#container'
|
|
13
|
+
*/
|
|
14
|
+
element: string | HTMLElement;
|
|
15
|
+
/**
|
|
16
|
+
* An {@link AdminPortalStyleConfig} object containing custom styling info.
|
|
17
|
+
*/
|
|
18
|
+
styles?: PartialDeep<AdminPortalStyleConfig>;
|
|
19
|
+
}
|
|
20
|
+
interface InjectedOptions {
|
|
21
|
+
client: StytchB2BHeadlessClient;
|
|
22
|
+
element: HTMLElement;
|
|
23
|
+
}
|
|
24
|
+
type ExcludeInjectedOptions<T> = Omit<T, keyof InjectedOptions>;
|
|
25
|
+
type AdminPortalSSOProps = AdminPortalComponentProps;
|
|
26
|
+
/**
|
|
27
|
+
* The Admin Portal SSO UI component.
|
|
28
|
+
* This component must be rendered within a {@link StytchB2BProvider}.
|
|
29
|
+
*
|
|
30
|
+
* See the {@link https://stytch.com/docs/b2b/sdks/javascript-sdk online reference}
|
|
31
|
+
*/
|
|
32
|
+
declare const AdminPortalSSO: (props: ExcludeInjectedOptions<AdminPortalComponentProps>) => JSX.Element;
|
|
33
|
+
export { AdminPortalSSO };
|
|
34
|
+
export type { AdminPortalSSOProps };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { AdminPortalStyleConfig } from "@stytch/vanilla-js/b2b/adminPortal";
|
|
3
|
+
import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
|
|
4
|
+
import { PartialDeep } from "type-fest";
|
|
5
|
+
interface AdminPortalComponentProps {
|
|
6
|
+
/**
|
|
7
|
+
* The Stytch B2B client to use.
|
|
8
|
+
*/
|
|
9
|
+
client: StytchB2BHeadlessClient;
|
|
10
|
+
/**
|
|
11
|
+
* An HTML element or query selector string for the element that should contain the UI.
|
|
12
|
+
* @example '#container'
|
|
13
|
+
*/
|
|
14
|
+
element: string | HTMLElement;
|
|
15
|
+
/**
|
|
16
|
+
* An {@link AdminPortalStyleConfig} object containing custom styling info.
|
|
17
|
+
*/
|
|
18
|
+
styles?: PartialDeep<AdminPortalStyleConfig>;
|
|
19
|
+
}
|
|
20
|
+
interface InjectedOptions {
|
|
21
|
+
client: StytchB2BHeadlessClient;
|
|
22
|
+
element: HTMLElement;
|
|
23
|
+
}
|
|
24
|
+
type ExcludeInjectedOptions<T> = Omit<T, keyof InjectedOptions>;
|
|
25
|
+
type AdminPortalSSOProps = AdminPortalComponentProps;
|
|
26
|
+
/**
|
|
27
|
+
* The Admin Portal SSO UI component.
|
|
28
|
+
* This component must be rendered within a {@link StytchB2BProvider}.
|
|
29
|
+
*
|
|
30
|
+
* See the {@link https://stytch.com/docs/b2b/sdks/javascript-sdk online reference}
|
|
31
|
+
*/
|
|
32
|
+
declare const AdminPortalSSO: (props: ExcludeInjectedOptions<AdminPortalComponentProps>) => JSX.Element;
|
|
33
|
+
export { AdminPortalSSO };
|
|
34
|
+
export type { AdminPortalSSOProps };
|