UNPKG

magically-sdk

Version:

Official SDK for Magically - Build mobile apps with AI

204 lines (175 loc) 6.04 kB
/** * Platform detection and abstraction layer * Provides environment-specific implementations */ interface StorageInterface { getItem: (key: string) => Promise<string | null>; setItem: (key: string, value: string) => Promise<void>; removeItem: (key: string) => Promise<void>; } interface WebBrowserInterface { openBrowserAsync: (url: string) => Promise<any>; openAuthSessionAsync?: (url: string, redirectUri: string) => Promise<any>; maybeCompleteAuthSession: () => { type: string }; } interface PlatformInterface { OS: string; select: (obj: any) => any; } interface LinkingInterface { createURL: (path?: string, options?: { scheme?: string; queryParams?: Record<string, string>; isTripleSlashed?: boolean }) => string; } interface SecureStoreInterface { getItemAsync: (key: string) => Promise<string | null>; setItemAsync: (key: string, value: string) => Promise<void>; deleteItemAsync: (key: string) => Promise<void>; } class EdgeStorage implements StorageInterface { async getItem(key: string): Promise<string | null> { // In edge environment, return null (no persistent storage) return null; } async setItem(key: string, value: string): Promise<void> { // No-op in edge environment } async removeItem(key: string): Promise<void> { // No-op in edge environment } } class EdgeWebBrowser implements WebBrowserInterface { async openBrowserAsync(url: string): Promise<any> { // Can't open browser in edge environment return { type: 'cancel' }; } maybeCompleteAuthSession() { return { type: 'success' }; } } class EdgePlatform implements PlatformInterface { OS = 'web'; select(obj: any) { return obj.web || obj.default; } } class EdgeLinking implements LinkingInterface { createURL(path?: string, options?: { scheme?: string; queryParams?: Record<string, string>; isTripleSlashed?: boolean }): string { // In edge environment, return a simple URL return path ? `exp://auth/${path}` : 'exp://auth/callback'; } } class EdgeSecureStore implements SecureStoreInterface { async getItemAsync(key: string): Promise<string | null> { // No secure storage in edge environment return null; } async setItemAsync(key: string, value: string): Promise<void> { // No-op in edge environment } async deleteItemAsync(key: string): Promise<void> { // No-op in edge environment } } class WebSecureStore implements SecureStoreInterface { async getItemAsync(key: string): Promise<string | null> { try { // Safe localStorage access for web if (typeof window !== 'undefined' && window.localStorage) { return window.localStorage.getItem(key); } return null; } catch (error) { console.warn('WebSecureStore: Failed to get item', error); return null; } } async setItemAsync(key: string, value: string): Promise<void> { try { // Safe localStorage access for web if (typeof window !== 'undefined' && window.localStorage) { window.localStorage.setItem(key, value); } } catch (error) { console.warn('WebSecureStore: Failed to set item', error); } } async deleteItemAsync(key: string): Promise<void> { try { // Safe localStorage access for web if (typeof window !== 'undefined' && window.localStorage) { window.localStorage.removeItem(key); } } catch (error) { console.warn('WebSecureStore: Failed to delete item', error); } } } // Detect environment function isEdgeEnvironment(): boolean { // Most reliable check: caches.default is UNIQUE to Cloudflare Workers if (typeof caches !== 'undefined' && typeof (caches as any).default !== 'undefined') { return true; } // Secondary check: navigator.userAgent (requires global_navigator compatibility flag) if (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') { return true; } // Default to false - assume React Native/Expo if not detected as Cloudflare Workers return false; } // Export platform-specific implementations export let AsyncStorage: StorageInterface; export let WebBrowser: WebBrowserInterface; export let Platform: PlatformInterface; export let SecureStore: SecureStoreInterface; export let Linking: LinkingInterface; // Initialize based on environment if (isEdgeEnvironment()) { // Edge environment - use stubs AsyncStorage = new EdgeStorage(); WebBrowser = new EdgeWebBrowser(); Platform = new EdgePlatform(); SecureStore = new EdgeSecureStore(); Linking = new EdgeLinking(); } else { // React Native environment - use actual implementations // These will be replaced by the bundler in React Native apps // Import core dependencies first (these should always be available) try { AsyncStorage = require('@react-native-async-storage/async-storage').default; } catch (e) { AsyncStorage = new EdgeStorage(); } try { WebBrowser = require('expo-web-browser'); } catch (e) { WebBrowser = new EdgeWebBrowser(); } try { Platform = require('react-native').Platform; } catch (e) { Platform = new EdgePlatform(); } // Import optional dependencies (may not be installed) // Check if we're on web platform first if (Platform.OS === 'web') { // Web platform uses localStorage through WebSecureStore SecureStore = new WebSecureStore(); } else { // Native platforms use expo-secure-store try { SecureStore = require('expo-secure-store'); } catch (e) { // Fallback to AsyncStorage wrapped in SecureStore interface if expo-secure-store not available SecureStore = { getItemAsync: async (key: string) => AsyncStorage.getItem(key), setItemAsync: async (key: string, value: string) => AsyncStorage.setItem(key, value), deleteItemAsync: async (key: string) => AsyncStorage.removeItem(key), }; } } try { Linking = require('expo-linking'); } catch (e) { Linking = new EdgeLinking(); } }