flipflag-sdk 1.1.21 → 1.1.22
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/index.js +131 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -13
- package/dist/index.mjs.map +1 -1
- package/dist/js.js +141 -13
- package/dist/js.js.map +1 -1
- package/dist/js.mjs +141 -13
- package/dist/js.mjs.map +1 -1
- package/dist/next.js +133 -27
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +133 -27
- package/dist/next.mjs.map +1 -1
- package/dist/react-native.js +131 -13
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +131 -13
- package/dist/react-native.mjs.map +1 -1
- package/dist/react.js +206 -65
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +207 -66
- package/dist/react.mjs.map +1 -1
- package/dist/types/core/FlipFlagSDK.d.ts +17 -4
- package/dist/types/js/featureFlagManager.d.ts +4 -0
- package/dist/types/next/server-utils.d.ts +1 -1
- package/dist/types/next/types.d.ts +1 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/vue.js +131 -13
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +131 -13
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-native.mjs","sources":["../src/core/FlipFlagSDK.ts","../src/react-native/FeatureFlagProvider.tsx","../src/react-native/useFeatureFlag.ts","../src/react-native/useFeatureFlags.ts","../src/react-native/useABTest.ts","../src/react-native/identifyUser.ts","../src/react-native/offlineStorage.ts"],"sourcesContent":["import {\n FlipFlagConfig,\n FeatureFlagResponse,\n FeatureFlagsResponse,\n ABTestResponse,\n ABTestEventResponse,\n ABTestsResponse,\n FlipFlagError,\n CacheEntry,\n RetryOptions,\n SDKState,\n IdentifyUserOptions,\n} from \"../types\";\n\nexport class FlipFlagSDK {\n private config: FlipFlagConfig;\n private cache = new Map<string, CacheEntry<any>>();\n private defaultBaseUrl = \"https://app.flipflag.ru\";\n private pullIntervalId?: NodeJS.Timeout;\n private state: SDKState;\n private stateListeners: Set<(state: SDKState) => void> = new Set();\n\n constructor(config: FlipFlagConfig) {\n this.config = {\n baseUrl: this.defaultBaseUrl,\n cacheTimeout: 30000, // 30 seconds\n retryAttempts: 3,\n retryDelay: 1000, // 1 second\n pullInterval: 60000, // 1 minute\n ...config,\n };\n\n this.state = {\n flags: {},\n abTests: {},\n lastFetch: null,\n isLoading: false,\n error: null,\n };\n\n // Start automatic pulling if pullInterval is set\n if (this.config.pullInterval && this.config.pullInterval > 0) {\n this.startPulling();\n }\n }\n\n /**\n * Identify user for A/B testing and user-specific flags\n */\n identifyUser(options: IdentifyUserOptions): void {\n this.config.userId = options.userId;\n\n // Clear A/B test cache since user changed\n this.clearABTestCache();\n\n // If we have a user, we might want to refresh immediately\n if (this.config.pullInterval && this.config.pullInterval > 0) {\n this.pullData();\n }\n }\n\n /**\n * Get current SDK state\n */\n getState(): SDKState {\n return { ...this.state };\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(callback: (state: SDKState) => void): () => void {\n this.stateListeners.add(callback);\n\n // Return unsubscribe function\n return () => {\n this.stateListeners.delete(callback);\n };\n }\n\n /**\n * Get a feature flag value from current state\n */\n getFlagValue(flagName: string): boolean {\n return this.state.flags[flagName] ?? false;\n }\n\n /**\n * Get A/B test variant from current state\n */\n getABTestVariant(testName: string): ABTestResponse | null {\n return this.state.abTests[testName] || null;\n }\n\n /**\n * Start automatic data pulling\n */\n private startPulling(): void {\n if (this.pullIntervalId) {\n clearInterval(this.pullIntervalId);\n }\n\n this.pullIntervalId = setInterval(() => {\n this.pullData();\n }, this.config.pullInterval!);\n\n // Initial pull\n this.pullData();\n }\n\n /**\n * Stop automatic data pulling\n */\n stopPulling(): void {\n if (this.pullIntervalId) {\n clearInterval(this.pullIntervalId);\n this.pullIntervalId = undefined;\n }\n }\n\n /**\n * Pull fresh data from API\n */\n private async pullData(): Promise<void> {\n try {\n this.updateState({ isLoading: true, error: null });\n\n // Pull flags\n const flagsResponse = await this.fetchAllFlags();\n\n // Pull A/B tests if user is identified\n let abTestsResponse: ABTestsResponse | null = null;\n if (this.config.userId) {\n try {\n abTestsResponse = await this.fetchAllABTests();\n } catch (error) {\n console.warn(\"Failed to fetch A/B tests:\", error);\n }\n }\n\n const newState: Partial<SDKState> = {\n flags: flagsResponse?.flags || {},\n lastFetch: new Date(),\n isLoading: false,\n error: null,\n };\n\n if (abTestsResponse) {\n const abTestsMap: Record<string, ABTestResponse> = {};\n abTestsResponse.abTests.forEach((test) => {\n // For each test, get the variant for current user\n if (this.config.userId) {\n // This would normally fetch the variant, but for demo we'll simulate\n abTestsMap[test.name] = {\n testName: test.name,\n testId: test.id,\n variantId: \"variant_a\", // Default variant\n variant: test.variants[0] || {\n id: \"default\",\n name: \"Default\",\n value: null,\n weight: 100,\n },\n timestamp: new Date().toISOString(),\n };\n }\n });\n newState.abTests = abTestsMap;\n }\n\n this.updateState(newState);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n this.updateState({\n isLoading: false,\n error: errorMessage,\n });\n console.error(\"Failed to pull data:\", error);\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private updateState(newState: Partial<SDKState>): void {\n this.state = { ...this.state, ...newState };\n\n // Notify all listeners\n this.stateListeners.forEach((callback) => {\n try {\n callback(this.state);\n } catch (error) {\n console.error(\"State listener error:\", error);\n }\n });\n }\n\n /**\n * Fetch all flags from API\n */\n private async fetchAllFlags(): Promise<FeatureFlagsResponse | null> {\n try {\n const url = new URL(\n `/api/sdk/flags/${this.config.projectId}`,\n this.config.baseUrl\n );\n if (this.config.environment) {\n url.searchParams.set(\"environment\", this.config.environment);\n }\n\n return await this.makeRequest<FeatureFlagsResponse>(url.toString());\n } catch (error) {\n console.error(\"Failed to fetch flags:\", error);\n return null;\n }\n }\n\n /**\n * Fetch all A/B tests from API\n */\n private async fetchAllABTests(): Promise<ABTestsResponse | null> {\n try {\n const url = new URL(\n `/api/sdk/ab-tests/${this.config.projectId}`,\n this.config.baseUrl\n );\n if (this.config.environment) {\n url.searchParams.set(\"environment\", this.config.environment);\n }\n\n return await this.makeRequest<ABTestsResponse>(url.toString());\n } catch (error) {\n console.error(\"Failed to fetch A/B tests:\", error);\n return null;\n }\n }\n\n /**\n * Clear A/B test cache\n */\n private clearABTestCache(): void {\n const abTestKeys = Array.from(this.cache.keys()).filter((key) =>\n key.startsWith(\"abtest:\")\n );\n abTestKeys.forEach((key) => this.cache.delete(key));\n }\n\n /**\n * Get all feature flags for a project\n */\n async getFlags(\n projectId: string = this.config.projectId,\n environment?: string\n ): Promise<FeatureFlagsResponse> {\n const cacheKey = `flags:${projectId}:${environment || \"all\"}`;\n const cached = this.getFromCache<FeatureFlagsResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(`/api/sdk/flags/${projectId}`, this.config.baseUrl);\n if (environment || this.config.environment) {\n url.searchParams.set(\n \"environment\",\n environment || this.config.environment!\n );\n }\n\n const response = await this.makeRequest<FeatureFlagsResponse>(\n url.toString()\n );\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Get a specific feature flag value\n */\n async getFlag(\n flagName: string,\n projectId: string = this.config.projectId,\n environment?: string\n ): Promise<FeatureFlagResponse> {\n // If we have the flag in state, return it immediately\n if (this.state.flags[flagName] !== undefined) {\n return {\n projectId: this.config.projectId,\n flagName,\n environment: this.config.environment || \"all\",\n value: this.state.flags[flagName],\n timestamp:\n this.state.lastFetch?.toISOString() || new Date().toISOString(),\n };\n }\n\n // Check if we're currently loading data (pullData in progress)\n // In this case, wait a bit and check state again\n if (this.state.isLoading) {\n // Wait up to 5 seconds for loading to complete\n for (let i = 0; i < 50; i++) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n if (!this.state.isLoading && this.state.flags[flagName] !== undefined) {\n return {\n projectId: this.config.projectId,\n flagName,\n environment: this.config.environment || \"all\",\n value: this.state.flags[flagName],\n timestamp:\n this.state.lastFetch?.toISOString() || new Date().toISOString(),\n };\n }\n }\n }\n\n const cacheKey = `flag:${projectId}:${flagName}:${environment || \"all\"}`;\n const cached = this.getFromCache<FeatureFlagResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(\n `/api/sdk/flags/${projectId}/${flagName}`,\n this.config.baseUrl\n );\n if (environment || this.config.environment) {\n url.searchParams.set(\n \"environment\",\n environment || this.config.environment!\n );\n }\n\n const response = await this.makeRequest<FeatureFlagResponse>(\n url.toString()\n );\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Get A/B test variant for a user\n */\n async getAbTestVariant(\n testName: string,\n userId: string,\n projectId: string = this.config.projectId\n ): Promise<ABTestResponse> {\n // If we have the A/B test in state, return it immediately\n const stateVariant = this.state.abTests[testName];\n if (stateVariant && stateVariant.testName === testName) {\n return stateVariant;\n }\n\n const cacheKey = `abtest:${projectId}:${testName}:${userId}`;\n const cached = this.getFromCache<ABTestResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(\n `/api/sdk/ab-test/${projectId}/${testName}`,\n this.config.baseUrl\n );\n\n const response = await this.makeRequest<ABTestResponse>(url, {\n headers: {\n \"X-User-ID\": userId,\n },\n });\n\n // Cache A/B test variants for longer since they shouldn't change frequently for a user\n this.setCache(cacheKey, response, this.config.cacheTimeout! * 10);\n\n return response;\n }\n\n /**\n * Record an A/B test event\n */\n async recordAbTestEvent(\n testName: string,\n userId: string,\n event: string,\n variantId: string,\n eventData?: Record<string, any>,\n projectId: string = this.config.projectId\n ): Promise<ABTestEventResponse> {\n const url = new URL(\n `/api/sdk/ab-test/${projectId}/${testName}/event`,\n this.config.baseUrl\n );\n\n return this.makeRequest<ABTestEventResponse>(url, {\n method: \"POST\",\n headers: {\n \"X-User-ID\": userId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n event,\n variantId,\n eventData,\n }),\n });\n }\n\n /**\n * Get all A/B tests for a project\n */\n async getAbTests(\n projectId: string = this.config.projectId\n ): Promise<ABTestsResponse> {\n const cacheKey = `abtests:${projectId}`;\n const cached = this.getFromCache<ABTestsResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(`/api/sdk/ab-tests/${projectId}`, this.config.baseUrl);\n\n const response = await this.makeRequest<ABTestsResponse>(url);\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Clear cache for specific key or all cache\n */\n clearCache(key?: string): void {\n if (key) {\n this.cache.delete(key);\n } else {\n this.cache.clear();\n }\n }\n\n /**\n * Update configuration\n */\n updateConfig(newConfig: Partial<FlipFlagConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n private async makeRequest<T>(\n url: string | URL,\n options: RequestInit = {}\n ): Promise<T> {\n // Convert URL object to string if needed\n const urlString = url instanceof URL ? url.toString() : url;\n\n // If URL starts with '/', prepend baseUrl and handle trailing slashes\n const fullUrl = urlString.startsWith(\"/\")\n ? `${this.config.baseUrl?.replace(/\\/$/, \"\") || this.defaultBaseUrl}${urlString}`\n : urlString;\n\n const headers = {\n \"X-API-Key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n ...options.headers,\n };\n\n const requestOptions: RequestInit = {\n ...options,\n headers,\n };\n\n return this.makeRequestWithRetry<T>(fullUrl, requestOptions);\n }\n\n private async makeRequestWithRetry<T>(\n url: string,\n options: RequestInit,\n retryOptions: RetryOptions = {\n attempts: this.config.retryAttempts!,\n delay: this.config.retryDelay!,\n backoff: 2,\n }\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= retryOptions.attempts; attempt++) {\n try {\n const response = await fetch(url, options);\n if (!response.ok) {\n console.log(\"retry sdk\");\n const errorData = await response.json().catch(() => ({}));\n throw new Error(\n `HTTP ${response.status}: ${errorData.error || response.statusText}`\n );\n }\n\n return await response.json();\n } catch (error) {\n lastError = error as Error;\n\n // Don't retry on client errors (4xx) except 429 (rate limit)\n if (error instanceof Error && error.message.includes(\"HTTP 4\")) {\n if (!error.message.includes(\"HTTP 429\")) {\n throw error;\n }\n }\n\n if (attempt < retryOptions.attempts) {\n const delay =\n retryOptions.delay * Math.pow(retryOptions.backoff, attempt - 1);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError!;\n }\n\n private getFromCache<T>(key: string): T | null {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n if (Date.now() - entry.timestamp > entry.ttl) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.data;\n }\n\n private setCache<T>(key: string, data: T, ttl: number): void {\n this.cache.set(key, {\n data,\n timestamp: Date.now(),\n ttl,\n });\n }\n\n /**\n * Cleanup method - should be called when SDK is no longer needed\n */\n public destroy(): void {\n this.stopPulling();\n this.stateListeners.clear();\n this.cache.clear();\n }\n}\n","import React, { createContext, useContext, ReactNode } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig } from \"../types\";\n\ninterface FeatureFlagContextValue {\n sdk: FlipFlagSDK;\n config: FlipFlagConfig;\n}\n\nconst FeatureFlagContext = createContext<FeatureFlagContextValue | null>(null);\n\ninterface FeatureFlagProviderProps {\n children: ReactNode;\n config: FlipFlagConfig;\n}\n\nexport function FeatureFlagProvider({\n children,\n config,\n}: FeatureFlagProviderProps) {\n const sdk = new FlipFlagSDK(config);\n\n const contextValue: FeatureFlagContextValue = {\n sdk,\n config,\n };\n\n return (\n <FeatureFlagContext.Provider value={contextValue}>\n {children}\n </FeatureFlagContext.Provider>\n );\n}\n\nexport function useFeatureFlagContext(): FeatureFlagContextValue {\n const context = useContext(FeatureFlagContext);\n\n if (!context) {\n throw new Error(\n \"useFeatureFlagContext must be used within a FeatureFlagProvider\"\n );\n }\n\n return context;\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FeatureFlagValue, FlipFlagConfig } from \"../types\";\nimport { FeatureFlagHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseFeatureFlagOptions {\n fallbackValue?: FeatureFlagValue;\n enabled?: boolean;\n}\n\nexport function useFeatureFlag(\n flagName: string,\n options: UseFeatureFlagOptions & { config?: FlipFlagConfig } = {}\n): FeatureFlagHookResult {\n const [value, setValue] = useState<FeatureFlagValue>(\n options.fallbackValue ?? false\n );\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useFeatureFlag must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const flagValue = sdk.getFlagValue(flagName);\n setValue(flagValue);\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n if (options.fallbackValue !== undefined) {\n setValue(options.fallbackValue);\n }\n setLoading(false);\n }\n }, [sdk, flagName, options.fallbackValue, options.enabled]);\n\n const refetch = useCallback(async () => {\n sdk.clearCache(\n `flag:${sdk[\"config\"].projectId}:${flagName}:${sdk[\"config\"].environment || \"all\"}`\n );\n setLoading(true);\n\n try {\n const response = await sdk.getFlag(flagName);\n setValue(response.value);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n if (options.fallbackValue !== undefined) {\n setValue(options.fallbackValue);\n }\n } finally {\n setLoading(false);\n }\n }, [sdk, flagName, options.fallbackValue]);\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const flagValue = state.flags[flagName];\n if (flagValue !== undefined) {\n setValue(flagValue);\n setLoading(false);\n setError(state.error);\n }\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n value,\n loading,\n error,\n refetch,\n };\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FeatureFlagValue, FlipFlagConfig } from \"../types\";\nimport { FeatureFlagsHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseFeatureFlagsOptions {\n fallbackValues?: Record<string, FeatureFlagValue>;\n enabled?: boolean;\n}\n\nexport function useFeatureFlags(\n flagNames: string[],\n options: UseFeatureFlagsOptions & { config?: FlipFlagConfig } = {}\n): FeatureFlagsHookResult {\n const [flags, setFlags] = useState<Record<string, FeatureFlagValue>>(() => {\n // Initialize with fallback values\n const initialFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n initialFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n return initialFlags;\n });\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useFeatureFlags must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const newFlags: Record<string, FeatureFlagValue> = { ...flags };\n let hasChanges = false;\n\n flagNames.forEach((flagName) => {\n const flagValue = sdk.getFlagValue(flagName);\n if (newFlags[flagName] !== flagValue) {\n newFlags[flagName] = flagValue;\n hasChanges = true;\n }\n });\n\n if (hasChanges) {\n setFlags(newFlags);\n }\n\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n // Use fallback values\n const fallbackFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n fallbackFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n setFlags(fallbackFlags);\n setLoading(false);\n }\n }, [sdk, flagNames, options.fallbackValues, options.enabled, flags]);\n\n const refetch = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n try {\n // Force refresh by triggering pull\n await Promise.all(\n flagNames.map((flagName) =>\n sdk.getFlag(flagName).catch(() => {\n // Ignore individual flag errors, will use state values\n })\n )\n );\n\n updateFromState();\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n // Use fallback values\n const fallbackFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n fallbackFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n setFlags(fallbackFlags);\n setLoading(false);\n }\n }, [sdk, flagNames, options.fallbackValues, updateFromState]);\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const newFlags: Record<string, FeatureFlagValue> = { ...flags };\n let hasChanges = false;\n\n flagNames.forEach((flagName) => {\n const flagValue = state.flags[flagName];\n if (flagValue !== undefined && newFlags[flagName] !== flagValue) {\n newFlags[flagName] = flagValue;\n hasChanges = true;\n }\n });\n\n if (hasChanges) {\n setFlags(newFlags);\n }\n\n setLoading(false);\n setError(state.error);\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n flags,\n loading,\n error,\n refetch,\n };\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { ABTestValue, FlipFlagConfig } from \"../types\";\nimport { ABTestHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseABTestOptions {\n userId: string;\n enabled?: boolean;\n}\n\nexport function useABTest(\n testName: string,\n options: UseABTestOptions & { config?: FlipFlagConfig }\n): ABTestHookResult {\n const [variant, setVariant] = useState<ABTestValue | null>(null);\n const [variantId, setVariantId] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useABTest must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const abTestVariant = sdk.getABTestVariant(testName);\n if (abTestVariant) {\n setVariant(abTestVariant.variant.value);\n setVariantId(abTestVariant.variantId);\n } else {\n setVariant(null);\n setVariantId(null);\n }\n\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n setVariant(null);\n setVariantId(null);\n setLoading(false);\n }\n }, [sdk, testName, options.enabled]);\n\n const recordEvent = useCallback(\n async (event: string, eventData?: Record<string, any>) => {\n if (!variantId) {\n console.warn(\"Cannot record event: no variant assigned yet\");\n return;\n }\n\n try {\n await sdk.recordAbTestEvent(\n testName,\n options.userId,\n event,\n variantId,\n eventData\n );\n } catch (err) {\n console.error(\"Failed to record A/B test event:\", err);\n }\n },\n [sdk, testName, options.userId, variantId]\n );\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const abTestVariant = state.abTests[testName];\n if (abTestVariant) {\n setVariant(abTestVariant.variant.value);\n setVariantId(abTestVariant.variantId);\n } else {\n setVariant(null);\n setVariantId(null);\n }\n\n setLoading(false);\n setError(state.error);\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n variant,\n variantId,\n loading,\n error,\n recordEvent,\n };\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n * Must be called within FeatureFlagProvider\n */\nexport function identifyUser(options: IdentifyUserOptions): void {\n const context = useFeatureFlagContext();\n context.sdk.identifyUser(options);\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport { OfflineStorage } from \"./types\";\n\n/**\n * Create offline storage using AsyncStorage\n */\nexport function createOfflineStorage(): OfflineStorage {\n return {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch (error) {\n console.error(\"AsyncStorage getItem error:\", error);\n return null;\n }\n },\n\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch (error) {\n console.error(\"AsyncStorage setItem error:\", error);\n }\n },\n\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch (error) {\n console.error(\"AsyncStorage removeItem error:\", error);\n }\n },\n };\n}\n\n/**\n * Create offline storage with custom storage implementation\n */\nexport function createCustomOfflineStorage(\n storage: OfflineStorage\n): OfflineStorage {\n return storage;\n}\n"],"names":["_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react-native.mjs","sources":["../src/core/FlipFlagSDK.ts","../src/react-native/FeatureFlagProvider.tsx","../src/react-native/useFeatureFlag.ts","../src/react-native/useFeatureFlags.ts","../src/react-native/useABTest.ts","../src/react-native/identifyUser.ts","../src/react-native/offlineStorage.ts"],"sourcesContent":["import {\n FlipFlagConfig,\n FeatureFlagResponse,\n FeatureFlagsResponse,\n ABTestResponse,\n ABTestEventResponse,\n ABTestsResponse,\n FlipFlagError,\n CacheEntry,\n RetryOptions,\n SDKState,\n IdentifyUserOptions,\n} from \"../types\";\n\nexport class FlipFlagSDK {\n private config: FlipFlagConfig;\n private cache = new Map<string, CacheEntry<any>>();\n private defaultBaseUrl = \"https://app.flipflag.ru\";\n private pullIntervalId?: NodeJS.Timeout;\n private state: SDKState;\n private stateListeners: Set<(state: SDKState) => void> = new Set();\n private maxListeners = 100; // Maximum number of listeners to prevent memory leaks\n\n constructor(config: FlipFlagConfig) {\n // Validate required configuration\n this.validateConfig(config);\n\n this.config = {\n baseUrl: this.defaultBaseUrl,\n cacheTimeout: 30000, // 30 seconds\n retryAttempts: 3,\n retryDelay: 1000, // 1 second\n pullInterval: 60000, // 1 minute\n ...config,\n };\n\n this.state = {\n flags: {},\n abTests: {},\n lastFetch: null,\n isLoading: false,\n error: null,\n };\n\n // Start automatic pulling if pullInterval is set\n if (this.config.pullInterval && this.config.pullInterval > 0) {\n this.startPulling();\n }\n }\n\n /**\n * Identify user for A/B testing and user-specific flags\n */\n identifyUser(options: IdentifyUserOptions): void {\n if (!options || typeof options !== \"object\") {\n throw new Error(\"options must be an object\");\n }\n\n if (!options.userId || typeof options.userId !== \"string\") {\n throw new Error(\"userId is required and must be a string\");\n }\n\n if (options.userProperties && typeof options.userProperties !== \"object\") {\n throw new Error(\"userProperties must be an object\");\n }\n\n this.config.userId = options.userId;\n\n // Clear A/B test cache since user changed\n this.clearABTestCache();\n\n // If we have a user, we might want to refresh immediately\n if (this.config.pullInterval && this.config.pullInterval > 0) {\n this.pullData();\n }\n }\n\n /**\n * Get current SDK state\n */\n getState(): SDKState {\n return { ...this.state };\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(callback: (state: SDKState) => void): () => void {\n if (this.stateListeners.size >= this.maxListeners) {\n console.warn(\n `Maximum number of listeners (${this.maxListeners}) reached. This may cause memory leaks.`\n );\n }\n\n this.stateListeners.add(callback);\n\n // Return unsubscribe function\n return () => {\n this.stateListeners.delete(callback);\n };\n }\n\n /**\n * Get a feature flag value from current state\n */\n getFlagValue(flagName: string): boolean {\n return this.state.flags[flagName] ?? false;\n }\n\n /**\n * Get A/B test variant from current state\n */\n getABTestVariant(testName: string): ABTestResponse | null {\n return this.state.abTests[testName] || null;\n }\n\n /**\n * Start automatic data pulling\n */\n private startPulling(): void {\n if (this.pullIntervalId) {\n clearInterval(this.pullIntervalId);\n }\n\n this.pullIntervalId = setInterval(() => {\n this.pullData();\n }, this.config.pullInterval!);\n\n // Initial pull\n this.pullData();\n }\n\n /**\n * Stop automatic data pulling\n */\n stopPulling(): void {\n if (this.pullIntervalId) {\n clearInterval(this.pullIntervalId);\n this.pullIntervalId = undefined;\n }\n }\n\n /**\n * Pull fresh data from API\n */\n private async pullData(): Promise<void> {\n try {\n this.updateState({ isLoading: true, error: null });\n\n // Pull flags\n const flagsResponse = await this.fetchAllFlags();\n\n // Pull A/B tests if user is identified\n let abTestsResponse: ABTestsResponse | null = null;\n if (this.config.userId) {\n try {\n abTestsResponse = await this.fetchAllABTests();\n } catch (error) {\n console.warn(\"Failed to fetch A/B tests:\", error);\n }\n }\n\n const newState: Partial<SDKState> = {\n flags: flagsResponse?.flags || {},\n lastFetch: new Date(),\n isLoading: false,\n error: null,\n };\n\n if (abTestsResponse) {\n const abTestsMap: Record<string, ABTestResponse> = {};\n abTestsResponse.abTests.forEach((test) => {\n // For each test, get the variant for current user\n if (this.config.userId) {\n // This would normally fetch the variant, but for demo we'll simulate\n abTestsMap[test.name] = {\n testName: test.name,\n testId: test.id,\n variantId: \"variant_a\", // Default variant\n variant: test.variants[0] || {\n id: \"default\",\n name: \"Default\",\n value: null,\n weight: 100,\n },\n timestamp: new Date().toISOString(),\n };\n }\n });\n newState.abTests = abTestsMap;\n }\n\n this.updateState(newState);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error\";\n this.updateState({\n isLoading: false,\n error: errorMessage,\n });\n console.error(\"Failed to pull data:\", error);\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private updateState(newState: Partial<SDKState>): void {\n this.state = { ...this.state, ...newState };\n\n // Notify all listeners\n this.stateListeners.forEach((callback) => {\n try {\n callback(this.state);\n } catch (error) {\n console.error(\"State listener error:\", error);\n // Remove faulty listener to prevent repeated errors\n this.stateListeners.delete(callback);\n }\n });\n }\n\n /**\n * Fetch all flags from API\n */\n private async fetchAllFlags(): Promise<FeatureFlagsResponse | null> {\n try {\n const url = new URL(\n `/api/sdk/flags/${this.config.projectId}`,\n this.config.baseUrl\n );\n if (this.config.environment) {\n url.searchParams.set(\"environment\", this.config.environment);\n }\n\n return await this.makeRequest<FeatureFlagsResponse>(url.toString());\n } catch (error) {\n console.error(\"Failed to fetch flags:\", error);\n return null;\n }\n }\n\n /**\n * Fetch all A/B tests from API\n */\n private async fetchAllABTests(): Promise<ABTestsResponse | null> {\n try {\n const url = new URL(\n `/api/sdk/ab-tests/${this.config.projectId}`,\n this.config.baseUrl\n );\n if (this.config.environment) {\n url.searchParams.set(\"environment\", this.config.environment);\n }\n\n return await this.makeRequest<ABTestsResponse>(url.toString());\n } catch (error) {\n console.error(\"Failed to fetch A/B tests:\", error);\n return null;\n }\n }\n\n /**\n * Clear A/B test cache\n */\n private clearABTestCache(): void {\n const abTestKeys = Array.from(this.cache.keys()).filter((key) =>\n key.startsWith(\"abtest:\")\n );\n abTestKeys.forEach((key) => this.cache.delete(key));\n }\n\n /**\n * Get all feature flags for a project\n */\n async getFlags(\n projectId: string = this.config.projectId,\n environment?: string\n ): Promise<FeatureFlagsResponse> {\n const cacheKey = `flags:${projectId}:${environment || \"all\"}`;\n const cached = this.getFromCache<FeatureFlagsResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(`/api/sdk/flags/${projectId}`, this.config.baseUrl);\n if (environment || this.config.environment) {\n url.searchParams.set(\n \"environment\",\n environment || this.config.environment!\n );\n }\n\n const response = await this.makeRequest<FeatureFlagsResponse>(\n url.toString()\n );\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Get a specific feature flag value\n */\n async getFlag(\n flagName: string,\n projectId: string = this.config.projectId,\n environment?: string\n ): Promise<FeatureFlagResponse> {\n if (!flagName || typeof flagName !== \"string\") {\n throw new Error(\"flagName is required and must be a string\");\n }\n\n if (!projectId || typeof projectId !== \"string\") {\n throw new Error(\"projectId must be a string\");\n }\n\n if (environment && typeof environment !== \"string\") {\n throw new Error(\"environment must be a string\");\n }\n // If we have the flag in state, return it immediately\n if (this.state.flags[flagName] !== undefined) {\n return {\n projectId: this.config.projectId,\n flagName,\n environment: this.config.environment || \"all\",\n value: this.state.flags[flagName],\n timestamp:\n this.state.lastFetch?.toISOString() || new Date().toISOString(),\n };\n }\n\n // Check if we're currently loading data (pullData in progress)\n // In this case, wait for loading to complete using Promise\n if (this.state.isLoading) {\n await this.waitForLoadingComplete();\n // After waiting, check state again\n if (this.state.flags[flagName] !== undefined) {\n return {\n projectId: this.config.projectId,\n flagName,\n environment: this.config.environment || \"all\",\n value: this.state.flags[flagName],\n timestamp:\n this.state.lastFetch?.toISOString() || new Date().toISOString(),\n };\n }\n }\n\n const cacheKey = `flag:${projectId}:${flagName}:${environment || \"all\"}`;\n const cached = this.getFromCache<FeatureFlagResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(\n `/api/sdk/flags/${projectId}/${flagName}`,\n this.config.baseUrl\n );\n if (environment || this.config.environment) {\n url.searchParams.set(\n \"environment\",\n environment || this.config.environment!\n );\n }\n\n const response = await this.makeRequest<FeatureFlagResponse>(\n url.toString()\n );\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Validate configuration\n */\n private validateConfig(config: FlipFlagConfig): void {\n if (!config.apiKey || typeof config.apiKey !== \"string\") {\n throw new Error(\"apiKey is required and must be a string\");\n }\n\n if (!config.projectId || typeof config.projectId !== \"string\") {\n throw new Error(\"projectId is required and must be a string\");\n }\n\n if (config.baseUrl && typeof config.baseUrl !== \"string\") {\n throw new Error(\"baseUrl must be a string\");\n }\n\n if (config.environment && typeof config.environment !== \"string\") {\n throw new Error(\"environment must be a string\");\n }\n\n if (config.userId && typeof config.userId !== \"string\") {\n throw new Error(\"userId must be a string\");\n }\n\n if (\n config.cacheTimeout &&\n (typeof config.cacheTimeout !== \"number\" || config.cacheTimeout < 0)\n ) {\n throw new Error(\"cacheTimeout must be a non-negative number\");\n }\n\n if (\n config.retryAttempts &&\n (typeof config.retryAttempts !== \"number\" || config.retryAttempts < 0)\n ) {\n throw new Error(\"retryAttempts must be a non-negative number\");\n }\n\n if (\n config.retryDelay &&\n (typeof config.retryDelay !== \"number\" || config.retryDelay < 0)\n ) {\n throw new Error(\"retryDelay must be a non-negative number\");\n }\n\n if (\n config.pullInterval &&\n (typeof config.pullInterval !== \"number\" || config.pullInterval < 0)\n ) {\n throw new Error(\"pullInterval must be a non-negative number\");\n }\n }\n\n /**\n * Wait for loading to complete with timeout\n */\n private async waitForLoadingComplete(timeout: number = 5000): Promise<void> {\n const startTime = Date.now();\n\n return new Promise((resolve, reject) => {\n const checkLoading = () => {\n if (!this.state.isLoading) {\n resolve();\n return;\n }\n\n if (Date.now() - startTime > timeout) {\n reject(new Error(\"Timeout waiting for SDK loading to complete\"));\n return;\n }\n\n // Check again after a short delay\n setTimeout(checkLoading, 50);\n };\n\n checkLoading();\n });\n }\n\n /**\n * Get A/B test variant for a user\n */\n async getAbTestVariant(\n testName: string,\n userId: string,\n projectId: string = this.config.projectId\n ): Promise<ABTestResponse> {\n if (!testName || typeof testName !== \"string\") {\n throw new Error(\"testName is required and must be a string\");\n }\n\n if (!userId || typeof userId !== \"string\") {\n throw new Error(\"userId is required and must be a string\");\n }\n\n if (!projectId || typeof projectId !== \"string\") {\n throw new Error(\"projectId must be a string\");\n }\n // If we have the A/B test in state, return it immediately\n const stateVariant = this.state.abTests[testName];\n if (stateVariant && stateVariant.testName === testName) {\n return stateVariant;\n }\n\n const cacheKey = `abtest:${projectId}:${testName}:${userId}`;\n const cached = this.getFromCache<ABTestResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(\n `/api/sdk/ab-test/${projectId}/${testName}`,\n this.config.baseUrl\n );\n\n const response = await this.makeRequest<ABTestResponse>(url, {\n headers: {\n \"X-User-ID\": userId,\n },\n });\n\n // Cache A/B test variants for longer since they shouldn't change frequently for a user\n this.setCache(cacheKey, response, this.config.cacheTimeout! * 10);\n\n return response;\n }\n\n /**\n * Record an A/B test event\n */\n async recordAbTestEvent(\n testName: string,\n userId: string,\n event: string,\n variantId: string,\n eventData?: Record<string, any>,\n projectId: string = this.config.projectId\n ): Promise<ABTestEventResponse> {\n const url = new URL(\n `/api/sdk/ab-test/${projectId}/${testName}/event`,\n this.config.baseUrl\n );\n\n return this.makeRequest<ABTestEventResponse>(url, {\n method: \"POST\",\n headers: {\n \"X-User-ID\": userId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n event,\n variantId,\n eventData,\n }),\n });\n }\n\n /**\n * Get all A/B tests for a project\n */\n async getAbTests(\n projectId: string = this.config.projectId\n ): Promise<ABTestsResponse> {\n const cacheKey = `abtests:${projectId}`;\n const cached = this.getFromCache<ABTestsResponse>(cacheKey);\n\n if (cached) {\n return cached;\n }\n\n const url = new URL(`/api/sdk/ab-tests/${projectId}`, this.config.baseUrl);\n\n const response = await this.makeRequest<ABTestsResponse>(url);\n this.setCache(cacheKey, response, this.config.cacheTimeout!);\n\n return response;\n }\n\n /**\n * Clear cache for specific key or all cache\n */\n clearCache(key?: string): void {\n if (key) {\n this.cache.delete(key);\n } else {\n this.cache.clear();\n }\n }\n\n /**\n * Clear cache for specific flag\n */\n clearFlagCache(flagName: string, environment?: string): void {\n const cacheKey = `flag:${this.config.projectId}:${flagName}:${environment || \"all\"}`;\n this.cache.delete(cacheKey);\n }\n\n /**\n * Clear cache for all flags\n */\n clearFlagsCache(environment?: string): void {\n const cacheKey = `flags:${this.config.projectId}:${environment || \"all\"}`;\n this.cache.delete(cacheKey);\n }\n\n /**\n * Clear cache for A/B test variant\n */\n clearABTestCache(testName?: string, userId?: string): void {\n if (testName && userId) {\n const cacheKey = `abtest:${this.config.projectId}:${testName}:${userId}`;\n this.cache.delete(cacheKey);\n } else {\n // Clear all A/B test cache\n const abTestKeys = Array.from(this.cache.keys()).filter((key) =>\n key.startsWith(\"abtest:\")\n );\n abTestKeys.forEach((key) => this.cache.delete(key));\n }\n }\n\n /**\n * Update configuration\n */\n updateConfig(newConfig: Partial<FlipFlagConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n private async makeRequest<T>(\n url: string | URL,\n options: RequestInit = {}\n ): Promise<T> {\n // Convert URL object to string if needed\n const urlString = url instanceof URL ? url.toString() : url;\n\n // If URL starts with '/', prepend baseUrl and handle trailing slashes\n const fullUrl = urlString.startsWith(\"/\")\n ? `${this.config.baseUrl?.replace(/\\/$/, \"\") || this.defaultBaseUrl}${urlString}`\n : urlString;\n\n const headers = {\n \"X-API-Key\": this.config.apiKey,\n \"Content-Type\": \"application/json\",\n ...options.headers,\n };\n\n const requestOptions: RequestInit = {\n ...options,\n headers,\n };\n\n return this.makeRequestWithRetry<T>(fullUrl, requestOptions);\n }\n\n private async makeRequestWithRetry<T>(\n url: string,\n options: RequestInit,\n retryOptions: RetryOptions = {\n attempts: this.config.retryAttempts!,\n delay: this.config.retryDelay!,\n backoff: 2,\n }\n ): Promise<T> {\n let lastError: Error;\n\n for (let attempt = 1; attempt <= retryOptions.attempts; attempt++) {\n try {\n const response = await fetch(url, options);\n if (!response.ok) {\n console.log(\"retry sdk\");\n const errorData = await response.json().catch(() => ({}));\n throw new Error(\n `HTTP ${response.status}: ${errorData.error || response.statusText}`\n );\n }\n\n return await response.json();\n } catch (error) {\n lastError = error as Error;\n\n // Don't retry on client errors (4xx) except 429 (rate limit)\n if (error instanceof Error && error.message.includes(\"HTTP 4\")) {\n if (!error.message.includes(\"HTTP 429\")) {\n throw error;\n }\n }\n\n if (attempt < retryOptions.attempts) {\n const delay =\n retryOptions.delay * Math.pow(retryOptions.backoff, attempt - 1);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError!;\n }\n\n private getFromCache<T>(key: string): T | null {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n if (Date.now() - entry.timestamp > entry.ttl) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.data;\n }\n\n private setCache<T>(key: string, data: T, ttl: number): void {\n this.cache.set(key, {\n data,\n timestamp: Date.now(),\n ttl,\n });\n }\n\n /**\n * Cleanup method - should be called when SDK is no longer needed\n */\n public destroy(): void {\n this.stopPulling();\n this.stateListeners.clear();\n this.cache.clear();\n }\n}\n","import React, { createContext, useContext, ReactNode } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig } from \"../types\";\n\ninterface FeatureFlagContextValue {\n sdk: FlipFlagSDK;\n config: FlipFlagConfig;\n}\n\nconst FeatureFlagContext = createContext<FeatureFlagContextValue | null>(null);\n\ninterface FeatureFlagProviderProps {\n children: ReactNode;\n config: FlipFlagConfig;\n}\n\nexport function FeatureFlagProvider({\n children,\n config,\n}: FeatureFlagProviderProps) {\n const sdk = new FlipFlagSDK(config);\n\n const contextValue: FeatureFlagContextValue = {\n sdk,\n config,\n };\n\n return (\n <FeatureFlagContext.Provider value={contextValue}>\n {children}\n </FeatureFlagContext.Provider>\n );\n}\n\nexport function useFeatureFlagContext(): FeatureFlagContextValue {\n const context = useContext(FeatureFlagContext);\n\n if (!context) {\n throw new Error(\n \"useFeatureFlagContext must be used within a FeatureFlagProvider\"\n );\n }\n\n return context;\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FeatureFlagValue, FlipFlagConfig } from \"../types\";\nimport { FeatureFlagHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseFeatureFlagOptions {\n fallbackValue?: FeatureFlagValue;\n enabled?: boolean;\n}\n\nexport function useFeatureFlag(\n flagName: string,\n options: UseFeatureFlagOptions & { config?: FlipFlagConfig } = {}\n): FeatureFlagHookResult {\n const [value, setValue] = useState<FeatureFlagValue>(\n options.fallbackValue ?? false\n );\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useFeatureFlag must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const flagValue = sdk.getFlagValue(flagName);\n setValue(flagValue);\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n if (options.fallbackValue !== undefined) {\n setValue(options.fallbackValue);\n }\n setLoading(false);\n }\n }, [sdk, flagName, options.fallbackValue, options.enabled]);\n\n const refetch = useCallback(async () => {\n sdk.clearCache(\n `flag:${sdk[\"config\"].projectId}:${flagName}:${sdk[\"config\"].environment || \"all\"}`\n );\n setLoading(true);\n\n try {\n const response = await sdk.getFlag(flagName);\n setValue(response.value);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n if (options.fallbackValue !== undefined) {\n setValue(options.fallbackValue);\n }\n } finally {\n setLoading(false);\n }\n }, [sdk, flagName, options.fallbackValue]);\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const flagValue = state.flags[flagName];\n if (flagValue !== undefined) {\n setValue(flagValue);\n setLoading(false);\n setError(state.error);\n }\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n value,\n loading,\n error,\n refetch,\n };\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FeatureFlagValue, FlipFlagConfig } from \"../types\";\nimport { FeatureFlagsHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseFeatureFlagsOptions {\n fallbackValues?: Record<string, FeatureFlagValue>;\n enabled?: boolean;\n}\n\nexport function useFeatureFlags(\n flagNames: string[],\n options: UseFeatureFlagsOptions & { config?: FlipFlagConfig } = {}\n): FeatureFlagsHookResult {\n const [flags, setFlags] = useState<Record<string, FeatureFlagValue>>(() => {\n // Initialize with fallback values\n const initialFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n initialFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n return initialFlags;\n });\n\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useFeatureFlags must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const newFlags: Record<string, FeatureFlagValue> = { ...flags };\n let hasChanges = false;\n\n flagNames.forEach((flagName) => {\n const flagValue = sdk.getFlagValue(flagName);\n if (newFlags[flagName] !== flagValue) {\n newFlags[flagName] = flagValue;\n hasChanges = true;\n }\n });\n\n if (hasChanges) {\n setFlags(newFlags);\n }\n\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n // Use fallback values\n const fallbackFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n fallbackFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n setFlags(fallbackFlags);\n setLoading(false);\n }\n }, [sdk, flagNames, options.fallbackValues, options.enabled, flags]);\n\n const refetch = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n try {\n // Force refresh by triggering pull\n await Promise.all(\n flagNames.map((flagName) =>\n sdk.getFlag(flagName).catch(() => {\n // Ignore individual flag errors, will use state values\n })\n )\n );\n\n updateFromState();\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n\n // Use fallback values\n const fallbackFlags: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n fallbackFlags[flagName] = options.fallbackValues?.[flagName] ?? false;\n });\n setFlags(fallbackFlags);\n setLoading(false);\n }\n }, [sdk, flagNames, options.fallbackValues, updateFromState]);\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const newFlags: Record<string, FeatureFlagValue> = { ...flags };\n let hasChanges = false;\n\n flagNames.forEach((flagName) => {\n const flagValue = state.flags[flagName];\n if (flagValue !== undefined && newFlags[flagName] !== flagValue) {\n newFlags[flagName] = flagValue;\n hasChanges = true;\n }\n });\n\n if (hasChanges) {\n setFlags(newFlags);\n }\n\n setLoading(false);\n setError(state.error);\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n flags,\n loading,\n error,\n refetch,\n };\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { ABTestValue, FlipFlagConfig } from \"../types\";\nimport { ABTestHookResult } from \"./types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\ninterface UseABTestOptions {\n userId: string;\n enabled?: boolean;\n}\n\nexport function useABTest(\n testName: string,\n options: UseABTestOptions & { config?: FlipFlagConfig }\n): ABTestHookResult {\n const [variant, setVariant] = useState<ABTestValue | null>(null);\n const [variantId, setVariantId] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // Try to get SDK from context, otherwise create new instance\n let sdk: FlipFlagSDK;\n try {\n const context = useFeatureFlagContext();\n sdk = context.sdk;\n } catch {\n if (!options.config) {\n throw new Error(\n \"useABTest must be used within FeatureFlagProvider or config must be provided\"\n );\n }\n sdk = new FlipFlagSDK(options.config);\n }\n\n const updateFromState = useCallback(() => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n try {\n const abTestVariant = sdk.getABTestVariant(testName);\n if (abTestVariant) {\n setVariant(abTestVariant.variant.value);\n setVariantId(abTestVariant.variantId);\n } else {\n setVariant(null);\n setVariantId(null);\n }\n\n setLoading(false);\n setError(null);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Unknown error\";\n setError(errorMessage);\n setVariant(null);\n setVariantId(null);\n setLoading(false);\n }\n }, [sdk, testName, options.enabled]);\n\n const recordEvent = useCallback(\n async (event: string, eventData?: Record<string, any>) => {\n if (!variantId) {\n console.warn(\"Cannot record event: no variant assigned yet\");\n return;\n }\n\n try {\n await sdk.recordAbTestEvent(\n testName,\n options.userId,\n event,\n variantId,\n eventData\n );\n } catch (err) {\n console.error(\"Failed to record A/B test event:\", err);\n }\n },\n [sdk, testName, options.userId, variantId]\n );\n\n useEffect(() => {\n // Subscribe to state changes\n const unsubscribe = sdk.subscribe((state) => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n const abTestVariant = state.abTests[testName];\n if (abTestVariant) {\n setVariant(abTestVariant.variant.value);\n setVariantId(abTestVariant.variantId);\n } else {\n setVariant(null);\n setVariantId(null);\n }\n\n setLoading(false);\n setError(state.error);\n });\n\n // Initial update from current state\n updateFromState();\n\n return unsubscribe;\n }, [updateFromState, options.enabled]);\n\n return {\n variant,\n variantId,\n loading,\n error,\n recordEvent,\n };\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { useFeatureFlagContext } from \"./FeatureFlagProvider\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n * Must be called within FeatureFlagProvider\n */\nexport function identifyUser(options: IdentifyUserOptions): void {\n const context = useFeatureFlagContext();\n context.sdk.identifyUser(options);\n}\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport { OfflineStorage } from \"./types\";\n\n/**\n * Create offline storage using AsyncStorage\n */\nexport function createOfflineStorage(): OfflineStorage {\n return {\n async getItem(key: string): Promise<string | null> {\n try {\n return await AsyncStorage.getItem(key);\n } catch (error) {\n console.error(\"AsyncStorage getItem error:\", error);\n return null;\n }\n },\n\n async setItem(key: string, value: string): Promise<void> {\n try {\n await AsyncStorage.setItem(key, value);\n } catch (error) {\n console.error(\"AsyncStorage setItem error:\", error);\n }\n },\n\n async removeItem(key: string): Promise<void> {\n try {\n await AsyncStorage.removeItem(key);\n } catch (error) {\n console.error(\"AsyncStorage removeItem error:\", error);\n }\n },\n };\n}\n\n/**\n * Create offline storage with custom storage implementation\n */\nexport function createCustomOfflineStorage(\n storage: OfflineStorage\n): OfflineStorage {\n return storage;\n}\n"],"names":["_jsx"],"mappings":"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"}
|
package/dist/react.js
CHANGED
|
@@ -8,6 +8,9 @@ class FlipFlagSDK {
|
|
|
8
8
|
this.cache = new Map();
|
|
9
9
|
this.defaultBaseUrl = "https://app.flipflag.ru";
|
|
10
10
|
this.stateListeners = new Set();
|
|
11
|
+
this.maxListeners = 100; // Maximum number of listeners to prevent memory leaks
|
|
12
|
+
// Validate required configuration
|
|
13
|
+
this.validateConfig(config);
|
|
11
14
|
this.config = {
|
|
12
15
|
baseUrl: this.defaultBaseUrl,
|
|
13
16
|
cacheTimeout: 30000, // 30 seconds
|
|
@@ -32,6 +35,15 @@ class FlipFlagSDK {
|
|
|
32
35
|
* Identify user for A/B testing and user-specific flags
|
|
33
36
|
*/
|
|
34
37
|
identifyUser(options) {
|
|
38
|
+
if (!options || typeof options !== "object") {
|
|
39
|
+
throw new Error("options must be an object");
|
|
40
|
+
}
|
|
41
|
+
if (!options.userId || typeof options.userId !== "string") {
|
|
42
|
+
throw new Error("userId is required and must be a string");
|
|
43
|
+
}
|
|
44
|
+
if (options.userProperties && typeof options.userProperties !== "object") {
|
|
45
|
+
throw new Error("userProperties must be an object");
|
|
46
|
+
}
|
|
35
47
|
this.config.userId = options.userId;
|
|
36
48
|
// Clear A/B test cache since user changed
|
|
37
49
|
this.clearABTestCache();
|
|
@@ -50,6 +62,9 @@ class FlipFlagSDK {
|
|
|
50
62
|
* Subscribe to state changes
|
|
51
63
|
*/
|
|
52
64
|
subscribe(callback) {
|
|
65
|
+
if (this.stateListeners.size >= this.maxListeners) {
|
|
66
|
+
console.warn(`Maximum number of listeners (${this.maxListeners}) reached. This may cause memory leaks.`);
|
|
67
|
+
}
|
|
53
68
|
this.stateListeners.add(callback);
|
|
54
69
|
// Return unsubscribe function
|
|
55
70
|
return () => {
|
|
@@ -160,6 +175,8 @@ class FlipFlagSDK {
|
|
|
160
175
|
}
|
|
161
176
|
catch (error) {
|
|
162
177
|
console.error("State listener error:", error);
|
|
178
|
+
// Remove faulty listener to prevent repeated errors
|
|
179
|
+
this.stateListeners.delete(callback);
|
|
163
180
|
}
|
|
164
181
|
});
|
|
165
182
|
}
|
|
@@ -224,6 +241,15 @@ class FlipFlagSDK {
|
|
|
224
241
|
*/
|
|
225
242
|
async getFlag(flagName, projectId = this.config.projectId, environment) {
|
|
226
243
|
var _a, _b;
|
|
244
|
+
if (!flagName || typeof flagName !== "string") {
|
|
245
|
+
throw new Error("flagName is required and must be a string");
|
|
246
|
+
}
|
|
247
|
+
if (!projectId || typeof projectId !== "string") {
|
|
248
|
+
throw new Error("projectId must be a string");
|
|
249
|
+
}
|
|
250
|
+
if (environment && typeof environment !== "string") {
|
|
251
|
+
throw new Error("environment must be a string");
|
|
252
|
+
}
|
|
227
253
|
// If we have the flag in state, return it immediately
|
|
228
254
|
if (this.state.flags[flagName] !== undefined) {
|
|
229
255
|
return {
|
|
@@ -235,20 +261,18 @@ class FlipFlagSDK {
|
|
|
235
261
|
};
|
|
236
262
|
}
|
|
237
263
|
// Check if we're currently loading data (pullData in progress)
|
|
238
|
-
// In this case, wait
|
|
264
|
+
// In this case, wait for loading to complete using Promise
|
|
239
265
|
if (this.state.isLoading) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
};
|
|
251
|
-
}
|
|
266
|
+
await this.waitForLoadingComplete();
|
|
267
|
+
// After waiting, check state again
|
|
268
|
+
if (this.state.flags[flagName] !== undefined) {
|
|
269
|
+
return {
|
|
270
|
+
projectId: this.config.projectId,
|
|
271
|
+
flagName,
|
|
272
|
+
environment: this.config.environment || "all",
|
|
273
|
+
value: this.state.flags[flagName],
|
|
274
|
+
timestamp: ((_b = this.state.lastFetch) === null || _b === void 0 ? void 0 : _b.toISOString()) || new Date().toISOString(),
|
|
275
|
+
};
|
|
252
276
|
}
|
|
253
277
|
}
|
|
254
278
|
const cacheKey = `flag:${projectId}:${flagName}:${environment || "all"}`;
|
|
@@ -264,10 +288,76 @@ class FlipFlagSDK {
|
|
|
264
288
|
this.setCache(cacheKey, response, this.config.cacheTimeout);
|
|
265
289
|
return response;
|
|
266
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Validate configuration
|
|
293
|
+
*/
|
|
294
|
+
validateConfig(config) {
|
|
295
|
+
if (!config.apiKey || typeof config.apiKey !== "string") {
|
|
296
|
+
throw new Error("apiKey is required and must be a string");
|
|
297
|
+
}
|
|
298
|
+
if (!config.projectId || typeof config.projectId !== "string") {
|
|
299
|
+
throw new Error("projectId is required and must be a string");
|
|
300
|
+
}
|
|
301
|
+
if (config.baseUrl && typeof config.baseUrl !== "string") {
|
|
302
|
+
throw new Error("baseUrl must be a string");
|
|
303
|
+
}
|
|
304
|
+
if (config.environment && typeof config.environment !== "string") {
|
|
305
|
+
throw new Error("environment must be a string");
|
|
306
|
+
}
|
|
307
|
+
if (config.userId && typeof config.userId !== "string") {
|
|
308
|
+
throw new Error("userId must be a string");
|
|
309
|
+
}
|
|
310
|
+
if (config.cacheTimeout &&
|
|
311
|
+
(typeof config.cacheTimeout !== "number" || config.cacheTimeout < 0)) {
|
|
312
|
+
throw new Error("cacheTimeout must be a non-negative number");
|
|
313
|
+
}
|
|
314
|
+
if (config.retryAttempts &&
|
|
315
|
+
(typeof config.retryAttempts !== "number" || config.retryAttempts < 0)) {
|
|
316
|
+
throw new Error("retryAttempts must be a non-negative number");
|
|
317
|
+
}
|
|
318
|
+
if (config.retryDelay &&
|
|
319
|
+
(typeof config.retryDelay !== "number" || config.retryDelay < 0)) {
|
|
320
|
+
throw new Error("retryDelay must be a non-negative number");
|
|
321
|
+
}
|
|
322
|
+
if (config.pullInterval &&
|
|
323
|
+
(typeof config.pullInterval !== "number" || config.pullInterval < 0)) {
|
|
324
|
+
throw new Error("pullInterval must be a non-negative number");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Wait for loading to complete with timeout
|
|
329
|
+
*/
|
|
330
|
+
async waitForLoadingComplete(timeout = 5000) {
|
|
331
|
+
const startTime = Date.now();
|
|
332
|
+
return new Promise((resolve, reject) => {
|
|
333
|
+
const checkLoading = () => {
|
|
334
|
+
if (!this.state.isLoading) {
|
|
335
|
+
resolve();
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (Date.now() - startTime > timeout) {
|
|
339
|
+
reject(new Error("Timeout waiting for SDK loading to complete"));
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
// Check again after a short delay
|
|
343
|
+
setTimeout(checkLoading, 50);
|
|
344
|
+
};
|
|
345
|
+
checkLoading();
|
|
346
|
+
});
|
|
347
|
+
}
|
|
267
348
|
/**
|
|
268
349
|
* Get A/B test variant for a user
|
|
269
350
|
*/
|
|
270
351
|
async getAbTestVariant(testName, userId, projectId = this.config.projectId) {
|
|
352
|
+
if (!testName || typeof testName !== "string") {
|
|
353
|
+
throw new Error("testName is required and must be a string");
|
|
354
|
+
}
|
|
355
|
+
if (!userId || typeof userId !== "string") {
|
|
356
|
+
throw new Error("userId is required and must be a string");
|
|
357
|
+
}
|
|
358
|
+
if (!projectId || typeof projectId !== "string") {
|
|
359
|
+
throw new Error("projectId must be a string");
|
|
360
|
+
}
|
|
271
361
|
// If we have the A/B test in state, return it immediately
|
|
272
362
|
const stateVariant = this.state.abTests[testName];
|
|
273
363
|
if (stateVariant && stateVariant.testName === testName) {
|
|
@@ -331,6 +421,34 @@ class FlipFlagSDK {
|
|
|
331
421
|
this.cache.clear();
|
|
332
422
|
}
|
|
333
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* Clear cache for specific flag
|
|
426
|
+
*/
|
|
427
|
+
clearFlagCache(flagName, environment) {
|
|
428
|
+
const cacheKey = `flag:${this.config.projectId}:${flagName}:${environment || "all"}`;
|
|
429
|
+
this.cache.delete(cacheKey);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Clear cache for all flags
|
|
433
|
+
*/
|
|
434
|
+
clearFlagsCache(environment) {
|
|
435
|
+
const cacheKey = `flags:${this.config.projectId}:${environment || "all"}`;
|
|
436
|
+
this.cache.delete(cacheKey);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Clear cache for A/B test variant
|
|
440
|
+
*/
|
|
441
|
+
clearABTestCache(testName, userId) {
|
|
442
|
+
if (testName && userId) {
|
|
443
|
+
const cacheKey = `abtest:${this.config.projectId}:${testName}:${userId}`;
|
|
444
|
+
this.cache.delete(cacheKey);
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
// Clear all A/B test cache
|
|
448
|
+
const abTestKeys = Array.from(this.cache.keys()).filter((key) => key.startsWith("abtest:"));
|
|
449
|
+
abTestKeys.forEach((key) => this.cache.delete(key));
|
|
450
|
+
}
|
|
451
|
+
}
|
|
334
452
|
/**
|
|
335
453
|
* Update configuration
|
|
336
454
|
*/
|
|
@@ -439,17 +557,18 @@ function useFeatureFlag(flagName, options = {}) {
|
|
|
439
557
|
const [loading, setLoading] = react.useState(true);
|
|
440
558
|
const [error, setError] = react.useState(null);
|
|
441
559
|
// Try to get SDK from context, otherwise create new instance
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
catch (_b) {
|
|
448
|
-
if (!options.config) {
|
|
449
|
-
throw new Error("useFeatureFlag must be used within FeatureFlagProvider or config must be provided");
|
|
560
|
+
const sdk = react.useMemo(() => {
|
|
561
|
+
try {
|
|
562
|
+
const context = useFeatureFlagContext();
|
|
563
|
+
return context.sdk;
|
|
450
564
|
}
|
|
451
|
-
|
|
452
|
-
|
|
565
|
+
catch (_a) {
|
|
566
|
+
if (!options.config) {
|
|
567
|
+
throw new Error("useFeatureFlag must be used within FeatureFlagProvider or config must be provided");
|
|
568
|
+
}
|
|
569
|
+
return new FlipFlagSDK(options.config);
|
|
570
|
+
}
|
|
571
|
+
}, [options.config]);
|
|
453
572
|
const updateFromState = react.useCallback(() => {
|
|
454
573
|
if (!options.enabled && options.enabled !== undefined) {
|
|
455
574
|
return;
|
|
@@ -526,6 +645,27 @@ function useFeatureFlag(flagName, options = {}) {
|
|
|
526
645
|
};
|
|
527
646
|
}
|
|
528
647
|
|
|
648
|
+
/**
|
|
649
|
+
* Wait for SDK loading to complete with timeout
|
|
650
|
+
*/
|
|
651
|
+
function waitForSDKLoading(sdk, timeout = 5000) {
|
|
652
|
+
const startTime = Date.now();
|
|
653
|
+
return new Promise((resolve, reject) => {
|
|
654
|
+
const checkLoading = () => {
|
|
655
|
+
if (!sdk.getState().isLoading) {
|
|
656
|
+
resolve();
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (Date.now() - startTime > timeout) {
|
|
660
|
+
reject(new Error("Timeout waiting for SDK loading to complete"));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
// Check again after a short delay
|
|
664
|
+
setTimeout(checkLoading, 50);
|
|
665
|
+
};
|
|
666
|
+
checkLoading();
|
|
667
|
+
});
|
|
668
|
+
}
|
|
529
669
|
function useFeatureFlags(flagNames, options = {}) {
|
|
530
670
|
const [flags, setFlags] = react.useState(() => {
|
|
531
671
|
// Initialize with fallback values
|
|
@@ -540,17 +680,18 @@ function useFeatureFlags(flagNames, options = {}) {
|
|
|
540
680
|
const [error, setError] = react.useState(null);
|
|
541
681
|
const [isInitialized, setIsInitialized] = react.useState(false);
|
|
542
682
|
// Try to get SDK from context, otherwise create new instance
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
catch (_a) {
|
|
549
|
-
if (!options.config) {
|
|
550
|
-
throw new Error("useFeatureFlags must be used within FeatureFlagProvider or config must be provided");
|
|
683
|
+
const sdk = react.useMemo(() => {
|
|
684
|
+
try {
|
|
685
|
+
const context = useFeatureFlagContext();
|
|
686
|
+
return context.sdk;
|
|
551
687
|
}
|
|
552
|
-
|
|
553
|
-
|
|
688
|
+
catch (_a) {
|
|
689
|
+
if (!options.config) {
|
|
690
|
+
throw new Error("useFeatureFlags must be used within FeatureFlagProvider or config must be provided");
|
|
691
|
+
}
|
|
692
|
+
return new FlipFlagSDK(options.config);
|
|
693
|
+
}
|
|
694
|
+
}, [options.config]);
|
|
554
695
|
const fetchFlags = react.useCallback(async () => {
|
|
555
696
|
if (!options.enabled && options.enabled !== undefined) {
|
|
556
697
|
return;
|
|
@@ -582,30 +723,29 @@ function useFeatureFlags(flagNames, options = {}) {
|
|
|
582
723
|
}
|
|
583
724
|
// If SDK is currently loading, wait for it to complete
|
|
584
725
|
if (sdk.getState().isLoading) {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const stateValue = sdk.getFlagValue(flagName);
|
|
595
|
-
if (stateValue !== undefined) {
|
|
596
|
-
updatedStateFlags[flagName] = stateValue;
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
updatedHasAllFlags = false;
|
|
600
|
-
}
|
|
601
|
-
});
|
|
602
|
-
if (updatedHasAllFlags) {
|
|
603
|
-
setFlags(updatedStateFlags);
|
|
604
|
-
setLoading(false);
|
|
605
|
-
return;
|
|
726
|
+
try {
|
|
727
|
+
await waitForSDKLoading(sdk);
|
|
728
|
+
// Check again if we now have all flags
|
|
729
|
+
const updatedStateFlags = {};
|
|
730
|
+
let updatedHasAllFlags = true;
|
|
731
|
+
flagNames.forEach((flagName) => {
|
|
732
|
+
const stateValue = sdk.getFlagValue(flagName);
|
|
733
|
+
if (stateValue !== undefined) {
|
|
734
|
+
updatedStateFlags[flagName] = stateValue;
|
|
606
735
|
}
|
|
736
|
+
else {
|
|
737
|
+
updatedHasAllFlags = false;
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
if (updatedHasAllFlags) {
|
|
741
|
+
setFlags(updatedStateFlags);
|
|
742
|
+
setLoading(false);
|
|
743
|
+
return;
|
|
607
744
|
}
|
|
608
745
|
}
|
|
746
|
+
catch (error) {
|
|
747
|
+
console.warn("Timeout waiting for SDK loading, proceeding with API call");
|
|
748
|
+
}
|
|
609
749
|
}
|
|
610
750
|
// If we still don't have all flags, make HTTP request
|
|
611
751
|
const response = await sdk.getFlags();
|
|
@@ -648,7 +788,7 @@ function useFeatureFlags(flagNames, options = {}) {
|
|
|
648
788
|
}, [sdk, fetchFlags]);
|
|
649
789
|
react.useEffect(() => {
|
|
650
790
|
fetchFlags();
|
|
651
|
-
}, []); //
|
|
791
|
+
}, [fetchFlags]); // Include fetchFlags dependency
|
|
652
792
|
// Subscribe to state changes for automatic updates
|
|
653
793
|
react.useEffect(() => {
|
|
654
794
|
const unsubscribe = sdk.subscribe((state) => {
|
|
@@ -689,17 +829,18 @@ function useABTest(testName, options) {
|
|
|
689
829
|
const [loading, setLoading] = react.useState(true);
|
|
690
830
|
const [error, setError] = react.useState(null);
|
|
691
831
|
// Try to get SDK from context, otherwise create new instance
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}
|
|
697
|
-
catch (_a) {
|
|
698
|
-
if (!options.config) {
|
|
699
|
-
throw new Error("useABTest must be used within FeatureFlagProvider or config must be provided");
|
|
832
|
+
const sdk = react.useMemo(() => {
|
|
833
|
+
try {
|
|
834
|
+
const context = useFeatureFlagContext();
|
|
835
|
+
return context.sdk;
|
|
700
836
|
}
|
|
701
|
-
|
|
702
|
-
|
|
837
|
+
catch (_a) {
|
|
838
|
+
if (!options.config) {
|
|
839
|
+
throw new Error("useABTest must be used within FeatureFlagProvider or config must be provided");
|
|
840
|
+
}
|
|
841
|
+
return new FlipFlagSDK(options.config);
|
|
842
|
+
}
|
|
843
|
+
}, [options.config]);
|
|
703
844
|
const fetchVariant = react.useCallback(async () => {
|
|
704
845
|
if (!options.enabled && options.enabled !== undefined) {
|
|
705
846
|
return;
|