flipflag-sdk 1.1.1 → 1.1.3
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/README.md +1 -27
- package/dist/index.js +31 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -12
- package/dist/index.mjs.map +1 -1
- package/dist/js.js +31 -12
- package/dist/js.js.map +1 -1
- package/dist/js.mjs +31 -12
- package/dist/js.mjs.map +1 -1
- package/dist/next.js +31 -12
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +31 -12
- package/dist/next.mjs.map +1 -1
- package/dist/react-native.js +31 -12
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +31 -12
- package/dist/react-native.mjs.map +1 -1
- package/dist/react.js +120 -12
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +120 -12
- package/dist/react.mjs.map +1 -1
- package/dist/vue.js +31 -12
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +31 -12
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/js.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
class FlipFlagSDK {
|
|
4
4
|
constructor(config) {
|
|
5
5
|
this.cache = new Map();
|
|
6
|
-
this.defaultBaseUrl = "https://app.flipflag.ru
|
|
6
|
+
this.defaultBaseUrl = "https://app.flipflag.ru";
|
|
7
7
|
this.stateListeners = new Set();
|
|
8
8
|
this.config = {
|
|
9
9
|
baseUrl: this.defaultBaseUrl,
|
|
@@ -165,7 +165,7 @@ class FlipFlagSDK {
|
|
|
165
165
|
*/
|
|
166
166
|
async fetchAllFlags() {
|
|
167
167
|
try {
|
|
168
|
-
return await this.makeRequest(`/sdk/flags/${this.config.projectId}`);
|
|
168
|
+
return await this.makeRequest(`/api/sdk/flags/${this.config.projectId}`);
|
|
169
169
|
}
|
|
170
170
|
catch (error) {
|
|
171
171
|
console.error("Failed to fetch flags:", error);
|
|
@@ -177,7 +177,7 @@ class FlipFlagSDK {
|
|
|
177
177
|
*/
|
|
178
178
|
async fetchAllABTests() {
|
|
179
179
|
try {
|
|
180
|
-
return await this.makeRequest(`/sdk/ab-tests/${this.config.projectId}`);
|
|
180
|
+
return await this.makeRequest(`/api/sdk/ab-tests/${this.config.projectId}`);
|
|
181
181
|
}
|
|
182
182
|
catch (error) {
|
|
183
183
|
console.error("Failed to fetch A/B tests:", error);
|
|
@@ -200,7 +200,7 @@ class FlipFlagSDK {
|
|
|
200
200
|
if (cached) {
|
|
201
201
|
return cached;
|
|
202
202
|
}
|
|
203
|
-
const url = new URL(`/sdk/flags/${projectId}`, this.config.baseUrl);
|
|
203
|
+
const url = new URL(`/api/sdk/flags/${projectId}`, this.config.baseUrl);
|
|
204
204
|
if (environment || this.config.environment) {
|
|
205
205
|
url.searchParams.set("environment", environment || this.config.environment);
|
|
206
206
|
}
|
|
@@ -212,7 +212,7 @@ class FlipFlagSDK {
|
|
|
212
212
|
* Get a specific feature flag value
|
|
213
213
|
*/
|
|
214
214
|
async getFlag(flagName, projectId = this.config.projectId, environment) {
|
|
215
|
-
var _a;
|
|
215
|
+
var _a, _b;
|
|
216
216
|
// If we have the flag in state, return it immediately
|
|
217
217
|
if (this.state.flags[flagName] !== undefined) {
|
|
218
218
|
return {
|
|
@@ -223,12 +223,29 @@ class FlipFlagSDK {
|
|
|
223
223
|
timestamp: ((_a = this.state.lastFetch) === null || _a === void 0 ? void 0 : _a.toISOString()) || new Date().toISOString(),
|
|
224
224
|
};
|
|
225
225
|
}
|
|
226
|
+
// Check if we're currently loading data (pullData in progress)
|
|
227
|
+
// In this case, wait a bit and check state again
|
|
228
|
+
if (this.state.isLoading) {
|
|
229
|
+
// Wait up to 5 seconds for loading to complete
|
|
230
|
+
for (let i = 0; i < 50; i++) {
|
|
231
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
232
|
+
if (!this.state.isLoading && this.state.flags[flagName] !== undefined) {
|
|
233
|
+
return {
|
|
234
|
+
projectId: this.config.projectId,
|
|
235
|
+
flagName,
|
|
236
|
+
environment: this.config.environment || "all",
|
|
237
|
+
value: this.state.flags[flagName],
|
|
238
|
+
timestamp: ((_b = this.state.lastFetch) === null || _b === void 0 ? void 0 : _b.toISOString()) || new Date().toISOString(),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
226
243
|
const cacheKey = `flag:${projectId}:${flagName}:${environment || "all"}`;
|
|
227
244
|
const cached = this.getFromCache(cacheKey);
|
|
228
245
|
if (cached) {
|
|
229
246
|
return cached;
|
|
230
247
|
}
|
|
231
|
-
const url = new URL(`/sdk/flags/${projectId}/${flagName}`, this.config.baseUrl);
|
|
248
|
+
const url = new URL(`/api/sdk/flags/${projectId}/${flagName}`, this.config.baseUrl);
|
|
232
249
|
if (environment || this.config.environment) {
|
|
233
250
|
url.searchParams.set("environment", environment || this.config.environment);
|
|
234
251
|
}
|
|
@@ -250,7 +267,7 @@ class FlipFlagSDK {
|
|
|
250
267
|
if (cached) {
|
|
251
268
|
return cached;
|
|
252
269
|
}
|
|
253
|
-
const url =
|
|
270
|
+
const url = new URL(`/api/sdk/ab-test/${projectId}/${testName}`, this.config.baseUrl);
|
|
254
271
|
const response = await this.makeRequest(url, {
|
|
255
272
|
headers: {
|
|
256
273
|
"X-User-ID": userId,
|
|
@@ -264,7 +281,7 @@ class FlipFlagSDK {
|
|
|
264
281
|
* Record an A/B test event
|
|
265
282
|
*/
|
|
266
283
|
async recordAbTestEvent(testName, userId, event, variantId, eventData, projectId = this.config.projectId) {
|
|
267
|
-
const url =
|
|
284
|
+
const url = new URL(`/api/sdk/ab-test/${projectId}/${testName}/event`, this.config.baseUrl);
|
|
268
285
|
return this.makeRequest(url, {
|
|
269
286
|
method: "POST",
|
|
270
287
|
headers: {
|
|
@@ -287,7 +304,7 @@ class FlipFlagSDK {
|
|
|
287
304
|
if (cached) {
|
|
288
305
|
return cached;
|
|
289
306
|
}
|
|
290
|
-
const url =
|
|
307
|
+
const url = new URL(`/api/sdk/ab-tests/${projectId}`, this.config.baseUrl);
|
|
291
308
|
const response = await this.makeRequest(url);
|
|
292
309
|
this.setCache(cacheKey, response, this.config.cacheTimeout);
|
|
293
310
|
return response;
|
|
@@ -311,10 +328,12 @@ class FlipFlagSDK {
|
|
|
311
328
|
}
|
|
312
329
|
async makeRequest(url, options = {}) {
|
|
313
330
|
var _a;
|
|
331
|
+
// Convert URL object to string if needed
|
|
332
|
+
const urlString = url instanceof URL ? url.toString() : url;
|
|
314
333
|
// If URL starts with '/', prepend baseUrl and handle trailing slashes
|
|
315
|
-
const fullUrl =
|
|
316
|
-
? `${((_a = this.config.baseUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, "")) || this.defaultBaseUrl}${
|
|
317
|
-
:
|
|
334
|
+
const fullUrl = urlString.startsWith("/")
|
|
335
|
+
? `${((_a = this.config.baseUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, "")) || this.defaultBaseUrl}${urlString}`
|
|
336
|
+
: urlString;
|
|
318
337
|
const headers = {
|
|
319
338
|
"X-API-Key": this.config.apiKey,
|
|
320
339
|
"Content-Type": "application/json",
|
package/dist/js.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js.js","sources":["../src/core/FlipFlagSDK.ts","../src/js/featureFlagManager.ts","../src/js/identifyUser.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/api\";\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 return await this.makeRequest<FeatureFlagsResponse>(\n `/sdk/flags/${this.config.projectId}`\n );\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 return await this.makeRequest<ABTestsResponse>(\n `/sdk/ab-tests/${this.config.projectId}`\n );\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(`/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 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 `/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 = `${this.config.baseUrl}/sdk/ab-test/${projectId}/${testName}`;\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 = `${this.config.baseUrl}/sdk/ab-test/${projectId}/${testName}/event`;\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 = `${this.config.baseUrl}/sdk/ab-tests/${projectId}`;\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,\n options: RequestInit = {}\n ): Promise<T> {\n // If URL starts with '/', prepend baseUrl and handle trailing slashes\n const fullUrl = url.startsWith(\"/\")\n ? `${this.config.baseUrl?.replace(/\\/$/, \"\") || this.defaultBaseUrl}${url}`\n : url;\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\n if (!response.ok) {\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 { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig, FeatureFlagValue, ABTestValue } from \"../types\";\n\ninterface FeatureFlagManagerOptions {\n config: FlipFlagConfig;\n autoRefresh?: boolean;\n refreshInterval?: number;\n}\n\nexport class FeatureFlagManager {\n private sdk: FlipFlagSDK;\n private flags: Map<string, FeatureFlagValue> = new Map();\n private abTests: Map<string, { variant: ABTestValue; variantId: string }> =\n new Map();\n private listeners: Map<string, Set<(value: any) => void>> = new Map();\n private refreshTimer?: NodeJS.Timeout;\n\n constructor(options: FeatureFlagManagerOptions) {\n this.sdk = new FlipFlagSDK(options.config);\n\n if (options.autoRefresh) {\n this.startAutoRefresh(options.refreshInterval || 30000);\n }\n }\n\n /**\n * Get a feature flag value\n */\n async getFlag(flagName: string): Promise<FeatureFlagValue> {\n try {\n const response = await this.sdk.getFlag(flagName);\n const value = response.value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n return value;\n } catch (error) {\n console.error(`Failed to get flag ${flagName}:`, error);\n return this.flags.get(flagName) ?? false;\n }\n }\n\n /**\n * Get multiple feature flags\n */\n async getFlags(\n flagNames: string[]\n ): Promise<Record<string, FeatureFlagValue>> {\n try {\n const response = await this.sdk.getFlags();\n const result: Record<string, FeatureFlagValue> = {};\n\n flagNames.forEach((flagName) => {\n const value = response.flags[flagName] ?? false;\n result[flagName] = value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n });\n\n return result;\n } catch (error) {\n console.error(\"Failed to get flags:\", error);\n const result: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n result[flagName] = this.flags.get(flagName) ?? false;\n });\n return result;\n }\n }\n\n /**\n * Get A/B test variant\n */\n async getABTestVariant(\n testName: string,\n userId: string\n ): Promise<{ variant: ABTestValue; variantId: string }> {\n try {\n const response = await this.sdk.getAbTestVariant(testName, userId);\n const result = {\n variant: response.variant.value,\n variantId: response.variantId,\n };\n this.abTests.set(`${testName}:${userId}`, result);\n this.notifyListeners(`${testName}:${userId}`, result);\n return result;\n } catch (error) {\n console.error(`Failed to get A/B test variant for ${testName}:`, error);\n return (\n this.abTests.get(`${testName}:${userId}`) ?? {\n variant: null,\n variantId: \"\",\n }\n );\n }\n }\n\n /**\n * Record A/B test event\n */\n async recordABTestEvent(\n testName: string,\n userId: string,\n event: string,\n eventData?: Record<string, any>\n ): Promise<void> {\n const testKey = `${testName}:${userId}`;\n const testData = this.abTests.get(testKey);\n\n if (!testData) {\n console.warn(`No A/B test data found for ${testKey}`);\n return;\n }\n\n try {\n await this.sdk.recordAbTestEvent(\n testName,\n userId,\n event,\n testData.variantId,\n eventData\n );\n } catch (error) {\n console.error(`Failed to record A/B test event for ${testName}:`, error);\n }\n }\n\n /**\n * Subscribe to flag changes\n */\n onFlagChange(\n flagName: string,\n callback: (value: FeatureFlagValue) => void\n ): () => void {\n if (!this.listeners.has(flagName)) {\n this.listeners.set(flagName, new Set());\n }\n this.listeners.get(flagName)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n const listeners = this.listeners.get(flagName);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.listeners.delete(flagName);\n }\n }\n };\n }\n\n /**\n * Get cached flag value\n */\n getCachedFlag(flagName: string): FeatureFlagValue | undefined {\n return this.flags.get(flagName);\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.sdk.clearCache();\n this.flags.clear();\n this.abTests.clear();\n }\n\n /**\n * Start auto-refresh\n */\n private startAutoRefresh(interval: number): void {\n this.refreshTimer = setInterval(async () => {\n try {\n // Refresh all cached flags\n for (const [flagName] of this.flags) {\n await this.getFlag(flagName);\n }\n } catch (error) {\n console.error(\"Auto-refresh failed:\", error);\n }\n }, interval);\n }\n\n /**\n * Stop auto-refresh\n */\n stopAutoRefresh(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n private notifyListeners(key: string, value: any): void {\n const listeners = this.listeners.get(key);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(value);\n } catch (error) {\n console.error(\"Flag change listener error:\", error);\n }\n });\n }\n }\n}\n\n/**\n * Create a feature flag manager instance\n */\nexport function createFeatureFlagManager(\n options: FeatureFlagManagerOptions\n): FeatureFlagManager {\n return new FeatureFlagManager(options);\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n */\nexport function identifyUser(\n sdk: FlipFlagSDK,\n options: IdentifyUserOptions\n): void {\n sdk.identifyUser(options);\n}\n\n/**\n * Global identifyUser function that works with the default SDK instance\n * Note: This requires a global SDK instance to be set up\n */\nexport function identifyUserGlobal(options: IdentifyUserOptions): void {\n // This would need to be implemented with a global registry\n // For now, throw an error\n throw new Error(\n \"Global identifyUser requires a global SDK instance. Use identifyUser(sdk, options) instead.\"\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"js.js","sources":["../src/core/FlipFlagSDK.ts","../src/js/featureFlagManager.ts","../src/js/identifyUser.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 return await this.makeRequest<FeatureFlagsResponse>(\n `/api/sdk/flags/${this.config.projectId}`\n );\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 return await this.makeRequest<ABTestsResponse>(\n `/api/sdk/ab-tests/${this.config.projectId}`\n );\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\n if (!response.ok) {\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 { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig, FeatureFlagValue, ABTestValue } from \"../types\";\n\ninterface FeatureFlagManagerOptions {\n config: FlipFlagConfig;\n autoRefresh?: boolean;\n refreshInterval?: number;\n}\n\nexport class FeatureFlagManager {\n private sdk: FlipFlagSDK;\n private flags: Map<string, FeatureFlagValue> = new Map();\n private abTests: Map<string, { variant: ABTestValue; variantId: string }> =\n new Map();\n private listeners: Map<string, Set<(value: any) => void>> = new Map();\n private refreshTimer?: NodeJS.Timeout;\n\n constructor(options: FeatureFlagManagerOptions) {\n this.sdk = new FlipFlagSDK(options.config);\n\n if (options.autoRefresh) {\n this.startAutoRefresh(options.refreshInterval || 30000);\n }\n }\n\n /**\n * Get a feature flag value\n */\n async getFlag(flagName: string): Promise<FeatureFlagValue> {\n try {\n const response = await this.sdk.getFlag(flagName);\n const value = response.value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n return value;\n } catch (error) {\n console.error(`Failed to get flag ${flagName}:`, error);\n return this.flags.get(flagName) ?? false;\n }\n }\n\n /**\n * Get multiple feature flags\n */\n async getFlags(\n flagNames: string[]\n ): Promise<Record<string, FeatureFlagValue>> {\n try {\n const response = await this.sdk.getFlags();\n const result: Record<string, FeatureFlagValue> = {};\n\n flagNames.forEach((flagName) => {\n const value = response.flags[flagName] ?? false;\n result[flagName] = value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n });\n\n return result;\n } catch (error) {\n console.error(\"Failed to get flags:\", error);\n const result: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n result[flagName] = this.flags.get(flagName) ?? false;\n });\n return result;\n }\n }\n\n /**\n * Get A/B test variant\n */\n async getABTestVariant(\n testName: string,\n userId: string\n ): Promise<{ variant: ABTestValue; variantId: string }> {\n try {\n const response = await this.sdk.getAbTestVariant(testName, userId);\n const result = {\n variant: response.variant.value,\n variantId: response.variantId,\n };\n this.abTests.set(`${testName}:${userId}`, result);\n this.notifyListeners(`${testName}:${userId}`, result);\n return result;\n } catch (error) {\n console.error(`Failed to get A/B test variant for ${testName}:`, error);\n return (\n this.abTests.get(`${testName}:${userId}`) ?? {\n variant: null,\n variantId: \"\",\n }\n );\n }\n }\n\n /**\n * Record A/B test event\n */\n async recordABTestEvent(\n testName: string,\n userId: string,\n event: string,\n eventData?: Record<string, any>\n ): Promise<void> {\n const testKey = `${testName}:${userId}`;\n const testData = this.abTests.get(testKey);\n\n if (!testData) {\n console.warn(`No A/B test data found for ${testKey}`);\n return;\n }\n\n try {\n await this.sdk.recordAbTestEvent(\n testName,\n userId,\n event,\n testData.variantId,\n eventData\n );\n } catch (error) {\n console.error(`Failed to record A/B test event for ${testName}:`, error);\n }\n }\n\n /**\n * Subscribe to flag changes\n */\n onFlagChange(\n flagName: string,\n callback: (value: FeatureFlagValue) => void\n ): () => void {\n if (!this.listeners.has(flagName)) {\n this.listeners.set(flagName, new Set());\n }\n this.listeners.get(flagName)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n const listeners = this.listeners.get(flagName);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.listeners.delete(flagName);\n }\n }\n };\n }\n\n /**\n * Get cached flag value\n */\n getCachedFlag(flagName: string): FeatureFlagValue | undefined {\n return this.flags.get(flagName);\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.sdk.clearCache();\n this.flags.clear();\n this.abTests.clear();\n }\n\n /**\n * Start auto-refresh\n */\n private startAutoRefresh(interval: number): void {\n this.refreshTimer = setInterval(async () => {\n try {\n // Refresh all cached flags\n for (const [flagName] of this.flags) {\n await this.getFlag(flagName);\n }\n } catch (error) {\n console.error(\"Auto-refresh failed:\", error);\n }\n }, interval);\n }\n\n /**\n * Stop auto-refresh\n */\n stopAutoRefresh(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n private notifyListeners(key: string, value: any): void {\n const listeners = this.listeners.get(key);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(value);\n } catch (error) {\n console.error(\"Flag change listener error:\", error);\n }\n });\n }\n }\n}\n\n/**\n * Create a feature flag manager instance\n */\nexport function createFeatureFlagManager(\n options: FeatureFlagManagerOptions\n): FeatureFlagManager {\n return new FeatureFlagManager(options);\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n */\nexport function identifyUser(\n sdk: FlipFlagSDK,\n options: IdentifyUserOptions\n): void {\n sdk.identifyUser(options);\n}\n\n/**\n * Global identifyUser function that works with the default SDK instance\n * Note: This requires a global SDK instance to be set up\n */\nexport function identifyUserGlobal(options: IdentifyUserOptions): void {\n // This would need to be implemented with a global registry\n // For now, throw an error\n throw new Error(\n \"Global identifyUser requires a global SDK instance. Use identifyUser(sdk, options) instead.\"\n );\n}\n"],"names":[],"mappings":";;MAca,WAAW,CAAA;AAQtB,IAAA,WAAA,CAAY,MAAsB,EAAA;AAN1B,QAAA,IAAA,CAAA,KAAK,GAAG,IAAI,GAAG,EAA2B;QAC1C,IAAA,CAAA,cAAc,GAAG,yBAAyB;AAG1C,QAAA,IAAA,CAAA,cAAc,GAAmC,IAAI,GAAG,EAAE;QAGhE,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,IAAI,CAAC,cAAc;YAC5B,YAAY,EAAE,KAAK;AACnB,YAAA,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;AACnB,YAAA,GAAG,MAAM;SACV;QAED,IAAI,CAAC,KAAK,GAAG;AACX,YAAA,KAAK,EAAE,EAAE;AACT,YAAA,OAAO,EAAE,EAAE;AACX,YAAA,SAAS,EAAE,IAAI;AACf,YAAA,SAAS,EAAE,KAAK;AAChB,YAAA,KAAK,EAAE,IAAI;SACZ;;AAGD,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,EAAE;YAC5D,IAAI,CAAC,YAAY,EAAE;QACrB;IACF;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,OAA4B,EAAA;QACvC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;;QAGnC,IAAI,CAAC,gBAAgB,EAAE;;AAGvB,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,EAAE;YAC5D,IAAI,CAAC,QAAQ,EAAE;QACjB;IACF;AAEA;;AAEG;IACH,QAAQ,GAAA;AACN,QAAA,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;IAC1B;AAEA;;AAEG;AACH,IAAA,SAAS,CAAC,QAAmC,EAAA;AAC3C,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC;;AAGjC,QAAA,OAAO,MAAK;AACV,YAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC;AACtC,QAAA,CAAC;IACH;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,QAAgB,EAAA;;QAC3B,OAAO,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,KAAK;IAC5C;AAEA;;AAEG;AACH,IAAA,gBAAgB,CAAC,QAAgB,EAAA;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI;IAC7C;AAEA;;AAEG;IACK,YAAY,GAAA;AAClB,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC;QACpC;AAEA,QAAA,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,MAAK;YACrC,IAAI,CAAC,QAAQ,EAAE;AACjB,QAAA,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,YAAa,CAAC;;QAG7B,IAAI,CAAC,QAAQ,EAAE;IACjB;AAEA;;AAEG;IACH,WAAW,GAAA;AACT,QAAA,IAAI,IAAI,CAAC,cAAc,EAAE;AACvB,YAAA,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC;AAClC,YAAA,IAAI,CAAC,cAAc,GAAG,SAAS;QACjC;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,QAAQ,GAAA;AACpB,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;;AAGlD,YAAA,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;;YAGhD,IAAI,eAAe,GAA2B,IAAI;AAClD,YAAA,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AACtB,gBAAA,IAAI;AACF,oBAAA,eAAe,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE;gBAChD;gBAAE,OAAO,KAAK,EAAE;AACd,oBAAA,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,CAAC;gBACnD;YACF;AAEA,YAAA,MAAM,QAAQ,GAAsB;gBAClC,KAAK,EAAE,CAAA,aAAa,KAAA,IAAA,IAAb,aAAa,uBAAb,aAAa,CAAE,KAAK,KAAI,EAAE;gBACjC,SAAS,EAAE,IAAI,IAAI,EAAE;AACrB,gBAAA,SAAS,EAAE,KAAK;AAChB,gBAAA,KAAK,EAAE,IAAI;aACZ;YAED,IAAI,eAAe,EAAE;gBACnB,MAAM,UAAU,GAAmC,EAAE;gBACrD,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,KAAI;;AAEvC,oBAAA,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;;AAEtB,wBAAA,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;4BACtB,QAAQ,EAAE,IAAI,CAAC,IAAI;4BACnB,MAAM,EAAE,IAAI,CAAC,EAAE;4BACf,SAAS,EAAE,WAAW;AACtB,4BAAA,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;AAC3B,gCAAA,EAAE,EAAE,SAAS;AACb,gCAAA,IAAI,EAAE,SAAS;AACf,gCAAA,KAAK,EAAE,IAAI;AACX,gCAAA,MAAM,EAAE,GAAG;AACZ,6BAAA;AACD,4BAAA,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACpC;oBACH;AACF,gBAAA,CAAC,CAAC;AACF,gBAAA,QAAQ,CAAC,OAAO,GAAG,UAAU;YAC/B;AAEA,YAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;QAC5B;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,eAAe;YAC1D,IAAI,CAAC,WAAW,CAAC;AACf,gBAAA,SAAS,EAAE,KAAK;AAChB,gBAAA,KAAK,EAAE,YAAY;AACpB,aAAA,CAAC;AACF,YAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;QAC9C;IACF;AAEA;;AAEG;AACK,IAAA,WAAW,CAAC,QAA2B,EAAA;AAC7C,QAAA,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,EAAE;;QAG3C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;AACvC,YAAA,IAAI;AACF,gBAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YACtB;YAAE,OAAO,KAAK,EAAE;AACd,gBAAA,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC;YAC/C;AACF,QAAA,CAAC,CAAC;IACJ;AAEA;;AAEG;AACK,IAAA,MAAM,aAAa,GAAA;AACzB,QAAA,IAAI;AACF,YAAA,OAAO,MAAM,IAAI,CAAC,WAAW,CAC3B,CAAA,eAAA,EAAkB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAA,CAAE,CAC1C;QACH;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC;AAC9C,YAAA,OAAO,IAAI;QACb;IACF;AAEA;;AAEG;AACK,IAAA,MAAM,eAAe,GAAA;AAC3B,QAAA,IAAI;AACF,YAAA,OAAO,MAAM,IAAI,CAAC,WAAW,CAC3B,CAAA,kBAAA,EAAqB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAA,CAAE,CAC7C;QACH;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC;AAClD,YAAA,OAAO,IAAI;QACb;IACF;AAEA;;AAEG;IACK,gBAAgB,GAAA;AACtB,QAAA,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,KAC1D,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAC1B;AACD,QAAA,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrD;AAEA;;AAEG;IACH,MAAM,QAAQ,CACZ,SAAA,GAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EACzC,WAAoB,EAAA;QAEpB,MAAM,QAAQ,GAAG,CAAA,MAAA,EAAS,SAAS,IAAI,WAAW,IAAI,KAAK,CAAA,CAAE;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAuB,QAAQ,CAAC;QAEhE,IAAI,MAAM,EAAE;AACV,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAE,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QACvE,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;AAC1C,YAAA,GAAG,CAAC,YAAY,CAAC,GAAG,CAClB,aAAa,EACb,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAY,CACxC;QACH;AAEA,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CACrC,GAAG,CAAC,QAAQ,EAAE,CACf;AACD,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,YAAa,CAAC;AAE5D,QAAA,OAAO,QAAQ;IACjB;AAEA;;AAEG;AACH,IAAA,MAAM,OAAO,CACX,QAAgB,EAChB,SAAA,GAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EACzC,WAAoB,EAAA;;;QAGpB,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE;YAC5C,OAAO;AACL,gBAAA,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;gBAChC,QAAQ;AACR,gBAAA,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,KAAK;gBAC7C,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;AACjC,gBAAA,SAAS,EACP,CAAA,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,SAAS,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,WAAW,EAAE,KAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aAClE;QACH;;;AAIA,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;;AAExB,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;AAC3B,gBAAA,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACxD,gBAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE;oBACrE,OAAO;AACL,wBAAA,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;wBAChC,QAAQ;AACR,wBAAA,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,KAAK;wBAC7C,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;AACjC,wBAAA,SAAS,EACP,CAAA,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,SAAS,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,WAAW,EAAE,KAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBAClE;gBACH;YACF;QACF;QAEA,MAAM,QAAQ,GAAG,CAAA,KAAA,EAAQ,SAAS,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,WAAW,IAAI,KAAK,CAAA,CAAE;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAsB,QAAQ,CAAC;QAE/D,IAAI,MAAM,EAAE;AACV,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,kBAAkB,SAAS,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,EACzC,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB;QACD,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;AAC1C,YAAA,GAAG,CAAC,YAAY,CAAC,GAAG,CAClB,aAAa,EACb,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC,WAAY,CACxC;QACH;AAEA,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CACrC,GAAG,CAAC,QAAQ,EAAE,CACf;AACD,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,YAAa,CAAC;AAE5D,QAAA,OAAO,QAAQ;IACjB;AAEA;;AAEG;AACH,IAAA,MAAM,gBAAgB,CACpB,QAAgB,EAChB,MAAc,EACd,SAAA,GAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAA;;QAGzC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QACjD,IAAI,YAAY,IAAI,YAAY,CAAC,QAAQ,KAAK,QAAQ,EAAE;AACtD,YAAA,OAAO,YAAY;QACrB;QAEA,MAAM,QAAQ,GAAG,CAAA,OAAA,EAAU,SAAS,IAAI,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAiB,QAAQ,CAAC;QAE1D,IAAI,MAAM,EAAE;AACV,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,SAAS,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,EAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAiB,GAAG,EAAE;AAC3D,YAAA,OAAO,EAAE;AACP,gBAAA,WAAW,EAAE,MAAM;AACpB,aAAA;AACF,SAAA,CAAC;;AAGF,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,YAAa,GAAG,EAAE,CAAC;AAEjE,QAAA,OAAO,QAAQ;IACjB;AAEA;;AAEG;AACH,IAAA,MAAM,iBAAiB,CACrB,QAAgB,EAChB,MAAc,EACd,KAAa,EACb,SAAiB,EACjB,SAA+B,EAC/B,SAAA,GAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAA;AAEzC,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,SAAS,CAAA,CAAA,EAAI,QAAQ,CAAA,MAAA,CAAQ,EACjD,IAAI,CAAC,MAAM,CAAC,OAAO,CACpB;AAED,QAAA,OAAO,IAAI,CAAC,WAAW,CAAsB,GAAG,EAAE;AAChD,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE;AACP,gBAAA,WAAW,EAAE,MAAM;AACnB,gBAAA,cAAc,EAAE,kBAAkB;AACnC,aAAA;AACD,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK;gBACL,SAAS;gBACT,SAAS;aACV,CAAC;AACH,SAAA,CAAC;IACJ;AAEA;;AAEG;IACH,MAAM,UAAU,CACd,SAAA,GAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAA;AAEzC,QAAA,MAAM,QAAQ,GAAG,CAAA,QAAA,EAAW,SAAS,EAAE;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAkB,QAAQ,CAAC;QAE3D,IAAI,MAAM,EAAE;AACV,YAAA,OAAO,MAAM;QACf;AAEA,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAA,kBAAA,EAAqB,SAAS,CAAA,CAAE,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAE1E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAkB,GAAG,CAAC;AAC7D,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,YAAa,CAAC;AAE5D,QAAA,OAAO,QAAQ;IACjB;AAEA;;AAEG;AACH,IAAA,UAAU,CAAC,GAAY,EAAA;QACrB,IAAI,GAAG,EAAE;AACP,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;QACxB;aAAO;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QACpB;IACF;AAEA;;AAEG;AACH,IAAA,YAAY,CAAC,SAAkC,EAAA;AAC7C,QAAA,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,EAAE;IAChD;AAEQ,IAAA,MAAM,WAAW,CACvB,GAAiB,EACjB,UAAuB,EAAE,EAAA;;;AAGzB,QAAA,MAAM,SAAS,GAAG,GAAG,YAAY,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,GAAG;;AAG3D,QAAA,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG;cACpC,GAAG,CAAA,CAAA,EAAA,GAAA,IAAI,CAAC,MAAM,CAAC,OAAO,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAI,IAAI,CAAC,cAAc,CAAA,EAAG,SAAS,CAAA;cAC7E,SAAS;AAEb,QAAA,MAAM,OAAO,GAAG;AACd,YAAA,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;AAC/B,YAAA,cAAc,EAAE,kBAAkB;YAClC,GAAG,OAAO,CAAC,OAAO;SACnB;AAED,QAAA,MAAM,cAAc,GAAgB;AAClC,YAAA,GAAG,OAAO;YACV,OAAO;SACR;QAED,OAAO,IAAI,CAAC,oBAAoB,CAAI,OAAO,EAAE,cAAc,CAAC;IAC9D;AAEQ,IAAA,MAAM,oBAAoB,CAChC,GAAW,EACX,OAAoB,EACpB,YAAA,GAA6B;AAC3B,QAAA,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,aAAc;AACpC,QAAA,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAW;AAC9B,QAAA,OAAO,EAAE,CAAC;AACX,KAAA,EAAA;AAED,QAAA,IAAI,SAAgB;AAEpB,QAAA,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE;AACjE,YAAA,IAAI;gBACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;AAE1C,gBAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,oBAAA,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;AACzD,oBAAA,MAAM,IAAI,KAAK,CACb,CAAA,KAAA,EAAQ,QAAQ,CAAC,MAAM,CAAA,EAAA,EAAK,SAAS,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CACrE;gBACH;AAEA,gBAAA,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE;YAC9B;YAAE,OAAO,KAAK,EAAE;gBACd,SAAS,GAAG,KAAc;;AAG1B,gBAAA,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;AACvC,wBAAA,MAAM,KAAK;oBACb;gBACF;AAEA,gBAAA,IAAI,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE;AACnC,oBAAA,MAAM,KAAK,GACT,YAAY,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,CAAC;AAClE,oBAAA,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC5D;YACF;QACF;AAEA,QAAA,MAAM,SAAU;IAClB;AAEQ,IAAA,YAAY,CAAI,GAAW,EAAA;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAEjC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE;AAC5C,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;AACtB,YAAA,OAAO,IAAI;QACb;QAEA,OAAO,KAAK,CAAC,IAAI;IACnB;AAEQ,IAAA,QAAQ,CAAI,GAAW,EAAE,IAAO,EAAE,GAAW,EAAA;AACnD,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI;AACJ,YAAA,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,GAAG;AACJ,SAAA,CAAC;IACJ;AAEA;;AAEG;IACI,OAAO,GAAA;QACZ,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE;AAC3B,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;IACpB;AACD;;MClhBY,kBAAkB,CAAA;AAQ7B,IAAA,WAAA,CAAY,OAAkC,EAAA;AANtC,QAAA,IAAA,CAAA,KAAK,GAAkC,IAAI,GAAG,EAAE;AAChD,QAAA,IAAA,CAAA,OAAO,GACb,IAAI,GAAG,EAAE;AACH,QAAA,IAAA,CAAA,SAAS,GAA2C,IAAI,GAAG,EAAE;QAInE,IAAI,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;AAE1C,QAAA,IAAI,OAAO,CAAC,WAAW,EAAE;YACvB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC;QACzD;IACF;AAEA;;AAEG;IACH,MAAM,OAAO,CAAC,QAAgB,EAAA;;AAC5B,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;AACjD,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK;YAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;AAC/B,YAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC;AACrC,YAAA,OAAO,KAAK;QACd;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,CAAA,mBAAA,EAAsB,QAAQ,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;YACvD,OAAO,CAAA,EAAA,GAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,KAAK;QAC1C;IACF;AAEA;;AAEG;IACH,MAAM,QAAQ,CACZ,SAAmB,EAAA;AAEnB,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YAC1C,MAAM,MAAM,GAAqC,EAAE;AAEnD,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;;gBAC7B,MAAM,KAAK,GAAG,CAAA,EAAA,GAAA,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,KAAK;AAC/C,gBAAA,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK;gBACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;AAC/B,gBAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC;AACvC,YAAA,CAAC,CAAC;AAEF,YAAA,OAAO,MAAM;QACf;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;YAC5C,MAAM,MAAM,GAAqC,EAAE;AACnD,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;;AAC7B,gBAAA,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,KAAK;AACtD,YAAA,CAAC,CAAC;AACF,YAAA,OAAO,MAAM;QACf;IACF;AAEA;;AAEG;AACH,IAAA,MAAM,gBAAgB,CACpB,QAAgB,EAChB,MAAc,EAAA;;AAEd,QAAA,IAAI;AACF,YAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC;AAClE,YAAA,MAAM,MAAM,GAAG;AACb,gBAAA,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK;gBAC/B,SAAS,EAAE,QAAQ,CAAC,SAAS;aAC9B;AACD,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,EAAE,MAAM,CAAC;YACjD,IAAI,CAAC,eAAe,CAAC,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,EAAE,MAAM,CAAC;AACrD,YAAA,OAAO,MAAM;QACf;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,CAAA,mCAAA,EAAsC,QAAQ,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AACvE,YAAA,QACE,CAAA,EAAA,GAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI;AAC3C,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE,EAAE;AACd,aAAA;QAEL;IACF;AAEA;;AAEG;IACH,MAAM,iBAAiB,CACrB,QAAgB,EAChB,MAAc,EACd,KAAa,EACb,SAA+B,EAAA;AAE/B,QAAA,MAAM,OAAO,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,EAAE;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAE1C,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,OAAO,CAAC,IAAI,CAAC,8BAA8B,OAAO,CAAA,CAAE,CAAC;YACrD;QACF;AAEA,QAAA,IAAI;AACF,YAAA,MAAM,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAC9B,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,CAAC,SAAS,EAClB,SAAS,CACV;QACH;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,CAAA,oCAAA,EAAuC,QAAQ,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;QAC1E;IACF;AAEA;;AAEG;IACH,YAAY,CACV,QAAgB,EAChB,QAA2C,EAAA;QAE3C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACjC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC;QACzC;AACA,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC;;AAG3C,QAAA,OAAO,MAAK;YACV,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9C,IAAI,SAAS,EAAE;AACb,gBAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC1B,gBAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;AACxB,oBAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;gBACjC;YACF;AACF,QAAA,CAAC;IACH;AAEA;;AAEG;AACH,IAAA,aAAa,CAAC,QAAgB,EAAA;QAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjC;AAEA;;AAEG;IACH,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE;AACrB,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;AAClB,QAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;IACtB;AAEA;;AAEG;AACK,IAAA,gBAAgB,CAAC,QAAgB,EAAA;AACvC,QAAA,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,YAAW;AACzC,YAAA,IAAI;;gBAEF,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;AACnC,oBAAA,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC9B;YACF;YAAE,OAAO,KAAK,EAAE;AACd,gBAAA,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC;YAC9C;QACF,CAAC,EAAE,QAAQ,CAAC;IACd;AAEA;;AAEG;IACH,eAAe,GAAA;AACb,QAAA,IAAI,IAAI,CAAC,YAAY,EAAE;AACrB,YAAA,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC;AAChC,YAAA,IAAI,CAAC,YAAY,GAAG,SAAS;QAC/B;IACF;IAEQ,eAAe,CAAC,GAAW,EAAE,KAAU,EAAA;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;QACzC,IAAI,SAAS,EAAE;AACb,YAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;AAC7B,gBAAA,IAAI;oBACF,QAAQ,CAAC,KAAK,CAAC;gBACjB;gBAAE,OAAO,KAAK,EAAE;AACd,oBAAA,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC;gBACrD;AACF,YAAA,CAAC,CAAC;QACJ;IACF;AACD;AAED;;AAEG;AACG,SAAU,wBAAwB,CACtC,OAAkC,EAAA;AAElC,IAAA,OAAO,IAAI,kBAAkB,CAAC,OAAO,CAAC;AACxC;;AClNA;;AAEG;AACG,SAAU,YAAY,CAC1B,GAAgB,EAChB,OAA4B,EAAA;AAE5B,IAAA,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC;AAC3B;;;;;;"}
|
package/dist/js.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class FlipFlagSDK {
|
|
2
2
|
constructor(config) {
|
|
3
3
|
this.cache = new Map();
|
|
4
|
-
this.defaultBaseUrl = "https://app.flipflag.ru
|
|
4
|
+
this.defaultBaseUrl = "https://app.flipflag.ru";
|
|
5
5
|
this.stateListeners = new Set();
|
|
6
6
|
this.config = {
|
|
7
7
|
baseUrl: this.defaultBaseUrl,
|
|
@@ -163,7 +163,7 @@ class FlipFlagSDK {
|
|
|
163
163
|
*/
|
|
164
164
|
async fetchAllFlags() {
|
|
165
165
|
try {
|
|
166
|
-
return await this.makeRequest(`/sdk/flags/${this.config.projectId}`);
|
|
166
|
+
return await this.makeRequest(`/api/sdk/flags/${this.config.projectId}`);
|
|
167
167
|
}
|
|
168
168
|
catch (error) {
|
|
169
169
|
console.error("Failed to fetch flags:", error);
|
|
@@ -175,7 +175,7 @@ class FlipFlagSDK {
|
|
|
175
175
|
*/
|
|
176
176
|
async fetchAllABTests() {
|
|
177
177
|
try {
|
|
178
|
-
return await this.makeRequest(`/sdk/ab-tests/${this.config.projectId}`);
|
|
178
|
+
return await this.makeRequest(`/api/sdk/ab-tests/${this.config.projectId}`);
|
|
179
179
|
}
|
|
180
180
|
catch (error) {
|
|
181
181
|
console.error("Failed to fetch A/B tests:", error);
|
|
@@ -198,7 +198,7 @@ class FlipFlagSDK {
|
|
|
198
198
|
if (cached) {
|
|
199
199
|
return cached;
|
|
200
200
|
}
|
|
201
|
-
const url = new URL(`/sdk/flags/${projectId}`, this.config.baseUrl);
|
|
201
|
+
const url = new URL(`/api/sdk/flags/${projectId}`, this.config.baseUrl);
|
|
202
202
|
if (environment || this.config.environment) {
|
|
203
203
|
url.searchParams.set("environment", environment || this.config.environment);
|
|
204
204
|
}
|
|
@@ -210,7 +210,7 @@ class FlipFlagSDK {
|
|
|
210
210
|
* Get a specific feature flag value
|
|
211
211
|
*/
|
|
212
212
|
async getFlag(flagName, projectId = this.config.projectId, environment) {
|
|
213
|
-
var _a;
|
|
213
|
+
var _a, _b;
|
|
214
214
|
// If we have the flag in state, return it immediately
|
|
215
215
|
if (this.state.flags[flagName] !== undefined) {
|
|
216
216
|
return {
|
|
@@ -221,12 +221,29 @@ class FlipFlagSDK {
|
|
|
221
221
|
timestamp: ((_a = this.state.lastFetch) === null || _a === void 0 ? void 0 : _a.toISOString()) || new Date().toISOString(),
|
|
222
222
|
};
|
|
223
223
|
}
|
|
224
|
+
// Check if we're currently loading data (pullData in progress)
|
|
225
|
+
// In this case, wait a bit and check state again
|
|
226
|
+
if (this.state.isLoading) {
|
|
227
|
+
// Wait up to 5 seconds for loading to complete
|
|
228
|
+
for (let i = 0; i < 50; i++) {
|
|
229
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
230
|
+
if (!this.state.isLoading && this.state.flags[flagName] !== undefined) {
|
|
231
|
+
return {
|
|
232
|
+
projectId: this.config.projectId,
|
|
233
|
+
flagName,
|
|
234
|
+
environment: this.config.environment || "all",
|
|
235
|
+
value: this.state.flags[flagName],
|
|
236
|
+
timestamp: ((_b = this.state.lastFetch) === null || _b === void 0 ? void 0 : _b.toISOString()) || new Date().toISOString(),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
224
241
|
const cacheKey = `flag:${projectId}:${flagName}:${environment || "all"}`;
|
|
225
242
|
const cached = this.getFromCache(cacheKey);
|
|
226
243
|
if (cached) {
|
|
227
244
|
return cached;
|
|
228
245
|
}
|
|
229
|
-
const url = new URL(`/sdk/flags/${projectId}/${flagName}`, this.config.baseUrl);
|
|
246
|
+
const url = new URL(`/api/sdk/flags/${projectId}/${flagName}`, this.config.baseUrl);
|
|
230
247
|
if (environment || this.config.environment) {
|
|
231
248
|
url.searchParams.set("environment", environment || this.config.environment);
|
|
232
249
|
}
|
|
@@ -248,7 +265,7 @@ class FlipFlagSDK {
|
|
|
248
265
|
if (cached) {
|
|
249
266
|
return cached;
|
|
250
267
|
}
|
|
251
|
-
const url =
|
|
268
|
+
const url = new URL(`/api/sdk/ab-test/${projectId}/${testName}`, this.config.baseUrl);
|
|
252
269
|
const response = await this.makeRequest(url, {
|
|
253
270
|
headers: {
|
|
254
271
|
"X-User-ID": userId,
|
|
@@ -262,7 +279,7 @@ class FlipFlagSDK {
|
|
|
262
279
|
* Record an A/B test event
|
|
263
280
|
*/
|
|
264
281
|
async recordAbTestEvent(testName, userId, event, variantId, eventData, projectId = this.config.projectId) {
|
|
265
|
-
const url =
|
|
282
|
+
const url = new URL(`/api/sdk/ab-test/${projectId}/${testName}/event`, this.config.baseUrl);
|
|
266
283
|
return this.makeRequest(url, {
|
|
267
284
|
method: "POST",
|
|
268
285
|
headers: {
|
|
@@ -285,7 +302,7 @@ class FlipFlagSDK {
|
|
|
285
302
|
if (cached) {
|
|
286
303
|
return cached;
|
|
287
304
|
}
|
|
288
|
-
const url =
|
|
305
|
+
const url = new URL(`/api/sdk/ab-tests/${projectId}`, this.config.baseUrl);
|
|
289
306
|
const response = await this.makeRequest(url);
|
|
290
307
|
this.setCache(cacheKey, response, this.config.cacheTimeout);
|
|
291
308
|
return response;
|
|
@@ -309,10 +326,12 @@ class FlipFlagSDK {
|
|
|
309
326
|
}
|
|
310
327
|
async makeRequest(url, options = {}) {
|
|
311
328
|
var _a;
|
|
329
|
+
// Convert URL object to string if needed
|
|
330
|
+
const urlString = url instanceof URL ? url.toString() : url;
|
|
312
331
|
// If URL starts with '/', prepend baseUrl and handle trailing slashes
|
|
313
|
-
const fullUrl =
|
|
314
|
-
? `${((_a = this.config.baseUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, "")) || this.defaultBaseUrl}${
|
|
315
|
-
:
|
|
332
|
+
const fullUrl = urlString.startsWith("/")
|
|
333
|
+
? `${((_a = this.config.baseUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, "")) || this.defaultBaseUrl}${urlString}`
|
|
334
|
+
: urlString;
|
|
316
335
|
const headers = {
|
|
317
336
|
"X-API-Key": this.config.apiKey,
|
|
318
337
|
"Content-Type": "application/json",
|
package/dist/js.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js.mjs","sources":["../src/core/FlipFlagSDK.ts","../src/js/featureFlagManager.ts","../src/js/identifyUser.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/api\";\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 return await this.makeRequest<FeatureFlagsResponse>(\n `/sdk/flags/${this.config.projectId}`\n );\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 return await this.makeRequest<ABTestsResponse>(\n `/sdk/ab-tests/${this.config.projectId}`\n );\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(`/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 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 `/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 = `${this.config.baseUrl}/sdk/ab-test/${projectId}/${testName}`;\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 = `${this.config.baseUrl}/sdk/ab-test/${projectId}/${testName}/event`;\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 = `${this.config.baseUrl}/sdk/ab-tests/${projectId}`;\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,\n options: RequestInit = {}\n ): Promise<T> {\n // If URL starts with '/', prepend baseUrl and handle trailing slashes\n const fullUrl = url.startsWith(\"/\")\n ? `${this.config.baseUrl?.replace(/\\/$/, \"\") || this.defaultBaseUrl}${url}`\n : url;\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\n if (!response.ok) {\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 { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig, FeatureFlagValue, ABTestValue } from \"../types\";\n\ninterface FeatureFlagManagerOptions {\n config: FlipFlagConfig;\n autoRefresh?: boolean;\n refreshInterval?: number;\n}\n\nexport class FeatureFlagManager {\n private sdk: FlipFlagSDK;\n private flags: Map<string, FeatureFlagValue> = new Map();\n private abTests: Map<string, { variant: ABTestValue; variantId: string }> =\n new Map();\n private listeners: Map<string, Set<(value: any) => void>> = new Map();\n private refreshTimer?: NodeJS.Timeout;\n\n constructor(options: FeatureFlagManagerOptions) {\n this.sdk = new FlipFlagSDK(options.config);\n\n if (options.autoRefresh) {\n this.startAutoRefresh(options.refreshInterval || 30000);\n }\n }\n\n /**\n * Get a feature flag value\n */\n async getFlag(flagName: string): Promise<FeatureFlagValue> {\n try {\n const response = await this.sdk.getFlag(flagName);\n const value = response.value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n return value;\n } catch (error) {\n console.error(`Failed to get flag ${flagName}:`, error);\n return this.flags.get(flagName) ?? false;\n }\n }\n\n /**\n * Get multiple feature flags\n */\n async getFlags(\n flagNames: string[]\n ): Promise<Record<string, FeatureFlagValue>> {\n try {\n const response = await this.sdk.getFlags();\n const result: Record<string, FeatureFlagValue> = {};\n\n flagNames.forEach((flagName) => {\n const value = response.flags[flagName] ?? false;\n result[flagName] = value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n });\n\n return result;\n } catch (error) {\n console.error(\"Failed to get flags:\", error);\n const result: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n result[flagName] = this.flags.get(flagName) ?? false;\n });\n return result;\n }\n }\n\n /**\n * Get A/B test variant\n */\n async getABTestVariant(\n testName: string,\n userId: string\n ): Promise<{ variant: ABTestValue; variantId: string }> {\n try {\n const response = await this.sdk.getAbTestVariant(testName, userId);\n const result = {\n variant: response.variant.value,\n variantId: response.variantId,\n };\n this.abTests.set(`${testName}:${userId}`, result);\n this.notifyListeners(`${testName}:${userId}`, result);\n return result;\n } catch (error) {\n console.error(`Failed to get A/B test variant for ${testName}:`, error);\n return (\n this.abTests.get(`${testName}:${userId}`) ?? {\n variant: null,\n variantId: \"\",\n }\n );\n }\n }\n\n /**\n * Record A/B test event\n */\n async recordABTestEvent(\n testName: string,\n userId: string,\n event: string,\n eventData?: Record<string, any>\n ): Promise<void> {\n const testKey = `${testName}:${userId}`;\n const testData = this.abTests.get(testKey);\n\n if (!testData) {\n console.warn(`No A/B test data found for ${testKey}`);\n return;\n }\n\n try {\n await this.sdk.recordAbTestEvent(\n testName,\n userId,\n event,\n testData.variantId,\n eventData\n );\n } catch (error) {\n console.error(`Failed to record A/B test event for ${testName}:`, error);\n }\n }\n\n /**\n * Subscribe to flag changes\n */\n onFlagChange(\n flagName: string,\n callback: (value: FeatureFlagValue) => void\n ): () => void {\n if (!this.listeners.has(flagName)) {\n this.listeners.set(flagName, new Set());\n }\n this.listeners.get(flagName)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n const listeners = this.listeners.get(flagName);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.listeners.delete(flagName);\n }\n }\n };\n }\n\n /**\n * Get cached flag value\n */\n getCachedFlag(flagName: string): FeatureFlagValue | undefined {\n return this.flags.get(flagName);\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.sdk.clearCache();\n this.flags.clear();\n this.abTests.clear();\n }\n\n /**\n * Start auto-refresh\n */\n private startAutoRefresh(interval: number): void {\n this.refreshTimer = setInterval(async () => {\n try {\n // Refresh all cached flags\n for (const [flagName] of this.flags) {\n await this.getFlag(flagName);\n }\n } catch (error) {\n console.error(\"Auto-refresh failed:\", error);\n }\n }, interval);\n }\n\n /**\n * Stop auto-refresh\n */\n stopAutoRefresh(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n private notifyListeners(key: string, value: any): void {\n const listeners = this.listeners.get(key);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(value);\n } catch (error) {\n console.error(\"Flag change listener error:\", error);\n }\n });\n }\n }\n}\n\n/**\n * Create a feature flag manager instance\n */\nexport function createFeatureFlagManager(\n options: FeatureFlagManagerOptions\n): FeatureFlagManager {\n return new FeatureFlagManager(options);\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n */\nexport function identifyUser(\n sdk: FlipFlagSDK,\n options: IdentifyUserOptions\n): void {\n sdk.identifyUser(options);\n}\n\n/**\n * Global identifyUser function that works with the default SDK instance\n * Note: This requires a global SDK instance to be set up\n */\nexport function identifyUserGlobal(options: IdentifyUserOptions): void {\n // This would need to be implemented with a global registry\n // For now, throw an error\n throw new Error(\n \"Global identifyUser requires a global SDK instance. Use identifyUser(sdk, options) instead.\"\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"js.mjs","sources":["../src/core/FlipFlagSDK.ts","../src/js/featureFlagManager.ts","../src/js/identifyUser.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 return await this.makeRequest<FeatureFlagsResponse>(\n `/api/sdk/flags/${this.config.projectId}`\n );\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 return await this.makeRequest<ABTestsResponse>(\n `/api/sdk/ab-tests/${this.config.projectId}`\n );\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\n if (!response.ok) {\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 { FlipFlagSDK } from \"../core/FlipFlagSDK\";\nimport { FlipFlagConfig, FeatureFlagValue, ABTestValue } from \"../types\";\n\ninterface FeatureFlagManagerOptions {\n config: FlipFlagConfig;\n autoRefresh?: boolean;\n refreshInterval?: number;\n}\n\nexport class FeatureFlagManager {\n private sdk: FlipFlagSDK;\n private flags: Map<string, FeatureFlagValue> = new Map();\n private abTests: Map<string, { variant: ABTestValue; variantId: string }> =\n new Map();\n private listeners: Map<string, Set<(value: any) => void>> = new Map();\n private refreshTimer?: NodeJS.Timeout;\n\n constructor(options: FeatureFlagManagerOptions) {\n this.sdk = new FlipFlagSDK(options.config);\n\n if (options.autoRefresh) {\n this.startAutoRefresh(options.refreshInterval || 30000);\n }\n }\n\n /**\n * Get a feature flag value\n */\n async getFlag(flagName: string): Promise<FeatureFlagValue> {\n try {\n const response = await this.sdk.getFlag(flagName);\n const value = response.value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n return value;\n } catch (error) {\n console.error(`Failed to get flag ${flagName}:`, error);\n return this.flags.get(flagName) ?? false;\n }\n }\n\n /**\n * Get multiple feature flags\n */\n async getFlags(\n flagNames: string[]\n ): Promise<Record<string, FeatureFlagValue>> {\n try {\n const response = await this.sdk.getFlags();\n const result: Record<string, FeatureFlagValue> = {};\n\n flagNames.forEach((flagName) => {\n const value = response.flags[flagName] ?? false;\n result[flagName] = value;\n this.flags.set(flagName, value);\n this.notifyListeners(flagName, value);\n });\n\n return result;\n } catch (error) {\n console.error(\"Failed to get flags:\", error);\n const result: Record<string, FeatureFlagValue> = {};\n flagNames.forEach((flagName) => {\n result[flagName] = this.flags.get(flagName) ?? false;\n });\n return result;\n }\n }\n\n /**\n * Get A/B test variant\n */\n async getABTestVariant(\n testName: string,\n userId: string\n ): Promise<{ variant: ABTestValue; variantId: string }> {\n try {\n const response = await this.sdk.getAbTestVariant(testName, userId);\n const result = {\n variant: response.variant.value,\n variantId: response.variantId,\n };\n this.abTests.set(`${testName}:${userId}`, result);\n this.notifyListeners(`${testName}:${userId}`, result);\n return result;\n } catch (error) {\n console.error(`Failed to get A/B test variant for ${testName}:`, error);\n return (\n this.abTests.get(`${testName}:${userId}`) ?? {\n variant: null,\n variantId: \"\",\n }\n );\n }\n }\n\n /**\n * Record A/B test event\n */\n async recordABTestEvent(\n testName: string,\n userId: string,\n event: string,\n eventData?: Record<string, any>\n ): Promise<void> {\n const testKey = `${testName}:${userId}`;\n const testData = this.abTests.get(testKey);\n\n if (!testData) {\n console.warn(`No A/B test data found for ${testKey}`);\n return;\n }\n\n try {\n await this.sdk.recordAbTestEvent(\n testName,\n userId,\n event,\n testData.variantId,\n eventData\n );\n } catch (error) {\n console.error(`Failed to record A/B test event for ${testName}:`, error);\n }\n }\n\n /**\n * Subscribe to flag changes\n */\n onFlagChange(\n flagName: string,\n callback: (value: FeatureFlagValue) => void\n ): () => void {\n if (!this.listeners.has(flagName)) {\n this.listeners.set(flagName, new Set());\n }\n this.listeners.get(flagName)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n const listeners = this.listeners.get(flagName);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.listeners.delete(flagName);\n }\n }\n };\n }\n\n /**\n * Get cached flag value\n */\n getCachedFlag(flagName: string): FeatureFlagValue | undefined {\n return this.flags.get(flagName);\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.sdk.clearCache();\n this.flags.clear();\n this.abTests.clear();\n }\n\n /**\n * Start auto-refresh\n */\n private startAutoRefresh(interval: number): void {\n this.refreshTimer = setInterval(async () => {\n try {\n // Refresh all cached flags\n for (const [flagName] of this.flags) {\n await this.getFlag(flagName);\n }\n } catch (error) {\n console.error(\"Auto-refresh failed:\", error);\n }\n }, interval);\n }\n\n /**\n * Stop auto-refresh\n */\n stopAutoRefresh(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = undefined;\n }\n }\n\n private notifyListeners(key: string, value: any): void {\n const listeners = this.listeners.get(key);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(value);\n } catch (error) {\n console.error(\"Flag change listener error:\", error);\n }\n });\n }\n }\n}\n\n/**\n * Create a feature flag manager instance\n */\nexport function createFeatureFlagManager(\n options: FeatureFlagManagerOptions\n): FeatureFlagManager {\n return new FeatureFlagManager(options);\n}\n","import { IdentifyUserOptions } from \"../types\";\nimport { FlipFlagSDK } from \"../core/FlipFlagSDK\";\n\n/**\n * Identify user for A/B testing and user-specific flags\n */\nexport function identifyUser(\n sdk: FlipFlagSDK,\n options: IdentifyUserOptions\n): void {\n sdk.identifyUser(options);\n}\n\n/**\n * Global identifyUser function that works with the default SDK instance\n * Note: This requires a global SDK instance to be set up\n */\nexport function identifyUserGlobal(options: IdentifyUserOptions): void {\n // This would need to be implemented with a global registry\n // For now, throw an error\n throw new Error(\n \"Global identifyUser requires a global SDK instance. Use identifyUser(sdk, options) instead.\"\n );\n}\n"],"names":[],"mappings":"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"}
|