@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.
Files changed (37) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -1
  3. package/b2b/adminPortal/package.json +6 -0
  4. package/dist/StytchB2BContext-162fadb4.d.ts +177 -0
  5. package/dist/StytchB2BContext-162fadb4.js +258 -0
  6. package/dist/StytchB2BContext-82437b10.d.ts +177 -0
  7. package/dist/StytchB2BContext-82437b10.js +276 -0
  8. package/dist/StytchSSRProxy-14916009.d.ts +3 -0
  9. package/dist/StytchSSRProxy-14916009.js +47 -0
  10. package/dist/StytchSSRProxy-63bc6323.d.ts +3 -0
  11. package/dist/StytchSSRProxy-63bc6323.js +52 -0
  12. package/dist/adminPortal/index.d.ts +34 -0
  13. package/dist/adminPortal/index.esm.d.ts +34 -0
  14. package/dist/adminPortal/index.esm.js +9519 -0
  15. package/dist/adminPortal/index.js +9527 -0
  16. package/dist/async-86a7f0d6.d.ts +18 -0
  17. package/dist/async-86a7f0d6.js +81 -0
  18. package/dist/async-b1e10055.d.ts +18 -0
  19. package/dist/async-b1e10055.js +77 -0
  20. package/dist/b2b/index.d.ts +3 -174
  21. package/dist/b2b/index.esm.d.ts +3 -174
  22. package/dist/b2b/index.esm.js +6 -340
  23. package/dist/b2b/index.headless.esm.js +1 -38
  24. package/dist/b2b/index.headless.js +2 -39
  25. package/dist/b2b/index.js +18 -353
  26. package/dist/b2b/index.ui.esm.js +1 -38
  27. package/dist/b2b/index.ui.js +2 -39
  28. package/dist/createDeepEqual-5555f2e1.d.ts +5 -0
  29. package/dist/errors-d9d48ed4.d.ts +4 -0
  30. package/dist/index-b14d4efe.d.ts +2 -0
  31. package/dist/index.esm.js +3 -86
  32. package/dist/index.headless.esm.js +1 -38
  33. package/dist/index.headless.js +2 -39
  34. package/dist/index.js +17 -100
  35. package/dist/index.ui.esm.js +1 -38
  36. package/dist/index.ui.js +2 -39
  37. package/package.json +3 -3
