@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
113 lines (103 loc) • 3.13 kB
text/typescript
import snakeCase from "lodash/snakeCase";
import semver from "semver";
import { Feature, FeatureId, Features } from "@ledgerhq/types-live";
import { getEnv } from "@ledgerhq/live-env";
import { LiveConfig } from "@ledgerhq/live-config/LiveConfig";
type GetFeature = <T extends FeatureId>(param: {
key: T;
appLanguage?: string;
allowOverride?: boolean;
localOverrides?: { [key in FeatureId]?: Feature | undefined };
}) => Features[T] | null;
export interface FirebaseFeatureFlagsProviderProps {
getFeature: GetFeature;
children: React.ReactNode;
}
export const formatToFirebaseFeatureId = (id: string) => `feature_${snakeCase(id)}`;
export const checkFeatureFlagVersion = (feature: Feature) => {
const platform = LiveConfig.instance.platform;
if (!feature?.enabled || !platform) {
return feature;
}
const featureSpecificVersion: string | undefined = (() => {
switch (platform) {
case "desktop":
return feature.desktop_version;
case "ios":
case "android":
return feature.mobile_version;
default:
return undefined;
}
})();
if (
featureSpecificVersion &&
!semver.satisfies(LiveConfig.instance.appVersion, featureSpecificVersion, {
includePrerelease: true,
})
) {
return {
enabledOverriddenForCurrentVersion: true,
...feature,
enabled: false,
};
}
return feature;
};
export const isFeature = (key: string): boolean => {
if (!LiveConfig.instance?.provider?.getValueByKey) {
return false;
}
try {
const value = LiveConfig.getValueByKey(formatToFirebaseFeatureId(key));
if (!value) {
return false;
}
return true;
} catch {
console.error(`Failed to check if feature "${key}" exists`);
return false;
}
};
export const getFeature: GetFeature = args => {
if (!LiveConfig.instance?.provider?.getValueByKey) {
return null;
}
const { key, appLanguage, localOverrides, allowOverride = true } = args;
try {
// Nb prioritize local overrides
if (allowOverride && localOverrides && localOverrides[key]) {
const feature = localOverrides[key];
if (feature) {
return checkFeatureFlagVersion(feature);
}
}
const envFlags = getEnv("FEATURE_FLAGS") as { [key in FeatureId]?: Feature } | undefined;
if (allowOverride && envFlags) {
const feature = envFlags[key];
if (feature)
return {
...feature,
overridesRemote: true,
overriddenByEnv: true,
};
}
const feature = LiveConfig.getValueByKey(formatToFirebaseFeatureId(key));
if (
feature.enabled &&
appLanguage &&
((feature.languages_whitelisted && !feature.languages_whitelisted.includes(appLanguage)) ||
(feature.languages_blacklisted && feature.languages_blacklisted.includes(appLanguage)))
) {
return {
enabledOverriddenForCurrentLanguage: true,
...feature,
enabled: false,
};
}
return checkFeatureFlagVersion(feature);
} catch {
// console.error(`Failed to retrieve feature "${key}"`);
return null;
}
};