UNPKG

@myflags/react

Version:

React bindings for MyFlags feature flag management

169 lines (164 loc) 5.08 kB
// src/Provider.tsx import { createContext, useContext, useEffect as useEffect2, useState as useState2 } from "react"; import { MyFlagsSDK } from "@myflags/core"; // src/hooks/useIndexedDB.ts import { useState, useCallback, useEffect, useRef } from "react"; var DB_NAME = "myflags"; var DB_VERSION = 1; var STORE_NAME = "flags"; function useIndexedDB(key, initialValue) { const [storedValue, setStoredValue] = useState(initialValue); const [isDbReady, setIsDbReady] = useState(false); const pendingWrites = useRef([]); const openDB = useCallback(() => { return new Promise((resolve, reject) => { if (typeof window === "undefined" || !window.indexedDB) { reject("IndexedDB not supported"); return; } const request = window.indexedDB.open(DB_NAME, DB_VERSION); request.onerror = () => { reject("Error opening IndexedDB"); }; request.onsuccess = (event) => { const db = event.target.result; resolve(db); }; request.onupgradeneeded = (event) => { const db = event.target.result; if (!db.objectStoreNames.contains(STORE_NAME)) { db.createObjectStore(STORE_NAME, { keyPath: "id" }); } }; }); }, []); const getValueFromDB = useCallback(async () => { if (typeof window === "undefined" || !window.indexedDB) { return initialValue; } try { const db = await openDB(); return new Promise((resolve) => { const transaction = db.transaction(STORE_NAME, "readonly"); const store = transaction.objectStore(STORE_NAME); const request = store.get(key); request.onerror = () => { resolve(initialValue); }; request.onsuccess = () => { const result = request.result; db.close(); if (result) { resolve(result.value); } else { resolve(initialValue); } }; }); } catch { return initialValue; } }, [key, initialValue, openDB]); const setValueInDB = useCallback( async (valueToStore) => { if (typeof window === "undefined" || !window.indexedDB) { console.warn("[MyFlags] IndexedDB not supported in this environment"); return; } try { const db = await openDB(); const transaction = db.transaction(STORE_NAME, "readwrite"); const store = transaction.objectStore(STORE_NAME); store.put({ id: key, value: valueToStore }); transaction.oncomplete = () => { db.close(); }; transaction.onerror = () => { db.close(); }; } catch (error) { console.error("[MyFlags] Error in setValueInDB:", error); } }, [key, openDB] ); useEffect(() => { const initializeDB = async () => { try { const value = await getValueFromDB(); setStoredValue(value); setIsDbReady(true); if (pendingWrites.current.length > 0) { for (const value2 of pendingWrites.current) { await setValueInDB(value2); } pendingWrites.current = []; } } catch { setIsDbReady(true); } }; initializeDB(); }, [getValueFromDB, setValueInDB]); const setValue = useCallback( (value) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); if (isDbReady) { setValueInDB(valueToStore); } else { pendingWrites.current.push(valueToStore); } } catch (error) { console.error("[MyFlags] Error in setValue:", error); } }, [storedValue, isDbReady, setValueInDB] ); return [storedValue, setValue]; } // src/Provider.tsx import { jsx } from "react/jsx-runtime"; var MyFlagsContext = createContext(null); function MyFlagsProvider(props) { const [flags, setFlags] = useIndexedDB("flags", {}); const [client] = useState2(() => new MyFlagsSDK(props.config)); useEffect2(() => { const unsubscribe = client.subscribe(setFlags); return () => unsubscribe(); }, [client]); return /* @__PURE__ */ jsx(MyFlagsContext.Provider, { value: flags, children: props.children }); } function useMyFlagsContext() { const context = useContext(MyFlagsContext); if (!context) throw new Error("MyFlagsContext not found"); return context; } // src/hooks/useFlag.ts function useFlag(name, defaultValue = false) { const context = useMyFlagsContext(); return context[name] || defaultValue; } // src/components/FeatureFlag.tsx import { Fragment, jsx as jsx2 } from "react/jsx-runtime"; var FeatureFlag = ({ name, children, defaultValue = false }) => { const isEnabled = useFlag(name, defaultValue); return /* @__PURE__ */ jsx2(Fragment, { children: children(isEnabled) }); }; // src/hooks/useFlags.ts function useFlags() { const context = useMyFlagsContext(); return context; } export { FeatureFlag, MyFlagsProvider, useFlag, useFlags }; //# sourceMappingURL=index.js.map