@@ -1,342 +1,8 @@
1
- import React, { useRef, useState, useEffect, useCallback, createContext, useContext, useMemo, useLayoutEffect } from '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
- const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
55
- const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
56
- You must use the UI SDK to use UI elements.
57
- Please make sure you are importing createStytchHeadlessClient from @stytch/nextjs/ui and not from @stytch/nextjs/headless.`;
58
-
59
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
- function invariant(cond, message) {
61
- if (!cond)
62
- throw new Error(message);
63
- }
64
-
65
- // useState can cause memory leaks if it is set after the component unmounted. For example, if it is
66
- // set after `await`, or in a `then`, `catch`, or `finally`, or in a setTimout/setInterval.
67
- const useAsyncState = (initialState) => {
68
- const isMounted = useRef(true);
69
- const [state, setState] = useState(initialState);
70
- useEffect(() => {
71
- isMounted.current = true;
72
- return () => {
73
- isMounted.current = false;
74
- };
75
- }, []);
76
- const setStateAction = useCallback((newState) => {
77
- isMounted.current && setState(newState);
78
- }, []);
79
- return [state, setStateAction];
80
- };
81
-
82
- const SSRStubKey = Symbol('__stytch_SSRStubKey');
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- const isStytchSSRProxy = (proxy) => {
85
- return !!proxy[SSRStubKey];
86
- };
87
-
88
- const initialMember = {
89
- member: null,
90
- fromCache: false,
91
- isInitialized: false,
92
- };
93
- const initialMemberSession = {
94
- session: null,
95
- fromCache: false,
96
- isInitialized: false,
97
- };
98
- const initialOrganization = {
99
- organization: null,
100
- fromCache: false,
101
- isInitialized: false,
102
- };
103
- const StytchContext = createContext({ isMounted: false });
104
- const StytchMemberContext = createContext(initialMember);
105
- const StytchMemberSessionContext = createContext(initialMemberSession);
106
- const StytchOrganizationContext = createContext(initialOrganization);
107
- const useIsMounted__INTERNAL = () => useContext(StytchContext).isMounted;
108
- const isUIClient = (client) => {
109
- return client.mount !== undefined;
110
- };
111
- /**
112
- * Returns the active member.
113
- * The Stytch SDKs are used for client-side authentication and session management.
114
- * Check the isInitialized property to determine if the SDK has completed initialization.
115
- * Check the fromCache property to determine if the session data is from persistent storage.
116
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
117
- * @example
118
- * const {member, isInitialized, fromCache} = useStytchMember();
119
- * if (!isInitialized) {
120
- * return <p>Loading...</p>;
121
- * }
122
- * return (<h1>Welcome, {member.name}</h1>);
123
- */
124
- const useStytchMember = () => {
125
- invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMember', 'StytchB2BProvider'));
126
- return useContext(StytchMemberContext);
127
- };
128
- /**
129
- * Returns the member's active Stytch member session.
130
- * The Stytch SDKs are used for client-side authentication and session management.
131
- * Check the isInitialized property to determine if the SDK has completed initialization.
132
- * Check the fromCache property to determine if the session data is from persistent storage.
133
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
134
- * @example
135
- * const {session, isInitialized, fromCache} = useStytchMemberSession();
136
- * useEffect(() => {
137
- * if (!isInitialized) {
138
- * return;
139
- * }
140
- * if (!session) {
141
- * router.replace('/login')
142
- * }
143
- * }, [session, isInitialized]);
144
- */
145
- const useStytchMemberSession = () => {
146
- invariant(useIsMounted__INTERNAL(), noProviderError('useStytchMemberSession', 'StytchB2BProvider'));
147
- return useContext(StytchMemberSessionContext);
148
- };
149
- /**
150
- * Returns the active Stytch organization.
151
- * The Stytch SDKs are used for client-side authentication and session management.
152
- * Check the isInitialized property to determine if the SDK has completed initialization.
153
- * Check the fromCache property to determine if the session data is from persistent storage.
154
- * See Next's {@link https://nextjs.org/docs/authentication#authenticating-statically-generated-pages documentation} for more.
155
- * @example
156
- * const {organization, isInitialized, fromCache} = useStytchOrganization();
157
- * if (!isInitialized) {
158
- * return <p>Loading...</p>;
159
- * }
160
- * return (<p>Welcome to {organization.organization_name}</p>);
161
- */
162
- const useStytchOrganization = () => {
163
- invariant(useIsMounted__INTERNAL(), noProviderError('useStytchOrganization', 'StytchB2BProvider'));
164
- return useContext(StytchOrganizationContext);
165
- };
166
- /**
167
- * Determines whether the logged-in member is allowed to perform the specified action on the specified resource.
168
- * Returns `true` if the member can perform the action, `false` otherwise.
169
- *
170
- * If the member is not logged in, this method will always return false.
171
- * If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
172
- *
173
- * Remember - authorization checks for sensitive actions should always occur on the backend as well.
174
- * @example
175
- * const isAuthorized = useStytchIsAuthorized<Permissions>('documents', 'edit');
176
- * return <button disabled={!isAuthorized}>Edit</button>
177
- */
178
- const useStytchIsAuthorized = (resourceId, action) => {
179
- invariant(useIsMounted__INTERNAL(), noProviderError('useStytchIsAuthorized', 'StytchB2BProvider'));
180
- const client = useStytchB2BClient();
181
- const { session } = useStytchMemberSession();
182
- const [isAuthorized, setIsAuthorized] = useAsyncState({
183
- isInitialized: false,
184
- fromCache: false,
185
- isAuthorized: false,
186
- });
187
- useEffect(() => {
188
- if (isStytchSSRProxy(client)) {
189
- return;
190
- }
191
- setIsAuthorized({
192
- isInitialized: true,
193
- fromCache: true,
194
- isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
195
- });
196
- }, [action, client, resourceId, setIsAuthorized]);
197
- useEffect(() => {
198
- if (isStytchSSRProxy(client)) {
199
- return;
200
- }
201
- client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
202
- setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
203
- });
204
- }, [client, session === null || session === void 0 ? void 0 : session.roles, resourceId, action, setIsAuthorized]);
205
- return isAuthorized;
206
- };
207
- /**
208
- * Returns the Stytch client stored in the Stytch context.
209
- *
210
- * @example
211
- * const stytch = useStytch();
212
- * useEffect(() => {
213
- * stytch.magicLinks.authenticate('...')
214
- * }, [stytch]);
215
- */
216
- const useStytchB2BClient = () => {
217
- const ctx = useContext(StytchContext);
218
- invariant(ctx.isMounted, noProviderError('useStytchB2BClient', 'StytchB2BProvider'));
219
- return ctx.client;
220
- };
221
- const withStytchB2BClient = (Component) => {
222
- const WithStytch = (props) => {
223
- invariant(useIsMounted__INTERNAL(), noProviderError('withStytchB2BClient', 'StytchB2BProvider'));
224
- return React.createElement(Component, Object.assign({}, props, { stytch: useStytchB2BClient() }));
225
- };
226
- WithStytch.displayName = `withStytch(${Component.displayName || Component.name || 'Component'})`;
227
- return WithStytch;
228
- };
229
- const withStytchMember = (Component) => {
230
- const WithStytchUser = (props) => {
231
- invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMember', 'StytchB2BProvider'));
232
- const { member, isInitialized, fromCache } = useStytchMember();
233
- return (React.createElement(Component, Object.assign({}, props, { stytchMember: member, stytchMemberIsInitialized: isInitialized, stytchMemberIsFromCache: fromCache })));
234
- };
235
- WithStytchUser.displayName = `withStytchMember(${Component.displayName || Component.name || 'Component'})`;
236
- return WithStytchUser;
237
- };
238
- const withStytchMemberSession = (Component) => {
239
- const WithStytchSession = (props) => {
240
- invariant(useIsMounted__INTERNAL(), noProviderError('withStytchMemberSession', 'StytchB2BProvider'));
241
- const { session, isInitialized, fromCache } = useStytchMemberSession();
242
- return (React.createElement(Component, Object.assign({}, props, { stytchMemberSession: session, stytchMemberSessionIsInitialized: isInitialized, stytchMemberSessionIsFromCache: fromCache })));
243
- };
244
- WithStytchSession.displayName = `withStytchMemberSession(${Component.displayName || Component.name || 'Component'})`;
245
- return WithStytchSession;
246
- };
247
- const withStytchOrganization = (Component) => {
248
- const WithStytchOrganization = (props) => {
249
- invariant(useIsMounted__INTERNAL(), noProviderError('withStytchOrganization', 'StytchB2BProvider'));
250
- const { organization, isInitialized, fromCache } = useStytchOrganization();
251
- return (React.createElement(Component, Object.assign({}, props, { stytchOrganization: organization, stytchOrganizationIsInitialized: isInitialized, stytchOrganizationIsFromCache: fromCache })));
252
- };
253
- WithStytchOrganization.displayName = `withStytchOrganization(${Component.displayName || Component.name || 'Component'})`;
254
- return WithStytchOrganization;
255
- };
256
- /**
257
- * Wrap your component with this HOC in order to receive the permissions for the logged-in member.
258
- * Evaluates all permissions granted to the logged-in member.
259
- * Returns a Record<RoleId, Record<Action, boolean>> response indicating the member's permissions.
260
- * Each boolean will be `true` if the member can perform the action, `false` otherwise.
261
- *
262
- * If the member is not logged in, all values will be false.
263
- *
264
- * Remember - authorization checks for sensitive actions should always occur on the backend as well.
265
- * @example
266
- * type Permissions = {
267
- * document: 'create' | 'read' | 'write
268
- * image: 'create' | 'read'
269
- * }
270
- *
271
- * const MyComponent = (props) => {
272
- * const canEditDocuments = props.stytchPermissions.document.edit;
273
- * const canReadImages = props.stytchPermissions.image.read;
274
- * }
275
- * return withStytchPermissions<Permissions>(MyComponent)
276
- */
277
- const withStytchPermissions = (Component) => {
278
- const WithStytchPermissions = (props) => {
279
- invariant(useIsMounted__INTERNAL(), noProviderError('useRBACPermissions', 'StytchB2BProvider'));
280
- const client = useStytchB2BClient();
281
- const { session } = useStytchMemberSession();
282
- const [permissions, setPermissions] = useAsyncState({ loaded: false, value: null });
283
- useEffect(() => {
284
- client.rbac
285
- .allPermissions()
286
- .then((permissions) => setPermissions({ loaded: true, value: permissions }));
287
- }, [client, session === null || session === void 0 ? void 0 : session.roles, setPermissions]);
288
- if (!permissions.loaded) {
289
- return null;
290
- }
291
- return React.createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
292
- };
293
- WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
294
- return WithStytchPermissions;
295
- };
296
- /**
297
- * The Stytch Context Provider.
298
- * Wrap your application with this component in `_app.js` in order to use Stytch everywhere in your app.
299
- * @example
300
- * const stytch = createStytchB2BHeadlessClient('public-token-<find yours in the stytch dashboard>')
301
- *
302
- * return (
303
- * <StytchB2BProvider stytch={stytch}>
304
- * <App />
305
- * </StytchB2BProvider>
306
- * )
307
- */
308
- const StytchB2BProvider = ({ stytch, children }) => {
309
- const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
310
- const [{ member, session, organization }, setClientState] = useAsyncState({
311
- member: initialMember,
312
- session: initialMemberSession,
313
- organization: initialOrganization,
314
- });
315
- useEffect(() => {
316
- if (isStytchSSRProxy(stytch)) {
317
- return;
318
- }
319
- setClientState({
320
- member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
321
- session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
322
- organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
323
- });
324
- return stytch.onStateChange(() => {
325
- setClientState((oldState) => {
326
- const newState = {
327
- member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
328
- session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
329
- organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
330
- };
331
- return mergeWithStableProps(oldState, newState);
332
- });
333
- });
334
- }, [setClientState, stytch]);
335
- return (React.createElement(StytchContext.Provider, { value: ctx },
336
- React.createElement(StytchOrganizationContext.Provider, { value: organization },
337
- React.createElement(StytchMemberContext.Provider, { value: member },
338
- React.createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
339
- };
1
+ import { u as useIsMounted__INTERNAL, a as useStytchB2BClient, i as isUIClient } from '../StytchB2BContext-162fadb4.js';
2
+ export { S as StytchB2BProvider, a as useStytchB2BClient, d as useStytchIsAuthorized, c as useStytchMember, b as useStytchMemberSession, e as useStytchOrganization, w as withStytchB2BClient, g as withStytchMember, f as withStytchMemberSession, h as withStytchOrganization, j as withStytchPermissions } from '../StytchB2BContext-162fadb4.js';
3
+ import React, { useRef, useLayoutEffect } from 'react';
4
+ import { i as invariant } from '../async-b1e10055.js';
5
+ import { a as noHeadlessClientError, n as noProviderError } from '../StytchSSRProxy-14916009.js';
340
6
 
341
7
  /**
342
8
  * The Stytch B2B UI component.
@@ -398,4 +64,4 @@ const StytchB2B = ({ styles, callbacks, config }) => {
398
64
  return React.createElement("div", { ref: containerEl });
399
65
  };
400
66
 
401
- export { StytchB2B, StytchB2BProvider, useStytchB2BClient, useStytchIsAuthorized, useStytchMember, useStytchMemberSession, useStytchOrganization, withStytchB2BClient, withStytchMember, withStytchMemberSession, withStytchOrganization, withStytchPermissions };
67
+ export { StytchB2B };
@@ -1,42 +1,5 @@
1
1
  import { StytchB2BHeadlessClient } from '@stytch/vanilla-js/b2b/headless';
2
-
3
- const cannotInvokeMethodOnServerError = (path) => `[Stytch] Invalid serverside function call to ${path}.
4
- The Stytch Javascript SDK is intended to ony be used on the client side.
5
- Make sure to wrap your API calls in a hook to ensure they are executed on the client.
6
- \`\`\`
7
- const myComponent = () => {
8
- const stytch = useStytch();
9
- // This will error out on the server.
10
- stytch.magicLinks.authenticate(...);
11
- useEffect(() => {
12
- // This will work well
13
- stytch.magicLinks.authenticate(...);
14
- }, []);
15
- }
16
- \`\`\`
17
-
18
- If you want to make API calls from server environments, please use the Stytch Node Library
19
- https://www.npmjs.com/package/stytch.
20
- `;
21
-
22
- const SSRStubKey = Symbol('__stytch_SSRStubKey');
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
- const createProxy = (path) => {
25
- // eslint-disable-next-line @typescript-eslint/no-empty-function
26
- const noop = () => { };
27
- return new Proxy(noop, {
28
- get(target, p) {
29
- if (p === SSRStubKey) {
30
- return true;
31
- }
32
- return createProxy(path + '.' + String(p));
33
- },
34
- apply() {
35
- throw new Error(cannotInvokeMethodOnServerError(path));
36
- },
37
- });
38
- };
39
- const createStytchSSRProxy = () => createProxy('stytch');
2
+ import { c as createStytchSSRProxy } from '../StytchSSRProxy-14916009.js';
40
3
 
