@lovart-open/flags 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/statsig/index.js +21 -12
- package/dist/statsig/index.js.map +1 -1
- package/package.json +1 -1
package/dist/statsig/index.js
CHANGED
|
@@ -49,7 +49,7 @@ function initStatsigClient(clientKey, user, options) {
|
|
|
49
49
|
}
|
|
50
50
|
function getStatsigClientSync() {
|
|
51
51
|
if (!client) {
|
|
52
|
-
throw new Error("[@lovart-open/statsig] Not initialized. Call initStatsigClient() first.");
|
|
52
|
+
throw new Error("[@lovart-open/flags/statsig] Not initialized. Call initStatsigClient() first.");
|
|
53
53
|
}
|
|
54
54
|
return client;
|
|
55
55
|
}
|
|
@@ -108,11 +108,15 @@ var FlagStore = class {
|
|
|
108
108
|
if (def.override !== void 0) {
|
|
109
109
|
return { flag: def.override, source: "override" };
|
|
110
110
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
try {
|
|
112
|
+
const currentGate = gate ?? getStatsigClientSync().getFeatureGate(keyStr, evaluationOptions);
|
|
113
|
+
return {
|
|
114
|
+
flag: currentGate.value,
|
|
115
|
+
source: currentGate.idType ? "remote" : "fallback"
|
|
116
|
+
};
|
|
117
|
+
} catch {
|
|
118
|
+
return { flag: false, source: "fallback" };
|
|
119
|
+
}
|
|
116
120
|
}
|
|
117
121
|
};
|
|
118
122
|
function createFlagStore(definitions) {
|
|
@@ -271,12 +275,17 @@ var ParamStore = class {
|
|
|
271
275
|
value = def.override;
|
|
272
276
|
source = "override";
|
|
273
277
|
} else {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
278
|
+
try {
|
|
279
|
+
const clientStore = statsigStore ?? getStatsigClientSync().getParameterStore(storeKey, evaluationOptions);
|
|
280
|
+
const config = clientStore?.__configuration?.[paramKey];
|
|
281
|
+
if (config !== void 0) {
|
|
282
|
+
value = clientStore.get(paramKey, def.fallback);
|
|
283
|
+
source = "remote";
|
|
284
|
+
} else {
|
|
285
|
+
value = def.fallback;
|
|
286
|
+
source = "fallback";
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
280
289
|
value = def.fallback;
|
|
281
290
|
source = "fallback";
|
|
282
291
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/statsig/flags.ts","../../src/statsig/client.ts","../../src/statsig/logger.ts","../../src/statsig/params.ts","../../src/statsig/index.ts"],"sourcesContent":["/**\n * Feature Flags factory module.\n * Use createFlagStore to create type-safe flag stores and hooks.\n */\n\nimport { useFeatureGate } from '@statsig/react-bindings';\n\nimport { getStatsigClientSync, isTestEnv } from './client';\nimport type { EvaluationOptions, FeatureGate, FlagDefinition, FlagSnapshot, FlagState } from './types';\n\nexport interface ResolveOptions extends EvaluationOptions {\n gate?: FeatureGate;\n search?: string;\n}\n\nconst TRUE_LITERALS = new Set(['1', 'true']);\nconst hasWindow = typeof window !== 'undefined';\n\n/**\n * Parse URL query string for flag overrides.\n * Format: ?ff.flag_name=1 or ?ff.flag_name=true\n */\nexport function parseUrlOverrides(search?: string): Record<string, boolean> {\n if (!hasWindow && !search) return {};\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const overrides: Record<string, boolean> = {};\n for (const [key, value] of params.entries()) {\n if (key.startsWith('ff.')) {\n overrides[key.slice(3)] = TRUE_LITERALS.has(value.trim().toLowerCase());\n }\n }\n return overrides;\n}\n\n/**\n * Type-safe FlagStore class.\n */\nexport class FlagStore<TDefinitions extends Record<string, FlagDefinition>> {\n private readonly definitions: TDefinitions;\n\n constructor(definitions: TDefinitions) {\n this.definitions = definitions;\n }\n\n /** Get snapshot of all flag states */\n get snapshot(): FlagSnapshot<Extract<keyof TDefinitions, string>> {\n const next: any = {};\n for (const key in this.definitions) {\n next[key] = this.resolve(key as any);\n }\n return next;\n }\n\n /** Get flag boolean value */\n getFlag = <K extends keyof TDefinitions>(key: K, options?: EvaluationOptions) =>\n this.getFlagState(key, options).flag;\n\n /** Get flag state with source info */\n getFlagState<K extends keyof TDefinitions>(key: K, options?: EvaluationOptions): FlagState {\n return this.resolve(key, options);\n }\n\n /**\n * Resolve flag value with priority: URL > test > override > remote > fallback\n */\n resolve<K extends keyof TDefinitions>(key: K, options?: ResolveOptions): FlagState {\n const { gate, search, ...evaluationOptions } = options ?? {};\n const def = this.definitions[key];\n if (!def) return { flag: false, source: 'fallback' };\n\n const keyStr = key as string;\n\n // 1. URL has highest priority\n const urlOverrides = parseUrlOverrides(search);\n if (urlOverrides[keyStr] !== undefined) {\n return { flag: urlOverrides[keyStr], source: 'url' };\n }\n\n // 2. Test environment override\n if (isTestEnv() && def.testOverride !== undefined) {\n return { flag: def.testOverride, source: 'test' };\n }\n\n // 3. Static override\n if (def.override !== undefined) {\n return { flag: def.override, source: 'override' };\n }\n\n // 4. Remote value from Statsig\n const currentGate = gate ?? getStatsigClientSync().getFeatureGate(keyStr, evaluationOptions);\n return {\n flag: currentGate.value,\n source: currentGate.idType ? 'remote' : 'fallback',\n };\n }\n}\n\n/**\n * Create a type-safe Flag Store with React hooks.\n *\n * @example\n * ```ts\n * const MY_FLAGS = {\n * dark_mode: { description: 'Dark mode toggle' },\n * new_checkout: { description: 'New checkout flow' },\n * } as const satisfies Record<string, FlagDefinition>;\n *\n * export const { flagStore, useFlag, useFlagState } = createFlagStore(MY_FLAGS);\n *\n * // Full type safety and autocomplete\n * const isDark = useFlag('dark_mode'); // ✓ autocomplete\n * useFlag('unknown'); // ✗ compile error\n * ```\n */\nexport function createFlagStore<T extends Record<string, FlagDefinition>>(definitions: T) {\n const store = new FlagStore(definitions);\n\n type FlagKey = Extract<keyof T, string>;\n\n /**\n * React Hook: Get flag state with source info.\n */\n function useFlagState(key: FlagKey, options?: EvaluationOptions): FlagState {\n const featureGate = useFeatureGate(key, options);\n return store.resolve(key, { gate: featureGate, ...options });\n }\n\n /**\n * React Hook: Get flag boolean value.\n */\n function useFlag(key: FlagKey, options?: EvaluationOptions): boolean {\n const featureGate = useFeatureGate(key, options);\n return store.resolve(key, { gate: featureGate, ...options }).flag;\n }\n\n return {\n /** FlagStore instance */\n flagStore: store,\n /** React Hook: Get flag boolean value */\n useFlag,\n /** React Hook: Get flag state { flag, source } */\n useFlagState,\n };\n}\n\n// Re-export types\nexport type { FlagDefinition } from './types';\n","/**\n * Statsig client initialization module.\n * Provides singleton pattern for StatsigClient.\n */\n\nimport { StatsigClient, type StatsigOptions, type StatsigUser } from '@statsig/js-client';\n\nimport { getLogger, type Logger, setLogger } from './logger';\n\nlet client: StatsigClient | null = null;\nlet testEnvDetector: (() => boolean) | null = null;\n\n/**\n * Bootstrap data structure for server-side rendering.\n * Pass this from your BFF/SSR layer to enable zero-network initialization.\n */\nexport interface StatsigBootstrap {\n user?: StatsigUser;\n data: string;\n}\n\nexport interface InitOptions extends StatsigOptions {\n /**\n * Test environment indicator.\n * When true or returns true, testOverride values will be used.\n *\n * - `boolean`: static value\n * - `() => boolean`: dynamic function\n * - `undefined`: testOverride disabled\n */\n isTestEnv?: boolean | (() => boolean);\n\n /**\n * Custom logger implementation.\n */\n logger?: Logger;\n\n /**\n * Bootstrap data from server (enables zero-network init).\n * The data will be set before initializeSync() is called.\n */\n bootstrap?: StatsigBootstrap | null;\n}\n\n/**\n * Initialize Statsig client (singleton).\n *\n * @example\n * ```ts\n * // Basic initialization\n * initStatsigClient('client-xxx', { userID: 'user-123' }, {\n * environment: { tier: 'production' },\n * isTestEnv: () => Boolean(window.__E2E__),\n * });\n *\n * // With server-side bootstrap (zero network)\n * initStatsigClient('client-xxx', { userID: 'user-123' }, {\n * environment: { tier: 'production' },\n * bootstrap: { data: '...' },\n * });\n * ```\n */\nexport function initStatsigClient(\n clientKey: string,\n user: StatsigUser,\n options?: InitOptions,\n): StatsigClient {\n if (client) return client;\n\n const { isTestEnv, logger, bootstrap, ...statsigOptions } = options ?? {};\n\n // Set custom logger\n if (logger) {\n setLogger(logger);\n }\n\n const log = getLogger();\n\n // Store test env detector\n if (typeof isTestEnv === 'function') {\n testEnvDetector = isTestEnv;\n } else if (typeof isTestEnv === 'boolean') {\n testEnvDetector = () => isTestEnv;\n }\n // else: undefined, testOverride disabled\n\n // Log initialization mode\n if (bootstrap) {\n log(`Initializing with bootstrap data (userID: '${user.userID}')`);\n } else {\n log(`Initializing in default mode (userID: '${user.userID}')`);\n }\n\n client = new StatsigClient(clientKey, user, statsigOptions);\n\n // Set bootstrap data before initializeSync (enables zero-network init)\n if (bootstrap?.data) {\n client.dataAdapter.setData(bootstrap.data);\n }\n\n client.initializeSync();\n return client;\n}\n\n/**\n * Get Statsig client synchronously.\n *\n * @throws Error if not initialized\n */\nexport function getStatsigClientSync(): StatsigClient {\n if (!client) {\n throw new Error('[@lovart-open/statsig] Not initialized. Call initStatsigClient() first.');\n }\n return client;\n}\n\n/**\n * Check if currently in test environment.\n * Returns false if isTestEnv was not configured.\n */\nexport function isTestEnv(): boolean {\n return testEnvDetector?.() ?? false;\n}\n","/**\n * Simple logger interface.\n */\n\nexport type Logger = (message: string, data?: unknown) => void;\n\nconst defaultLogger: Logger = (message, data) => {\n if (data !== undefined) {\n console.info(`[statsig] ${message}`, data);\n } else {\n console.info(`[statsig] ${message}`);\n }\n};\n\nlet currentLogger: Logger = defaultLogger;\n\n/**\n * Set a custom logger implementation.\n */\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\n/**\n * Get the current logger instance.\n */\nexport function getLogger(): Logger {\n return currentLogger;\n}\n","/**\n * Parameter Stores factory module.\n * Use createParamStore to create type-safe parameter stores and hooks.\n */\n\nimport { merge, set } from 'lodash-es';\nimport { useParameterStore } from '@statsig/react-bindings';\nimport z from 'zod';\n\nimport { getStatsigClientSync, isTestEnv } from './client';\n\n/** Parameter definition */\nexport interface ParamDefinition<T = unknown> {\n schema: z.ZodType<T>;\n fallback: T;\n description?: string;\n testOverride?: T;\n override?: T;\n}\n\n/** Parameter store definition */\nexport interface ParamStoreDefinition<TParams extends Record<string, ParamDefinition<any>>> {\n description?: string;\n keep?: boolean;\n params: TParams;\n}\n\n/** Helper function to define a single param with type inference */\nexport function defineParam<T>(def: ParamDefinition<T>): ParamDefinition<T> {\n return def;\n}\n\nconst hasWindow = typeof window !== 'undefined';\nconst FP_PREFIX = 'fp.';\n\n/** Event name for schema mismatch errors */\nexport const PARAM_SCHEMA_MISMATCH_EVENT = 'param-schema-mismatch';\n\n/** Detail payload for schema mismatch event */\nexport interface ParamSchemaMismatchDetail {\n storeKey: string;\n paramKey: string;\n source: string;\n value: unknown;\n error: z.ZodError;\n}\n\n/** Dispatch schema mismatch event (browser only) */\nfunction dispatchSchemaMismatchEvent(detail: ParamSchemaMismatchDetail): void {\n if (!hasWindow) return;\n window.dispatchEvent(new CustomEvent(PARAM_SCHEMA_MISMATCH_EVENT, { detail }));\n}\n\n/**\n * Parse URL query string for param store overrides (standalone function).\n * Format: ?fp.store.param=value or ?fp.store={\"param\":\"value\"}\n *\n * @example\n * parseParamStoreUrlOverrides('?fp.config.debug=true')\n * // => { config: { debug: true } }\n */\nexport function parseParamStoreUrlOverrides(search?: string): Record<string, Record<string, unknown>> {\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [key, value] of params.entries()) {\n if (!key.startsWith(FP_PREFIX)) continue;\n const rest = key.slice(FP_PREFIX.length);\n const dotIndex = rest.indexOf('.');\n\n if (dotIndex >= 0) {\n const path = rest;\n const coerced = tryCoerceBasic(value);\n set(result, path, coerced);\n } else {\n const path = rest;\n try {\n const obj = JSON.parse(value);\n if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {\n result[path] = merge(result[path] ?? {}, obj);\n }\n } catch {\n // ignore\n }\n }\n }\n return result;\n}\n\n/** Basic type coercion without schema (for standalone parse function) */\nfunction tryCoerceBasic(raw: string): unknown {\n const trimmed = raw.trim();\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n return JSON.parse(trimmed);\n } catch {\n // ignore\n }\n }\n const num = Number(raw);\n if (!Number.isNaN(num) && raw !== '') return num;\n if (raw === 'true') return true;\n if (raw === 'false') return false;\n if (raw === 'null') return null;\n return raw;\n}\n\n/** Try to coerce string value to the expected type based on schema */\nfunction tryCoerce(raw: string, def: ParamDefinition | undefined): unknown {\n const trimmed = raw.trim();\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n return JSON.parse(trimmed);\n } catch {\n // ignore\n }\n }\n if (def?.schema) {\n const num = Number(raw);\n if (!Number.isNaN(num) && def.schema.safeParse(num).success) {\n return num;\n }\n if (raw === 'true' && def.schema.safeParse(true).success) return true;\n if (raw === 'false' && def.schema.safeParse(false).success) return false;\n if (raw === 'null' && def.schema.safeParse(null).success) return null;\n }\n return raw;\n}\n\n/** Single param state with value and source */\nexport interface ParamState<T> {\n value: T;\n source: 'url' | 'test' | 'override' | 'remote' | 'fallback';\n error?: z.ZodError;\n fallback?: T;\n}\n\n/** Store handle for accessing params */\nexport interface ParamStoreHandle<TParams extends Record<string, ParamDefinition<any>>> {\n get<P extends keyof TParams>(paramKey: P): z.infer<TParams[P]['schema']>;\n getState<P extends keyof TParams>(paramKey: P): ParamState<z.infer<TParams[P]['schema']>>;\n}\n\n/** Infer value types from param definitions */\nexport type ParamStoreValue<TParams extends Record<string, ParamDefinition<any>>> = {\n [K in keyof TParams]: z.infer<TParams[K]['schema']>;\n};\n\n/** Statsig ParameterStore return type */\ntype StatsigParameterStore = ReturnType<ReturnType<typeof getStatsigClientSync>['getParameterStore']>;\n\n/** Resolve options for param lookup */\nexport interface ParamResolveOptions {\n statsigStore?: StatsigParameterStore | null;\n search?: string;\n disableExposureLog?: boolean;\n}\n\n/**\n * Type-safe ParamStore class.\n */\nexport class ParamStore<TStores extends Record<string, ParamStoreDefinition<any>>> {\n private readonly definitions: TStores;\n\n constructor(definitions: TStores) {\n this.definitions = definitions;\n }\n\n /**\n * Parse URL query string for param overrides.\n * Format: ?fp.store.param=value or ?fp.store={\"param\":\"value\"}\n */\n private parseUrlOverrides(search?: string): Record<string, Record<string, unknown>> {\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [key, value] of params.entries()) {\n if (!key.startsWith(FP_PREFIX)) continue;\n const rest = key.slice(FP_PREFIX.length);\n const dotIndex = rest.indexOf('.');\n\n if (dotIndex >= 0) {\n const path = rest;\n const storeKey = rest.slice(0, dotIndex);\n const paramKey = rest.slice(dotIndex + 1);\n const storeDef = this.definitions[storeKey];\n const paramDef = storeDef?.params[paramKey];\n set(result, path, tryCoerce(value, paramDef));\n } else {\n const path = rest;\n try {\n const obj = JSON.parse(value);\n if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {\n result[path] = merge(result[path] ?? {}, obj);\n }\n } catch {\n // ignore\n }\n }\n }\n return result;\n }\n\n /**\n * Resolve param value with priority: URL > test > override > remote > fallback\n */\n private resolve<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<TStores[K]['params'][P]['schema']>> {\n const { statsigStore, search, ...evaluationOptions } = options ?? {};\n const storeDef = this.definitions[storeKey];\n if (!storeDef) {\n throw new Error(`[ParamStore] Unknown store: ${String(storeKey)}`);\n }\n\n const def = storeDef.params[paramKey as string] as ParamDefinition;\n if (!def) {\n throw new Error(`[ParamStore] Unknown param: ${String(storeKey)}.${String(paramKey)}`);\n }\n\n const schema = def.schema;\n let value: unknown;\n let source: ParamState<unknown>['source'];\n\n // 1. URL has highest priority\n const urlOverrides = this.parseUrlOverrides(search);\n const urlVal = urlOverrides[storeKey as string]?.[paramKey as string];\n if (urlVal !== undefined) {\n value = urlVal;\n source = 'url';\n }\n // 2. Test environment override\n else if (isTestEnv() && def.testOverride !== undefined) {\n value = def.testOverride;\n source = 'test';\n }\n // 3. Static override\n else if (def.override !== undefined) {\n value = def.override;\n source = 'override';\n }\n // 4. Remote value from Statsig\n else {\n const clientStore = statsigStore ?? getStatsigClientSync().getParameterStore(storeKey as string, evaluationOptions);\n const config = (clientStore as any)?.__configuration?.[paramKey as string];\n if (config !== undefined) {\n value = clientStore.get(paramKey as string, def.fallback);\n source = 'remote';\n } else {\n value = def.fallback;\n source = 'fallback';\n }\n }\n\n // Schema validation\n const parsed = schema.safeParse(value);\n if (!parsed.success) {\n console.error(`[ParamStore] Schema mismatch (${source}): ${String(storeKey)}.${String(paramKey)}`, value, parsed.error);\n dispatchSchemaMismatchEvent({\n storeKey: String(storeKey),\n paramKey: String(paramKey),\n source,\n value,\n error: parsed.error,\n });\n const fallbackVal = def.fallback;\n if (source === 'remote') {\n return { value: fallbackVal, source: 'fallback', error: parsed.error };\n }\n return { value: value as any, source, error: parsed.error, fallback: fallbackVal };\n }\n return { value: parsed.data, source };\n }\n\n /** Get param state with value and source info */\n getParamState<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<TStores[K]['params'][P]['schema']>> {\n return this.resolve(storeKey, paramKey, options);\n }\n\n /** Get param value directly */\n getParam<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): z.infer<TStores[K]['params'][P]['schema']> {\n return this.resolve(storeKey, paramKey, options).value;\n }\n\n /** Get store handle for multiple param access */\n getStore<K extends keyof TStores>(\n storeKey: K,\n options?: ParamResolveOptions,\n ): ParamStoreHandle<TStores[K]['params']> {\n const { statsigStore, ...rest } = options ?? {};\n let cachedStore: StatsigParameterStore | null | undefined = statsigStore;\n if (cachedStore === undefined) {\n try {\n cachedStore = getStatsigClientSync().getParameterStore(storeKey as string, rest);\n } catch {\n cachedStore = null;\n }\n }\n const opts: ParamResolveOptions = { ...rest, statsigStore: cachedStore };\n return {\n get: <P extends keyof TStores[K]['params']>(paramKey: P) => this.resolve(storeKey, paramKey, opts).value,\n getState: <P extends keyof TStores[K]['params']>(paramKey: P) => this.resolve(storeKey, paramKey, opts),\n };\n }\n}\n\n/**\n * Create a type-safe Param Store with React hooks.\n *\n * @example\n * ```ts\n * const MY_PARAMS = {\n * homepage_cta: {\n * description: 'Homepage CTA button',\n * params: {\n * text: defineParam({ schema: z.string(), fallback: 'Learn More' }),\n * color: defineParam({ schema: z.enum(['red', 'blue']), fallback: 'blue' }),\n * },\n * },\n * } as const satisfies Record<string, ParamStoreDefinition<any>>;\n *\n * export const { paramStore, useParam, useParamState } = createParamStore(MY_PARAMS);\n *\n * // Full type safety and autocomplete\n * const text = useParam('homepage_cta', 'text'); // string type\n * const color = useParam('homepage_cta', 'color'); // 'red' | 'blue' type\n * ```\n */\nexport function createParamStore<T extends Record<string, ParamStoreDefinition<any>>>(definitions: T) {\n const store = new ParamStore(definitions);\n\n type StoreKey = Extract<keyof T, string>;\n\n /**\n * React Hook: Get store handle for multiple param access.\n */\n function useParamStore<K extends StoreKey>(\n storeKey: K,\n options?: ParamResolveOptions,\n ): ParamStoreHandle<T[K]['params']> {\n const statsigStore = useParameterStore(storeKey, options);\n return store.getStore(storeKey, { ...options, statsigStore });\n }\n\n /**\n * React Hook: Get single param state.\n */\n function useParamState<K extends StoreKey, P extends keyof T[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<T[K]['params'][P]['schema']>> {\n const statsigStore = useParameterStore(storeKey, options);\n return store.getParamState(storeKey, paramKey, { ...options, statsigStore });\n }\n\n /**\n * React Hook: Get single param value.\n */\n function useParam<K extends StoreKey, P extends keyof T[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): z.infer<T[K]['params'][P]['schema']> {\n return useParamState(storeKey, paramKey, options).value;\n }\n\n return {\n /** ParamStore instance */\n paramStore: store,\n /** React Hook: Get single param value */\n useParam,\n /** React Hook: Get single param state */\n useParamState,\n /** React Hook: Get store handle */\n useParamStore,\n };\n}\n","/**\n * @lovart-open/flags/statsig\n *\n * Type-safe Feature Flag and Parameter Store management library.\n *\n * Feature flag priority: URL > testOverride > override > remote > fallback(false)\n * Parameter Store priority: URL > testOverride > override > remote > fallback\n */\n\n// Flag factory and types\nexport { createFlagStore, FlagStore, parseUrlOverrides, type ResolveOptions } from './flags';\n\n// Param factory and types\nexport {\n createParamStore,\n defineParam,\n PARAM_SCHEMA_MISMATCH_EVENT,\n type ParamSchemaMismatchDetail,\n parseParamStoreUrlOverrides,\n ParamStore,\n type ParamDefinition,\n type ParamResolveOptions,\n type ParamState,\n type ParamStoreDefinition,\n type ParamStoreHandle,\n type ParamStoreValue,\n} from './params';\n\n// Logger\nexport { getLogger, setLogger, type Logger } from './logger';\n\n// Statsig client\nexport {\n getStatsigClientSync,\n initStatsigClient,\n isTestEnv,\n type InitOptions,\n type StatsigBootstrap,\n} from './client';\n\n// Core types\nexport {\n type EvaluationOptions,\n type FeatureGate,\n type FlagDefinition,\n type FlagKeyOf,\n type FlagPriority,\n type FlagSnapshot,\n type FlagState,\n type RemoteFlagValues,\n} from './types';\n\n// Statsig React bindings (re-export)\nexport * from '@statsig/react-bindings';\n"],"mappings":"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","names":["isTestEnv","hasWindow"]}
|
|
1
|
+
{"version":3,"sources":["../../src/statsig/flags.ts","../../src/statsig/client.ts","../../src/statsig/logger.ts","../../src/statsig/params.ts","../../src/statsig/index.ts"],"sourcesContent":["/**\n * Feature Flags factory module.\n * Use createFlagStore to create type-safe flag stores and hooks.\n */\n\nimport { useFeatureGate } from '@statsig/react-bindings';\n\nimport { getStatsigClientSync, isTestEnv } from './client';\nimport type { EvaluationOptions, FeatureGate, FlagDefinition, FlagSnapshot, FlagState } from './types';\n\nexport interface ResolveOptions extends EvaluationOptions {\n gate?: FeatureGate;\n search?: string;\n}\n\nconst TRUE_LITERALS = new Set(['1', 'true']);\nconst hasWindow = typeof window !== 'undefined';\n\n/**\n * Parse URL query string for flag overrides.\n * Format: ?ff.flag_name=1 or ?ff.flag_name=true\n */\nexport function parseUrlOverrides(search?: string): Record<string, boolean> {\n if (!hasWindow && !search) return {};\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const overrides: Record<string, boolean> = {};\n for (const [key, value] of params.entries()) {\n if (key.startsWith('ff.')) {\n overrides[key.slice(3)] = TRUE_LITERALS.has(value.trim().toLowerCase());\n }\n }\n return overrides;\n}\n\n/**\n * Type-safe FlagStore class.\n */\nexport class FlagStore<TDefinitions extends Record<string, FlagDefinition>> {\n private readonly definitions: TDefinitions;\n\n constructor(definitions: TDefinitions) {\n this.definitions = definitions;\n }\n\n /** Get snapshot of all flag states */\n get snapshot(): FlagSnapshot<Extract<keyof TDefinitions, string>> {\n const next: any = {};\n for (const key in this.definitions) {\n next[key] = this.resolve(key as any);\n }\n return next;\n }\n\n /** Get flag boolean value */\n getFlag = <K extends keyof TDefinitions>(key: K, options?: EvaluationOptions) =>\n this.getFlagState(key, options).flag;\n\n /** Get flag state with source info */\n getFlagState<K extends keyof TDefinitions>(key: K, options?: EvaluationOptions): FlagState {\n return this.resolve(key, options);\n }\n\n /**\n * Resolve flag value with priority: URL > test > override > remote > fallback\n */\n resolve<K extends keyof TDefinitions>(key: K, options?: ResolveOptions): FlagState {\n const { gate, search, ...evaluationOptions } = options ?? {};\n const def = this.definitions[key];\n if (!def) return { flag: false, source: 'fallback' };\n\n const keyStr = key as string;\n\n // 1. URL has highest priority\n const urlOverrides = parseUrlOverrides(search);\n if (urlOverrides[keyStr] !== undefined) {\n return { flag: urlOverrides[keyStr], source: 'url' };\n }\n\n // 2. Test environment override\n if (isTestEnv() && def.testOverride !== undefined) {\n return { flag: def.testOverride, source: 'test' };\n }\n\n // 3. Static override\n if (def.override !== undefined) {\n return { flag: def.override, source: 'override' };\n }\n\n // 4. Remote value from Statsig\n try {\n const currentGate = gate ?? getStatsigClientSync().getFeatureGate(keyStr, evaluationOptions);\n return {\n flag: currentGate.value,\n source: currentGate.idType ? 'remote' : 'fallback',\n };\n } catch {\n return { flag: false, source: 'fallback' };\n }\n }\n}\n\n/**\n * Create a type-safe Flag Store with React hooks.\n *\n * @example\n * ```ts\n * const MY_FLAGS = {\n * dark_mode: { description: 'Dark mode toggle' },\n * new_checkout: { description: 'New checkout flow' },\n * } as const satisfies Record<string, FlagDefinition>;\n *\n * export const { flagStore, useFlag, useFlagState } = createFlagStore(MY_FLAGS);\n *\n * // Full type safety and autocomplete\n * const isDark = useFlag('dark_mode'); // ✓ autocomplete\n * useFlag('unknown'); // ✗ compile error\n * ```\n */\nexport function createFlagStore<T extends Record<string, FlagDefinition>>(definitions: T) {\n const store = new FlagStore(definitions);\n\n type FlagKey = Extract<keyof T, string>;\n\n /**\n * React Hook: Get flag state with source info.\n */\n function useFlagState(key: FlagKey, options?: EvaluationOptions): FlagState {\n const featureGate = useFeatureGate(key, options);\n return store.resolve(key, { gate: featureGate, ...options });\n }\n\n /**\n * React Hook: Get flag boolean value.\n */\n function useFlag(key: FlagKey, options?: EvaluationOptions): boolean {\n const featureGate = useFeatureGate(key, options);\n return store.resolve(key, { gate: featureGate, ...options }).flag;\n }\n\n return {\n /** FlagStore instance */\n flagStore: store,\n /** React Hook: Get flag boolean value */\n useFlag,\n /** React Hook: Get flag state { flag, source } */\n useFlagState,\n };\n}\n\n// Re-export types\nexport type { FlagDefinition } from './types';\n","/**\n * Statsig client initialization module.\n * Provides singleton pattern for StatsigClient.\n */\n\nimport { StatsigClient, type StatsigOptions, type StatsigUser } from '@statsig/js-client';\n\nimport { getLogger, type Logger, setLogger } from './logger';\n\nlet client: StatsigClient | null = null;\nlet testEnvDetector: (() => boolean) | null = null;\n\n/**\n * Bootstrap data structure for server-side rendering.\n * Pass this from your BFF/SSR layer to enable zero-network initialization.\n */\nexport interface StatsigBootstrap {\n user?: StatsigUser;\n data: string;\n}\n\nexport interface InitOptions extends StatsigOptions {\n /**\n * Test environment indicator.\n * When true or returns true, testOverride values will be used.\n *\n * - `boolean`: static value\n * - `() => boolean`: dynamic function\n * - `undefined`: testOverride disabled\n */\n isTestEnv?: boolean | (() => boolean);\n\n /**\n * Custom logger implementation.\n */\n logger?: Logger;\n\n /**\n * Bootstrap data from server (enables zero-network init).\n * The data will be set before initializeSync() is called.\n */\n bootstrap?: StatsigBootstrap | null;\n}\n\n/**\n * Initialize Statsig client (singleton).\n *\n * @example\n * ```ts\n * // Basic initialization\n * initStatsigClient('client-xxx', { userID: 'user-123' }, {\n * environment: { tier: 'production' },\n * isTestEnv: () => Boolean(window.__E2E__),\n * });\n *\n * // With server-side bootstrap (zero network)\n * initStatsigClient('client-xxx', { userID: 'user-123' }, {\n * environment: { tier: 'production' },\n * bootstrap: { data: '...' },\n * });\n * ```\n */\nexport function initStatsigClient(\n clientKey: string,\n user: StatsigUser,\n options?: InitOptions,\n): StatsigClient {\n if (client) return client;\n\n const { isTestEnv, logger, bootstrap, ...statsigOptions } = options ?? {};\n\n // Set custom logger\n if (logger) {\n setLogger(logger);\n }\n\n const log = getLogger();\n\n // Store test env detector\n if (typeof isTestEnv === 'function') {\n testEnvDetector = isTestEnv;\n } else if (typeof isTestEnv === 'boolean') {\n testEnvDetector = () => isTestEnv;\n }\n // else: undefined, testOverride disabled\n\n // Log initialization mode\n if (bootstrap) {\n log(`Initializing with bootstrap data (userID: '${user.userID}')`);\n } else {\n log(`Initializing in default mode (userID: '${user.userID}')`);\n }\n\n client = new StatsigClient(clientKey, user, statsigOptions);\n\n // Set bootstrap data before initializeSync (enables zero-network init)\n if (bootstrap?.data) {\n client.dataAdapter.setData(bootstrap.data);\n }\n\n client.initializeSync();\n return client;\n}\n\n/**\n * Get Statsig client synchronously.\n *\n * @throws Error if not initialized\n */\nexport function getStatsigClientSync(): StatsigClient {\n if (!client) {\n throw new Error('[@lovart-open/flags/statsig] Not initialized. Call initStatsigClient() first.');\n }\n return client;\n}\n\n/**\n * Check if currently in test environment.\n * Returns false if isTestEnv was not configured.\n */\nexport function isTestEnv(): boolean {\n return testEnvDetector?.() ?? false;\n}\n","/**\n * Simple logger interface.\n */\n\nexport type Logger = (message: string, data?: unknown) => void;\n\nconst defaultLogger: Logger = (message, data) => {\n if (data !== undefined) {\n console.info(`[statsig] ${message}`, data);\n } else {\n console.info(`[statsig] ${message}`);\n }\n};\n\nlet currentLogger: Logger = defaultLogger;\n\n/**\n * Set a custom logger implementation.\n */\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\n/**\n * Get the current logger instance.\n */\nexport function getLogger(): Logger {\n return currentLogger;\n}\n","/**\n * Parameter Stores factory module.\n * Use createParamStore to create type-safe parameter stores and hooks.\n */\n\nimport { merge, set } from 'lodash-es';\nimport { useParameterStore } from '@statsig/react-bindings';\nimport z from 'zod';\n\nimport { getStatsigClientSync, isTestEnv } from './client';\n\n/** Parameter definition */\nexport interface ParamDefinition<T = unknown> {\n schema: z.ZodType<T>;\n fallback: T;\n description?: string;\n testOverride?: T;\n override?: T;\n}\n\n/** Parameter store definition */\nexport interface ParamStoreDefinition<TParams extends Record<string, ParamDefinition<any>>> {\n description?: string;\n keep?: boolean;\n params: TParams;\n}\n\n/** Helper function to define a single param with type inference */\nexport function defineParam<T>(def: ParamDefinition<T>): ParamDefinition<T> {\n return def;\n}\n\nconst hasWindow = typeof window !== 'undefined';\nconst FP_PREFIX = 'fp.';\n\n/** Event name for schema mismatch errors */\nexport const PARAM_SCHEMA_MISMATCH_EVENT = 'param-schema-mismatch';\n\n/** Detail payload for schema mismatch event */\nexport interface ParamSchemaMismatchDetail {\n storeKey: string;\n paramKey: string;\n source: string;\n value: unknown;\n error: z.ZodError;\n}\n\n/** Dispatch schema mismatch event (browser only) */\nfunction dispatchSchemaMismatchEvent(detail: ParamSchemaMismatchDetail): void {\n if (!hasWindow) return;\n window.dispatchEvent(new CustomEvent(PARAM_SCHEMA_MISMATCH_EVENT, { detail }));\n}\n\n/**\n * Parse URL query string for param store overrides (standalone function).\n * Format: ?fp.store.param=value or ?fp.store={\"param\":\"value\"}\n *\n * @example\n * parseParamStoreUrlOverrides('?fp.config.debug=true')\n * // => { config: { debug: true } }\n */\nexport function parseParamStoreUrlOverrides(search?: string): Record<string, Record<string, unknown>> {\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [key, value] of params.entries()) {\n if (!key.startsWith(FP_PREFIX)) continue;\n const rest = key.slice(FP_PREFIX.length);\n const dotIndex = rest.indexOf('.');\n\n if (dotIndex >= 0) {\n const path = rest;\n const coerced = tryCoerceBasic(value);\n set(result, path, coerced);\n } else {\n const path = rest;\n try {\n const obj = JSON.parse(value);\n if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {\n result[path] = merge(result[path] ?? {}, obj);\n }\n } catch {\n // ignore\n }\n }\n }\n return result;\n}\n\n/** Basic type coercion without schema (for standalone parse function) */\nfunction tryCoerceBasic(raw: string): unknown {\n const trimmed = raw.trim();\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n return JSON.parse(trimmed);\n } catch {\n // ignore\n }\n }\n const num = Number(raw);\n if (!Number.isNaN(num) && raw !== '') return num;\n if (raw === 'true') return true;\n if (raw === 'false') return false;\n if (raw === 'null') return null;\n return raw;\n}\n\n/** Try to coerce string value to the expected type based on schema */\nfunction tryCoerce(raw: string, def: ParamDefinition | undefined): unknown {\n const trimmed = raw.trim();\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n return JSON.parse(trimmed);\n } catch {\n // ignore\n }\n }\n if (def?.schema) {\n const num = Number(raw);\n if (!Number.isNaN(num) && def.schema.safeParse(num).success) {\n return num;\n }\n if (raw === 'true' && def.schema.safeParse(true).success) return true;\n if (raw === 'false' && def.schema.safeParse(false).success) return false;\n if (raw === 'null' && def.schema.safeParse(null).success) return null;\n }\n return raw;\n}\n\n/** Single param state with value and source */\nexport interface ParamState<T> {\n value: T;\n source: 'url' | 'test' | 'override' | 'remote' | 'fallback';\n error?: z.ZodError;\n fallback?: T;\n}\n\n/** Store handle for accessing params */\nexport interface ParamStoreHandle<TParams extends Record<string, ParamDefinition<any>>> {\n get<P extends keyof TParams>(paramKey: P): z.infer<TParams[P]['schema']>;\n getState<P extends keyof TParams>(paramKey: P): ParamState<z.infer<TParams[P]['schema']>>;\n}\n\n/** Infer value types from param definitions */\nexport type ParamStoreValue<TParams extends Record<string, ParamDefinition<any>>> = {\n [K in keyof TParams]: z.infer<TParams[K]['schema']>;\n};\n\n/** Statsig ParameterStore return type */\ntype StatsigParameterStore = ReturnType<ReturnType<typeof getStatsigClientSync>['getParameterStore']>;\n\n/** Resolve options for param lookup */\nexport interface ParamResolveOptions {\n statsigStore?: StatsigParameterStore | null;\n search?: string;\n disableExposureLog?: boolean;\n}\n\n/**\n * Type-safe ParamStore class.\n */\nexport class ParamStore<TStores extends Record<string, ParamStoreDefinition<any>>> {\n private readonly definitions: TStores;\n\n constructor(definitions: TStores) {\n this.definitions = definitions;\n }\n\n /**\n * Parse URL query string for param overrides.\n * Format: ?fp.store.param=value or ?fp.store={\"param\":\"value\"}\n */\n private parseUrlOverrides(search?: string): Record<string, Record<string, unknown>> {\n const searchString = search ?? (hasWindow ? window.location.search : '');\n const params = new URLSearchParams(searchString);\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [key, value] of params.entries()) {\n if (!key.startsWith(FP_PREFIX)) continue;\n const rest = key.slice(FP_PREFIX.length);\n const dotIndex = rest.indexOf('.');\n\n if (dotIndex >= 0) {\n const path = rest;\n const storeKey = rest.slice(0, dotIndex);\n const paramKey = rest.slice(dotIndex + 1);\n const storeDef = this.definitions[storeKey];\n const paramDef = storeDef?.params[paramKey];\n set(result, path, tryCoerce(value, paramDef));\n } else {\n const path = rest;\n try {\n const obj = JSON.parse(value);\n if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {\n result[path] = merge(result[path] ?? {}, obj);\n }\n } catch {\n // ignore\n }\n }\n }\n return result;\n }\n\n /**\n * Resolve param value with priority: URL > test > override > remote > fallback\n */\n private resolve<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<TStores[K]['params'][P]['schema']>> {\n const { statsigStore, search, ...evaluationOptions } = options ?? {};\n const storeDef = this.definitions[storeKey];\n if (!storeDef) {\n throw new Error(`[ParamStore] Unknown store: ${String(storeKey)}`);\n }\n\n const def = storeDef.params[paramKey as string] as ParamDefinition;\n if (!def) {\n throw new Error(`[ParamStore] Unknown param: ${String(storeKey)}.${String(paramKey)}`);\n }\n\n const schema = def.schema;\n let value: unknown;\n let source: ParamState<unknown>['source'];\n\n // 1. URL has highest priority\n const urlOverrides = this.parseUrlOverrides(search);\n const urlVal = urlOverrides[storeKey as string]?.[paramKey as string];\n if (urlVal !== undefined) {\n value = urlVal;\n source = 'url';\n }\n // 2. Test environment override\n else if (isTestEnv() && def.testOverride !== undefined) {\n value = def.testOverride;\n source = 'test';\n }\n // 3. Static override\n else if (def.override !== undefined) {\n value = def.override;\n source = 'override';\n }\n // 4. Remote value from Statsig\n else {\n try {\n const clientStore = statsigStore ?? getStatsigClientSync().getParameterStore(storeKey as string, evaluationOptions);\n const config = (clientStore as any)?.__configuration?.[paramKey as string];\n if (config !== undefined) {\n value = clientStore.get(paramKey as string, def.fallback);\n source = 'remote';\n } else {\n value = def.fallback;\n source = 'fallback';\n }\n } catch {\n value = def.fallback;\n source = 'fallback';\n }\n }\n\n // Schema validation\n const parsed = schema.safeParse(value);\n if (!parsed.success) {\n console.error(`[ParamStore] Schema mismatch (${source}): ${String(storeKey)}.${String(paramKey)}`, value, parsed.error);\n dispatchSchemaMismatchEvent({\n storeKey: String(storeKey),\n paramKey: String(paramKey),\n source,\n value,\n error: parsed.error,\n });\n const fallbackVal = def.fallback;\n if (source === 'remote') {\n return { value: fallbackVal, source: 'fallback', error: parsed.error };\n }\n return { value: value as any, source, error: parsed.error, fallback: fallbackVal };\n }\n return { value: parsed.data, source };\n }\n\n /** Get param state with value and source info */\n getParamState<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<TStores[K]['params'][P]['schema']>> {\n return this.resolve(storeKey, paramKey, options);\n }\n\n /** Get param value directly */\n getParam<K extends keyof TStores, P extends keyof TStores[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): z.infer<TStores[K]['params'][P]['schema']> {\n return this.resolve(storeKey, paramKey, options).value;\n }\n\n /** Get store handle for multiple param access */\n getStore<K extends keyof TStores>(\n storeKey: K,\n options?: ParamResolveOptions,\n ): ParamStoreHandle<TStores[K]['params']> {\n const { statsigStore, ...rest } = options ?? {};\n let cachedStore: StatsigParameterStore | null | undefined = statsigStore;\n if (cachedStore === undefined) {\n try {\n cachedStore = getStatsigClientSync().getParameterStore(storeKey as string, rest);\n } catch {\n cachedStore = null;\n }\n }\n const opts: ParamResolveOptions = { ...rest, statsigStore: cachedStore };\n return {\n get: <P extends keyof TStores[K]['params']>(paramKey: P) => this.resolve(storeKey, paramKey, opts).value,\n getState: <P extends keyof TStores[K]['params']>(paramKey: P) => this.resolve(storeKey, paramKey, opts),\n };\n }\n}\n\n/**\n * Create a type-safe Param Store with React hooks.\n *\n * @example\n * ```ts\n * const MY_PARAMS = {\n * homepage_cta: {\n * description: 'Homepage CTA button',\n * params: {\n * text: defineParam({ schema: z.string(), fallback: 'Learn More' }),\n * color: defineParam({ schema: z.enum(['red', 'blue']), fallback: 'blue' }),\n * },\n * },\n * } as const satisfies Record<string, ParamStoreDefinition<any>>;\n *\n * export const { paramStore, useParam, useParamState } = createParamStore(MY_PARAMS);\n *\n * // Full type safety and autocomplete\n * const text = useParam('homepage_cta', 'text'); // string type\n * const color = useParam('homepage_cta', 'color'); // 'red' | 'blue' type\n * ```\n */\nexport function createParamStore<T extends Record<string, ParamStoreDefinition<any>>>(definitions: T) {\n const store = new ParamStore(definitions);\n\n type StoreKey = Extract<keyof T, string>;\n\n /**\n * React Hook: Get store handle for multiple param access.\n */\n function useParamStore<K extends StoreKey>(\n storeKey: K,\n options?: ParamResolveOptions,\n ): ParamStoreHandle<T[K]['params']> {\n const statsigStore = useParameterStore(storeKey, options);\n return store.getStore(storeKey, { ...options, statsigStore });\n }\n\n /**\n * React Hook: Get single param state.\n */\n function useParamState<K extends StoreKey, P extends keyof T[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): ParamState<z.infer<T[K]['params'][P]['schema']>> {\n const statsigStore = useParameterStore(storeKey, options);\n return store.getParamState(storeKey, paramKey, { ...options, statsigStore });\n }\n\n /**\n * React Hook: Get single param value.\n */\n function useParam<K extends StoreKey, P extends keyof T[K]['params']>(\n storeKey: K,\n paramKey: P,\n options?: ParamResolveOptions,\n ): z.infer<T[K]['params'][P]['schema']> {\n return useParamState(storeKey, paramKey, options).value;\n }\n\n return {\n /** ParamStore instance */\n paramStore: store,\n /** React Hook: Get single param value */\n useParam,\n /** React Hook: Get single param state */\n useParamState,\n /** React Hook: Get store handle */\n useParamStore,\n };\n}\n","/**\n * @lovart-open/flags/statsig\n *\n * Type-safe Feature Flag and Parameter Store management library.\n *\n * Feature flag priority: URL > testOverride > override > remote > fallback(false)\n * Parameter Store priority: URL > testOverride > override > remote > fallback\n */\n\n// Flag factory and types\nexport { createFlagStore, FlagStore, parseUrlOverrides, type ResolveOptions } from './flags';\n\n// Param factory and types\nexport {\n createParamStore,\n defineParam,\n PARAM_SCHEMA_MISMATCH_EVENT,\n type ParamSchemaMismatchDetail,\n parseParamStoreUrlOverrides,\n ParamStore,\n type ParamDefinition,\n type ParamResolveOptions,\n type ParamState,\n type ParamStoreDefinition,\n type ParamStoreHandle,\n type ParamStoreValue,\n} from './params';\n\n// Logger\nexport { getLogger, setLogger, type Logger } from './logger';\n\n// Statsig client\nexport {\n getStatsigClientSync,\n initStatsigClient,\n isTestEnv,\n type InitOptions,\n type StatsigBootstrap,\n} from './client';\n\n// Core types\nexport {\n type EvaluationOptions,\n type FeatureGate,\n type FlagDefinition,\n type FlagKeyOf,\n type FlagPriority,\n type FlagSnapshot,\n type FlagState,\n type RemoteFlagValues,\n} from './types';\n\n// Statsig React bindings (re-export)\nexport * from '@statsig/react-bindings';\n"],"mappings":"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","names":["isTestEnv","hasWindow"]}
|