2025-05-28 15:36:51 -07:00

85 lines
2.4 KiB
TypeScript

import { FC, createContext, useContext, useEffect, useState } from "react";
import { toCamelCase } from "~/helpers/casing";
import { getFeatureFlagsFromCharacterService } from "~/helpers/characterServiceApi";
const featureFlagsToGet = [
"release-gate-ims",
"release-gate-gfs-blessings-ui",
"release-gate-character-sheet-tour",
"release-gate-premade-characters",
];
export const defaultFlags = {
imsFlag: false,
gfsBlessingsUiFlag: false,
characterSheetTourFlag: false,
premadeCharactersFlag: false,
};
export type FeatureFlags = typeof defaultFlags;
export interface FeatureFlagContextType extends FeatureFlags {
featureFlags: FeatureFlags;
}
export const FeatureFlagContext = createContext<FeatureFlagContextType>(null!);
interface ProviderProps {
defaultOverrides?: Partial<FeatureFlags>;
}
export const FeatureFlagProvider: FC<ProviderProps> = ({
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 `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, "")
// Change `2d` to `tactical` since var can't start with number
.replace(/2d/i, "tactical");
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 (
<FeatureFlagContext.Provider value={{ ...featureFlags, featureFlags }}>
{children}
</FeatureFlagContext.Provider>
);
};
export const useFeatureFlags = () => {
return useContext(FeatureFlagContext);
};