UNPKG

@myflags/react

Version:

React bindings for MyFlags feature flag management

199 lines (192 loc) 6.42 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { FeatureFlag: () => FeatureFlag, MyFlagsProvider: () => MyFlagsProvider, useFlag: () => useFlag, useFlags: () => useFlags }); module.exports = __toCommonJS(index_exports); // src/Provider.tsx var import_react2 = require("react"); var import_core = require("@myflags/core"); // src/hooks/useIndexedDB.ts var import_react = require("react"); var DB_NAME = "myflags"; var DB_VERSION = 1; var STORE_NAME = "flags"; function useIndexedDB(key, initialValue) { const [storedValue, setStoredValue] = (0, import_react.useState)(initialValue); const [isDbReady, setIsDbReady] = (0, import_react.useState)(false); const pendingWrites = (0, import_react.useRef)([]); const openDB = (0, import_react.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 = (0, import_react.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 = (0, import_react.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] ); (0, import_react.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 = (0, import_react.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 var import_jsx_runtime = require("react/jsx-runtime"); var MyFlagsContext = (0, import_react2.createContext)(null); function MyFlagsProvider(props) { const [flags, setFlags] = useIndexedDB("flags", {}); const [client] = (0, import_react2.useState)(() => new import_core.MyFlagsSDK(props.config)); (0, import_react2.useEffect)(() => { const unsubscribe = client.subscribe(setFlags); return () => unsubscribe(); }, [client]); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MyFlagsContext.Provider, { value: flags, children: props.children }); } function useMyFlagsContext() { const context = (0, import_react2.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 var import_jsx_runtime2 = require("react/jsx-runtime"); var FeatureFlag = ({ name, children, defaultValue = false }) => { const isEnabled = useFlag(name, defaultValue); return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: children(isEnabled) }); }; // src/hooks/useFlags.ts function useFlags() { const context = useMyFlagsContext(); return context; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { FeatureFlag, MyFlagsProvider, useFlag, useFlags }); //# sourceMappingURL=index.cjs.map