Type-safe Feature Flag and Parameter Store library built on Statsig, with a fully synchronous architecture.
npm install @lovart-open/flags
# or
pnpm add @lovart-open/flagsInitialize the Statsig client at your app entry point:
import{initStatsigClient}from'@lovart-open/flags/statsig';initStatsigClient('your-statsig-client-key',{userID: 'user-123'},{environment: {tier: 'production'},});- Type-safe: Full TypeScript type inference and autocomplete
- Synchronous: No loading states, no skeleton screens
- Multi-layer priority:
URL > testOverride > override > remote > fallback(false)
import{createFlagStore,typeFlagDefinition}from'@lovart-open/flags/statsig';// 1. Define your flagsconstMY_FLAGS={dark_mode: {description: 'Dark mode toggle'},new_checkout: {description: 'New checkout flow',testOverride: true,// Force enable in E2E tests},beta_feature: {description: 'Beta feature',override: false,// Static override, ignores remote},}asconstsatisfiesRecord<string,FlagDefinition>;// 2. Create type-safe store and hooksexportconst{ flagStore, useFlag, useFlagState }=createFlagStore(MY_FLAGS);// 3. Export types (optional)exporttypeMyFlagKey=keyoftypeofMY_FLAGS;import{useFlag,useFlagState}from'./my-flags';functionApp(){// Get boolean value directlyconstisDark=useFlag('dark_mode');// ✓ autocomplete// Get full state with source infoconststate=useFlagState('new_checkout');console.log(state.flag,state.source);// true, 'remote'returnisDark ? <DarkTheme/> : <LightTheme/>;}import{flagStore}from'./my-flags';// Get single flagconstenabled=flagStore.getFlag('dark_mode');// Get snapshot of all flagsconstsnapshot=flagStore.snapshot;?ff.dark_mode=1 → Force enable
?ff.dark_mode=0 → Force disable
- Type-safe: Zod schema validation + TypeScript inference
- Synchronous: Same as Feature Flags
- Multi-layer priority:
URL > testOverride > override > remote > fallback
import{z}from'zod';import{createParamStore,defineParam,typeParamStoreDefinition}from'@lovart-open/flags/statsig';// 1. Define your param storesconstMY_PARAMS={homepage_cta: {description: 'Homepage CTA button',params: {text: defineParam({schema: z.enum(['Learn More','Get Started','Sign Up']),fallback: 'Learn More',description: 'Button text',}),color: defineParam({schema: z.enum(['gray','red','blue']),fallback: 'gray',testOverride: 'blue',// Use in E2E tests}),visible: defineParam({schema: z.boolean(),fallback: true,}),},},pricing: {description: 'Pricing config',params: {discount: defineParam({schema: z.number().min(0).max(100),fallback: 0,}),currency: defineParam({schema: z.enum(['USD','CNY','EUR']),fallback: 'USD',}),},},}asconstsatisfiesRecord<string,ParamStoreDefinition<any>>;// 2. Create type-safe store and hooksexportconst{ paramStore, useParam, useParamState, useParamStore }=createParamStore(MY_PARAMS);import{useParam,useParamStore}from'./my-params';functionCTAButton(){// Get value directly (with full type hints)consttext=useParam('homepage_cta','text');// 'Learn More' | 'Get Started' | 'Sign Up'constcolor=useParam('homepage_cta','color');// 'gray' | 'red' | 'blue'// Or get entire store handleconststore=useParamStore('homepage_cta');constvisible=store.get('visible');// booleanif(!visible)returnnull;return<buttonstyle={{ color }}>{text}</button>;}import{paramStore}from'./my-params';// Get single paramconstdiscount=paramStore.getParam('pricing','discount');// number// Get store handleconststore=paramStore.getStore('pricing');store.get('currency');// 'USD' | 'CNY' | 'EUR'# Single param override
?fp.homepage_cta.text=Get Started
?fp.pricing.discount=20
# Entire store JSON override
?fp.homepage_cta={"text":"Get Started","visible":false}
import{initStatsigClient,setLogger}from'@lovart-open/flags/statsig';// Option 1: Pass during initinitStatsigClient('client-xxx',{userID: 'user-123'},{logger: (message)=>myLogger.info(message),});// Option 2: Set globallysetLogger((message)=>myLogger.info(message));Configure isTestEnv in initialization to enable testOverride values:
initStatsigClient('client-xxx',{userID: 'user-123'},{isTestEnv: ()=>Boolean(window.__E2E__),});// playwright/cypress testsawaitpage.addInitScript(()=>{window.__E2E__=true;});initStatsigClient('client-xxx',{userID: 'user-123'},{bootstrap: {data: bootstrapDataFromServer,// Pre-fetched from BFF},});| Property | Type | Description |
|---|---|---|
description | string | Human-readable description |
testOverride | boolean | Fixed value in E2E tests |
override | boolean | Static override (priority over remote) |
keep | boolean | Mark as kept locally (no remote needed) |
| Property | Type | Description |
|---|---|---|
schema | z.ZodType | Zod schema (required) |
fallback | T | Default value (required) |
description | string | Human-readable description |
testOverride | T | Fixed value in E2E tests |
override | T | Static override |
MIT