@intra-mart/smartlime 1.5.0 → 2.0.0-dev.20241121

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.
@@ -1,14 +1,14 @@
1
- type ForceRender = () => void;
2
- export declare const createRenderTarget: () => {
3
- addEventListener: (callback: ForceRender) => void;
4
- removeEventListener: (callback: ForceRender) => void;
5
- dispatch: () => void;
1
+ type ForceRender<T> = (args?: T) => void;
2
+ export declare const createRenderTarget: <T = undefined>() => {
3
+ addEventListener: (callback: ForceRender<T>) => void;
4
+ removeEventListener: (callback: ForceRender<T>) => void;
5
+ dispatch: (args?: T | undefined) => void;
6
6
  };
7
- export type CreateRenderTarget = typeof createRenderTarget;
8
- export type RenderTarget = ReturnType<CreateRenderTarget>;
9
- export declare const useRenderTarget: () => {
10
- addEventListener: (callback: ForceRender) => void;
11
- removeEventListener: (callback: ForceRender) => void;
12
- dispatch: () => void;
7
+ export type CreateRenderTarget<T = undefined> = typeof createRenderTarget<T>;
8
+ export type RenderTarget<T = undefined> = ReturnType<CreateRenderTarget<T>>;
9
+ export declare const useRenderTarget: <T = undefined>() => {
10
+ addEventListener: (callback: ForceRender<T>) => void;
11
+ removeEventListener: (callback: ForceRender<T>) => void;
12
+ dispatch: (args?: T | undefined) => void;
13
13
  };
14
14
  export {};
@@ -12,11 +12,11 @@ export const createRenderTarget = () => {
12
12
  }
13
13
  }
14
14
  };
