/** * Platform detection and automatic adapter selection */ import type { SecureStorageAdapter, SecureStorageOptions } from "./types"; import { MemorySecureStorage } from "./memory"; import { WebSecureStorage } from "./web"; /** * Detected platform */ export type Platform = "react-native" | "expo" | "web" | "node" | "unknown"; /** * Detect the current platform */ export function detectPlatform(): Platform { // Check for React Native if (typeof navigator !== "undefined" && navigator.product === "ReactNative") { // Check for Expo try { // @ts-ignore - dynamic require const Constants = require("expo-constants"); if (Constants?.expoConfig) return "expo"; } catch { // Not Expo } return "react-native"; } // Check for Node.js if (typeof process !== "undefined" && process.versions?.node) { return "node"; } // Check for browser if (typeof window !== "undefined" && typeof document !== "undefined") { return "web"; } return "unknown"; } /** * Create the best available secure storage adapter for the current platform */ export async function createSecureStorage( options: SecureStorageOptions = {} ): Promise { const platform = detectPlatform(); switch (platform) { case "react-native": // Try to use react-native-keychain try { const { ReactNativeKeychainStorage } = await import("./rn-keychain"); const adapter = new ReactNativeKeychainStorage(options); if (adapter.available) return adapter; } catch { // Keychain not available } // Fall through to memory console.warn("STYX: react-native-keychain not available, using memory storage"); return new MemorySecureStorage(options); case "expo": // Try to use expo-secure-store try { const { ExpoSecureStorage } = await import("./expo-secure-store"); const adapter = new ExpoSecureStorage(options); if (adapter.available) return adapter; } catch { // SecureStore not available } console.warn("STYX: expo-secure-store not available, using memory storage"); return new MemorySecureStorage(options); case "web": const webStorage = new WebSecureStorage(options); if (webStorage.available) { await webStorage.init(); return webStorage; } console.warn("STYX: Web Crypto not available, using memory storage"); return new MemorySecureStorage(options); case "node": // Node.js - use memory storage (or could implement file-based) console.warn("STYX: Using memory storage in Node.js environment"); return new MemorySecureStorage(options); default: return new MemorySecureStorage(options); } } /** * Check if secure storage is available on this platform */ export function isSecureStorageAvailable(): boolean { const platform = detectPlatform(); switch (platform) { case "react-native": case "expo": return true; // Assume keychain/keystore is available on mobile case "web": return typeof window?.crypto?.subtle !== "undefined"; default: return false; } }