1+ /**
2+ * React Native Polyfills for Fluid SDK
3+ *
4+ * Import this file at the top of your React Native app
5+ * BEFORE importing the Fluid SDK:
6+ *
7+ * import 'react-native-get-random-values';
8+ * import { FluidClient } from '@fluid-dev/sdk/react-native';
9+ */
10+
11+ /**
12+ * Safe localStorage replacement for React Native.
13+ * Falls back to an in-memory store when localStorage is unavailable.
14+ */
15+ const memoryStore : Record < string , string > = { } ;
16+
17+ export const safeStorage = {
18+ getItem ( key : string ) : string | null {
19+ try {
20+ if ( typeof localStorage !== "undefined" ) {
21+ return localStorage . getItem ( key ) ;
22+ }
23+ } catch { }
24+ return memoryStore [ key ] ?? null ;
25+ } ,
26+
27+ setItem ( key : string , value : string ) : void {
28+ try {
29+ if ( typeof localStorage !== "undefined" ) {
30+ localStorage . setItem ( key , value ) ;
31+ return ;
32+ }
33+ } catch { }
34+ memoryStore [ key ] = value ;
35+ } ,
36+
37+ removeItem ( key : string ) : void {
38+ try {
39+ if ( typeof localStorage !== "undefined" ) {
40+ localStorage . removeItem ( key ) ;
41+ return ;
42+ }
43+ } catch { }
44+ delete memoryStore [ key ] ;
45+ } ,
46+ } ;
47+
48+ /**
49+ * Safe fetch sender — works in React Native, browser, and Node.
50+ * Replaces navigator.sendBeacon and Image pixel ping.
51+ */
52+ export function safeSend ( url : string , data : unknown ) : void {
53+ try {
54+ if ( typeof navigator !== "undefined" && navigator . sendBeacon ) {
55+ const blob = new Blob ( [ JSON . stringify ( data ) ] , {
56+ type : "application/json" ,
57+ } ) ;
58+ navigator . sendBeacon ( url , blob ) ;
59+ return ;
60+ }
61+
62+ if ( typeof fetch !== "undefined" ) {
63+ fetch ( url , {
64+ method : "POST" ,
65+ headers : { "Content-Type" : "application/json" } ,
66+ body : JSON . stringify ( data ) ,
67+ } ) . catch ( ( ) => { } ) ;
68+ return ;
69+ }
70+ } catch {
71+ // Silently fail — telemetry must never block SDK functionality
72+ }
73+ }
74+
75+ /**
76+ * Safe domain getter — returns hostname in browser,
77+ * 'react-native' in RN, 'server-side' in Node.
78+ */
79+ export function getSafeDomain ( ) : string {
80+ try {
81+ if ( typeof window !== "undefined" && window . location ?. hostname ) {
82+ return window . location . hostname ;
83+ }
84+ if ( typeof navigator !== "undefined" && navigator . product === "ReactNative" ) {
85+ return "react-native" ;
86+ }
87+ } catch { }
88+ return "server-side" ;
89+ }
90+
91+ /**
92+ * Returns true if the current environment is React Native.
93+ */
94+ export function isReactNative ( ) : boolean {
95+ return (
96+ typeof navigator !== "undefined" && navigator . product === "ReactNative"
97+ ) ;
98+ }
0 commit comments