@explorins/pers-sdk-react-native 2.0.4 → 2.0.5

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/dist/index.js CHANGED
@@ -27823,12 +27823,20 @@ class PersApiClient {
27823
27823
  /**
27824
27824
  * Ensures valid authentication token before making requests
27825
27825
  *
27826
- * Delegates to TokenRefreshManager for centralized token logic.
27827
- * Called without await for optimal performance - requests proceed immediately
27828
- * while token validation/refresh happens in background.
27826
+ * Validates the current token and automatically refreshes if expired or near expiration.
27827
+ * Uses a 120-second margin - tokens are refreshed if they expire within 2 minutes.
27828
+ *
27829
+ * This method is called automatically before each request but can also be called
27830
+ * manually when needed (e.g., app resume from background).
27829
27831
  *
27830
- * @private
27831
27832
  * @returns Promise that resolves when token validation is complete
27833
+ * @throws Error if token refresh fails
27834
+ *
27835
+ * @example
27836
+ * ```typescript
27837
+ * // Validate tokens when app becomes active
27838
+ * await apiClient.ensureValidToken();
27839
+ * ```
27832
27840
  */
27833
27841
  async ensureValidToken() {
27834
27842
  if (!this.mergedConfig.authProvider) {
@@ -28572,6 +28580,39 @@ class AuthManager {
28572
28580
  const authService = this.apiClient.getAuthService();
28573
28581
  await authService.clearTokens();
28574
28582
  }
28583
+ /**
28584
+ * Ensure authentication token is valid
28585
+ *
28586
+ * Checks if the current token is expired or about to expire and automatically
28587
+ * refreshes it if needed. This is useful for ensuring valid authentication
28588
+ * before performing critical operations or when app resumes from background.
28589
+ *
28590
+ * Uses a 120-second margin - tokens are refreshed if they expire within 2 minutes.
28591
+ *
28592
+ * @returns Promise that resolves when token is validated/refreshed
28593
+ *
28594
+ * @example App Resume (React Native)
28595
+ * ```typescript
28596
+ * AppState.addEventListener('change', async (state) => {
28597
+ * if (state === 'active') {
28598
+ * // Validate tokens when app returns from background
28599
+ * await sdk.auth.ensureValidToken().catch(console.error);
28600
+ * }
28601
+ * });
28602
+ * ```
28603
+ *
28604
+ * @example Before Critical Operation
28605
+ * ```typescript
28606
+ * async function processPayment() {
28607
+ * // Ensure token is valid before payment
28608
+ * await sdk.auth.ensureValidToken();
28609
+ * const result = await sdk.purchases.createPurchase(paymentData);
28610
+ * }
28611
+ * ```
28612
+ */
28613
+ async ensureValidToken() {
28614
+ return this.apiClient.ensureValidToken();
28615
+ }
28575
28616
  /**
28576
28617
  * Check if SDK has valid authentication
28577
28618
  *
@@ -34118,19 +34159,24 @@ class AsyncStorageTokenStorage {
34118
34159
  }
34119
34160
  async set(key, value) {
34120
34161
  try {
34121
- await this.asyncStorage.setItem(`${this.keyPrefix}${key}`, value);
34162
+ const fullKey = `${this.keyPrefix}${key}`;
34163
+ await this.asyncStorage.setItem(fullKey, value);
34164
+ console.log(`[AsyncStorage] Token stored: ${key}`);
34122
34165
  }
34123
34166
  catch (error) {
34124
- console.error(`Failed to store token ${key}:`, error);
34167
+ console.error(`[AsyncStorage] Failed to store token ${key}:`, error);
34125
34168
  throw new Error(`Token storage failed: ${error}`);
34126
34169
  }
34127
34170
  }
34128
34171
  async get(key) {
34129
34172
  try {
34130
- return await this.asyncStorage.getItem(`${this.keyPrefix}${key}`);
34173
+ const fullKey = `${this.keyPrefix}${key}`;
34174
+ const value = await this.asyncStorage.getItem(fullKey);
34175
+ console.log(`[AsyncStorage] Token retrieved: ${key} - ${value ? 'exists' : 'null'}`);
34176
+ return value;
34131
34177
  }
34132
34178
  catch (error) {
34133
- console.error(`Failed to retrieve token ${key}:`, error);
34179
+ console.error(`[AsyncStorage] Failed to retrieve token ${key}:`, error);
34134
34180
  return null;
34135
34181
  }
34136
34182
  }
@@ -34147,11 +34193,16 @@ class AsyncStorageTokenStorage {
34147
34193
  const allKeys = await this.asyncStorage.getAllKeys();
34148
34194
  const ourKeys = allKeys.filter(key => key.startsWith(this.keyPrefix));
34149
34195
  if (ourKeys.length > 0) {
34196
+ console.log(`[AsyncStorage] Clearing ${ourKeys.length} token(s):`, ourKeys);
34150
34197
  await this.asyncStorage.multiRemove(ourKeys);
34198
+ console.log('[AsyncStorage] All tokens cleared successfully');
34199
+ }
34200
+ else {
34201
+ console.log('[AsyncStorage] No tokens to clear');
34151
34202
  }
34152
34203
  }
34153
34204
  catch (error) {
34154
- console.error('Failed to clear token storage:', error);
34205
+ console.error('[AsyncStorage] Failed to clear token storage:', error);
34155
34206
  }
34156
34207
  }
34157
34208
  }
@@ -34649,6 +34700,70 @@ const PersSDKProvider = ({ children, config }) => {
34649
34700
  throw error;
34650
34701
  }
34651
34702
  }, [sdk, isAuthenticated, isInitialized]);
34703
+ // Listen for authentication status changes and refresh user data when tokens are renewed
34704
+ react.useEffect(() => {
34705
+ if (!authProvider || !isInitialized)
34706
+ return;
34707
+ // Access the config object with proper type safety
34708
+ const providerConfig = authProvider.config;
34709
+ if (!providerConfig)
34710
+ return;
34711
+ // Set up auth status change handler
34712
+ const originalHandler = providerConfig.onAuthStatusChange;
34713
+ const authStatusHandler = async (status) => {
34714
+ console.log('[PersSDK] Auth status changed:', status);
34715
+ // Call original handler first if it exists
34716
+ if (originalHandler) {
34717
+ await originalHandler(status);
34718
+ }
34719
+ // If token was refreshed successfully and user is authenticated, reload user data
34720
+ if (status === 'authenticated' && isAuthenticated && sdk) {
34721
+ try {
34722
+ console.log('[PersSDK] Token refreshed, reloading user data...');
34723
+ await refreshUserData();
34724
+ }
34725
+ catch (error) {
34726
+ console.error('[PersSDK] Failed to refresh user data after token renewal:', error);
34727
+ }
34728
+ }
34729
+ // If authentication failed, clear state
34730
+ if (status === 'auth_failed') {
34731
+ console.log('[PersSDK] Authentication failed, clearing state');
34732
+ setAuthenticationState(null, false);
34733
+ }
34734
+ };
34735
+ // Inject our handler into the auth provider config
34736
+ providerConfig.onAuthStatusChange = authStatusHandler;
34737
+ // Cleanup
34738
+ return () => {
34739
+ if (originalHandler) {
34740
+ providerConfig.onAuthStatusChange = originalHandler;
34741
+ }
34742
+ };
34743
+ }, [authProvider, isInitialized, isAuthenticated, sdk, refreshUserData, setAuthenticationState]);
34744
+ // iOS/Android: Monitor app state and validate tokens when app becomes active
34745
+ react.useEffect(() => {
34746
+ if (!sdk || reactNative.Platform.OS === 'web') {
34747
+ return;
34748
+ }
34749
+ const handleAppStateChange = async (nextAppState) => {
34750
+ if (nextAppState === 'active' && isAuthenticated) {
34751
+ console.log('[PersSDK] App became active - validating tokens');
34752
+ try {
34753
+ // Trigger token validation when app resumes from background
34754
+ // This ensures tokens are checked after extended inactivity
34755
+ await sdk.auth.ensureValidToken();
34756
+ }
34757
+ catch (error) {
34758
+ console.warn('[PersSDK] Token validation failed on app resume:', error);
34759
+ }
34760
+ }
34761
+ };
34762
+ const subscription = reactNative.AppState.addEventListener('change', handleAppStateChange);
34763
+ return () => {
34764
+ subscription?.remove();
34765
+ };
34766
+ }, [sdk, isAuthenticated]);
34652
34767
  const contextValue = react.useMemo(() => ({
34653
34768
  // Main SDK instance
34654
34769
  sdk,