import { FC, PropsWithChildren, createContext, useContext, useEffect, useState, } from "react"; import { toCamelCase } from "~/helpers/casing"; import { getFeatureFlagsFromCharacterService } from "~/helpers/characterServiceApi"; const featureFlagsToGet = [ "release-gate-character-sheet-tour", "circuit-breaker.datadog-rum-characters-app", ]; export const defaultFlags = { characterSheetTourFlag: false, datadogRumCharactersAppFlag: false, }; export type FeatureFlags = typeof defaultFlags; export interface FeatureFlagContextType extends FeatureFlags { featureFlags: FeatureFlags; } export const FeatureFlagContext = createContext(null!); interface ProviderProps extends PropsWithChildren { defaultOverrides?: Partial; } export const FeatureFlagProvider: FC = ({ children, defaultOverrides, }) => { const [featureFlags, setFeatureFlags] = useState({ ...defaultFlags, ...defaultOverrides, }); const convertFlagsToKeys = (flags: Object) => { return Object.keys(flags).reduce((acc, flag) => { // Perform any manipulations to remove unwanted characters const formattedFlag = flag // Remove `character-app` from the flag name .replace(/character-app\./i, "") // Remove `circuit-breaker` from the flag name .replace(/circuit-breaker\./i, "") // Remove `release-gate` from the flag name .replace(/release-gate\W/i, "") // Remove `character-sheet` from flag name if not the tour flag .replace(/character-sheet\W(?!tour)/i, ""); const key = toCamelCase(`${formattedFlag}Flag`); return { ...acc, [key]: flags[flag] }; }, {}); }; const getFeatureFlags = async () => { try { const req = await getFeatureFlagsFromCharacterService(featureFlagsToGet); const res = await req.json(); const flags = convertFlagsToKeys(res.data) as FeatureFlags; setFeatureFlags(flags); } catch (err) { console.error(err); } }; useEffect(() => { if (!defaultOverrides) getFeatureFlags(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultOverrides]); return ( {children} ); }; export const useFeatureFlags = () => { return useContext(FeatureFlagContext); };