41
4
  /**
42
5
  * Creates a Headless Stytch client object to call the stytch B2B APIs.
@@ -3,44 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var headless = require('@stytch/vanilla-js/b2b/headless');
6
-
7
- const cannotInvokeMethodOnServerError = (path) => `[Stytch] Invalid serverside function call to ${path}.
8
- The Stytch Javascript SDK is intended to ony be used on the client side.
9
- Make sure to wrap your API calls in a hook to ensure they are executed on the client.
10
- \`\`\`
11
- const myComponent = () => {
12
- const stytch = useStytch();
13
- // This will error out on the server.
14
- stytch.magicLinks.authenticate(...);
15
- useEffect(() => {
16
- // This will work well
17
- stytch.magicLinks.authenticate(...);
18
- }, []);
19
- }
20
- \`\`\`
21
-
22
- If you want to make API calls from server environments, please use the Stytch Node Library
23
- https://www.npmjs.com/package/stytch.
24
- `;
25
-
26
- const SSRStubKey = Symbol('__stytch_SSRStubKey');
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- const createProxy = (path) => {
29
- // eslint-disable-next-line @typescript-eslint/no-empty-function
30
- const noop = () => { };
31
- return new Proxy(noop, {
32
- get(target, p) {
33
- if (p === SSRStubKey) {
34
- return true;
35
- }
36
- return createProxy(path + '.' + String(p));
37
- },
38
- apply() {
39
- throw new Error(cannotInvokeMethodOnServerError(path));
40
- },
41
- });
42
- };
43
- const createStytchSSRProxy = () => createProxy('stytch');
6
+ var StytchSSRProxy = require('../StytchSSRProxy-63bc6323.js');
44
7
 
45
8
  /**
46
9
  * Creates a Headless Stytch client object to call the stytch B2B APIs.
@@ -57,7 +20,7 @@ const createStytchSSRProxy = () => createProxy('stytch');
57
20
  */
58
21
  const createStytchB2BHeadlessClient = (...args) => {
59
22
  if (typeof window === 'undefined') {
60
- return createStytchSSRProxy();
23
+ return StytchSSRProxy.createStytchSSRProxy();
61
24
  }
62
25
  return new headless.StytchB2BHeadlessClient(...args);
63
26
  };