@stytch/react 18.0.0 → 18.2.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 +18 -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 +43 -0
- package/dist/adminPortal/index.esm.d.ts +43 -0
- package/dist/adminPortal/index.esm.js +10350 -0
- package/dist/adminPortal/index.js +10359 -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
package/dist/b2b/index.js
CHANGED
|
@@ -2,309 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var StytchB2BContext = require('../StytchB2BContext-ce9e254c.js');
|
|
5
6
|
var React = require('react');
|
|
7
|
+
var invariant = require('../invariant-ae5a5bce.js');
|
|
6
8
|
|
|
7
9
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
10
|
|
|
9
11
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
12
|
|
|
11
|
-
const createDeepEqual = ({ KEYS_TO_EXCLUDE = [] } = {}) => {
|
|
12
|
-
// If comparing functions, this may need some work. Not sure the
|
|
13
|
-
// best path for this: compare instance (what it currently does),
|
|
14
|
-
// stringify and compare, etc.
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
-
const deepEqual = (a, b) => {
|
|
17
|
-
// Ensures type is the same
|
|
18
|
-
if (typeof a !== typeof b)
|
|
19
|
-
return false;
|
|
20
|
-
// arrays, null, and objects all have type 'object'
|
|
21
|
-
if (a === null || b === null)
|
|
22
|
-
return a === b;
|
|
23
|
-
if (typeof a === 'object') {
|
|
24
|
-
if (Object.keys(a).length !== Object.keys(b).length || Object.keys(a).some((k) => !(k in b)))
|
|
25
|
-
return false;
|
|
26
|
-
return Object.entries(a)
|
|
27
|
-
.filter(([k]) => !KEYS_TO_EXCLUDE.includes(k))
|
|
28
|
-
.every(([k, v]) => deepEqual(v, b[k]));
|
|
29
|
-
}
|
|
30
|
-
// boolean, string, number, undefined
|
|
31
|
-
return a === b;
|
|
32
|
-
};
|
|
33
|
-
return deepEqual;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const deepEqual = createDeepEqual();
|
|
37
|
-
/**
|
|
38
|
-
* Returns a version of `newValue` whose properties that are deeply equal to
|
|
39
|
-
* those in `oldValue` are replaced with those from `oldValue`. This provides a
|
|
40
|
-
* limited form of "structural sharing" that provides a stable reference for
|
|
41
|
-
* unchanged slices of the object.
|
|
42
|
-
*
|
|
43
|
-
* If `oldValue` and `newValue` are referentially equal, the same value is
|
|
44
|
-
* returned.
|
|
45
|
-
*
|
|
46
|
-
* @param oldValue The old value
|
|
47
|
-
* @param newValue The new value
|
|
48
|
-
*/
|
|
49
|
-
const mergeWithStableProps = (oldValue, newValue) => {
|
|
50
|
-
// If the values are already referentially the same, just return the new value
|
|
51
|
-
if (oldValue === newValue) {
|
|
52
|
-
return newValue;
|
|
53
|
-
}
|
|
54
|
-
return Object.keys(oldValue).reduce((acc, key) => {
|
|
55
|
-
if (key in newValue && deepEqual(oldValue[key], newValue[key])) {
|
|
56
|
-
acc[key] = oldValue[key];
|
|
57
|
-
}
|
|
58
|
-
return acc;
|
|
59
|
-
}, Object.assign({}, newValue));
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
63
|
-
const B2BProviderMustBeUniqueError = 'You cannot render a <StytchB2BProvider> inside another <StytchB2BProvider>.';
|
|
64
|
-
const noSSRError = `The @stytch/react library is not meant for use with serverside environments like NextJS.
|
|
65
|
-
Use the @stytch/nextjs library instead -
|
|
66
|
-
npm remove @stytch/react && npm install @stytch/nextjs
|
|
67
|
-
`;
|
|
68
|
-
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
69
|
-
You must use the UI SDK to use UI elements.
|
|
70
|
-
Please make sure you are importing from @stytch/vanilla-js and not from the @stytch/vanilla-js/headless.`;
|
|
71
|
-
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
-
function invariant(cond, message) {
|
|
74
|
-
if (!cond)
|
|
75
|
-
throw new Error(message);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// useState can cause memory leaks if it is set after the component unmounted. For example, if it is
|
|
79
|
-
// set after `await`, or in a `then`, `catch`, or `finally`, or in a setTimout/setInterval.
|
|
80
|
-
const useAsyncState = (initialState) => {
|
|
81
|
-
const isMounted = React.useRef(true);
|
|
82
|
-
const [state, setState] = React.useState(initialState);
|
|
83
|
-
React.useEffect(() => {
|
|
84
|
-
isMounted.current = true;
|
|
85
|
-
return () => {
|
|
86
|
-
isMounted.current = false;
|
|
87
|
-
};
|
|
88
|
-
}, []);
|
|
89
|
-
const setStateAction = React.useCallback((newState) => {
|
|
90
|
-
isMounted.current && setState(newState);
|
|
91
|
-
}, []);
|
|
92
|
-
return [state, setStateAction];
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const initialMember = {
|
|
96
|
-
member: null,
|
|
97
|
-
fromCache: false,
|
|
98
|
-
};
|
|
99
|
-
const initialMemberSession = {
|
|
100
|
-
session: null,
|
|
101
|
-
fromCache: false,
|
|
102
|
-
};
|
|
103
|
-
const initialOrganization = {
|
|
104
|
-
organization: null,
|
|
105
|
-
fromCache: false,
|
|
106
|
-
};
|
|
107
|
-
const StytchB2BContext = React.createContext({ isMounted: false });
|
|
108
|
-
const StytchMemberContext = React.createContext(initialMember);
|
|
109
|
-
const StytchMemberSessionContext = React.createContext(initialMemberSession);
|
|
110
|
-
const StytchOrganizationContext = React.createContext(initialOrganization);
|
|
111
|
-
const useIsMounted__INTERNAL = () => React.useContext(StytchB2BContext).isMounted;
|
|
112
|
-
const isUIClient = (client) => {
|
|
113
|
-
return client.mount !== undefined;
|
|
114
|
-
};
|
|
115
|
-
/**
|
|
116
|
-
* Returns the active Member.
|
|
117
|
-
* Check the fromCache property to determine if the member data is from persistent storage.
|
|
118
|
-
* @example
|
|
119
|
-
* const {member} = useStytchMember();
|
|
120
|
-
* return (<h1>Welcome, {member.name}</h1>);
|
|
121
|
-
* @returns A {@link SWRUser}
|
|
122
|
-
*/
|
|
123
|
-
const useStytchMember = () => {
|
|
124
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMember', 'StytchB2BProvider'));
|
|
125
|
-
return React.useContext(StytchMemberContext);
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Returns the active member's Stytch member session.
|
|
129
|
-
* @example
|
|
130
|
-
* const { session } = useStytchMemberSession();
|
|
131
|
-
* useEffect(() => {
|
|
132
|
-
* if (!session) {
|
|
133
|
-
* router.replace('/login')
|
|
134
|
-
* }
|
|
135
|
-
* }, [session]);
|
|
136
|
-
* @returns A {@link SWRMemberSession}
|
|
137
|
-
*/
|
|
138
|
-
const useStytchMemberSession = () => {
|
|
139
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
|
|
140
|
-
return React.useContext(StytchMemberSessionContext);
|
|
141
|
-
};
|
|
142
|
-
/**
|
|
143
|
-
* Returns the active Stytch organization.
|
|
144
|
-
* @example
|
|
145
|
-
* const { organization } = useStytchOrganization();
|
|
146
|
-
* return organization ? <p>Welcome to {organization.organization_name}</p> : <p>Log in to continue!</p>;
|
|
147
|
-
* @returns A {@link SWROrganization}
|
|
148
|
-
*/
|
|
149
|
-
const useStytchOrganization = () => {
|
|
150
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchOrganization', 'StytchB2BProvider'));
|
|
151
|
-
return React.useContext(StytchOrganizationContext);
|
|
152
|
-
};
|
|
153
|
-
/**
|
|
154
|
-
* Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
|
|
155
|
-
* Returns `true` if the member can perform the action, `false` otherwise.
|
|
156
|
-
*
|
|
157
|
-
* If the member is not logged in, this method will always return false.
|
|
158
|
-
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
159
|
-
*
|
|
160
|
-
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
161
|
-
* @example
|
|
162
|
-
* const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
163
|
-
* return <button disabled={!isAuthorized}>Edit</button>
|
|
164
|
-
*/
|
|
165
|
-
const useStytchIsAuthorized = (resourceId, action) => {
|
|
166
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchIsAuthorized', 'StytchB2BProvider'));
|
|
167
|
-
const client = useStytchB2BClient();
|
|
168
|
-
const { session } = useStytchMemberSession();
|
|
169
|
-
const [isAuthorized, setIsAuthorized] = useAsyncState({
|
|
170
|
-
fromCache: true,
|
|
171
|
-
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
172
|
-
});
|
|
173
|
-
React.useEffect(() => {
|
|
174
|
-
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => setIsAuthorized({
|
|
175
|
-
fromCache: false,
|
|
176
|
-
isAuthorized,
|
|
177
|
-
}));
|
|
178
|
-
}, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
|
|
179
|
-
return isAuthorized;
|
|
180
|
-
};
|
|
181
|
-
/**
|
|
182
|
-
* Returns the Stytch B2B client stored in the Stytch context.
|
|
183
|
-
*
|
|
184
|
-
* @example
|
|
185
|
-
* const stytch = useStytchB2BClient();
|
|
186
|
-
* useEffect(() => {
|
|
187
|
-
* stytch.magicLinks.authenticate('...')
|
|
188
|
-
* }, [stytch]);
|
|
189
|
-
*/
|
|
190
|
-
const useStytchB2BClient = () => {
|
|
191
|
-
const ctx = React.useContext(StytchB2BContext);
|
|
192
|
-
invariant(ctx.isMounted, noProviderError('useStytchB2BClient', 'StytchB2BProvider'));
|
|
193
|
-
return ctx.client;
|
|
194
|
-
};
|
|
195
|
-
const withStytchB2BClient = (Component) => {
|
|
196
|
-
const WithStytch = (props) => {
|
|
197
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchB2BClient', 'StytchB2BProvider'));
|
|
198
|
-
return React__default['default'].createElement(Component, Object.assign({}, props, { stytch: useStytchB2BClient() }));
|
|
199
|
-
};
|
|
200
|
-
WithStytch.displayName = `withStytch(${Component.displayName || Component.name || 'Component'})`;
|
|
201
|
-
return WithStytch;
|
|
202
|
-
};
|
|
203
|
-
const withStytchMember = (Component) => {
|
|
204
|
-
const WithStytchUser = (props) => {
|
|
205
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMember', 'StytchB2BProvider'));
|
|
206
|
-
const { member, fromCache } = useStytchMember();
|
|
207
|
-
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsFromCache: fromCache }));
|
|
208
|
-
};
|
|
209
|
-
WithStytchUser.displayName = `withStytchUser(${Component.displayName || Component.name || 'Component'})`;
|
|
210
|
-
return WithStytchUser;
|
|
211
|
-
};
|
|
212
|
-
const withStytchMemberSession = (Component) => {
|
|
213
|
-
const WithStytchSession = (props) => {
|
|
214
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMemberSession', 'StytchB2BProvider'));
|
|
215
|
-
const { session, fromCache } = useStytchMemberSession();
|
|
216
|
-
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsFromCache: fromCache }));
|
|
217
|
-
};
|
|
218
|
-
WithStytchSession.displayName = `withStytchSession(${Component.displayName || Component.name || 'Component'})`;
|
|
219
|
-
return WithStytchSession;
|
|
220
|
-
};
|
|
221
|
-
const withStytchOrganization = (Component) => {
|
|
222
|
-
const WithStytchOrganization = (props) => {
|
|
223
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchOrganization', 'StytchB2BProvider'));
|
|
224
|
-
const { organization, fromCache } = useStytchOrganization();
|
|
225
|
-
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsFromCache: fromCache }));
|
|
226
|
-
};
|
|
227
|
-
WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
|
|
228
|
-
return WithStytchOrganization;
|
|
229
|
-
};
|
|
230
|
-
/**
|
|
231
|
-
* Wrap your component with this HOC in order to receive the permissions for the logged-in member.
|
|
232
|
-
* Evaluates all permissions granted to the logged-in member.
|
|
233
|
-
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
|
|
234
|
-
* Each boolean will be `true` if the member can perform the action, `false` otherwise.
|
|
235
|
-
*
|
|
236
|
-
* If the member is not logged in, all values will be false.
|
|
237
|
-
*
|
|
238
|
-
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
239
|
-
* @example
|
|
240
|
-
* type Permissions = {
|
|
241
|
-
* document: 'create' | 'read' | 'write
|
|
242
|
-
* image: 'create' | 'read'
|
|
243
|
-
* }
|
|
244
|
-
*
|
|
245
|
-
* const MyComponent = (props) => {
|
|
246
|
-
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
247
|
-
* const canReadImages = props.stytchPermissions.image.read;
|
|
248
|
-
* }
|
|
249
|
-
* return withStytchPermissions<Permissions>(MyComponent)
|
|
250
|
-
*/
|
|
251
|
-
const withStytchPermissions = (Component) => {
|
|
252
|
-
const WithStytchPermissions = (props) => {
|
|
253
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useRBACPermissions', 'StytchB2BProvider'));
|
|
254
|
-
const client = useStytchB2BClient();
|
|
255
|
-
const { session } = useStytchMemberSession();
|
|
256
|
-
const [permissions, setPermissions] = useAsyncState({ loaded: false, value: null });
|
|
257
|
-
React.useEffect(() => {
|
|
258
|
-
client.rbac
|
|
259
|
-
.allPermissions()
|
|
260
|
-
.then((permissions) => setPermissions({ loaded: true, value: permissions }));
|
|
261
|
-
}, [client, session === null || session === void 0 ? void 0 : session.roles, setPermissions]);
|
|
262
|
-
if (!permissions.loaded) {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
|
|
266
|
-
};
|
|
267
|
-
WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
|
|
268
|
-
return WithStytchPermissions;
|
|
269
|
-
};
|
|
270
|
-
/**
|
|
271
|
-
* The Stytch Context Provider.
|
|
272
|
-
* Wrap your application with this component in the root file in order to use Stytch everywhere in your app.
|
|
273
|
-
* @example
|
|
274
|
-
* const stytch = new StytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
|
|
275
|
-
*
|
|
276
|
-
* ReactDOM.render(
|
|
277
|
-
* <StytchB2BProvider stytch={stytch}>
|
|
278
|
-
* <App />
|
|
279
|
-
* </StytchProvider>,
|
|
280
|
-
* document.getElementById('root'),
|
|
281
|
-
* )
|
|
282
|
-
*/
|
|
283
|
-
const StytchB2BProvider = ({ stytch, children }) => {
|
|
284
|
-
invariant(!useIsMounted__INTERNAL(), B2BProviderMustBeUniqueError);
|
|
285
|
-
invariant(typeof window !== 'undefined', noSSRError);
|
|
286
|
-
const ctx = React.useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
287
|
-
const [{ member, session, organization }, setClientState] = useAsyncState({
|
|
288
|
-
session: stytch.session.getInfo(),
|
|
289
|
-
member: stytch.self.getInfo(),
|
|
290
|
-
organization: stytch.organization.getInfo(),
|
|
291
|
-
});
|
|
292
|
-
React.useEffect(() => stytch.onStateChange(() => {
|
|
293
|
-
setClientState((oldState) => {
|
|
294
|
-
const newState = {
|
|
295
|
-
session: stytch.session.getInfo(),
|
|
296
|
-
member: stytch.self.getInfo(),
|
|
297
|
-
organization: stytch.organization.getInfo(),
|
|
298
|
-
};
|
|
299
|
-
return mergeWithStableProps(oldState, newState);
|
|
300
|
-
});
|
|
301
|
-
}), [setClientState, stytch]);
|
|
302
|
-
return (React__default['default'].createElement(StytchB2BContext.Provider, { value: ctx },
|
|
303
|
-
React__default['default'].createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
304
|
-
React__default['default'].createElement(StytchMemberContext.Provider, { value: member },
|
|
305
|
-
React__default['default'].createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
306
|
-
};
|
|
307
|
-
|
|
308
13
|
/**
|
|
309
14
|
* The Stytch B2B UI component.
|
|
310
15
|
* This component can only be used with a {@link StytchB2BUIClient} client constructor
|
|
@@ -340,12 +45,12 @@ const StytchB2BProvider = ({ stytch, children }) => {
|
|
|
340
45
|
* @param props {@link StytchB2BProps}
|
|
341
46
|
*/
|
|
342
47
|
const StytchB2B = ({ styles, callbacks, config }) => {
|
|
343
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('<StytchB2B />'));
|
|
344
|
-
const stytchClient = useStytchB2BClient();
|
|
48
|
+
invariant.invariant(StytchB2BContext.useIsMounted__INTERNAL(), invariant.noProviderError('<StytchB2B />'));
|
|
49
|
+
const stytchClient = StytchB2BContext.useStytchB2BClient();
|
|
345
50
|
const containerEl = React.useRef(null);
|
|
346
51
|
React.useLayoutEffect(() => {
|
|
347
|
-
if (!isUIClient(stytchClient)) {
|
|
348
|
-
throw Error(noHeadlessClientError);
|
|
52
|
+
if (!StytchB2BContext.isUIClient(stytchClient)) {
|
|
53
|
+
throw Error(invariant.noHeadlessClientError);
|
|
349
54
|
}
|
|
350
55
|
if (!containerEl.current) {
|
|
351
56
|
return;
|
|
@@ -365,15 +70,15 @@ const StytchB2B = ({ styles, callbacks, config }) => {
|
|
|
365
70
|
return React__default['default'].createElement("div", { ref: containerEl });
|
|
366
71
|
};
|
|
367
72
|
|
|
73
|
+
exports.StytchB2BProvider = StytchB2BContext.StytchB2BProvider;
|
|
74
|
+
exports.useStytchB2BClient = StytchB2BContext.useStytchB2BClient;
|
|
75
|
+
exports.useStytchIsAuthorized = StytchB2BContext.useStytchIsAuthorized;
|
|
76
|
+
exports.useStytchMember = StytchB2BContext.useStytchMember;
|
|
77
|
+
exports.useStytchMemberSession = StytchB2BContext.useStytchMemberSession;
|
|
78
|
+
exports.useStytchOrganization = StytchB2BContext.useStytchOrganization;
|
|
79
|
+
exports.withStytchB2BClient = StytchB2BContext.withStytchB2BClient;
|
|
80
|
+
exports.withStytchMember = StytchB2BContext.withStytchMember;
|
|
81
|
+
exports.withStytchMemberSession = StytchB2BContext.withStytchMemberSession;
|
|
82
|
+
exports.withStytchOrganization = StytchB2BContext.withStytchOrganization;
|
|
83
|
+
exports.withStytchPermissions = StytchB2BContext.withStytchPermissions;
|
|
368
84
|
exports.StytchB2B = StytchB2B;
|
|
369
|
-
exports.StytchB2BProvider = StytchB2BProvider;
|
|
370
|
-
exports.useStytchB2BClient = useStytchB2BClient;
|
|
371
|
-
exports.useStytchIsAuthorized = useStytchIsAuthorized;
|
|
372
|
-
exports.useStytchMember = useStytchMember;
|
|
373
|
-
exports.useStytchMemberSession = useStytchMemberSession;
|
|
374
|
-
exports.useStytchOrganization = useStytchOrganization;
|
|
375
|
-
exports.withStytchB2BClient = withStytchB2BClient;
|
|
376
|
-
exports.withStytchMember = withStytchMember;
|
|
377
|
-
exports.withStytchMemberSession = withStytchMemberSession;
|
|
378
|
-
exports.withStytchOrganization = withStytchOrganization;
|
|
379
|
-
exports.withStytchPermissions = withStytchPermissions;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,88 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
3
|
-
const createDeepEqual = ({ KEYS_TO_EXCLUDE = [] } = {}) => {
|
|
4
|
-
// If comparing functions, this may need some work. Not sure the
|
|
5
|
-
// best path for this: compare instance (what it currently does),
|
|
6
|
-
// stringify and compare, etc.
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
-
const deepEqual = (a, b) => {
|
|
9
|
-
// Ensures type is the same
|
|
10
|
-
if (typeof a !== typeof b)
|
|
11
|
-
return false;
|
|
12
|
-
// arrays, null, and objects all have type 'object'
|
|
13
|
-
if (a === null || b === null)
|
|
14
|
-
return a === b;
|
|
15
|
-
if (typeof a === 'object') {
|
|
16
|
-
if (Object.keys(a).length !== Object.keys(b).length || Object.keys(a).some((k) => !(k in b)))
|
|
17
|
-
return false;
|
|
18
|
-
return Object.entries(a)
|
|
19
|
-
.filter(([k]) => !KEYS_TO_EXCLUDE.includes(k))
|
|
20
|
-
.every(([k, v]) => deepEqual(v, b[k]));
|
|
21
|
-
}
|
|
22
|
-
// boolean, string, number, undefined
|
|
23
|
-
return a === b;
|
|
24
|
-
};
|
|
25
|
-
return deepEqual;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const deepEqual = createDeepEqual();
|
|
29
|
-
/**
|
|
30
|
-
* Returns a version of `newValue` whose properties that are deeply equal to
|
|
31
|
-
* those in `oldValue` are replaced with those from `oldValue`. This provides a
|
|
32
|
-
* limited form of "structural sharing" that provides a stable reference for
|
|
33
|
-
* unchanged slices of the object.
|
|
34
|
-
*
|
|
35
|
-
* If `oldValue` and `newValue` are referentially equal, the same value is
|
|
36
|
-
* returned.
|
|
37
|
-
*
|
|
38
|
-
* @param oldValue The old value
|
|
39
|
-
* @param newValue The new value
|
|
40
|
-
*/
|
|
41
|
-
const mergeWithStableProps = (oldValue, newValue) => {
|
|
42
|
-
// If the values are already referentially the same, just return the new value
|
|
43
|
-
if (oldValue === newValue) {
|
|
44
|
-
return newValue;
|
|
45
|
-
}
|
|
46
|
-
return Object.keys(oldValue).reduce((acc, key) => {
|
|
47
|
-
if (key in newValue && deepEqual(oldValue[key], newValue[key])) {
|
|
48
|
-
acc[key] = oldValue[key];
|
|
49
|
-
}
|
|
50
|
-
return acc;
|
|
51
|
-
}, Object.assign({}, newValue));
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// useState can cause memory leaks if it is set after the component unmounted. For example, if it is
|
|
55
|
-
// set after `await`, or in a `then`, `catch`, or `finally`, or in a setTimout/setInterval.
|
|
56
|
-
const useAsyncState = (initialState) => {
|
|
57
|
-
const isMounted = useRef(true);
|
|
58
|
-
const [state, setState] = useState(initialState);
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
isMounted.current = true;
|
|
61
|
-
return () => {
|
|
62
|
-
isMounted.current = false;
|
|
63
|
-
};
|
|
64
|
-
}, []);
|
|
65
|
-
const setStateAction = useCallback((newState) => {
|
|
66
|
-
isMounted.current && setState(newState);
|
|
67
|
-
}, []);
|
|
68
|
-
return [state, setStateAction];
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
72
|
-
const providerMustBeUniqueError = 'You cannot render a <StytchProvider> inside another <StytchProvider>.';
|
|
73
|
-
const noSSRError = `The @stytch/react library is not meant for use with serverside environments like NextJS.
|
|
74
|
-
Use the @stytch/nextjs library instead -
|
|
75
|
-
npm remove @stytch/react && npm install @stytch/nextjs
|
|
76
|
-
`;
|
|
77
|
-
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
78
|
-
You must use the UI SDK to use UI elements.
|
|
79
|
-
Please make sure you are importing from @stytch/vanilla-js and not from the @stytch/vanilla-js/headless.`;
|
|
80
|
-
|
|
81
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
-
function invariant(cond, message) {
|
|
83
|
-
if (!cond)
|
|
84
|
-
throw new Error(message);
|
|
85
|
-
}
|
|
1
|
+
import React, { createContext, useContext, useMemo, useEffect, useRef, useLayoutEffect } from 'react';
|
|
2
|
+
import { i as invariant, u as useAsyncState, m as mergeWithStableProps, n as noProviderError, p as providerMustBeUniqueError, a as noSSRError, b as noHeadlessClientError } from './invariant-568a7633.js';
|
|
86
3
|
|
|
87
4
|
const initialUser = {
|
|
88
5
|
user: null,
|
package/dist/index.js
CHANGED
|
@@ -3,95 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var invariant = require('./invariant-ae5a5bce.js');
|
|
6
7
|
|
|
7
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
9
|
|
|
9
10
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
11
|
|
|
11
|
-
const createDeepEqual = ({ KEYS_TO_EXCLUDE = [] } = {}) => {
|
|
12
|
-
// If comparing functions, this may need some work. Not sure the
|
|
13
|
-
// best path for this: compare instance (what it currently does),
|
|
14
|
-
// stringify and compare, etc.
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
-
const deepEqual = (a, b) => {
|
|
17
|
-
// Ensures type is the same
|
|
18
|
-
if (typeof a !== typeof b)
|
|
19
|
-
return false;
|
|
20
|
-
// arrays, null, and objects all have type 'object'
|
|
21
|
-
if (a === null || b === null)
|
|
22
|
-
return a === b;
|
|
23
|
-
if (typeof a === 'object') {
|
|
24
|
-
if (Object.keys(a).length !== Object.keys(b).length || Object.keys(a).some((k) => !(k in b)))
|
|
25
|
-
return false;
|
|
26
|
-
return Object.entries(a)
|
|
27
|
-
.filter(([k]) => !KEYS_TO_EXCLUDE.includes(k))
|
|
28
|
-
.every(([k, v]) => deepEqual(v, b[k]));
|
|
29
|
-
}
|
|
30
|
-
// boolean, string, number, undefined
|
|
31
|
-
return a === b;
|
|
32
|
-
};
|
|
33
|
-
return deepEqual;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const deepEqual = createDeepEqual();
|
|
37
|
-
/**
|
|
38
|
-
* Returns a version of `newValue` whose properties that are deeply equal to
|
|
39
|
-
* those in `oldValue` are replaced with those from `oldValue`. This provides a
|
|
40
|
-
* limited form of "structural sharing" that provides a stable reference for
|
|
41
|
-
* unchanged slices of the object.
|
|
42
|
-
*
|
|
43
|
-
* If `oldValue` and `newValue` are referentially equal, the same value is
|
|
44
|
-
* returned.
|
|
45
|
-
*
|
|
46
|
-
* @param oldValue The old value
|
|
47
|
-
* @param newValue The new value
|
|
48
|
-
*/
|
|
49
|
-
const mergeWithStableProps = (oldValue, newValue) => {
|
|
50
|
-
// If the values are already referentially the same, just return the new value
|
|
51
|
-
if (oldValue === newValue) {
|
|
52
|
-
return newValue;
|
|
53
|
-
}
|
|
54
|
-
return Object.keys(oldValue).reduce((acc, key) => {
|
|
55
|
-
if (key in newValue && deepEqual(oldValue[key], newValue[key])) {
|
|
56
|
-
acc[key] = oldValue[key];
|
|
57
|
-
}
|
|
58
|
-
return acc;
|
|
59
|
-
}, Object.assign({}, newValue));
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// useState can cause memory leaks if it is set after the component unmounted. For example, if it is
|
|
63
|
-
// set after `await`, or in a `then`, `catch`, or `finally`, or in a setTimout/setInterval.
|
|
64
|
-
const useAsyncState = (initialState) => {
|
|
65
|
-
const isMounted = React.useRef(true);
|
|
66
|
-
const [state, setState] = React.useState(initialState);
|
|
67
|
-
React.useEffect(() => {
|
|
68
|
-
isMounted.current = true;
|
|
69
|
-
return () => {
|
|
70
|
-
isMounted.current = false;
|
|
71
|
-
};
|
|
72
|
-
}, []);
|
|
73
|
-
const setStateAction = React.useCallback((newState) => {
|
|
74
|
-
isMounted.current && setState(newState);
|
|
75
|
-
}, []);
|
|
76
|
-
return [state, setStateAction];
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
80
|
-
const providerMustBeUniqueError = 'You cannot render a <StytchProvider> inside another <StytchProvider>.';
|
|
81
|
-
const noSSRError = `The @stytch/react library is not meant for use with serverside environments like NextJS.
|
|
82
|
-
Use the @stytch/nextjs library instead -
|
|
83
|
-
npm remove @stytch/react && npm install @stytch/nextjs
|
|
84
|
-
`;
|
|
85
|
-
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
86
|
-
You must use the UI SDK to use UI elements.
|
|
87
|
-
Please make sure you are importing from @stytch/vanilla-js and not from the @stytch/vanilla-js/headless.`;
|
|
88
|
-
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
|
-
function invariant(cond, message) {
|
|
91
|
-
if (!cond)
|
|
92
|
-
throw new Error(message);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
12
|
const initialUser = {
|
|
96
13
|
user: null,
|
|
97
14
|
fromCache: false,
|
|
@@ -116,7 +33,7 @@ const isUIClient = (client) => {
|
|
|
116
33
|
* @returns A {@link SWRUser}
|
|
117
34
|
*/
|
|
118
35
|
const useStytchUser = () => {
|
|
119
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchUser'));
|
|
36
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchUser'));
|
|
120
37
|
return React.useContext(StytchUserContext);
|
|
121
38
|
};
|
|
122
39
|
/**
|
|
@@ -131,7 +48,7 @@ const useStytchUser = () => {
|
|
|
131
48
|
* @returns A {@link SWRSession}
|
|
132
49
|
*/
|
|
133
50
|
const useStytchSession = () => {
|
|
134
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchSession'));
|
|
51
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('useStytchSession'));
|
|
135
52
|
return React.useContext(StytchSessionContext);
|
|
136
53
|
};
|
|
137
54
|
/**
|
|
@@ -145,12 +62,12 @@ const useStytchSession = () => {
|
|
|
145
62
|
*/
|
|
146
63
|
const useStytch = () => {
|
|
147
64
|
const ctx = React.useContext(StytchContext);
|
|
148
|
-
invariant(ctx.isMounted, noProviderError('useStytch'));
|
|
65
|
+
invariant.invariant(ctx.isMounted, invariant.noProviderError('useStytch'));
|
|
149
66
|
return ctx.client;
|
|
150
67
|
};
|
|
151
68
|
const withStytch = (Component) => {
|
|
152
69
|
const WithStytch = (props) => {
|
|
153
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytch'));
|
|
70
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytch'));
|
|
154
71
|
return React__default['default'].createElement(Component, Object.assign({}, props, { stytch: useStytch() }));
|
|
155
72
|
};
|
|
156
73
|
WithStytch.displayName = `withStytch(${Component.displayName || Component.name || 'Component'})`;
|
|
@@ -158,7 +75,7 @@ const withStytch = (Component) => {
|
|
|
158
75
|
};
|
|
159
76
|
const withStytchUser = (Component) => {
|
|
160
77
|
const WithStytchUser = (props) => {
|
|
161
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchUser'));
|
|
78
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchUser'));
|
|
162
79
|
const { user, fromCache } = useStytchUser();
|
|
163
80
|
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchUser: user, stytchUserIsFromCache: fromCache }));
|
|
164
81
|
};
|
|
@@ -167,7 +84,7 @@ const withStytchUser = (Component) => {
|
|
|
167
84
|
};
|
|
168
85
|
const withStytchSession = (Component) => {
|
|
169
86
|
const WithStytchSession = (props) => {
|
|
170
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('withStytchSession'));
|
|
87
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('withStytchSession'));
|
|
171
88
|
const { session, fromCache } = useStytchSession();
|
|
172
89
|
return React__default['default'].createElement(Component, Object.assign({}, props, { stytchSession: session, stytchSessionIsFromCache: fromCache }));
|
|
173
90
|
};
|
|
@@ -188,10 +105,10 @@ const withStytchSession = (Component) => {
|
|
|
188
105
|
* )
|
|
189
106
|
*/
|
|
190
107
|
const StytchProvider = ({ stytch, children }) => {
|
|
191
|
-
invariant(!useIsMounted__INTERNAL(), providerMustBeUniqueError);
|
|
192
|
-
invariant(typeof window !== 'undefined', noSSRError);
|
|
108
|
+
invariant.invariant(!useIsMounted__INTERNAL(), invariant.providerMustBeUniqueError);
|
|
109
|
+
invariant.invariant(typeof window !== 'undefined', invariant.noSSRError);
|
|
193
110
|
const ctx = React.useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
194
|
-
const [{ user, session }, setClientState] = useAsyncState({
|
|
111
|
+
const [{ user, session }, setClientState] = invariant.useAsyncState({
|
|
195
112
|
session: stytch.session.getInfo(),
|
|
196
113
|
user: stytch.user.getInfo(),
|
|
197
114
|
});
|
|
@@ -201,7 +118,7 @@ const StytchProvider = ({ stytch, children }) => {
|
|
|
201
118
|
session: stytch.session.getInfo(),
|
|
202
119
|
user: stytch.user.getInfo(),
|
|
203
120
|
};
|
|
204
|
-
return mergeWithStableProps(oldState, newState);
|
|
121
|
+
return invariant.mergeWithStableProps(oldState, newState);
|
|
205
122
|
});
|
|
206
123
|
}), [setClientState, stytch]);
|
|
207
124
|
return (React__default['default'].createElement(StytchContext.Provider, { value: ctx },
|
|
@@ -241,12 +158,12 @@ const StytchProvider = ({ stytch, children }) => {
|
|
|
241
158
|
* @param props {@link StytchProps}
|
|
242
159
|
*/
|
|
243
160
|
const StytchLogin = ({ config, styles, callbacks }) => {
|
|
244
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('<StytchLogin />'));
|
|
161
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('<StytchLogin />'));
|
|
245
162
|
const stytchClient = useStytch();
|
|
246
163
|
const containerEl = React.useRef(null);
|
|
247
164
|
React.useLayoutEffect(() => {
|
|
248
165
|
if (!isUIClient(stytchClient)) {
|
|
249
|
-
throw Error(noHeadlessClientError);
|
|
166
|
+
throw Error(invariant.noHeadlessClientError);
|
|
250
167
|
}
|
|
251
168
|
if (!containerEl.current) {
|
|
252
169
|
return;
|
|
@@ -301,12 +218,12 @@ const StytchLogin = ({ config, styles, callbacks }) => {
|
|
|
301
218
|
* @param callbacks - An optional {@link Callbacks} object
|
|
302
219
|
*/
|
|
303
220
|
const StytchPasswordReset = ({ config, styles, callbacks, passwordResetToken }) => {
|
|
304
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('<StytchResetPassword />'));
|
|
221
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('<StytchResetPassword />'));
|
|
305
222
|
const stytchClient = useStytch();
|
|
306
223
|
const containerEl = React.useRef(null);
|
|
307
224
|
React.useLayoutEffect(() => {
|
|
308
225
|
if (!isUIClient(stytchClient)) {
|
|
309
|
-
throw Error(noHeadlessClientError);
|
|
226
|
+
throw Error(invariant.noHeadlessClientError);
|
|
310
227
|
}
|
|
311
228
|
if (!containerEl.current) {
|
|
312
229
|
return;
|
|
@@ -360,13 +277,13 @@ const StytchPasskeyRegistration = ({ config, styles, callbacks }) => {
|
|
|
360
277
|
* @param styles - An optional {@link StyleConfig} to customize the look and feel of the screen.
|
|
361
278
|
* @param callbacks - An optional {@link Callbacks} object
|
|
362
279
|
*/
|
|
363
|
-
invariant(useIsMounted__INTERNAL(), noProviderError('<StytchPasskeyRegistration />'));
|
|
280
|
+
invariant.invariant(useIsMounted__INTERNAL(), invariant.noProviderError('<StytchPasskeyRegistration />'));
|
|
364
281
|
const stytchClient = useStytch();
|
|
365
282
|
const user = useStytchUser();
|
|
366
283
|
const containerEl = React.useRef(null);
|
|
367
284
|
React.useLayoutEffect(() => {
|
|
368
285
|
if (!isUIClient(stytchClient)) {
|
|
369
|
-
throw Error(noHeadlessClientError);
|
|
286
|
+
throw Error(invariant.noHeadlessClientError);
|
|
370
287
|
}
|
|
371
288
|
if (!containerEl.current) {
|
|
372
289
|
return;
|