@myflags/react
Version:
React bindings for MyFlags feature flag management
199 lines (192 loc) • 6.42 kB
JavaScript
;
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