@logto/react 0.1.3 → 0.1.6

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/lib/context.d.ts CHANGED
@@ -4,8 +4,10 @@ export declare type LogtoContextProps = {
4
4
  logtoClient?: LogtoClient;
5
5
  isAuthenticated: boolean;
6
6
  loadingCount: number;
7
+ error?: Error;
7
8
  setIsAuthenticated: React.Dispatch<React.SetStateAction<boolean>>;
8
9
  setLoadingCount: React.Dispatch<React.SetStateAction<number>>;
10
+ setError: React.Dispatch<React.SetStateAction<Error | undefined>>;
9
11
  };
10
12
  export declare const throwContextError: () => never;
11
13
  export declare const LogtoContext: import("react").Context<LogtoContextProps>;
package/lib/context.js CHANGED
@@ -10,6 +10,8 @@ exports.LogtoContext = (0, react_1.createContext)({
10
10
  logtoClient: undefined,
11
11
  isAuthenticated: false,
12
12
  loadingCount: 0,
13
+ error: undefined,
13
14
  setIsAuthenticated: exports.throwContextError,
14
15
  setLoadingCount: exports.throwContextError,
16
+ setError: exports.throwContextError,
15
17
  });
@@ -1,14 +1,17 @@
1
1
  import { IdTokenClaims, UserInfoResponse } from '@logto/browser';
2
- import { Nullable } from '@silverhand/essentials';
3
2
  declare type Logto = {
4
3
  isAuthenticated: boolean;
5
4
  isLoading: boolean;
6
- fetchUserInfo: () => Promise<UserInfoResponse>;
7
- getAccessToken: (resource?: string) => Promise<Nullable<string>>;
8
- getIdTokenClaims: () => IdTokenClaims;
5
+ error?: Error;
6
+ fetchUserInfo: () => Promise<UserInfoResponse | undefined>;
7
+ getAccessToken: (resource?: string) => Promise<string | undefined>;
8
+ getIdTokenClaims: () => IdTokenClaims | undefined;
9
9
  signIn: (redirectUri: string) => Promise<void>;
10
10
  signOut: (postLogoutRedirectUri: string) => Promise<void>;
11
11
  };
12
- declare const useHandleSignInCallback: () => void;
12
+ declare const useHandleSignInCallback: (returnToPageUrl?: string) => {
13
+ isLoading: boolean;
14
+ isAuthenticated: boolean;
15
+ };
13
16
  declare const useLogto: () => Logto;
14
17
  export { useLogto, useHandleSignInCallback };
@@ -4,7 +4,8 @@ exports.useHandleSignInCallback = exports.useLogto = void 0;
4
4
  const react_1 = require("react");
5
5
  const context_1 = require("../context");
6
6
  const useLoadingState = () => {
7
- const { setLoadingCount } = (0, react_1.useContext)(context_1.LogtoContext);
7
+ const { loadingCount, setLoadingCount } = (0, react_1.useContext)(context_1.LogtoContext);
8
+ const isLoading = loadingCount > 0;
8
9
  const setLoadingState = (0, react_1.useCallback)((state) => {
9
10
  if (state) {
10
11
  setLoadingCount((count) => count + 1);
@@ -13,78 +14,136 @@ const useLoadingState = () => {
13
14
  setLoadingCount((count) => Math.max(0, count - 1));
14
15
  }
15
16
  }, [setLoadingCount]);
16
- return setLoadingState;
17
+ return { isLoading, setLoadingState };
18
+ };
19
+ const useErrorHandler = () => {
20
+ const { setError } = (0, react_1.useContext)(context_1.LogtoContext);
21
+ const handleError = (0, react_1.useCallback)((error, fallbackErrorMessage) => {
22
+ if (error instanceof Error) {
23
+ setError(error);
24
+ }
25
+ else if (fallbackErrorMessage) {
26
+ setError(new Error(fallbackErrorMessage));
27
+ }
28
+ }, [setError]);
29
+ return { handleError };
17
30
  };
18
- const useHandleSignInCallback = () => {
31
+ const useHandleSignInCallback = (returnToPageUrl = window.location.origin) => {
19
32
  const { logtoClient, isAuthenticated, setIsAuthenticated } = (0, react_1.useContext)(context_1.LogtoContext);
20
- const setLoadingState = useLoadingState();
33
+ const { isLoading, setLoadingState } = useLoadingState();
34
+ const { handleError } = useErrorHandler();
21
35
  const handleSignInCallback = (0, react_1.useCallback)(async (callbackUri) => {
22
36
  if (!logtoClient) {
23
37
  return (0, context_1.throwContextError)();
24
38
  }
25
39
  setLoadingState(true);
26
- await logtoClient.handleSignInCallback(callbackUri);
27
- setLoadingState(false);
28
- setIsAuthenticated(true);
29
- }, [logtoClient, setIsAuthenticated, setLoadingState]);
40
+ try {
41
+ await logtoClient.handleSignInCallback(callbackUri);
42
+ setIsAuthenticated(true);
43
+ }
44
+ catch (error) {
45
+ handleError(error, 'Unexpected error occurred while handling sign in callback.');
46
+ }
47
+ finally {
48
+ setLoadingState(false);
49
+ }
50
+ window.location.assign(returnToPageUrl);
51
+ }, [logtoClient, returnToPageUrl, setIsAuthenticated, setLoadingState, handleError]);
30
52
  (0, react_1.useEffect)(() => {
31
53
  if (!isAuthenticated && logtoClient?.isSignInRedirected(window.location.href)) {
32
54
  void handleSignInCallback(window.location.href);
33
55
  }
34
56
  }, [handleSignInCallback, isAuthenticated, logtoClient]);
57
+ return {
58
+ isLoading,
59
+ isAuthenticated,
60
+ };
35
61
  };
