mirror of
https://github.com/block/buzz.git
synced 2026-11-04 00:12:02 +00:00
1. Migration: existing users auto-seed experimental features as enabled
on first load (no feature loss on upgrade). New installs get opt-in UX.
2. Reactivity: SettingsView uses useFeatureSnapshot() so section list
updates instantly when toggles change (fixes stale useMemo deps).
3. Standards: Switch component replaces raw checkboxes, data-testid on
every toggle (feature-toggle-{id}, feature-toggle-dev-global).
4. Tests: 11 unit tests for resolveEnabled covering all tiers + edge cases.
5. Architecture: @features-manifest Vite alias replaces fragile ../../../../
relative import. Test loader also resolves the alias.
6. Versioned localStorage: keys now use -v1 suffix aligned to manifest version.
7. Cache: JSON.parse result cached across hook instances per render cycle.
8. Dev warning: console.warn in dev when getFeature() returns undefined.
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
31 lines
872 B
TypeScript
31 lines
872 B
TypeScript
import type { FeatureTier } from "./types";
|
|
|
|
/**
|
|
* Pure resolution logic for feature visibility.
|
|
* No side effects, no imports beyond types — safe to test in isolation.
|
|
*
|
|
* @param isDev - Whether the current build is a dev build.
|
|
* Defaults to `import.meta.env?.DEV ?? false` for runtime use.
|
|
*/
|
|
export function resolveEnabled(
|
|
tier: FeatureTier,
|
|
featureId: string,
|
|
overrides: Record<string, boolean>,
|
|
devToggle: boolean,
|
|
isDev: boolean = (import.meta.env?.DEV as boolean) ?? false,
|
|
): boolean {
|
|
switch (tier) {
|
|
case "stable":
|
|
return true;
|
|
case "experimental":
|
|
return overrides[featureId] === true;
|
|
case "dev":
|
|
if (!isDev) return false;
|
|
if (!devToggle) return false;
|
|
// Allow per-feature suppression even in dev
|
|
return overrides[featureId] !== false;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|