From 36608849ec64e953e3be456172502762e3c33df9 Mon Sep 17 00:00:00 2001 From: Igor Monadical Date: Wed, 24 Sep 2025 11:57:49 -0400 Subject: [PATCH] fix: restore feature boolean logic (#671) Co-authored-by: Igor Loskutov --- www/app/lib/clientEnv.ts | 7 ++++-- www/app/lib/features.ts | 53 ++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/www/app/lib/clientEnv.ts b/www/app/lib/clientEnv.ts index 04797ce2..2c4a01c8 100644 --- a/www/app/lib/clientEnv.ts +++ b/www/app/lib/clientEnv.ts @@ -21,8 +21,10 @@ const FEATURE_ENV_NAMES = [ FEATURE_ROOMS_ENV_NAME, ] as const; +export type FeatureEnvName = (typeof FEATURE_ENV_NAMES)[number]; + export type EnvFeaturePartial = { - [key in (typeof FEATURE_ENV_NAMES)[number]]: boolean; + [key in FeatureEnvName]: boolean | null; }; // CONTRACT: isomorphic with JSON.stringify @@ -51,7 +53,8 @@ export const getClientEnvClient = (): ClientEnvCommon => { return clientEnv!; }; -const parseBooleanString = (str: string | undefined): boolean => { +const parseBooleanString = (str: string | undefined): boolean | null => { + if (str === undefined) return null; return str === "true"; }; diff --git a/www/app/lib/features.ts b/www/app/lib/features.ts index a96e23ef..eebfc816 100644 --- a/www/app/lib/features.ts +++ b/www/app/lib/features.ts @@ -4,6 +4,8 @@ import { FEATURE_REQUIRE_LOGIN_ENV_NAME, FEATURE_ROOMS_ENV_NAME, FEATURE_SEND_TO_ZULIP_ENV_NAME, + FeatureEnvName, + getClientEnv, } from "./clientEnv"; export const FEATURES = [ @@ -26,37 +28,30 @@ export const DEFAULT_FEATURES: Features = { rooms: true, } as const; -function parseBooleanEnv( - value: string | undefined, - defaultValue: boolean = false, -): boolean { - if (!value) return defaultValue; - return value.toLowerCase() === "true"; -} +export const ENV_TO_FEATURE: { + [k in FeatureEnvName]: FeatureName; +} = { + FEATURE_REQUIRE_LOGIN: "requireLogin", + FEATURE_PRIVACY: "privacy", + FEATURE_BROWSE: "browse", + FEATURE_SEND_TO_ZULIP: "sendToZulip", + FEATURE_ROOMS: "rooms", +} as const; -const features: Features = { - requireLogin: parseBooleanEnv( - process.env[FEATURE_REQUIRE_LOGIN_ENV_NAME], - DEFAULT_FEATURES.requireLogin, - ), - privacy: parseBooleanEnv( - process.env[FEATURE_PRIVACY_ENV_NAME], - DEFAULT_FEATURES.privacy, - ), - browse: parseBooleanEnv( - process.env[FEATURE_BROWSE_ENV_NAME], - DEFAULT_FEATURES.browse, - ), - sendToZulip: parseBooleanEnv( - process.env[FEATURE_SEND_TO_ZULIP_ENV_NAME], - DEFAULT_FEATURES.sendToZulip, - ), - rooms: parseBooleanEnv( - process.env[FEATURE_ROOMS_ENV_NAME], - DEFAULT_FEATURES.rooms, - ), +export const FEATURE_TO_ENV: { + [k in FeatureName]: FeatureEnvName; +} = { + requireLogin: "FEATURE_REQUIRE_LOGIN", + privacy: "FEATURE_PRIVACY", + browse: "FEATURE_BROWSE", + sendToZulip: "FEATURE_SEND_TO_ZULIP", + rooms: "FEATURE_ROOMS", }; +const features = getClientEnv(); + export const featureEnabled = (featureName: FeatureName): boolean => { - return features[featureName]; + const isSet = features[FEATURE_TO_ENV[featureName]]; + if (isSet === null) return DEFAULT_FEATURES[featureName]; + return isSet; };