36
62
  exports.useHandleSignInCallback = useHandleSignInCallback;
37
63
  const useLogto = () => {
38
- const { logtoClient, loadingCount, isAuthenticated, setIsAuthenticated } = (0, react_1.useContext)(context_1.LogtoContext);
39
- const setLoadingState = useLoadingState();
64
+ const { logtoClient, loadingCount, isAuthenticated, error, setIsAuthenticated } = (0, react_1.useContext)(context_1.LogtoContext);
65
+ const { setLoadingState } = useLoadingState();
66
+ const { handleError } = useErrorHandler();
40
67
  const isLoading = loadingCount > 0;
41
68
  const signIn = (0, react_1.useCallback)(async (redirectUri) => {
42
69
  if (!logtoClient) {
43
70
  return (0, context_1.throwContextError)();
44
71
  }
45
72
  setLoadingState(true);
46
- await logtoClient.signIn(redirectUri);
47
- setLoadingState(false);
48
- }, [logtoClient, setLoadingState]);
73
+ try {
74
+ await logtoClient.signIn(redirectUri);
75
+ }
76
+ catch (error) {
77
+ handleError(error, 'Unexpected error occurred while signing in.');
78
+ }
79
+ finally {
80
+ setLoadingState(false);
81
+ }
82
+ }, [logtoClient, setLoadingState, handleError]);
49
83
  const signOut = (0, react_1.useCallback)(async (postLogoutRedirectUri) => {
50
84
  if (!logtoClient) {
51
85
  return (0, context_1.throwContextError)();
52
86
  }
53
87
  setLoadingState(true);
54
- await logtoClient.signOut(postLogoutRedirectUri);
55
- setLoadingState(false);
56
- setIsAuthenticated(false);
57
- }, [logtoClient, setIsAuthenticated, setLoadingState]);
88
+ try {
89
+ await logtoClient.signOut(postLogoutRedirectUri);
90
+ setIsAuthenticated(false);
91
+ }
92
+ catch (error) {
93
+ handleError(error, 'Unexpected error occurred while signing out.');
94
+ }
95
+ finally {
96
+ setLoadingState(false);
97
+ }
98
+ }, [logtoClient, setIsAuthenticated, setLoadingState, handleError]);
58
99
  const fetchUserInfo = (0, react_1.useCallback)(async () => {
59
100
  if (!logtoClient) {
60
101
  return (0, context_1.throwContextError)();
61
102
  }
62
103
  setLoadingState(true);
63
- const userInfo = await logtoClient.fetchUserInfo();
64
- setLoadingState(false);
65
- return userInfo;
66
- }, [logtoClient, setLoadingState]);
104
+ try {
105
+ return await logtoClient.fetchUserInfo();
106
+ }
107
+ catch (error) {
108
+ handleError(error, 'Unexpected error occurred while fetching user info.');
109
+ }
110
+ finally {
111
+ setLoadingState(false);
112
+ }
113
+ }, [logtoClient, setLoadingState, handleError]);
67
114
  const getAccessToken = (0, react_1.useCallback)(async (resource) => {
68
115
  if (!logtoClient) {
69
116
  return (0, context_1.throwContextError)();
70
117
  }
71
118
  setLoadingState(true);
72
- const accessToken = await logtoClient.getAccessToken(resource);
73
- setLoadingState(false);
74
- return accessToken;
75
- }, [logtoClient, setLoadingState]);
119
+ try {
120
+ return await logtoClient.getAccessToken(resource);
121
+ }
122
+ catch (error) {
123
+ handleError(error, 'Unexpected error occurred while getting access token.');
124
+ }
125
+ finally {
126
+ setLoadingState(false);
127
+ }
128
+ }, [logtoClient, setLoadingState, handleError]);
76
129
  const getIdTokenClaims = (0, react_1.useCallback)(() => {
77
130
  if (!logtoClient) {
78
131
  return (0, context_1.throwContextError)();
79
132
  }
80
- return logtoClient.getIdTokenClaims();
81
- }, [logtoClient]);
133
+ try {
134
+ return logtoClient.getIdTokenClaims();
135
+ }
136
+ catch (error) {
137
+ handleError(error, 'Unexpected error occurred while getting id token claims.');
138
+ }
139
+ }, [logtoClient, handleError]);
82
140
  if (!logtoClient) {
83
141
  return (0, context_1.throwContextError)();
84
142
  }
