@stytch/nextjs 18.0.0 → 19.0.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 +12 -0
- package/dist/b2b/index.esm.js +73 -40
- package/dist/b2b/index.headless.d.ts +1 -1
- package/dist/b2b/index.headless.esm.d.ts +1 -1
- package/dist/b2b/index.js +73 -40
- package/dist/b2b/index.ui.d.ts +1 -1
- package/dist/b2b/index.ui.esm.d.ts +1 -1
- package/dist/index.esm.js +69 -22
- package/dist/index.headless.d.ts +2 -1
- package/dist/index.headless.esm.d.ts +2 -1
- package/dist/index.js +69 -22
- package/dist/index.ui.d.ts +2 -1
- package/dist/index.ui.esm.d.ts +2 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @stytch/nextjs
|
|
2
2
|
|
|
3
|
+
## 19.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- a0fbe9f: Update minimum peer dependency on `@stytch/vanilla-js` to `^4.9.0`
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [a0fbe9f]
|
|
12
|
+
- Updated dependencies [a0fbe9f]
|
|
13
|
+
- @stytch/vanilla-js@4.9.0
|
|
14
|
+
|
|
3
15
|
## 18.0.0
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/b2b/index.esm.js
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
import React, { useRef, useState, useEffect, useCallback, createContext, useContext, useMemo, useLayoutEffect } from 'react';
|
|
2
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
|
+
|
|
3
54
|
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
4
55
|
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
5
56
|
You must use the UI SDK to use UI elements.
|
|
@@ -256,53 +307,35 @@ const withStytchPermissions = (Component) => {
|
|
|
256
307
|
*/
|
|
257
308
|
const StytchB2BProvider = ({ stytch, children }) => {
|
|
258
309
|
const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
259
|
-
const [member,
|
|
260
|
-
|
|
261
|
-
|
|
310
|
+
const [{ member, session, organization }, setClientState] = useAsyncState({
|
|
311
|
+
member: initialMember,
|
|
312
|
+
session: initialMemberSession,
|
|
313
|
+
organization: initialOrganization,
|
|
314
|
+
});
|
|
262
315
|
useEffect(() => {
|
|
263
316
|
if (isStytchSSRProxy(stytch)) {
|
|
264
317
|
return;
|
|
265
318
|
}
|
|
266
|
-
|
|
267
|
-
member: stytch.self.
|
|
268
|
-
|
|
269
|
-
isInitialized: true,
|
|
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 }),
|
|
270
323
|
});
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
+
});
|
|
275
333
|
});
|
|
276
|
-
|
|
277
|
-
organization: stytch.organization.getSync(),
|
|
278
|
-
fromCache: true,
|
|
279
|
-
isInitialized: true,
|
|
280
|
-
});
|
|
281
|
-
const unsubscribeMember = stytch.self.onChange((member) => setMember({ member, fromCache: false, isInitialized: true }));
|
|
282
|
-
const unsubscribeMemberSession = stytch.session.onChange((session) => setMemberSession({ session, fromCache: false, isInitialized: true }));
|
|
283
|
-
const unsubscribeOrganization = stytch.organization.onChange((organization) => setOrganization({ organization, fromCache: false, isInitialized: true }));
|
|
284
|
-
return () => {
|
|
285
|
-
unsubscribeMember();
|
|
286
|
-
unsubscribeMemberSession();
|
|
287
|
-
unsubscribeOrganization();
|
|
288
|
-
};
|
|
289
|
-
}, [stytch, setMember, setMemberSession, setOrganization]);
|
|
290
|
-
const allValuesReady = !!member.member === !!session.session && !!session.session === !!organization.organization;
|
|
291
|
-
const finalValues = allValuesReady
|
|
292
|
-
? {
|
|
293
|
-
member,
|
|
294
|
-
session,
|
|
295
|
-
organization,
|
|
296
|
-
}
|
|
297
|
-
: {
|
|
298
|
-
member: initialMember,
|
|
299
|
-
session: initialMemberSession,
|
|
300
|
-
organization: initialOrganization,
|
|
301
|
-
};
|
|
334
|
+
}, [setClientState, stytch]);
|
|
302
335
|
return (React.createElement(StytchContext.Provider, { value: ctx },
|
|
303
|
-
React.createElement(StytchOrganizationContext.Provider, { value:
|
|
304
|
-
React.createElement(StytchMemberContext.Provider, { value:
|
|
305
|
-
React.createElement(StytchMemberSessionContext.Provider, { value:
|
|
336
|
+
React.createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
337
|
+
React.createElement(StytchMemberContext.Provider, { value: member },
|
|
338
|
+
React.createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
306
339
|
};
|
|
307
340
|
|
|
308
341
|
/**
|
|
@@ -12,5 +12,5 @@ import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
|
|
|
12
12
|
* )
|
|
13
13
|
* @returns A {@link StytchB2BHeadlessClient}
|
|
14
14
|
*/
|
|
15
|
-
declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("
|
|
15
|
+
declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
|
|
16
16
|
export { createStytchB2BHeadlessClient };
|
|
@@ -12,5 +12,5 @@ import { StytchB2BHeadlessClient } from "@stytch/vanilla-js/b2b/headless";
|
|
|
12
12
|
* )
|
|
13
13
|
* @returns A {@link StytchB2BHeadlessClient}
|
|
14
14
|
*/
|
|
15
|
-
declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("
|
|
15
|
+
declare const createStytchB2BHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BHeadlessClient;
|
|
16
16
|
export { createStytchB2BHeadlessClient };
|
package/dist/b2b/index.js
CHANGED
|
@@ -8,6 +8,57 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
10
|
|
|
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
|
+
|
|
11
62
|
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
12
63
|
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
13
64
|
You must use the UI SDK to use UI elements.
|
|
@@ -264,53 +315,35 @@ const withStytchPermissions = (Component) => {
|
|
|
264
315
|
*/
|
|
265
316
|
const StytchB2BProvider = ({ stytch, children }) => {
|
|
266
317
|
const ctx = React.useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
267
|
-
const [member,
|
|
268
|
-
|
|
269
|
-
|
|
318
|
+
const [{ member, session, organization }, setClientState] = useAsyncState({
|
|
319
|
+
member: initialMember,
|
|
320
|
+
session: initialMemberSession,
|
|
321
|
+
organization: initialOrganization,
|
|
322
|
+
});
|
|
270
323
|
React.useEffect(() => {
|
|
271
324
|
if (isStytchSSRProxy(stytch)) {
|
|
272
325
|
return;
|
|
273
326
|
}
|
|
274
|
-
|
|
275
|
-
member: stytch.self.
|
|
276
|
-
|
|
277
|
-
isInitialized: true,
|
|
327
|
+
setClientState({
|
|
328
|
+
member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
|
|
329
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
330
|
+
organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
|
|
278
331
|
});
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
332
|
+
return stytch.onStateChange(() => {
|
|
333
|
+
setClientState((oldState) => {
|
|
334
|
+
const newState = {
|
|
335
|
+
member: Object.assign(Object.assign({}, stytch.self.getInfo()), { isInitialized: true }),
|
|
336
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
337
|
+
organization: Object.assign(Object.assign({}, stytch.organization.getInfo()), { isInitialized: true }),
|
|
338
|
+
};
|
|
339
|
+
return mergeWithStableProps(oldState, newState);
|
|
340
|
+
});
|
|
283
341
|
});
|
|
284
|
-
|
|
285
|
-
organization: stytch.organization.getSync(),
|
|
286
|
-
fromCache: true,
|
|
287
|
-
isInitialized: true,
|
|
288
|
-
});
|
|
289
|
-
const unsubscribeMember = stytch.self.onChange((member) => setMember({ member, fromCache: false, isInitialized: true }));
|
|
290
|
-
const unsubscribeMemberSession = stytch.session.onChange((session) => setMemberSession({ session, fromCache: false, isInitialized: true }));
|
|
291
|
-
const unsubscribeOrganization = stytch.organization.onChange((organization) => setOrganization({ organization, fromCache: false, isInitialized: true }));
|
|
292
|
-
return () => {
|
|
293
|
-
unsubscribeMember();
|
|
294
|
-
unsubscribeMemberSession();
|
|
295
|
-
unsubscribeOrganization();
|
|
296
|
-
};
|
|
297
|
-
}, [stytch, setMember, setMemberSession, setOrganization]);
|
|
298
|
-
const allValuesReady = !!member.member === !!session.session && !!session.session === !!organization.organization;
|
|
299
|
-
const finalValues = allValuesReady
|
|
300
|
-
? {
|
|
301
|
-
member,
|
|
302
|
-
session,
|
|
303
|
-
organization,
|
|
304
|
-
}
|
|
305
|
-
: {
|
|
306
|
-
member: initialMember,
|
|
307
|
-
session: initialMemberSession,
|
|
308
|
-
organization: initialOrganization,
|
|
309
|
-
};
|
|
342
|
+
}, [setClientState, stytch]);
|
|
310
343
|
return (React__default['default'].createElement(StytchContext.Provider, { value: ctx },
|
|
311
|
-
React__default['default'].createElement(StytchOrganizationContext.Provider, { value:
|
|
312
|
-
React__default['default'].createElement(StytchMemberContext.Provider, { value:
|
|
313
|
-
React__default['default'].createElement(StytchMemberSessionContext.Provider, { value:
|
|
344
|
+
React__default['default'].createElement(StytchOrganizationContext.Provider, { value: organization },
|
|
345
|
+
React__default['default'].createElement(StytchMemberContext.Provider, { value: member },
|
|
346
|
+
React__default['default'].createElement(StytchMemberSessionContext.Provider, { value: session }, children)))));
|
|
314
347
|
};
|
|
315
348
|
|
|
316
349
|
/**
|
package/dist/b2b/index.ui.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ import { StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
|
|
|
13
13
|
* )
|
|
14
14
|
* @returns A {@link StytchB2BUIClient}
|
|
15
15
|
*/
|
|
16
|
-
declare const createStytchB2BUIClient: (_PUBLIC_TOKEN: string, options?: import("
|
|
16
|
+
declare const createStytchB2BUIClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BUIClient;
|
|
17
17
|
export { createStytchB2BUIClient };
|
|
@@ -13,5 +13,5 @@ import { StytchB2BUIClient } from "@stytch/vanilla-js/b2b";
|
|
|
13
13
|
* )
|
|
14
14
|
* @returns A {@link StytchB2BUIClient}
|
|
15
15
|
*/
|
|
16
|
-
declare const createStytchB2BUIClient: (_PUBLIC_TOKEN: string, options?: import("
|
|
16
|
+
declare const createStytchB2BUIClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchB2BUIClient;
|
|
17
17
|
export { createStytchB2BUIClient };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
import React, { useRef, useState, useEffect, useCallback, createContext, useContext, useMemo, useLayoutEffect } from 'react';
|
|
2
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
|
+
|
|
3
54
|
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
4
55
|
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
5
56
|
You must use the UI SDK to use UI elements.
|
|
@@ -143,35 +194,31 @@ const withStytchSession = (Component) => {
|
|
|
143
194
|
*/
|
|
144
195
|
const StytchProvider = ({ stytch, children }) => {
|
|
145
196
|
const ctx = useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
146
|
-
const [user,
|
|
147
|
-
|
|
197
|
+
const [{ user, session }, setClientState] = useAsyncState({
|
|
198
|
+
session: initialSession,
|
|
199
|
+
user: initialUser,
|
|
200
|
+
});
|
|
148
201
|
useEffect(() => {
|
|
149
202
|
if (isStytchSSRProxy(stytch)) {
|
|
150
203
|
return;
|
|
151
204
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
isInitialized: true,
|
|
205
|
+
setClientState({
|
|
206
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
207
|
+
user: Object.assign(Object.assign({}, stytch.user.getInfo()), { isInitialized: true }),
|
|
156
208
|
});
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
209
|
+
return stytch.onStateChange(() => {
|
|
210
|
+
setClientState((oldState) => {
|
|
211
|
+
const newState = {
|
|
212
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
213
|
+
user: Object.assign(Object.assign({}, stytch.user.getInfo()), { isInitialized: true }),
|
|
214
|
+
};
|
|
215
|
+
return mergeWithStableProps(oldState, newState);
|
|
216
|
+
});
|
|
161
217
|
});
|
|
162
|
-
|
|
163
|
-
const unsubscribeSession = stytch.session.onChange((session) => setSession({ session, fromCache: false, isInitialized: true }));
|
|
164
|
-
return () => {
|
|
165
|
-
unsubscribeUser();
|
|
166
|
-
unsubscribeSession();
|
|
167
|
-
};
|
|
168
|
-
}, [stytch, setUser, setSession]);
|
|
169
|
-
// TODO (SDK-813): Remove this when we have a single top-level onChange handler
|
|
170
|
-
const finalSess = !!session.session === !!user.user ? session : initialSession;
|
|
171
|
-
const finalUser = !!session.session === !!user.user ? user : initialUser;
|
|
218
|
+
}, [setClientState, stytch]);
|
|
172
219
|
return (React.createElement(StytchContext.Provider, { value: ctx },
|
|
173
|
-
React.createElement(StytchUserContext.Provider, { value:
|
|
174
|
-
React.createElement(StytchSessionContext.Provider, { value:
|
|
220
|
+
React.createElement(StytchUserContext.Provider, { value: user },
|
|
221
|
+
React.createElement(StytchSessionContext.Provider, { value: session }, children))));
|
|
175
222
|
};
|
|
176
223
|
|
|
177
224
|
// cc https://medium.com/@alexandereardon/uselayouteffect-and-ssr-192986cdcf7a
|
package/dist/index.headless.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
1
2
|
/**
|
|
2
3
|
* Creates a Headless Stytch client object to call the stytch APIs.
|
|
3
4
|
* The Stytch client is not available serverside.
|
|
@@ -11,5 +12,5 @@
|
|
|
11
12
|
* )
|
|
12
13
|
* @returns A {@link StytchHeadlessClient}
|
|
13
14
|
*/
|
|
14
|
-
declare const createStytchHeadlessClient:
|
|
15
|
+
declare const createStytchHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchHeadlessClient;
|
|
15
16
|
export { createStytchHeadlessClient };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
1
2
|
/**
|
|
2
3
|
* Creates a Headless Stytch client object to call the stytch APIs.
|
|
3
4
|
* The Stytch client is not available serverside.
|
|
@@ -11,5 +12,5 @@
|
|
|
11
12
|
* )
|
|
12
13
|
* @returns A {@link StytchHeadlessClient}
|
|
13
14
|
*/
|
|
14
|
-
declare const createStytchHeadlessClient:
|
|
15
|
+
declare const createStytchHeadlessClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchHeadlessClient;
|
|
15
16
|
export { createStytchHeadlessClient };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,57 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
10
|
|
|
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
|
+
|
|
11
62
|
const noProviderError = (item, provider = 'StytchProvider') => `${item} can only be used inside <${provider}>.`;
|
|
12
63
|
const noHeadlessClientError = `Tried to create a Stytch Login UI element using the Stytch Headless SDK.
|
|
13
64
|
You must use the UI SDK to use UI elements.
|
|
@@ -151,35 +202,31 @@ const withStytchSession = (Component) => {
|
|
|
151
202
|
*/
|
|
152
203
|
const StytchProvider = ({ stytch, children }) => {
|
|
153
204
|
const ctx = React.useMemo(() => ({ client: stytch, isMounted: true }), [stytch]);
|
|
154
|
-
const [user,
|
|
155
|
-
|
|
205
|
+
const [{ user, session }, setClientState] = useAsyncState({
|
|
206
|
+
session: initialSession,
|
|
207
|
+
user: initialUser,
|
|
208
|
+
});
|
|
156
209
|
React.useEffect(() => {
|
|
157
210
|
if (isStytchSSRProxy(stytch)) {
|
|
158
211
|
return;
|
|
159
212
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
isInitialized: true,
|
|
213
|
+
setClientState({
|
|
214
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
215
|
+
user: Object.assign(Object.assign({}, stytch.user.getInfo()), { isInitialized: true }),
|
|
164
216
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
217
|
+
return stytch.onStateChange(() => {
|
|
218
|
+
setClientState((oldState) => {
|
|
219
|
+
const newState = {
|
|
220
|
+
session: Object.assign(Object.assign({}, stytch.session.getInfo()), { isInitialized: true }),
|
|
221
|
+
user: Object.assign(Object.assign({}, stytch.user.getInfo()), { isInitialized: true }),
|
|
222
|
+
};
|
|
223
|
+
return mergeWithStableProps(oldState, newState);
|
|
224
|
+
});
|
|
169
225
|
});
|
|
170
|
-
|
|
171
|
-
const unsubscribeSession = stytch.session.onChange((session) => setSession({ session, fromCache: false, isInitialized: true }));
|
|
172
|
-
return () => {
|
|
173
|
-
unsubscribeUser();
|
|
174
|
-
unsubscribeSession();
|
|
175
|
-
};
|
|
176
|
-
}, [stytch, setUser, setSession]);
|
|
177
|
-
// TODO (SDK-813): Remove this when we have a single top-level onChange handler
|
|
178
|
-
const finalSess = !!session.session === !!user.user ? session : initialSession;
|
|
179
|
-
const finalUser = !!session.session === !!user.user ? user : initialUser;
|
|
226
|
+
}, [setClientState, stytch]);
|
|
180
227
|
return (React__default['default'].createElement(StytchContext.Provider, { value: ctx },
|
|
181
|
-
React__default['default'].createElement(StytchUserContext.Provider, { value:
|
|
182
|
-
React__default['default'].createElement(StytchSessionContext.Provider, { value:
|
|
228
|
+
React__default['default'].createElement(StytchUserContext.Provider, { value: user },
|
|
229
|
+
React__default['default'].createElement(StytchSessionContext.Provider, { value: session }, children))));
|
|
183
230
|
};
|
|
184
231
|
|
|
185
232
|
// cc https://medium.com/@alexandereardon/uselayouteffect-and-ssr-192986cdcf7a
|
package/dist/index.ui.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StytchUIClient } from "@stytch/vanilla-js";
|
|
1
2
|
/**
|
|
2
3
|
* Creates a Stytch UI client object to call the Stytch APIs and render Stytch UI components.
|
|
3
4
|
* The Stytch client is not available serverside.
|
|
@@ -12,5 +13,5 @@
|
|
|
12
13
|
* )
|
|
13
14
|
* @returns A {@link StytchUIClient}
|
|
14
15
|
*/
|
|
15
|
-
declare const createStytchUIClient:
|
|
16
|
+
declare const createStytchUIClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchUIClient;
|
|
16
17
|
export { createStytchUIClient };
|
package/dist/index.ui.esm.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StytchUIClient } from "@stytch/vanilla-js";
|
|
1
2
|
/**
|
|
2
3
|
* Creates a Stytch UI client object to call the Stytch APIs and render Stytch UI components.
|
|
3
4
|
* The Stytch client is not available serverside.
|
|
@@ -12,5 +13,5 @@
|
|
|
12
13
|
* )
|
|
13
14
|
* @returns A {@link StytchUIClient}
|
|
14
15
|
*/
|
|
15
|
-
declare const createStytchUIClient:
|
|
16
|
+
declare const createStytchUIClient: (_PUBLIC_TOKEN: string, options?: import("core/dist/public").StytchClientOptions | undefined) => StytchUIClient;
|
|
16
17
|
export { createStytchUIClient };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stytch/nextjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "Stytch's official Next.js Library",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"author": "Stytch",
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@babel/runtime": "7.18.6",
|
|
25
|
-
"@stytch/
|
|
25
|
+
"@stytch/js-utils": "0.0.0",
|
|
26
|
+
"@stytch/vanilla-js": "4.9.0",
|
|
26
27
|
"@testing-library/react": "14.0.0",
|
|
27
28
|
"eslint-config-custom": "0.0.1",
|
|
28
29
|
"react": "18.2.0",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"typescript": "5.3.3"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
|
35
|
-
"@stytch/vanilla-js": "^4.
|
|
36
|
+
"@stytch/vanilla-js": "^4.9.0",
|
|
36
37
|
"react": ">= 17.0.2",
|
|
37
38
|
"react-dom": ">= 17.0.2"
|
|
38
39
|
},
|