15
- const dispatch = () => {
15
+ const dispatch = (args) => {
16
16
  for (let i = 0, l = listenerList.length; i < l; i++) {
17
17
  const listener = listenerList[i];
18
18
  if (listener)
19
- listener();
19
+ listener(args);
20
20
  }
21
21
  };
22
22
  return {
@@ -1,6 +1,17 @@
1
1
  /// <reference types="react" />
2
- import { AuthState, StartAuthResult } from '.';
3
2
  import { RenderTarget } from '../../_shared/renderTarget';
3
+ import { AuthSessionResult } from 'expo-auth-session';
4
+ import { IMOAuthError } from './IMOAuthError';
5
+ export type AuthState = 'initializing' | 'unauthorized' | 'authorized';
6
+ export type StartAuthResult = {
7
+ readonly type: 'cancel' | 'dismiss' | 'opened' | 'locked' | 'error';
8
+ readonly detail: AuthSessionResult;
9
+ } | {
10
+ readonly type: 'success';
11
+ } | {
12
+ readonly type: 'exception';
13
+ readonly exceptionDetail: unknown;
14
+ };
4
15
  export interface OAuthContext {
5
16
  getAuthState: () => AuthState;
6
17
  getToken: () => string | null;
@@ -10,5 +21,6 @@ export interface OAuthContext {
10
21
  startAuth: () => Promise<StartAuthResult>;
11
22
  tokenRenderTarget: RenderTarget;
12
23
  authStateRenderTarget: RenderTarget;
24
+ authErrorRenderTarget: RenderTarget<IMOAuthError>;
13
25
  }
14
26
  export declare const Context: import("react").Context<OAuthContext | null>;
@@ -3,3 +3,4 @@ export * from './useIMToken';
3
3
  export * from './useStartAuth';
4
4
  export * from './useAuthState';
5
5
  export * from './useAuthStateEffect';
6
+ export * from './useAuthError';
@@ -3,3 +3,4 @@ export * from './useIMToken';
3
3
  export * from './useStartAuth';
4
4
  export * from './useAuthState';
5
5
  export * from './useAuthStateEffect';
6
+ export * from './useAuthError';
@@ -0,0 +1,2 @@
1
+ import { IMOAuthError } from '../IMOAuthError';
2
+ export declare const useAuthError: (callBack: (error?: IMOAuthError) => void) => void;
@@ -0,0 +1,15 @@
1
+ import { useContext, useEffect } from 'react';
2
+ import { Context as DefaultContext } from '../Context';
3
+ import { IMOAuthError } from '../IMOAuthError';
4
+ export const useAuthError = (callBack) => {
5
+ const oauthContext = useContext(DefaultContext);
6
+ if (oauthContext == null) {
7
+ throw new IMOAuthError('useAuthError requires either a Context provide or an ancestor element with a IMOAuthProvider.');
8
+ }
9
+ useEffect(() => {
10
+ oauthContext.authErrorRenderTarget.addEventListener(callBack);
11
+ return () => {
12
+ oauthContext.authErrorRenderTarget.removeEventListener(callBack);
13
+ };
14
+ }, [callBack]);
15
+ };
@@ -1,2 +1,2 @@
1
1
  import { Context as DefaultContext } from '../Context';
2
- export declare const useAuthState: (Context?: typeof DefaultContext) => import("..").AuthState;
2
+ export declare const useAuthState: (Context?: typeof DefaultContext) => import("../Context").AuthState;
@@ -1,4 +1,4 @@
1
- import { AuthState } from '..';
1
+ import { AuthState } from '../Context';
2
2
  /**
3
3
  * sugar syntax that sets the return value of "useAuthState" to the deps of "useEffect"
4
4
  * this may be deprecated in the future
@@ -1,2 +1,2 @@
1
1
  import { Context as DefaultContext } from '../Context';
2
- export declare const useStartAuth: (Context?: typeof DefaultContext) => () => Promise<import("..").StartAuthResult>;
2
+ export declare const useStartAuth: (Context?: typeof DefaultContext) => () => Promise<import("../Context").StartAuthResult>;
@@ -1,22 +1,13 @@
1
1
  /// <reference types="react" />
2
- import { AuthSessionResult, Prompt } from 'expo-auth-session';
2
+ import * as SecureStore from 'expo-secure-store';
3
+ import { Prompt } from 'expo-auth-session';
3
4
  import { Context as DefaultContext } from './Context';
4
- export type AuthState = 'initializing' | 'unauthorized' | 'authorized';
5
5
  export type TokenState = {
6
6
  baseUrl: string;
7
7
  accessToken: string;
8
8
  refreshToken?: string;
9
9
  expirationDate?: number;
10
10
  };
11
- export type StartAuthResult = {
12
- readonly type: 'cancel' | 'dismiss' | 'opened' | 'locked' | 'error';
13
- readonly detail: AuthSessionResult;
14
- } | {
15
- readonly type: 'success';
16
- } | {
17
- readonly type: 'exception';
18
- readonly exceptionDetail: unknown;
19
- };
20
11
  export declare const IMPrompt: {
21
12
  readonly Login: Prompt.Login;
22
13
  readonly None: Prompt.None;
@@ -29,12 +20,16 @@ interface RequestConfig {
29
20
  state?: string;
30
21
  prompt?: Prompt.Login | Prompt.None;
31
22
  }
23
+ interface SecureStoreConfig {
24
+ storeKey?: string;
25
+ keychainAccessible?: SecureStore.KeychainAccessibilityConstant;
26
+ }
32
27
  interface IMOAuthProps {
33
28
  children: JSX.Element;
34
29
  requestConfig: RequestConfig;
35
30
  remainingTimeToRunRefresh?: number;
36
- storageKey?: string;
31
+ secureStore?: SecureStoreConfig;
37
32
  oauthContext?: typeof DefaultContext;
38
33
  }
39
- export declare const IMOAuth: ({ children, requestConfig, remainingTimeToRunRefresh, storageKey, oauthContext, }: IMOAuthProps) => import("react").JSX.Element;
34
+ export declare const IMOAuth: ({ children, requestConfig, remainingTimeToRunRefresh, secureStore, oauthContext, }: IMOAuthProps) => import("react").JSX.Element;
40
35
  export {};
@@ -1,7 +1,7 @@
1
1
  import * as SecureStore from 'expo-secure-store';
2
2
  import { exchangeCodeAsync, loadAsync, Prompt, refreshAsync, } from 'expo-auth-session';
3
3
  import { useCallback, useLayoutEffect, useMemo, useRef, } from 'react';
4
- import { Context as DefaultContext } from './Context';
4
+ import { Context as DefaultContext, } from './Context';
5
5
  import { IMOAuthError } from './IMOAuthError';
6
6
  import { useRenderTarget } from '../../_shared/renderTarget';
7
7
  import { useIMBaseUrl } from '../..';
@@ -51,10 +51,17 @@ const useDiscovery = () => {
51
51
  };
52
52
  }, [encodedBaseUrl]);
53
53
  };
54
- const useStorageKey = (storageKey) => {
54
+ const useStoreConfig = (secureStore) => {
55
+ const storeKey = secureStore?.storeKey;
56
+ const keychainAccessible = secureStore?.keychainAccessible;
55
57
  return useMemo(() => {
56
- return storageKey ? storageKey : DEFAULT_STORAGE_KEY;
57
- }, [storageKey]);
58
+ return {
59
+ storeKey: storeKey ? storeKey : DEFAULT_STORAGE_KEY,
60
+ keychainAccessible: keychainAccessible !== void 0
61
+ ? keychainAccessible
62
+ : SecureStore.WHEN_UNLOCKED,
63
+ };
64
+ }, [storeKey, keychainAccessible]);
58
65
  };
59
66
  const useRemainingTimeToRunRefresh = (remainingTimeToRunRefresh) => {
60
67
  return useMemo(() => {
@@ -63,20 +70,26 @@ const useRemainingTimeToRunRefresh = (remainingTimeToRunRefresh) => {
63
70
  : DEFAULT_REMAINING_TIME_TO_RUN_REFRESH;
64
71
  }, [remainingTimeToRunRefresh]);
65
72
  };
66
- const saveTokenStorage = async (storageKey, baseUrl, accessToken, refreshToken, expirationDate) => {
73
+ const saveTokenStorage = async (storeConfig, baseUrl, accessToken, refreshToken, expirationDate) => {
67
74
  const item = {
68
75
  baseUrl,
69
76
  accessToken,
70
77
  refreshToken,
71
78
  expirationDate,
72
79
  };
73
- return await SecureStore.setItemAsync(storageKey, JSON.stringify(item));
80
+ return await SecureStore.setItemAsync(storeConfig.storeKey, JSON.stringify(item), {
81
+ keychainAccessible: storeConfig.keychainAccessible,
82
+ });
74
83
  };
75
- const deleteTokenStorage = async (tokenStorageKey) => {
76
- return await SecureStore.deleteItemAsync(tokenStorageKey);
84
+ const deleteTokenStorage = async (storeConfig) => {
85
+ return await SecureStore.deleteItemAsync(storeConfig.storeKey, {
86
+ keychainAccessible: storeConfig.keychainAccessible,
87
+ });
77
88
  };
78
- const getTokenStorage = async (storageKey) => {
79
- const state = await SecureStore.getItemAsync(storageKey);
89
+ const getTokenStorage = async (storeConfig) => {
90
+ const state = await SecureStore.getItemAsync(storeConfig.storeKey, {
91
+ keychainAccessible: storeConfig.keychainAccessible,
92
+ });
80
93
  if (state == null)
81
94
  return;
82
95
  const result = JSON.parse(state);
@@ -116,7 +129,7 @@ const checkExpirationDateOfToken = (expirationDate, remainingTimeToRunRefresh) =
116
129
  return true;
117
130
  return false;
118
131
  };
119
- const useRefresh = (storageKey, refreshTokenRef, expirationDateRef, requestConfig, discovery, setToken, destroy) => {
132
+ const useRefresh = (storeConfig, refreshTokenRef, expirationDateRef, requestConfig, discovery, setToken, destroy) => {
120
133
  const baseUrl = useIMBaseUrl();
121
134
  const lockedRef = useRef(false);
122
135
  const waitingLineRef = useRef([]);
@@ -163,7 +176,7 @@ const useRefresh = (storageKey, refreshTokenRef, expirationDateRef, requestConfi
163
176
  }, discovery);
164
177
  const { accessToken, refreshToken, expiresIn } = tokenResponse;
165
178
  const expirationDate = expiresIn ? createExpirationDate(expiresIn) : 0;
166
- await saveTokenStorage(storageKey, baseUrl, accessToken, refreshToken, expirationDate);
179
+ await saveTokenStorage(storeConfig, baseUrl, accessToken, refreshToken, expirationDate);
167
180
  refreshTokenRef.current = refreshToken ? refreshToken : null;
168
181
  expirationDateRef.current = expirationDate;
169
182
  setToken(accessToken);
@@ -178,36 +191,49 @@ const useRefresh = (storageKey, refreshTokenRef, expirationDateRef, requestConfi
178
191
  throw error;
179
192
  }
180
193
  }
181
- }, [storageKey, requestConfig, discovery, destroy]);
194
+ }, [storeConfig, requestConfig, discovery, destroy]);
182
195
  };
183
- const useStartAuth = (storageKey, remainingTimeToRunRefresh, refreshTokenRef, expirationDateRef, requestConfig, discovery, setToken, refresh, setAuthState) => {
196
+ const useStartAuth = (storeConfig, remainingTimeToRunRefresh, refreshTokenRef, expirationDateRef, requestConfig, discovery, setToken, refresh, setAuthState, authErrorRenderTarget) => {
184
197
  const currentBaseUrl = useIMBaseUrl();
185
198
  useLayoutEffect(() => {
186
199
  (async () => {
187
- const tokenState = await getTokenStorage(storageKey);
188
- if (tokenState) {
189
- const { baseUrl, accessToken, refreshToken, expirationDate } = tokenState;
190
- const expired = checkExpirationDateOfToken(expirationDate ? expirationDate : 0, remainingTimeToRunRefresh);
191
- refreshTokenRef.current = refreshToken ? refreshToken : null;
192
- expirationDateRef.current = expirationDate ? expirationDate : null;
193
- if (currentBaseUrl === baseUrl) {
194
- if (expired) {
195
- await refresh(); // NOTE consideration of how users can catch errors thrown here.
200
+ try {
201
+ const tokenState = await getTokenStorage(storeConfig);
202
+ if (tokenState) {
203
+ const { baseUrl, accessToken, refreshToken, expirationDate } = tokenState;
204
+ const expired = checkExpirationDateOfToken(expirationDate ? expirationDate : 0, remainingTimeToRunRefresh);
205
+ refreshTokenRef.current = refreshToken ? refreshToken : null;
206
+ expirationDateRef.current = expirationDate ? expirationDate : null;
207
+ if (currentBaseUrl === baseUrl) {
208
+ if (expired) {
209
+ await refresh(); // NOTE consideration of how users can catch errors thrown here.
210
+ }
211
+ else {
212
+ setToken(accessToken);
213
+ }
214
+ setAuthState('authorized');
196
215
  }
197
216
  else {
198
- setToken(accessToken);
217
+ setAuthState('unauthorized');
199
218
  }
200
- setAuthState('authorized');
201
219
  }
202
220
  else {
203
221
  setAuthState('unauthorized');
204
222
  }
205
223
  }
206
- else {
224
+ catch (e) {
207
225
  setAuthState('unauthorized');
226
+ authErrorRenderTarget.dispatch(new IMOAuthError('an exception occurred while checking the token state.', {
227
+ cause: e,
228
+ }));
208
229
  }
209
230
  })();
210
- }, [storageKey, remainingTimeToRunRefresh, refresh]);
231
+ }, [
232
+ storeConfig.storeKey,
233
+ storeConfig.keychainAccessible,
234
+ remainingTimeToRunRefresh,
235
+ refresh,
236
+ ]);
211
237
  const startAuth = useCallback(async () => {
212
238
  const authRequest = await loadAsync({
213
239
  ...requestConfig,
@@ -236,7 +262,7 @@ const useStartAuth = (storageKey, remainingTimeToRunRefresh, refreshTokenRef, ex
236
262
  }, discovery);
237
263
  const { accessToken, refreshToken, expiresIn } = tokenResponse;
238
264
  const expirationDate = expiresIn ? createExpirationDate(expiresIn) : 0;
239
- await saveTokenStorage(storageKey, currentBaseUrl, accessToken, refreshToken, expirationDate);
265
+ await saveTokenStorage(storeConfig, currentBaseUrl, accessToken, refreshToken, expirationDate);
240
266
  refreshTokenRef.current = refreshToken ? refreshToken : null;
241
267
  expirationDateRef.current = expirationDate;
242
268
  setToken(accessToken);
@@ -256,14 +282,14 @@ const useStartAuth = (storageKey, remainingTimeToRunRefresh, refreshTokenRef, ex
256
282
  }, [requestConfig, discovery]);
257
283
  return startAuth;
258
284
  };
259
- const useDestroy = (storageKey, refreshTokenRef, expirationDateRef, setToken, setAuthState) => {
285
+ const useDestroy = (storeConfig, refreshTokenRef, expirationDateRef, setToken, setAuthState) => {
260
286
  return useCallback(async () => {
261
- await deleteTokenStorage(storageKey);
287
+ await deleteTokenStorage(storeConfig);
262
288
  setToken(null);
263
289
  refreshTokenRef.current = null;
264
290
  expirationDateRef.current = null;
265
291
  setAuthState('unauthorized');
266
- }, [storageKey, setAuthState]);
292
+ }, [storeConfig, setAuthState]);
267
293
  };
268
294
  const useGetTokenAsync = (tokenRef, expirationDateRef, remainingTimeToRunRefresh, refresh) => {
269
295
  return useCallback(async () => {
@@ -276,7 +302,7 @@ const useGetTokenAsync = (tokenRef, expirationDateRef, remainingTimeToRunRefresh
276
302
  return tokenRef.current;
277
303
  }, [refresh]);
278
304
  };
279
- export const IMOAuth = ({ children, requestConfig, remainingTimeToRunRefresh, storageKey, oauthContext, }) => {
305
+ export const IMOAuth = ({ children, requestConfig, remainingTimeToRunRefresh, secureStore, oauthContext, }) => {
280
306
  const Context = oauthContext || DefaultContext;
281
307
  const contextRef = useRef();
282
308
  const authStateRenderTarget = useRenderTarget();
@@ -285,13 +311,14 @@ export const IMOAuth = ({ children, requestConfig, remainingTimeToRunRefresh, st
285
311
  const [tokenRef, setToken, getToken] = useTokenRef(tokenRenderTarget);
286
312
  const refreshTokenRef = useRef(null);
287
313
  const expirationDateRef = useRef(null);
288
- const _storageKey = useStorageKey(storageKey);
314
+ const storeConfig = useStoreConfig(secureStore);
289
315
  const _remainingTimeToRunRefresh = useRemainingTimeToRunRefresh(remainingTimeToRunRefresh);
290
316
  const _requestConfig = useRequestConfig(requestConfig);
291
317
  const _discovery = useDiscovery();
292
- const destroy = useDestroy(_storageKey, refreshTokenRef, expirationDateRef, setToken, setAuthState);
293
- const refresh = useRefresh(_storageKey, refreshTokenRef, expirationDateRef, _requestConfig, _discovery, setToken, destroy);
294
- const startAuth = useStartAuth(_storageKey, _remainingTimeToRunRefresh, refreshTokenRef, expirationDateRef, _requestConfig, _discovery, setToken, refresh, setAuthState);
318
+ const authErrorRenderTarget = useRenderTarget();
319
+ const destroy = useDestroy(storeConfig, refreshTokenRef, expirationDateRef, setToken, setAuthState);
320
+ const refresh = useRefresh(storeConfig, refreshTokenRef, expirationDateRef, _requestConfig, _discovery, setToken, destroy);
321
+ const startAuth = useStartAuth(storeConfig, _remainingTimeToRunRefresh, refreshTokenRef, expirationDateRef, _requestConfig, _discovery, setToken, refresh, setAuthState, authErrorRenderTarget);
295
322
  const getTokenAsync = useGetTokenAsync(tokenRef, expirationDateRef, _remainingTimeToRunRefresh, refresh);
296
323
  contextRef.current = {
297
324
  getAuthState,
@@ -302,6 +329,7 @@ export const IMOAuth = ({ children, requestConfig, remainingTimeToRunRefresh, st
302
329
  startAuth,
303
330
  tokenRenderTarget,
304
331
  authStateRenderTarget,
332
+ authErrorRenderTarget,
305
333
  };
306
334
  return (<Context.Provider value={contextRef.current}>{children}</Context.Provider>);
307
335
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@intra-mart/smartlime",
3
3
  "description": "expoで使用できるintra mart accelplatform SDK",
4
- "version": "1.5.0",
4
+ "version": "2.0.0-dev.20241121",
5
5
  "keywords": [
6
6
  "intra-mart",
7
7
  "AccelPlatform",