UNPKG

a0-purchases

Version:

Lightweight subscription management for AI apps with auto-detecting providers

132 lines 5.94 kB
import AsyncStorage from "@react-native-async-storage/async-storage"; import { USER_ID_STORAGE_KEY } from "./constants"; import { backendClient } from "./api/backendClient"; // Debug flag (set by PurchasesService) let debugEnabled = false; export const setDebugEnabled = (enabled) => { debugEnabled = enabled; }; const log = (...args) => { if (debugEnabled) { console.log(...args); } }; // Anonymous user ID prefix export const ANONYMOUS_USER_PREFIX = "$AnonymousUser:"; // Generates a simple anonymous ID const generateAnonymousId = () => { return `${ANONYMOUS_USER_PREFIX}${Math.random().toString(36).substring(2, 15)}${Math.random().toString(36).substring(2, 15)}`; }; // Check if a user ID is anonymous export const isAnonymousUserId = (userId) => { return !!userId && userId.startsWith(ANONYMOUS_USER_PREFIX); }; // Gets the user ID from storage, or uses the provided custom ID, or generates a new anonymous one export const getOrCreateUserId = async (customUserId) => { // If custom user ID provided, we may need to link the previous ID (if any) if (customUserId) { try { log('[IAP Storage] getOrCreateUserId called with customUserId:', customUserId); const existingId = await AsyncStorage.getItem(USER_ID_STORAGE_KEY); log('[IAP Storage] Existing ID from storage:', existingId); // Persist the new ID immediately await AsyncStorage.setItem(USER_ID_STORAGE_KEY, customUserId); log('[IAP Storage] Saved new customUserId to storage'); // Ensure new user exists on backend log('[IAP Storage] Logging in new user:', customUserId); await backendClient.login(customUserId); log('[IAP Storage] New user login successful'); if (existingId && existingId !== customUserId) { // Only link if the old ID was anonymous if (isAnonymousUserId(existingId)) { log('[IAP Storage] Previous ID was anonymous, will link to new user:', { oldId: existingId, newId: customUserId, isOldAnonymous: true }); // Ensure old ID exists (idempotent) try { log('[IAP Storage] Ensuring old user exists:', existingId); await backendClient.login(existingId); log('[IAP Storage] Old user login successful'); } catch (e) { console.warn('[IAP Storage] Failed ensuring old user exists (non-blocking)', e); } // Link / alias the two IDs try { log('[IAP Storage] Calling linkAlias:', { from: existingId, to: customUserId }); await backendClient.linkAlias(existingId, customUserId); log('[IAP Storage] LinkAlias successful'); } catch (e) { console.error('[IAP Storage] Failed to link alias', e); } } else { log('[IAP Storage] Previous ID was not anonymous, skipping link:', { oldId: existingId, newId: customUserId, reason: 'Only anonymous users should be linked' }); } } else { log('[IAP Storage] No linking needed:', { existingId, customUserId, reason: !existingId ? 'No existing ID' : 'Same ID' }); } } catch (error) { console.error('[IAP Storage] Error logging in user:', error); } return customUserId; } try { // No custom ID provided - check what's in storage log('[IAP Storage] No customUserId provided, checking storage'); let userId = await AsyncStorage.getItem(USER_ID_STORAGE_KEY); log('[IAP Storage] ID from storage:', userId); // If stored ID is NOT anonymous, we need to reset to anonymous if (userId && !isAnonymousUserId(userId)) { log('[IAP Storage] Stored ID is not anonymous, resetting to new anonymous user:', { oldId: userId, reason: 'App initialized without customUserId but had non-anonymous ID in storage' }); // Generate new anonymous ID userId = generateAnonymousId(); log('[IAP Storage] Generated new anonymous ID:', userId); await AsyncStorage.setItem(USER_ID_STORAGE_KEY, userId); // Note: We do NOT link the old custom ID to the new anonymous ID for security } else if (!userId) { // No ID in storage, generate anonymous userId = generateAnonymousId(); log('[IAP Storage] Generated new anonymous ID:', userId); await AsyncStorage.setItem(USER_ID_STORAGE_KEY, userId); } log('[IAP Storage] Logging in user:', userId); await backendClient.login(userId); log('[IAP Storage] User login successful'); return userId; } catch (error) { console.error('[IAP Storage] Error logging in user:', error); return generateAnonymousId(); } }; // Clears the stored user ID (e.g., on logout) export const clearUserId = async () => { await AsyncStorage.removeItem(USER_ID_STORAGE_KEY); }; // Persist a provided user ID (e.g., after login) export const setUserId = async (newUserId) => { if (!newUserId) { console.warn("[IAP Storage] setUserId called with empty value – ignored."); return; } await AsyncStorage.setItem(USER_ID_STORAGE_KEY, newUserId); }; //# sourceMappingURL=storage.js.map