85
143
  return {
86
144
  isAuthenticated,
87
145
  isLoading,
146
+ error,
88
147
  signIn,
89
148
  signOut,
90
149
  fetchUserInfo,
package/lib/provider.js CHANGED
@@ -34,13 +34,16 @@ const LogtoProvider = ({ config, children }) => {
34
34
  const [loadingCount, setLoadingCount] = (0, react_1.useState)(0);
35
35
  const memorizedLogtoClient = (0, react_1.useMemo)(() => ({ logtoClient: new browser_1.default(config) }), [config]);
36
36
  const [isAuthenticated, setIsAuthenticated] = (0, react_1.useState)(memorizedLogtoClient.logtoClient.isAuthenticated);
37
+ const [error, setError] = (0, react_1.useState)();
37
38
  const memorizedContextValue = (0, react_1.useMemo)(() => ({
38
39
  ...memorizedLogtoClient,
39
40
  isAuthenticated,
40
41
  setIsAuthenticated,
41
42
  loadingCount,
42
43
  setLoadingCount,
43
- }), [memorizedLogtoClient, isAuthenticated, loadingCount]);
44
+ error,
45
+ setError,
46
+ }), [memorizedLogtoClient, isAuthenticated, loadingCount, error]);
44
47
  return react_1.default.createElement(context_1.LogtoContext.Provider, { value: memorizedContextValue }, children);
45
48
  };
46
49
  exports.LogtoProvider = LogtoProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/react",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "main": "./lib/index.js",
5
5
  "exports": "./lib/index.js",
6
6
  "typings": "./lib/index.d.ts",
@@ -21,19 +21,19 @@
21
21
  "lint": "eslint --ext .ts --ext .tsx src",
22
22
  "test": "jest",
23
23
  "test:coverage": "jest --silent --coverage",
24
- "prepack": "pnpm test && pnpm build"
24
+ "prepack": "pnpm test"
25
25
  },
26
26
  "dependencies": {
27
- "@logto/browser": "^0.1.3",
27
+ "@logto/browser": "^0.1.5",
28
28
  "@silverhand/essentials": "^1.1.6"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@jest/types": "^27.5.1",
32
- "@silverhand/eslint-config": "^0.9.1",
33
- "@silverhand/eslint-config-react": "^0.9.1",
34
- "@silverhand/ts-config": "^0.9.1",
35
- "@silverhand/ts-config-react": "^0.9.1",
36
- "@testing-library/react-hooks": "^7.0.2",
32
+ "@silverhand/eslint-config": "^0.10.0",
33
+ "@silverhand/eslint-config-react": "^0.10.0",
34
+ "@silverhand/ts-config": "^0.10.0",
35
+ "@silverhand/ts-config-react": "^0.10.0",
36
+ "@testing-library/react-hooks": "^8.0.0",
37
37
  "@types/jest": "^27.4.1",
38
38
  "@types/react": "^17.0.39",
39
39
  "eslint": "^8.9.0",
@@ -55,5 +55,5 @@
55
55
  "publishConfig": {
56
56
  "access": "public"
57
57
  },
58
- "gitHead": "2a59d35046744dd1284eb81804cf0ef9a35f41e6"
58
+ "gitHead": "2f998aac6870c1e0487987905d4abadd864af621"
59
59
  }