@featureflare/sdk-js 0.0.32 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +31 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +31 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -680,7 +680,9 @@ var FeatureFlareClient = class {
|
|
|
680
680
|
}
|
|
681
681
|
const url = new URL(this.realtimeSsePath, this.apiBaseUrl);
|
|
682
682
|
url.searchParams.set("sdkKey", this.sdkKey);
|
|
683
|
-
|
|
683
|
+
if (this.expectedEnvKey) {
|
|
684
|
+
url.searchParams.set("expectedEnvKey", this.expectedEnvKey);
|
|
685
|
+
}
|
|
684
686
|
this.eventSource = new EventSourceImpl(url.toString());
|
|
685
687
|
this.eventSource.onopen = () => {
|
|
686
688
|
this.emit("connectionState", { state: "connected", transport: "sse" });
|
|
@@ -730,6 +732,34 @@ var FeatureFlareClient = class {
|
|
|
730
732
|
}
|
|
731
733
|
this.emit("connectionState", { state: "offline", transport: "none" });
|
|
732
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.
|
|
737
|
+
* The API evaluates the report against active rollback policies and may trigger an automated
|
|
738
|
+
* rollback if configured thresholds are breached.
|
|
739
|
+
*
|
|
740
|
+
* Errors from this call are silently swallowed so that reporting never disrupts the host application.
|
|
741
|
+
*/
|
|
742
|
+
async reportError(report) {
|
|
743
|
+
if (!this.sdkKey) return;
|
|
744
|
+
try {
|
|
745
|
+
await fetch(`${this.apiBaseUrl}/api/v1/sdk/report`, {
|
|
746
|
+
method: "POST",
|
|
747
|
+
headers: {
|
|
748
|
+
"content-type": "application/json",
|
|
749
|
+
"x-featureflare-sdk-key": this.sdkKey
|
|
750
|
+
},
|
|
751
|
+
body: JSON.stringify({
|
|
752
|
+
flagKey: report.flagKey,
|
|
753
|
+
errorRate: report.errorRate,
|
|
754
|
+
latencyMs: report.latencyMs,
|
|
755
|
+
observedAt: report.observedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
756
|
+
envKey: this.envKey,
|
|
757
|
+
context: report.context
|
|
758
|
+
})
|
|
759
|
+
});
|
|
760
|
+
} catch {
|
|
761
|
+
}
|
|
762
|
+
}
|
|
733
763
|
dispose() {
|
|
734
764
|
this.stopRealtime();
|
|
735
765
|
this.listeners.update.clear();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["metadata"],"mappings":"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","file":"index.cjs","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareCacheSource = 'bootstrap' | 'network' | 'realtime' | 'persistent';\nexport type FeatureFlareEvaluationReason = 'fresh_cache' | 'stale_cache' | 'bootstrap' | 'default' | 'network' | 'kill_switch';\n\nexport type FeatureFlareEvaluationMetadata = {\n reason: FeatureFlareEvaluationReason;\n isStale: boolean;\n latencyMs: number;\n source: FeatureFlareCacheSource | 'default' | 'kill_switch';\n updatedAt?: number;\n staleAt?: number;\n expiresAt?: number;\n};\n\nexport type FeatureFlareEvaluationResult = {\n value: boolean;\n metadata: FeatureFlareEvaluationMetadata;\n};\n\nexport type FeatureFlareMetricName =\n | 'ff_eval_latency_ms'\n | 'ff_cache_hit_ratio'\n | 'ff_revalidate_latency_ms'\n | 'ff_realtime_lag_ms'\n | 'ff_killswitch_apply_latency_ms';\n\nexport type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;\n\nexport type FeatureFlarePersistentSnapshot = {\n revision?: number;\n killSwitches?: string[];\n flags: Record<\n string,\n {\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source?: FeatureFlareCacheSource;\n revision?: number;\n }\n >;\n};\n\nexport type FeatureFlarePersistentCacheAdapter = {\n load: (envKey: string) => Promise<FeatureFlarePersistentSnapshot | null> | FeatureFlarePersistentSnapshot | null;\n save: (envKey: string, snapshot: FeatureFlarePersistentSnapshot) => Promise<void> | void;\n};\n\nexport type FeatureFlareBootstrapPayload = {\n revision?: number;\n killSwitches?: string[];\n flags?:\n | Record<string, boolean>\n | Array<{ key: string; value: boolean; revision?: number; updatedAt?: number }>;\n};\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n timeoutMs?: number;\n maxRetries?: number;\n backoffMs?: number;\n jitter?: number;\n cacheTtlMs?: number;\n staleTtlMs?: number;\n bootstrap?: FeatureFlareBootstrapPayload;\n persistentCache?: FeatureFlarePersistentCacheAdapter;\n onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n realtime?: {\n enabled?: boolean;\n pollingIntervalMs?: number;\n ssePath?: string;\n };\n};\n\ntype CacheItem = {\n envKey: string;\n flagKey: string;\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source: FeatureFlareCacheSource;\n revision: number;\n};\n\ntype RealtimeEventPayload = {\n type: 'flag.updated' | 'flag.deleted' | 'env.kill_switch.updated' | 'snapshot.invalidate';\n timestamp?: number;\n revision?: number;\n data?: Record<string, unknown>;\n};\n\ntype FeatureFlareClientEvents = {\n update: { changedKeys: string[]; source: FeatureFlareCacheSource | 'network' };\n circuitOpen: { envKey: string; reason: string };\n circuitClose: { envKey: string };\n connectionState: { state: 'connected' | 'degraded' | 'offline'; transport: 'sse' | 'polling' | 'none' };\n};\n\nfunction getEnvKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_ENV_KEY?.trim() ||\n process.env.SHIPIT_ENV_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction monotonicNow(): number {\n if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nfunction normalizeBoolMap(\n input: { flags?: Array<{ key: string; value: boolean }>; values?: Record<string, boolean> }\n): Array<{ key: string; value: boolean }> {\n if (Array.isArray(input.flags)) {\n return input.flags\n .filter((entry): entry is { key: string; value: boolean } =>\n Boolean(entry) && typeof entry.key === 'string' && typeof entry.value === 'boolean'\n )\n .map((entry) => ({ key: entry.key, value: entry.value }));\n }\n\n const values = input.values ?? {};\n return Object.entries(values).map(([key, value]) => ({ key, value: Boolean(value) }));\n}\n\nexport class InMemoryMetricsCollector {\n private readonly buckets = new Map<string, number[]>();\n\n record = (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => {\n const key = `${metricName}:${JSON.stringify(tags ?? {})}`;\n const list = this.buckets.get(key) ?? [];\n list.push(value);\n this.buckets.set(key, list);\n };\n\n get(metricName: FeatureFlareMetricName): Array<{ tags: FeatureFlareMetricTags; values: number[] }> {\n const rows: Array<{ tags: FeatureFlareMetricTags; values: number[] }> = [];\n for (const [key, values] of this.buckets.entries()) {\n if (!key.startsWith(`${metricName}:`)) continue;\n rows.push({\n tags: JSON.parse(key.slice(metricName.length + 1)) as FeatureFlareMetricTags,\n values: [...values]\n });\n }\n return rows;\n }\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n private readonly expectedEnvKey: string | null;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly backoffMs: number;\n private readonly jitter: number;\n private readonly cacheTtlMs: number;\n private readonly staleTtlMs: number;\n private readonly persistentCache: FeatureFlarePersistentCacheAdapter | undefined;\n private readonly onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n private readonly listeners: {\n [K in keyof FeatureFlareClientEvents]: Set<(payload: FeatureFlareClientEvents[K]) => void>;\n } = {\n update: new Set(),\n circuitOpen: new Set(),\n circuitClose: new Set(),\n connectionState: new Set()\n };\n\n private readonly cache = new Map<string, CacheItem>();\n private readonly diagnostics = new Map<string, FeatureFlareEvaluationMetadata>();\n private readonly killSwitches = new Set<string>();\n\n private revision = 0;\n private circuitOpen = false;\n private persistentLoadPromise: Promise<void> | null = null;\n private readonly inFlightRevalidate = new Map<string, Promise<Array<{ key: string; value: boolean }> | null>>();\n private lastUser: FeatureFlareUser | null = null;\n private lastDefaultValue = false;\n\n private realtimeEnabled = true;\n private realtimePollingMs = 15000;\n private realtimeSsePath = '/api/v1/sdk/stream';\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private eventSource: EventSource | null = null;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n const explicitOrEnvKey = options.envKey?.trim() || getEnvKeyFromEnv() || null;\n this.envKey = explicitOrEnvKey ?? 'production';\n this.expectedEnvKey = explicitOrEnvKey;\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n\n this.timeoutMs = Number.isFinite(options.timeoutMs) && (options.timeoutMs ?? 0) > 0 ? Number(options.timeoutMs) : 3000;\n this.maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) >= 0 ? Number(options.maxRetries) : 2;\n this.backoffMs = Number.isFinite(options.backoffMs) && (options.backoffMs ?? 0) > 0 ? Number(options.backoffMs) : 200;\n this.jitter = Number.isFinite(options.jitter) && (options.jitter ?? 0) >= 0 ? Number(options.jitter) : 0.25;\n\n this.cacheTtlMs = Number.isFinite(options.cacheTtlMs) && (options.cacheTtlMs ?? 0) > 0 ? Number(options.cacheTtlMs) : 60000;\n const configuredStaleTtlMs =\n Number.isFinite(options.staleTtlMs) && (options.staleTtlMs ?? 0) > 0 ? Number(options.staleTtlMs) : 10000;\n this.staleTtlMs = Math.min(configuredStaleTtlMs, this.cacheTtlMs);\n\n this.persistentCache = options.persistentCache;\n this.onMetric = options.onMetric;\n\n this.realtimeEnabled = options.realtime?.enabled ?? true;\n this.realtimePollingMs =\n Number.isFinite(options.realtime?.pollingIntervalMs) && (options.realtime?.pollingIntervalMs ?? 0) > 0\n ? Number(options.realtime?.pollingIntervalMs)\n : 15000;\n this.realtimeSsePath = options.realtime?.ssePath ?? '/api/v1/sdk/stream';\n\n this.applyBootstrap(options.bootstrap);\n this.persistentLoadPromise = this.loadPersistentCache();\n\n if (this.realtimeEnabled && this.sdkKey) {\n this.startRealtime();\n }\n }\n\n private getCacheKey(flagKey: string): string {\n return `${this.envKey}:${flagKey}`;\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n private emit<K extends keyof FeatureFlareClientEvents>(event: K, payload: FeatureFlareClientEvents[K]): void {\n for (const listener of this.listeners[event]) {\n listener(payload);\n }\n }\n\n on<K extends keyof FeatureFlareClientEvents>(\n event: K,\n listener: (payload: FeatureFlareClientEvents[K]) => void\n ): () => void {\n this.listeners[event].add(listener);\n return () => {\n this.listeners[event].delete(listener);\n };\n }\n\n private emitMetric(metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags): void {\n this.onMetric?.(metricName, value, tags);\n }\n\n private async ensurePersistentLoaded(): Promise<void> {\n if (!this.persistentLoadPromise) return;\n await this.persistentLoadPromise;\n }\n\n private async loadPersistentCache(): Promise<void> {\n if (!this.persistentCache) return;\n try {\n const snapshot = await this.persistentCache.load(this.envKey);\n if (!snapshot) return;\n this.revision = Math.max(this.revision, snapshot.revision ?? 0);\n for (const killSwitchKey of snapshot.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n for (const [flagKey, item] of Object.entries(snapshot.flags ?? {})) {\n const existing = this.cache.get(this.getCacheKey(flagKey));\n if (existing && existing.source === 'bootstrap') continue;\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value: Boolean(item.value),\n updatedAt: Number(item.updatedAt) || Date.now(),\n staleAt: Number(item.staleAt) || Date.now(),\n expiresAt: Number(item.expiresAt) || Date.now(),\n source: item.source ?? 'persistent',\n revision: item.revision ?? 0\n });\n }\n } catch {\n // Ignore persistent cache failures; runtime must stay non-throwing for outage semantics.\n }\n }\n\n private async persistCache(): Promise<void> {\n if (!this.persistentCache) return;\n const snapshot: FeatureFlarePersistentSnapshot = {\n revision: this.revision,\n killSwitches: [...this.killSwitches],\n flags: {}\n };\n\n for (const [key, item] of this.cache.entries()) {\n if (!key.startsWith(`${this.envKey}:`)) continue;\n snapshot.flags[item.flagKey] = {\n value: item.value,\n updatedAt: item.updatedAt,\n staleAt: item.staleAt,\n expiresAt: item.expiresAt,\n source: item.source,\n revision: item.revision\n };\n }\n\n try {\n await this.persistentCache.save(this.envKey, snapshot);\n } catch {\n // Persistent errors must not break evaluation.\n }\n }\n\n private makeCacheWindow(at = Date.now()): Pick<CacheItem, 'updatedAt' | 'staleAt' | 'expiresAt'> {\n return {\n updatedAt: at,\n staleAt: at + this.staleTtlMs,\n expiresAt: at + this.cacheTtlMs\n };\n }\n\n private setCacheItem(\n flagKey: string,\n value: boolean,\n source: FeatureFlareCacheSource,\n revision = this.revision,\n at = Date.now()\n ): void {\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value,\n source,\n revision,\n ...this.makeCacheWindow(at)\n });\n }\n\n private applyBootstrap(bootstrap?: FeatureFlareBootstrapPayload): void {\n if (!bootstrap) return;\n this.revision = Math.max(this.revision, bootstrap.revision ?? 0);\n for (const killSwitchKey of bootstrap.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n const apply = (flagKey: string, value: boolean, revision?: number, updatedAt?: number) => {\n this.setCacheItem(flagKey, value, 'bootstrap', revision ?? this.revision, updatedAt ?? Date.now());\n };\n\n if (Array.isArray(bootstrap.flags)) {\n for (const item of bootstrap.flags) {\n if (!item || typeof item.key !== 'string') continue;\n apply(item.key, Boolean(item.value), item.revision, item.updatedAt);\n }\n return;\n }\n\n for (const [flagKey, value] of Object.entries(bootstrap.flags ?? {})) {\n apply(flagKey, Boolean(value));\n }\n }\n\n private getCacheState(item: CacheItem | undefined, now = Date.now()): 'fresh' | 'stale' | 'expired' | 'missing' {\n if (!item) return 'missing';\n if (now <= item.staleAt) return 'fresh';\n if (now <= item.expiresAt) return 'stale';\n return 'expired';\n }\n\n private setCircuitState(isOpen: boolean, reason = ''): void {\n if (this.circuitOpen === isOpen) return;\n this.circuitOpen = isOpen;\n if (isOpen) {\n this.emit('circuitOpen', { envKey: this.envKey, reason });\n return;\n }\n this.emit('circuitClose', { envKey: this.envKey });\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, transport: 'network' | 'polling') {\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const ac = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeout =\n ac !== null\n ? setTimeout(() => {\n ac.abort();\n }, this.timeoutMs)\n : null;\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: ac?.signal\n });\n\n if (timeout) clearTimeout(timeout);\n\n if (!response.ok && isRetriableStatus(response.status) && attempt < this.maxRetries) {\n lastError = new Error(`HTTP ${response.status}`);\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n continue;\n }\n\n return response;\n } catch (error) {\n if (timeout) clearTimeout(timeout);\n lastError = error;\n if (attempt >= this.maxRetries) break;\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n }\n }\n\n this.setCircuitState(true, transport);\n throw lastError;\n }\n\n private collectCachedFlags(): Array<{ key: string; value: boolean }> {\n const now = Date.now();\n const flags: Array<{ key: string; value: boolean }> = [];\n\n for (const [cacheKey, item] of this.cache.entries()) {\n if (!cacheKey.startsWith(`${this.envKey}:`)) continue;\n if (this.killSwitches.has(item.flagKey)) {\n flags.push({ key: item.flagKey, value: false });\n continue;\n }\n\n const state = this.getCacheState(item, now);\n if (state === 'missing' || state === 'expired') continue;\n flags.push({ key: item.flagKey, value: item.value });\n }\n\n return flags.sort((a, b) => a.key.localeCompare(b.key));\n }\n\n getCachedFlags(): {\n flags: Array<{ key: string; value: boolean }>;\n hasData: boolean;\n } {\n const flags = this.collectCachedFlags();\n return { flags, hasData: flags.length > 0 };\n }\n\n getFlagDiagnostics(flagKey: string): FeatureFlareEvaluationMetadata | null {\n return this.diagnostics.get(this.getCacheKey(flagKey)) ?? null;\n }\n\n setKillSwitch(flagKey: string, enabled: boolean): void {\n const started = monotonicNow();\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n const elapsed = monotonicNow() - started;\n this.emitMetric('ff_killswitch_apply_latency_ms', elapsed, {\n env: this.envKey,\n result: enabled ? 'enabled' : 'disabled'\n });\n this.emit('update', { changedKeys: [flagKey], source: 'realtime' });\n void this.persistCache();\n }\n\n private async fetchEvalFromNetwork(\n flagKey: string,\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean\n ): Promise<boolean | null> {\n const response = this.sdkKey\n ? await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/eval`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n 'network'\n )\n : await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/eval`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n },\n 'network'\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as { value?: boolean; revision?: number; killSwitch?: boolean };\n const value = typeof json.value === 'boolean' ? json.value : defaultValue;\n\n if (json.killSwitch === true) {\n this.killSwitches.add(flagKey);\n }\n\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n this.setCacheItem(flagKey, value, 'network', revision);\n this.setCircuitState(false);\n void this.persistCache();\n this.emit('update', { changedKeys: [flagKey], source: 'network' });\n return value;\n }\n\n private async fetchFlagsFromNetwork(\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean,\n transport: 'network' | 'polling'\n ): Promise<Array<{ key: string; value: boolean }> | null> {\n if (!this.sdkKey) {\n return null;\n }\n\n const started = monotonicNow();\n\n try {\n const response = await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/flags`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n transport\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as {\n flags?: Array<{ key: string; value: boolean }>;\n values?: Record<string, boolean>;\n revision?: number;\n killSwitches?: string[];\n };\n\n const list = normalizeBoolMap(json);\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n\n if (Array.isArray(json.killSwitches)) {\n for (const key of json.killSwitches) {\n this.killSwitches.add(key);\n }\n }\n\n const changed = new Set<string>();\n for (const entry of list) {\n const existing = this.cache.get(this.getCacheKey(entry.key));\n if (!existing || existing.value !== entry.value || existing.revision !== revision) {\n changed.add(entry.key);\n }\n this.setCacheItem(entry.key, entry.value, 'network', revision);\n }\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'network' });\n }\n\n this.setCircuitState(false);\n void this.persistCache();\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport\n });\n return list;\n } catch {\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport,\n result: 'error'\n });\n return null;\n }\n }\n\n private revalidate(normalizedUser: FeatureFlareUser, defaultValue: boolean): Promise<Array<{ key: string; value: boolean }> | null> {\n const existing = this.inFlightRevalidate.get(this.envKey);\n if (existing) return existing;\n\n const promise = this.fetchFlagsFromNetwork(normalizedUser, defaultValue, 'network').finally(() => {\n this.inFlightRevalidate.delete(this.envKey);\n });\n\n this.inFlightRevalidate.set(this.envKey, promise);\n return promise;\n }\n\n async evaluate(\n flagKey: string,\n user: FeatureFlareUserPayload,\n defaultValue = false\n ): Promise<FeatureFlareEvaluationResult> {\n const started = monotonicNow();\n await this.ensurePersistentLoaded();\n\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n if (this.killSwitches.has(flagKey)) {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'kill_switch',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'kill_switch'\n };\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'disabled'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: false, metadata };\n }\n\n const cacheItem = this.cache.get(this.getCacheKey(flagKey));\n const cacheState = this.getCacheState(cacheItem);\n\n if (cacheItem && cacheState === 'fresh') {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent' ? 'bootstrap' : 'fresh_cache',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'cache_hit'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && cacheState === 'stale') {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'stale_cache',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'stale'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && (cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent')) {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'bootstrap',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'bootstrap'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n try {\n const networkValue = await this.fetchEvalFromNetwork(flagKey, normalizedUser, defaultValue);\n if (networkValue !== null) {\n const item = this.cache.get(this.getCacheKey(flagKey));\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'network',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'network',\n updatedAt: item?.updatedAt,\n staleAt: item?.staleAt,\n expiresAt: item?.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'network'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: networkValue, metadata };\n }\n } catch {\n // Fall through to deterministic default for outage semantics.\n }\n\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'default',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'default'\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'default'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: defaultValue, metadata };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const result = await this.evaluate(flagKey, user, defaultValue);\n return result.value;\n }\n\n async flags(user: FeatureFlareUserPayload, defaultValue = false): Promise<Array<{ key: string; value: boolean }>> {\n await this.ensurePersistentLoaded();\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n const list = await this.revalidate(normalizedUser, defaultValue);\n if (list && list.length > 0) {\n return list.map((entry) => ({\n key: entry.key,\n value: this.killSwitches.has(entry.key) ? false : entry.value\n }));\n }\n\n const cached = this.collectCachedFlags();\n if (cached.length > 0) return cached;\n return [];\n }\n\n private applyRealtimeMessage(message: RealtimeEventPayload): void {\n if (typeof message.revision === 'number' && message.revision < this.revision) {\n return;\n }\n\n if (typeof message.revision === 'number') {\n this.revision = message.revision;\n }\n\n const changed = new Set<string>();\n const now = Date.now();\n\n if (message.type === 'flag.updated') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const value = typeof message.data?.value === 'boolean' ? message.data.value : null;\n if (flagKey !== null && value !== null) {\n this.setCacheItem(flagKey, value, 'realtime', message.revision ?? this.revision, now);\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'flag.deleted') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n if (flagKey !== null) {\n this.cache.delete(this.getCacheKey(flagKey));\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'env.kill_switch.updated') {\n const started = monotonicNow();\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const enabled = typeof message.data?.enabled === 'boolean' ? message.data.enabled : true;\n if (flagKey !== null) {\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n changed.add(flagKey);\n this.emitMetric('ff_killswitch_apply_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling',\n result: enabled ? 'enabled' : 'disabled'\n });\n }\n }\n\n if (message.type === 'snapshot.invalidate' && this.lastUser) {\n void this.revalidate(this.lastUser, this.lastDefaultValue);\n }\n\n const eventLagMs = Math.max(0, Date.now() - (message.timestamp ?? Date.now()));\n this.emitMetric('ff_realtime_lag_ms', eventLagMs, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling'\n });\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'realtime' });\n void this.persistCache();\n }\n }\n\n private startPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n const tick = async () => {\n if (!this.lastUser) {\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n return;\n }\n await this.fetchFlagsFromNetwork(this.lastUser, this.lastDefaultValue, 'polling');\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n };\n\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n }\n\n private connectSse(attempt = 0): void {\n const EventSourceImpl = typeof EventSource !== 'undefined' ? EventSource : null;\n if (!EventSourceImpl || !this.sdkKey) {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.startPolling();\n return;\n }\n\n const url = new URL(this.realtimeSsePath, this.apiBaseUrl);\n url.searchParams.set('sdkKey', this.sdkKey);\n url.searchParams.set('envKey', this.envKey);\n\n this.eventSource = new EventSourceImpl(url.toString());\n\n this.eventSource.onopen = () => {\n this.emit('connectionState', { state: 'connected', transport: 'sse' });\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n };\n\n this.eventSource.onmessage = (event: MessageEvent) => {\n try {\n const payload = JSON.parse(String(event.data)) as RealtimeEventPayload;\n this.applyRealtimeMessage(payload);\n } catch {\n // Ignore malformed realtime messages.\n }\n };\n\n this.eventSource.onerror = () => {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.eventSource?.close();\n this.eventSource = null;\n this.startPolling();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const backoff = Math.min(this.backoffMs * (attempt + 1), 30000);\n this.reconnectTimer = setTimeout(() => {\n this.connectSse(attempt + 1);\n }, backoff);\n };\n }\n\n startRealtime(): void {\n this.realtimeEnabled = true;\n this.connectSse(0);\n }\n\n stopRealtime(): void {\n this.realtimeEnabled = false;\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.emit('connectionState', { state: 'offline', transport: 'none' });\n }\n\n dispose(): void {\n this.stopRealtime();\n this.listeners.update.clear();\n this.listeners.circuitOpen.clear();\n this.listeners.circuitClose.clear();\n this.listeners.connectionState.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["metadata"],"mappings":"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","file":"index.cjs","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareCacheSource = 'bootstrap' | 'network' | 'realtime' | 'persistent';\nexport type FeatureFlareEvaluationReason = 'fresh_cache' | 'stale_cache' | 'bootstrap' | 'default' | 'network' | 'kill_switch';\n\nexport type FeatureFlareEvaluationMetadata = {\n reason: FeatureFlareEvaluationReason;\n isStale: boolean;\n latencyMs: number;\n source: FeatureFlareCacheSource | 'default' | 'kill_switch';\n updatedAt?: number;\n staleAt?: number;\n expiresAt?: number;\n};\n\nexport type FeatureFlareEvaluationResult = {\n value: boolean;\n metadata: FeatureFlareEvaluationMetadata;\n};\n\nexport type FeatureFlareMetricName =\n | 'ff_eval_latency_ms'\n | 'ff_cache_hit_ratio'\n | 'ff_revalidate_latency_ms'\n | 'ff_realtime_lag_ms'\n | 'ff_killswitch_apply_latency_ms';\n\nexport type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;\n\nexport type FeatureFlareErrorReport = {\n /** The flag key being evaluated when the error was observed. */\n flagKey: string;\n /** Observed error rate as a fraction from 0 to 1 (e.g. 0.05 = 5%). */\n errorRate: number;\n /** Observed p99 latency in milliseconds. */\n latencyMs?: number;\n /** ISO-8601 timestamp of the observation window end. Defaults to now. */\n observedAt?: string;\n /** Optional free-form context about the error (e.g. HTTP status, exception name). */\n context?: Record<string, string | number | boolean>;\n};\n\nexport type FeatureFlarePersistentSnapshot = {\n revision?: number;\n killSwitches?: string[];\n flags: Record<\n string,\n {\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source?: FeatureFlareCacheSource;\n revision?: number;\n }\n >;\n};\n\nexport type FeatureFlarePersistentCacheAdapter = {\n load: (envKey: string) => Promise<FeatureFlarePersistentSnapshot | null> | FeatureFlarePersistentSnapshot | null;\n save: (envKey: string, snapshot: FeatureFlarePersistentSnapshot) => Promise<void> | void;\n};\n\nexport type FeatureFlareBootstrapPayload = {\n revision?: number;\n killSwitches?: string[];\n flags?:\n | Record<string, boolean>\n | Array<{ key: string; value: boolean; revision?: number; updatedAt?: number }>;\n};\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n timeoutMs?: number;\n maxRetries?: number;\n backoffMs?: number;\n jitter?: number;\n cacheTtlMs?: number;\n staleTtlMs?: number;\n bootstrap?: FeatureFlareBootstrapPayload;\n persistentCache?: FeatureFlarePersistentCacheAdapter;\n onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n realtime?: {\n enabled?: boolean;\n pollingIntervalMs?: number;\n ssePath?: string;\n };\n};\n\ntype CacheItem = {\n envKey: string;\n flagKey: string;\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source: FeatureFlareCacheSource;\n revision: number;\n};\n\ntype RealtimeEventPayload = {\n type: 'flag.updated' | 'flag.deleted' | 'env.kill_switch.updated' | 'snapshot.invalidate';\n timestamp?: number;\n revision?: number;\n data?: Record<string, unknown>;\n};\n\ntype FeatureFlareClientEvents = {\n update: { changedKeys: string[]; source: FeatureFlareCacheSource | 'network' };\n circuitOpen: { envKey: string; reason: string };\n circuitClose: { envKey: string };\n connectionState: { state: 'connected' | 'degraded' | 'offline'; transport: 'sse' | 'polling' | 'none' };\n};\n\nfunction getEnvKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_ENV_KEY?.trim() ||\n process.env.SHIPIT_ENV_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction monotonicNow(): number {\n if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nfunction normalizeBoolMap(\n input: { flags?: Array<{ key: string; value: boolean }>; values?: Record<string, boolean> }\n): Array<{ key: string; value: boolean }> {\n if (Array.isArray(input.flags)) {\n return input.flags\n .filter((entry): entry is { key: string; value: boolean } =>\n Boolean(entry) && typeof entry.key === 'string' && typeof entry.value === 'boolean'\n )\n .map((entry) => ({ key: entry.key, value: entry.value }));\n }\n\n const values = input.values ?? {};\n return Object.entries(values).map(([key, value]) => ({ key, value: Boolean(value) }));\n}\n\nexport class InMemoryMetricsCollector {\n private readonly buckets = new Map<string, number[]>();\n\n record = (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => {\n const key = `${metricName}:${JSON.stringify(tags ?? {})}`;\n const list = this.buckets.get(key) ?? [];\n list.push(value);\n this.buckets.set(key, list);\n };\n\n get(metricName: FeatureFlareMetricName): Array<{ tags: FeatureFlareMetricTags; values: number[] }> {\n const rows: Array<{ tags: FeatureFlareMetricTags; values: number[] }> = [];\n for (const [key, values] of this.buckets.entries()) {\n if (!key.startsWith(`${metricName}:`)) continue;\n rows.push({\n tags: JSON.parse(key.slice(metricName.length + 1)) as FeatureFlareMetricTags,\n values: [...values]\n });\n }\n return rows;\n }\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n private readonly expectedEnvKey: string | null;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly backoffMs: number;\n private readonly jitter: number;\n private readonly cacheTtlMs: number;\n private readonly staleTtlMs: number;\n private readonly persistentCache: FeatureFlarePersistentCacheAdapter | undefined;\n private readonly onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n private readonly listeners: {\n [K in keyof FeatureFlareClientEvents]: Set<(payload: FeatureFlareClientEvents[K]) => void>;\n } = {\n update: new Set(),\n circuitOpen: new Set(),\n circuitClose: new Set(),\n connectionState: new Set()\n };\n\n private readonly cache = new Map<string, CacheItem>();\n private readonly diagnostics = new Map<string, FeatureFlareEvaluationMetadata>();\n private readonly killSwitches = new Set<string>();\n\n private revision = 0;\n private circuitOpen = false;\n private persistentLoadPromise: Promise<void> | null = null;\n private readonly inFlightRevalidate = new Map<string, Promise<Array<{ key: string; value: boolean }> | null>>();\n private lastUser: FeatureFlareUser | null = null;\n private lastDefaultValue = false;\n\n private realtimeEnabled = true;\n private realtimePollingMs = 15000;\n private realtimeSsePath = '/api/v1/sdk/stream';\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private eventSource: EventSource | null = null;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n const explicitOrEnvKey = options.envKey?.trim() || getEnvKeyFromEnv() || null;\n this.envKey = explicitOrEnvKey ?? 'production';\n this.expectedEnvKey = explicitOrEnvKey;\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n\n this.timeoutMs = Number.isFinite(options.timeoutMs) && (options.timeoutMs ?? 0) > 0 ? Number(options.timeoutMs) : 3000;\n this.maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) >= 0 ? Number(options.maxRetries) : 2;\n this.backoffMs = Number.isFinite(options.backoffMs) && (options.backoffMs ?? 0) > 0 ? Number(options.backoffMs) : 200;\n this.jitter = Number.isFinite(options.jitter) && (options.jitter ?? 0) >= 0 ? Number(options.jitter) : 0.25;\n\n this.cacheTtlMs = Number.isFinite(options.cacheTtlMs) && (options.cacheTtlMs ?? 0) > 0 ? Number(options.cacheTtlMs) : 60000;\n const configuredStaleTtlMs =\n Number.isFinite(options.staleTtlMs) && (options.staleTtlMs ?? 0) > 0 ? Number(options.staleTtlMs) : 10000;\n this.staleTtlMs = Math.min(configuredStaleTtlMs, this.cacheTtlMs);\n\n this.persistentCache = options.persistentCache;\n this.onMetric = options.onMetric;\n\n this.realtimeEnabled = options.realtime?.enabled ?? true;\n this.realtimePollingMs =\n Number.isFinite(options.realtime?.pollingIntervalMs) && (options.realtime?.pollingIntervalMs ?? 0) > 0\n ? Number(options.realtime?.pollingIntervalMs)\n : 15000;\n this.realtimeSsePath = options.realtime?.ssePath ?? '/api/v1/sdk/stream';\n\n this.applyBootstrap(options.bootstrap);\n this.persistentLoadPromise = this.loadPersistentCache();\n\n if (this.realtimeEnabled && this.sdkKey) {\n this.startRealtime();\n }\n }\n\n private getCacheKey(flagKey: string): string {\n return `${this.envKey}:${flagKey}`;\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n private emit<K extends keyof FeatureFlareClientEvents>(event: K, payload: FeatureFlareClientEvents[K]): void {\n for (const listener of this.listeners[event]) {\n listener(payload);\n }\n }\n\n on<K extends keyof FeatureFlareClientEvents>(\n event: K,\n listener: (payload: FeatureFlareClientEvents[K]) => void\n ): () => void {\n this.listeners[event].add(listener);\n return () => {\n this.listeners[event].delete(listener);\n };\n }\n\n private emitMetric(metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags): void {\n this.onMetric?.(metricName, value, tags);\n }\n\n private async ensurePersistentLoaded(): Promise<void> {\n if (!this.persistentLoadPromise) return;\n await this.persistentLoadPromise;\n }\n\n private async loadPersistentCache(): Promise<void> {\n if (!this.persistentCache) return;\n try {\n const snapshot = await this.persistentCache.load(this.envKey);\n if (!snapshot) return;\n this.revision = Math.max(this.revision, snapshot.revision ?? 0);\n for (const killSwitchKey of snapshot.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n for (const [flagKey, item] of Object.entries(snapshot.flags ?? {})) {\n const existing = this.cache.get(this.getCacheKey(flagKey));\n if (existing && existing.source === 'bootstrap') continue;\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value: Boolean(item.value),\n updatedAt: Number(item.updatedAt) || Date.now(),\n staleAt: Number(item.staleAt) || Date.now(),\n expiresAt: Number(item.expiresAt) || Date.now(),\n source: item.source ?? 'persistent',\n revision: item.revision ?? 0\n });\n }\n } catch {\n // Ignore persistent cache failures; runtime must stay non-throwing for outage semantics.\n }\n }\n\n private async persistCache(): Promise<void> {\n if (!this.persistentCache) return;\n const snapshot: FeatureFlarePersistentSnapshot = {\n revision: this.revision,\n killSwitches: [...this.killSwitches],\n flags: {}\n };\n\n for (const [key, item] of this.cache.entries()) {\n if (!key.startsWith(`${this.envKey}:`)) continue;\n snapshot.flags[item.flagKey] = {\n value: item.value,\n updatedAt: item.updatedAt,\n staleAt: item.staleAt,\n expiresAt: item.expiresAt,\n source: item.source,\n revision: item.revision\n };\n }\n\n try {\n await this.persistentCache.save(this.envKey, snapshot);\n } catch {\n // Persistent errors must not break evaluation.\n }\n }\n\n private makeCacheWindow(at = Date.now()): Pick<CacheItem, 'updatedAt' | 'staleAt' | 'expiresAt'> {\n return {\n updatedAt: at,\n staleAt: at + this.staleTtlMs,\n expiresAt: at + this.cacheTtlMs\n };\n }\n\n private setCacheItem(\n flagKey: string,\n value: boolean,\n source: FeatureFlareCacheSource,\n revision = this.revision,\n at = Date.now()\n ): void {\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value,\n source,\n revision,\n ...this.makeCacheWindow(at)\n });\n }\n\n private applyBootstrap(bootstrap?: FeatureFlareBootstrapPayload): void {\n if (!bootstrap) return;\n this.revision = Math.max(this.revision, bootstrap.revision ?? 0);\n for (const killSwitchKey of bootstrap.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n const apply = (flagKey: string, value: boolean, revision?: number, updatedAt?: number) => {\n this.setCacheItem(flagKey, value, 'bootstrap', revision ?? this.revision, updatedAt ?? Date.now());\n };\n\n if (Array.isArray(bootstrap.flags)) {\n for (const item of bootstrap.flags) {\n if (!item || typeof item.key !== 'string') continue;\n apply(item.key, Boolean(item.value), item.revision, item.updatedAt);\n }\n return;\n }\n\n for (const [flagKey, value] of Object.entries(bootstrap.flags ?? {})) {\n apply(flagKey, Boolean(value));\n }\n }\n\n private getCacheState(item: CacheItem | undefined, now = Date.now()): 'fresh' | 'stale' | 'expired' | 'missing' {\n if (!item) return 'missing';\n if (now <= item.staleAt) return 'fresh';\n if (now <= item.expiresAt) return 'stale';\n return 'expired';\n }\n\n private setCircuitState(isOpen: boolean, reason = ''): void {\n if (this.circuitOpen === isOpen) return;\n this.circuitOpen = isOpen;\n if (isOpen) {\n this.emit('circuitOpen', { envKey: this.envKey, reason });\n return;\n }\n this.emit('circuitClose', { envKey: this.envKey });\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, transport: 'network' | 'polling') {\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const ac = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeout =\n ac !== null\n ? setTimeout(() => {\n ac.abort();\n }, this.timeoutMs)\n : null;\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: ac?.signal\n });\n\n if (timeout) clearTimeout(timeout);\n\n if (!response.ok && isRetriableStatus(response.status) && attempt < this.maxRetries) {\n lastError = new Error(`HTTP ${response.status}`);\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n continue;\n }\n\n return response;\n } catch (error) {\n if (timeout) clearTimeout(timeout);\n lastError = error;\n if (attempt >= this.maxRetries) break;\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n }\n }\n\n this.setCircuitState(true, transport);\n throw lastError;\n }\n\n private collectCachedFlags(): Array<{ key: string; value: boolean }> {\n const now = Date.now();\n const flags: Array<{ key: string; value: boolean }> = [];\n\n for (const [cacheKey, item] of this.cache.entries()) {\n if (!cacheKey.startsWith(`${this.envKey}:`)) continue;\n if (this.killSwitches.has(item.flagKey)) {\n flags.push({ key: item.flagKey, value: false });\n continue;\n }\n\n const state = this.getCacheState(item, now);\n if (state === 'missing' || state === 'expired') continue;\n flags.push({ key: item.flagKey, value: item.value });\n }\n\n return flags.sort((a, b) => a.key.localeCompare(b.key));\n }\n\n getCachedFlags(): {\n flags: Array<{ key: string; value: boolean }>;\n hasData: boolean;\n } {\n const flags = this.collectCachedFlags();\n return { flags, hasData: flags.length > 0 };\n }\n\n getFlagDiagnostics(flagKey: string): FeatureFlareEvaluationMetadata | null {\n return this.diagnostics.get(this.getCacheKey(flagKey)) ?? null;\n }\n\n setKillSwitch(flagKey: string, enabled: boolean): void {\n const started = monotonicNow();\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n const elapsed = monotonicNow() - started;\n this.emitMetric('ff_killswitch_apply_latency_ms', elapsed, {\n env: this.envKey,\n result: enabled ? 'enabled' : 'disabled'\n });\n this.emit('update', { changedKeys: [flagKey], source: 'realtime' });\n void this.persistCache();\n }\n\n private async fetchEvalFromNetwork(\n flagKey: string,\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean\n ): Promise<boolean | null> {\n const response = this.sdkKey\n ? await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/eval`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n 'network'\n )\n : await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/eval`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n },\n 'network'\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as { value?: boolean; revision?: number; killSwitch?: boolean };\n const value = typeof json.value === 'boolean' ? json.value : defaultValue;\n\n if (json.killSwitch === true) {\n this.killSwitches.add(flagKey);\n }\n\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n this.setCacheItem(flagKey, value, 'network', revision);\n this.setCircuitState(false);\n void this.persistCache();\n this.emit('update', { changedKeys: [flagKey], source: 'network' });\n return value;\n }\n\n private async fetchFlagsFromNetwork(\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean,\n transport: 'network' | 'polling'\n ): Promise<Array<{ key: string; value: boolean }> | null> {\n if (!this.sdkKey) {\n return null;\n }\n\n const started = monotonicNow();\n\n try {\n const response = await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/flags`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n transport\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as {\n flags?: Array<{ key: string; value: boolean }>;\n values?: Record<string, boolean>;\n revision?: number;\n killSwitches?: string[];\n };\n\n const list = normalizeBoolMap(json);\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n\n if (Array.isArray(json.killSwitches)) {\n for (const key of json.killSwitches) {\n this.killSwitches.add(key);\n }\n }\n\n const changed = new Set<string>();\n for (const entry of list) {\n const existing = this.cache.get(this.getCacheKey(entry.key));\n if (!existing || existing.value !== entry.value || existing.revision !== revision) {\n changed.add(entry.key);\n }\n this.setCacheItem(entry.key, entry.value, 'network', revision);\n }\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'network' });\n }\n\n this.setCircuitState(false);\n void this.persistCache();\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport\n });\n return list;\n } catch {\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport,\n result: 'error'\n });\n return null;\n }\n }\n\n private revalidate(normalizedUser: FeatureFlareUser, defaultValue: boolean): Promise<Array<{ key: string; value: boolean }> | null> {\n const existing = this.inFlightRevalidate.get(this.envKey);\n if (existing) return existing;\n\n const promise = this.fetchFlagsFromNetwork(normalizedUser, defaultValue, 'network').finally(() => {\n this.inFlightRevalidate.delete(this.envKey);\n });\n\n this.inFlightRevalidate.set(this.envKey, promise);\n return promise;\n }\n\n async evaluate(\n flagKey: string,\n user: FeatureFlareUserPayload,\n defaultValue = false\n ): Promise<FeatureFlareEvaluationResult> {\n const started = monotonicNow();\n await this.ensurePersistentLoaded();\n\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n if (this.killSwitches.has(flagKey)) {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'kill_switch',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'kill_switch'\n };\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'disabled'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: false, metadata };\n }\n\n const cacheItem = this.cache.get(this.getCacheKey(flagKey));\n const cacheState = this.getCacheState(cacheItem);\n\n if (cacheItem && cacheState === 'fresh') {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent' ? 'bootstrap' : 'fresh_cache',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'cache_hit'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && cacheState === 'stale') {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'stale_cache',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'stale'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && (cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent')) {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'bootstrap',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'bootstrap'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n try {\n const networkValue = await this.fetchEvalFromNetwork(flagKey, normalizedUser, defaultValue);\n if (networkValue !== null) {\n const item = this.cache.get(this.getCacheKey(flagKey));\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'network',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'network',\n updatedAt: item?.updatedAt,\n staleAt: item?.staleAt,\n expiresAt: item?.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'network'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: networkValue, metadata };\n }\n } catch {\n // Fall through to deterministic default for outage semantics.\n }\n\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'default',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'default'\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'default'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: defaultValue, metadata };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const result = await this.evaluate(flagKey, user, defaultValue);\n return result.value;\n }\n\n async flags(user: FeatureFlareUserPayload, defaultValue = false): Promise<Array<{ key: string; value: boolean }>> {\n await this.ensurePersistentLoaded();\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n const list = await this.revalidate(normalizedUser, defaultValue);\n if (list && list.length > 0) {\n return list.map((entry) => ({\n key: entry.key,\n value: this.killSwitches.has(entry.key) ? false : entry.value\n }));\n }\n\n const cached = this.collectCachedFlags();\n if (cached.length > 0) return cached;\n return [];\n }\n\n private applyRealtimeMessage(message: RealtimeEventPayload): void {\n if (typeof message.revision === 'number' && message.revision < this.revision) {\n return;\n }\n\n if (typeof message.revision === 'number') {\n this.revision = message.revision;\n }\n\n const changed = new Set<string>();\n const now = Date.now();\n\n if (message.type === 'flag.updated') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const value = typeof message.data?.value === 'boolean' ? message.data.value : null;\n if (flagKey !== null && value !== null) {\n this.setCacheItem(flagKey, value, 'realtime', message.revision ?? this.revision, now);\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'flag.deleted') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n if (flagKey !== null) {\n this.cache.delete(this.getCacheKey(flagKey));\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'env.kill_switch.updated') {\n const started = monotonicNow();\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const enabled = typeof message.data?.enabled === 'boolean' ? message.data.enabled : true;\n if (flagKey !== null) {\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n changed.add(flagKey);\n this.emitMetric('ff_killswitch_apply_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling',\n result: enabled ? 'enabled' : 'disabled'\n });\n }\n }\n\n if (message.type === 'snapshot.invalidate' && this.lastUser) {\n void this.revalidate(this.lastUser, this.lastDefaultValue);\n }\n\n const eventLagMs = Math.max(0, Date.now() - (message.timestamp ?? Date.now()));\n this.emitMetric('ff_realtime_lag_ms', eventLagMs, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling'\n });\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'realtime' });\n void this.persistCache();\n }\n }\n\n private startPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n const tick = async () => {\n if (!this.lastUser) {\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n return;\n }\n await this.fetchFlagsFromNetwork(this.lastUser, this.lastDefaultValue, 'polling');\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n };\n\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n }\n\n private connectSse(attempt = 0): void {\n const EventSourceImpl = typeof EventSource !== 'undefined' ? EventSource : null;\n if (!EventSourceImpl || !this.sdkKey) {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.startPolling();\n return;\n }\n\n const url = new URL(this.realtimeSsePath, this.apiBaseUrl);\n url.searchParams.set('sdkKey', this.sdkKey);\n if (this.expectedEnvKey) {\n url.searchParams.set('expectedEnvKey', this.expectedEnvKey);\n }\n\n this.eventSource = new EventSourceImpl(url.toString());\n\n this.eventSource.onopen = () => {\n this.emit('connectionState', { state: 'connected', transport: 'sse' });\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n };\n\n this.eventSource.onmessage = (event: MessageEvent) => {\n try {\n const payload = JSON.parse(String(event.data)) as RealtimeEventPayload;\n this.applyRealtimeMessage(payload);\n } catch {\n // Ignore malformed realtime messages.\n }\n };\n\n this.eventSource.onerror = () => {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.eventSource?.close();\n this.eventSource = null;\n this.startPolling();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const backoff = Math.min(this.backoffMs * (attempt + 1), 30000);\n this.reconnectTimer = setTimeout(() => {\n this.connectSse(attempt + 1);\n }, backoff);\n };\n }\n\n startRealtime(): void {\n this.realtimeEnabled = true;\n this.connectSse(0);\n }\n\n stopRealtime(): void {\n this.realtimeEnabled = false;\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.emit('connectionState', { state: 'offline', transport: 'none' });\n }\n\n /**\n * Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.\n * The API evaluates the report against active rollback policies and may trigger an automated\n * rollback if configured thresholds are breached.\n *\n * Errors from this call are silently swallowed so that reporting never disrupts the host application.\n */\n async reportError(report: FeatureFlareErrorReport): Promise<void> {\n if (!this.sdkKey) return;\n try {\n await fetch(`${this.apiBaseUrl}/api/v1/sdk/report`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey: report.flagKey,\n errorRate: report.errorRate,\n latencyMs: report.latencyMs,\n observedAt: report.observedAt ?? new Date().toISOString(),\n envKey: this.envKey,\n context: report.context\n })\n });\n } catch {\n // Reporting failures must never surface to the caller.\n }\n }\n\n dispose(): void {\n this.stopRealtime();\n this.listeners.update.clear();\n this.listeners.circuitOpen.clear();\n this.listeners.circuitClose.clear();\n this.listeners.connectionState.clear();\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,18 @@ type FeatureFlareEvaluationResult = {
|
|
|
28
28
|
};
|
|
29
29
|
type FeatureFlareMetricName = 'ff_eval_latency_ms' | 'ff_cache_hit_ratio' | 'ff_revalidate_latency_ms' | 'ff_realtime_lag_ms' | 'ff_killswitch_apply_latency_ms';
|
|
30
30
|
type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;
|
|
31
|
+
type FeatureFlareErrorReport = {
|
|
32
|
+
/** The flag key being evaluated when the error was observed. */
|
|
33
|
+
flagKey: string;
|
|
34
|
+
/** Observed error rate as a fraction from 0 to 1 (e.g. 0.05 = 5%). */
|
|
35
|
+
errorRate: number;
|
|
36
|
+
/** Observed p99 latency in milliseconds. */
|
|
37
|
+
latencyMs?: number;
|
|
38
|
+
/** ISO-8601 timestamp of the observation window end. Defaults to now. */
|
|
39
|
+
observedAt?: string;
|
|
40
|
+
/** Optional free-form context about the error (e.g. HTTP status, exception name). */
|
|
41
|
+
context?: Record<string, string | number | boolean>;
|
|
42
|
+
};
|
|
31
43
|
type FeatureFlarePersistentSnapshot = {
|
|
32
44
|
revision?: number;
|
|
33
45
|
killSwitches?: string[];
|
|
@@ -168,7 +180,15 @@ declare class FeatureFlareClient {
|
|
|
168
180
|
private connectSse;
|
|
169
181
|
startRealtime(): void;
|
|
170
182
|
stopRealtime(): void;
|
|
183
|
+
/**
|
|
184
|
+
* Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.
|
|
185
|
+
* The API evaluates the report against active rollback policies and may trigger an automated
|
|
186
|
+
* rollback if configured thresholds are breached.
|
|
187
|
+
*
|
|
188
|
+
* Errors from this call are silently swallowed so that reporting never disrupts the host application.
|
|
189
|
+
*/
|
|
190
|
+
reportError(report: FeatureFlareErrorReport): Promise<void>;
|
|
171
191
|
dispose(): void;
|
|
172
192
|
}
|
|
173
193
|
|
|
174
|
-
export { type FeatureFlareBootstrapPayload, type FeatureFlareCacheSource, FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareEvaluationMetadata, type FeatureFlareEvaluationReason, type FeatureFlareEvaluationResult, type FeatureFlareMetricName, type FeatureFlareMetricTags, type FeatureFlarePersistentCacheAdapter, type FeatureFlarePersistentSnapshot, type FeatureFlareUserPayload, InMemoryMetricsCollector };
|
|
194
|
+
export { type FeatureFlareBootstrapPayload, type FeatureFlareCacheSource, FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareErrorReport, type FeatureFlareEvaluationMetadata, type FeatureFlareEvaluationReason, type FeatureFlareEvaluationResult, type FeatureFlareMetricName, type FeatureFlareMetricTags, type FeatureFlarePersistentCacheAdapter, type FeatureFlarePersistentSnapshot, type FeatureFlareUserPayload, InMemoryMetricsCollector };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,18 @@ type FeatureFlareEvaluationResult = {
|
|
|
28
28
|
};
|
|
29
29
|
type FeatureFlareMetricName = 'ff_eval_latency_ms' | 'ff_cache_hit_ratio' | 'ff_revalidate_latency_ms' | 'ff_realtime_lag_ms' | 'ff_killswitch_apply_latency_ms';
|
|
30
30
|
type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;
|
|
31
|
+
type FeatureFlareErrorReport = {
|
|
32
|
+
/** The flag key being evaluated when the error was observed. */
|
|
33
|
+
flagKey: string;
|
|
34
|
+
/** Observed error rate as a fraction from 0 to 1 (e.g. 0.05 = 5%). */
|
|
35
|
+
errorRate: number;
|
|
36
|
+
/** Observed p99 latency in milliseconds. */
|
|
37
|
+
latencyMs?: number;
|
|
38
|
+
/** ISO-8601 timestamp of the observation window end. Defaults to now. */
|
|
39
|
+
observedAt?: string;
|
|
40
|
+
/** Optional free-form context about the error (e.g. HTTP status, exception name). */
|
|
41
|
+
context?: Record<string, string | number | boolean>;
|
|
42
|
+
};
|
|
31
43
|
type FeatureFlarePersistentSnapshot = {
|
|
32
44
|
revision?: number;
|
|
33
45
|
killSwitches?: string[];
|
|
@@ -168,7 +180,15 @@ declare class FeatureFlareClient {
|
|
|
168
180
|
private connectSse;
|
|
169
181
|
startRealtime(): void;
|
|
170
182
|
stopRealtime(): void;
|
|
183
|
+
/**
|
|
184
|
+
* Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.
|
|
185
|
+
* The API evaluates the report against active rollback policies and may trigger an automated
|
|
186
|
+
* rollback if configured thresholds are breached.
|
|
187
|
+
*
|
|
188
|
+
* Errors from this call are silently swallowed so that reporting never disrupts the host application.
|
|
189
|
+
*/
|
|
190
|
+
reportError(report: FeatureFlareErrorReport): Promise<void>;
|
|
171
191
|
dispose(): void;
|
|
172
192
|
}
|
|
173
193
|
|
|
174
|
-
export { type FeatureFlareBootstrapPayload, type FeatureFlareCacheSource, FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareEvaluationMetadata, type FeatureFlareEvaluationReason, type FeatureFlareEvaluationResult, type FeatureFlareMetricName, type FeatureFlareMetricTags, type FeatureFlarePersistentCacheAdapter, type FeatureFlarePersistentSnapshot, type FeatureFlareUserPayload, InMemoryMetricsCollector };
|
|
194
|
+
export { type FeatureFlareBootstrapPayload, type FeatureFlareCacheSource, FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareErrorReport, type FeatureFlareEvaluationMetadata, type FeatureFlareEvaluationReason, type FeatureFlareEvaluationResult, type FeatureFlareMetricName, type FeatureFlareMetricTags, type FeatureFlarePersistentCacheAdapter, type FeatureFlarePersistentSnapshot, type FeatureFlareUserPayload, InMemoryMetricsCollector };
|
package/dist/index.js
CHANGED
|
@@ -678,7 +678,9 @@ var FeatureFlareClient = class {
|
|
|
678
678
|
}
|
|
679
679
|
const url = new URL(this.realtimeSsePath, this.apiBaseUrl);
|
|
680
680
|
url.searchParams.set("sdkKey", this.sdkKey);
|
|
681
|
-
|
|
681
|
+
if (this.expectedEnvKey) {
|
|
682
|
+
url.searchParams.set("expectedEnvKey", this.expectedEnvKey);
|
|
683
|
+
}
|
|
682
684
|
this.eventSource = new EventSourceImpl(url.toString());
|
|
683
685
|
this.eventSource.onopen = () => {
|
|
684
686
|
this.emit("connectionState", { state: "connected", transport: "sse" });
|
|
@@ -728,6 +730,34 @@ var FeatureFlareClient = class {
|
|
|
728
730
|
}
|
|
729
731
|
this.emit("connectionState", { state: "offline", transport: "none" });
|
|
730
732
|
}
|
|
733
|
+
/**
|
|
734
|
+
* Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.
|
|
735
|
+
* The API evaluates the report against active rollback policies and may trigger an automated
|
|
736
|
+
* rollback if configured thresholds are breached.
|
|
737
|
+
*
|
|
738
|
+
* Errors from this call are silently swallowed so that reporting never disrupts the host application.
|
|
739
|
+
*/
|
|
740
|
+
async reportError(report) {
|
|
741
|
+
if (!this.sdkKey) return;
|
|
742
|
+
try {
|
|
743
|
+
await fetch(`${this.apiBaseUrl}/api/v1/sdk/report`, {
|
|
744
|
+
method: "POST",
|
|
745
|
+
headers: {
|
|
746
|
+
"content-type": "application/json",
|
|
747
|
+
"x-featureflare-sdk-key": this.sdkKey
|
|
748
|
+
},
|
|
749
|
+
body: JSON.stringify({
|
|
750
|
+
flagKey: report.flagKey,
|
|
751
|
+
errorRate: report.errorRate,
|
|
752
|
+
latencyMs: report.latencyMs,
|
|
753
|
+
observedAt: report.observedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
754
|
+
envKey: this.envKey,
|
|
755
|
+
context: report.context
|
|
756
|
+
})
|
|
757
|
+
});
|
|
758
|
+
} catch {
|
|
759
|
+
}
|
|
760
|
+
}
|
|
731
761
|
dispose() {
|
|
732
762
|
this.stopRealtime();
|
|
733
763
|
this.listeners.update.clear();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["metadata"],"mappings":"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","file":"index.js","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareCacheSource = 'bootstrap' | 'network' | 'realtime' | 'persistent';\nexport type FeatureFlareEvaluationReason = 'fresh_cache' | 'stale_cache' | 'bootstrap' | 'default' | 'network' | 'kill_switch';\n\nexport type FeatureFlareEvaluationMetadata = {\n reason: FeatureFlareEvaluationReason;\n isStale: boolean;\n latencyMs: number;\n source: FeatureFlareCacheSource | 'default' | 'kill_switch';\n updatedAt?: number;\n staleAt?: number;\n expiresAt?: number;\n};\n\nexport type FeatureFlareEvaluationResult = {\n value: boolean;\n metadata: FeatureFlareEvaluationMetadata;\n};\n\nexport type FeatureFlareMetricName =\n | 'ff_eval_latency_ms'\n | 'ff_cache_hit_ratio'\n | 'ff_revalidate_latency_ms'\n | 'ff_realtime_lag_ms'\n | 'ff_killswitch_apply_latency_ms';\n\nexport type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;\n\nexport type FeatureFlarePersistentSnapshot = {\n revision?: number;\n killSwitches?: string[];\n flags: Record<\n string,\n {\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source?: FeatureFlareCacheSource;\n revision?: number;\n }\n >;\n};\n\nexport type FeatureFlarePersistentCacheAdapter = {\n load: (envKey: string) => Promise<FeatureFlarePersistentSnapshot | null> | FeatureFlarePersistentSnapshot | null;\n save: (envKey: string, snapshot: FeatureFlarePersistentSnapshot) => Promise<void> | void;\n};\n\nexport type FeatureFlareBootstrapPayload = {\n revision?: number;\n killSwitches?: string[];\n flags?:\n | Record<string, boolean>\n | Array<{ key: string; value: boolean; revision?: number; updatedAt?: number }>;\n};\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n timeoutMs?: number;\n maxRetries?: number;\n backoffMs?: number;\n jitter?: number;\n cacheTtlMs?: number;\n staleTtlMs?: number;\n bootstrap?: FeatureFlareBootstrapPayload;\n persistentCache?: FeatureFlarePersistentCacheAdapter;\n onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n realtime?: {\n enabled?: boolean;\n pollingIntervalMs?: number;\n ssePath?: string;\n };\n};\n\ntype CacheItem = {\n envKey: string;\n flagKey: string;\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source: FeatureFlareCacheSource;\n revision: number;\n};\n\ntype RealtimeEventPayload = {\n type: 'flag.updated' | 'flag.deleted' | 'env.kill_switch.updated' | 'snapshot.invalidate';\n timestamp?: number;\n revision?: number;\n data?: Record<string, unknown>;\n};\n\ntype FeatureFlareClientEvents = {\n update: { changedKeys: string[]; source: FeatureFlareCacheSource | 'network' };\n circuitOpen: { envKey: string; reason: string };\n circuitClose: { envKey: string };\n connectionState: { state: 'connected' | 'degraded' | 'offline'; transport: 'sse' | 'polling' | 'none' };\n};\n\nfunction getEnvKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_ENV_KEY?.trim() ||\n process.env.SHIPIT_ENV_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction monotonicNow(): number {\n if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nfunction normalizeBoolMap(\n input: { flags?: Array<{ key: string; value: boolean }>; values?: Record<string, boolean> }\n): Array<{ key: string; value: boolean }> {\n if (Array.isArray(input.flags)) {\n return input.flags\n .filter((entry): entry is { key: string; value: boolean } =>\n Boolean(entry) && typeof entry.key === 'string' && typeof entry.value === 'boolean'\n )\n .map((entry) => ({ key: entry.key, value: entry.value }));\n }\n\n const values = input.values ?? {};\n return Object.entries(values).map(([key, value]) => ({ key, value: Boolean(value) }));\n}\n\nexport class InMemoryMetricsCollector {\n private readonly buckets = new Map<string, number[]>();\n\n record = (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => {\n const key = `${metricName}:${JSON.stringify(tags ?? {})}`;\n const list = this.buckets.get(key) ?? [];\n list.push(value);\n this.buckets.set(key, list);\n };\n\n get(metricName: FeatureFlareMetricName): Array<{ tags: FeatureFlareMetricTags; values: number[] }> {\n const rows: Array<{ tags: FeatureFlareMetricTags; values: number[] }> = [];\n for (const [key, values] of this.buckets.entries()) {\n if (!key.startsWith(`${metricName}:`)) continue;\n rows.push({\n tags: JSON.parse(key.slice(metricName.length + 1)) as FeatureFlareMetricTags,\n values: [...values]\n });\n }\n return rows;\n }\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n private readonly expectedEnvKey: string | null;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly backoffMs: number;\n private readonly jitter: number;\n private readonly cacheTtlMs: number;\n private readonly staleTtlMs: number;\n private readonly persistentCache: FeatureFlarePersistentCacheAdapter | undefined;\n private readonly onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n private readonly listeners: {\n [K in keyof FeatureFlareClientEvents]: Set<(payload: FeatureFlareClientEvents[K]) => void>;\n } = {\n update: new Set(),\n circuitOpen: new Set(),\n circuitClose: new Set(),\n connectionState: new Set()\n };\n\n private readonly cache = new Map<string, CacheItem>();\n private readonly diagnostics = new Map<string, FeatureFlareEvaluationMetadata>();\n private readonly killSwitches = new Set<string>();\n\n private revision = 0;\n private circuitOpen = false;\n private persistentLoadPromise: Promise<void> | null = null;\n private readonly inFlightRevalidate = new Map<string, Promise<Array<{ key: string; value: boolean }> | null>>();\n private lastUser: FeatureFlareUser | null = null;\n private lastDefaultValue = false;\n\n private realtimeEnabled = true;\n private realtimePollingMs = 15000;\n private realtimeSsePath = '/api/v1/sdk/stream';\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private eventSource: EventSource | null = null;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n const explicitOrEnvKey = options.envKey?.trim() || getEnvKeyFromEnv() || null;\n this.envKey = explicitOrEnvKey ?? 'production';\n this.expectedEnvKey = explicitOrEnvKey;\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n\n this.timeoutMs = Number.isFinite(options.timeoutMs) && (options.timeoutMs ?? 0) > 0 ? Number(options.timeoutMs) : 3000;\n this.maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) >= 0 ? Number(options.maxRetries) : 2;\n this.backoffMs = Number.isFinite(options.backoffMs) && (options.backoffMs ?? 0) > 0 ? Number(options.backoffMs) : 200;\n this.jitter = Number.isFinite(options.jitter) && (options.jitter ?? 0) >= 0 ? Number(options.jitter) : 0.25;\n\n this.cacheTtlMs = Number.isFinite(options.cacheTtlMs) && (options.cacheTtlMs ?? 0) > 0 ? Number(options.cacheTtlMs) : 60000;\n const configuredStaleTtlMs =\n Number.isFinite(options.staleTtlMs) && (options.staleTtlMs ?? 0) > 0 ? Number(options.staleTtlMs) : 10000;\n this.staleTtlMs = Math.min(configuredStaleTtlMs, this.cacheTtlMs);\n\n this.persistentCache = options.persistentCache;\n this.onMetric = options.onMetric;\n\n this.realtimeEnabled = options.realtime?.enabled ?? true;\n this.realtimePollingMs =\n Number.isFinite(options.realtime?.pollingIntervalMs) && (options.realtime?.pollingIntervalMs ?? 0) > 0\n ? Number(options.realtime?.pollingIntervalMs)\n : 15000;\n this.realtimeSsePath = options.realtime?.ssePath ?? '/api/v1/sdk/stream';\n\n this.applyBootstrap(options.bootstrap);\n this.persistentLoadPromise = this.loadPersistentCache();\n\n if (this.realtimeEnabled && this.sdkKey) {\n this.startRealtime();\n }\n }\n\n private getCacheKey(flagKey: string): string {\n return `${this.envKey}:${flagKey}`;\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n private emit<K extends keyof FeatureFlareClientEvents>(event: K, payload: FeatureFlareClientEvents[K]): void {\n for (const listener of this.listeners[event]) {\n listener(payload);\n }\n }\n\n on<K extends keyof FeatureFlareClientEvents>(\n event: K,\n listener: (payload: FeatureFlareClientEvents[K]) => void\n ): () => void {\n this.listeners[event].add(listener);\n return () => {\n this.listeners[event].delete(listener);\n };\n }\n\n private emitMetric(metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags): void {\n this.onMetric?.(metricName, value, tags);\n }\n\n private async ensurePersistentLoaded(): Promise<void> {\n if (!this.persistentLoadPromise) return;\n await this.persistentLoadPromise;\n }\n\n private async loadPersistentCache(): Promise<void> {\n if (!this.persistentCache) return;\n try {\n const snapshot = await this.persistentCache.load(this.envKey);\n if (!snapshot) return;\n this.revision = Math.max(this.revision, snapshot.revision ?? 0);\n for (const killSwitchKey of snapshot.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n for (const [flagKey, item] of Object.entries(snapshot.flags ?? {})) {\n const existing = this.cache.get(this.getCacheKey(flagKey));\n if (existing && existing.source === 'bootstrap') continue;\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value: Boolean(item.value),\n updatedAt: Number(item.updatedAt) || Date.now(),\n staleAt: Number(item.staleAt) || Date.now(),\n expiresAt: Number(item.expiresAt) || Date.now(),\n source: item.source ?? 'persistent',\n revision: item.revision ?? 0\n });\n }\n } catch {\n // Ignore persistent cache failures; runtime must stay non-throwing for outage semantics.\n }\n }\n\n private async persistCache(): Promise<void> {\n if (!this.persistentCache) return;\n const snapshot: FeatureFlarePersistentSnapshot = {\n revision: this.revision,\n killSwitches: [...this.killSwitches],\n flags: {}\n };\n\n for (const [key, item] of this.cache.entries()) {\n if (!key.startsWith(`${this.envKey}:`)) continue;\n snapshot.flags[item.flagKey] = {\n value: item.value,\n updatedAt: item.updatedAt,\n staleAt: item.staleAt,\n expiresAt: item.expiresAt,\n source: item.source,\n revision: item.revision\n };\n }\n\n try {\n await this.persistentCache.save(this.envKey, snapshot);\n } catch {\n // Persistent errors must not break evaluation.\n }\n }\n\n private makeCacheWindow(at = Date.now()): Pick<CacheItem, 'updatedAt' | 'staleAt' | 'expiresAt'> {\n return {\n updatedAt: at,\n staleAt: at + this.staleTtlMs,\n expiresAt: at + this.cacheTtlMs\n };\n }\n\n private setCacheItem(\n flagKey: string,\n value: boolean,\n source: FeatureFlareCacheSource,\n revision = this.revision,\n at = Date.now()\n ): void {\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value,\n source,\n revision,\n ...this.makeCacheWindow(at)\n });\n }\n\n private applyBootstrap(bootstrap?: FeatureFlareBootstrapPayload): void {\n if (!bootstrap) return;\n this.revision = Math.max(this.revision, bootstrap.revision ?? 0);\n for (const killSwitchKey of bootstrap.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n const apply = (flagKey: string, value: boolean, revision?: number, updatedAt?: number) => {\n this.setCacheItem(flagKey, value, 'bootstrap', revision ?? this.revision, updatedAt ?? Date.now());\n };\n\n if (Array.isArray(bootstrap.flags)) {\n for (const item of bootstrap.flags) {\n if (!item || typeof item.key !== 'string') continue;\n apply(item.key, Boolean(item.value), item.revision, item.updatedAt);\n }\n return;\n }\n\n for (const [flagKey, value] of Object.entries(bootstrap.flags ?? {})) {\n apply(flagKey, Boolean(value));\n }\n }\n\n private getCacheState(item: CacheItem | undefined, now = Date.now()): 'fresh' | 'stale' | 'expired' | 'missing' {\n if (!item) return 'missing';\n if (now <= item.staleAt) return 'fresh';\n if (now <= item.expiresAt) return 'stale';\n return 'expired';\n }\n\n private setCircuitState(isOpen: boolean, reason = ''): void {\n if (this.circuitOpen === isOpen) return;\n this.circuitOpen = isOpen;\n if (isOpen) {\n this.emit('circuitOpen', { envKey: this.envKey, reason });\n return;\n }\n this.emit('circuitClose', { envKey: this.envKey });\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, transport: 'network' | 'polling') {\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const ac = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeout =\n ac !== null\n ? setTimeout(() => {\n ac.abort();\n }, this.timeoutMs)\n : null;\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: ac?.signal\n });\n\n if (timeout) clearTimeout(timeout);\n\n if (!response.ok && isRetriableStatus(response.status) && attempt < this.maxRetries) {\n lastError = new Error(`HTTP ${response.status}`);\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n continue;\n }\n\n return response;\n } catch (error) {\n if (timeout) clearTimeout(timeout);\n lastError = error;\n if (attempt >= this.maxRetries) break;\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n }\n }\n\n this.setCircuitState(true, transport);\n throw lastError;\n }\n\n private collectCachedFlags(): Array<{ key: string; value: boolean }> {\n const now = Date.now();\n const flags: Array<{ key: string; value: boolean }> = [];\n\n for (const [cacheKey, item] of this.cache.entries()) {\n if (!cacheKey.startsWith(`${this.envKey}:`)) continue;\n if (this.killSwitches.has(item.flagKey)) {\n flags.push({ key: item.flagKey, value: false });\n continue;\n }\n\n const state = this.getCacheState(item, now);\n if (state === 'missing' || state === 'expired') continue;\n flags.push({ key: item.flagKey, value: item.value });\n }\n\n return flags.sort((a, b) => a.key.localeCompare(b.key));\n }\n\n getCachedFlags(): {\n flags: Array<{ key: string; value: boolean }>;\n hasData: boolean;\n } {\n const flags = this.collectCachedFlags();\n return { flags, hasData: flags.length > 0 };\n }\n\n getFlagDiagnostics(flagKey: string): FeatureFlareEvaluationMetadata | null {\n return this.diagnostics.get(this.getCacheKey(flagKey)) ?? null;\n }\n\n setKillSwitch(flagKey: string, enabled: boolean): void {\n const started = monotonicNow();\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n const elapsed = monotonicNow() - started;\n this.emitMetric('ff_killswitch_apply_latency_ms', elapsed, {\n env: this.envKey,\n result: enabled ? 'enabled' : 'disabled'\n });\n this.emit('update', { changedKeys: [flagKey], source: 'realtime' });\n void this.persistCache();\n }\n\n private async fetchEvalFromNetwork(\n flagKey: string,\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean\n ): Promise<boolean | null> {\n const response = this.sdkKey\n ? await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/eval`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n 'network'\n )\n : await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/eval`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n },\n 'network'\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as { value?: boolean; revision?: number; killSwitch?: boolean };\n const value = typeof json.value === 'boolean' ? json.value : defaultValue;\n\n if (json.killSwitch === true) {\n this.killSwitches.add(flagKey);\n }\n\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n this.setCacheItem(flagKey, value, 'network', revision);\n this.setCircuitState(false);\n void this.persistCache();\n this.emit('update', { changedKeys: [flagKey], source: 'network' });\n return value;\n }\n\n private async fetchFlagsFromNetwork(\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean,\n transport: 'network' | 'polling'\n ): Promise<Array<{ key: string; value: boolean }> | null> {\n if (!this.sdkKey) {\n return null;\n }\n\n const started = monotonicNow();\n\n try {\n const response = await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/flags`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n transport\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as {\n flags?: Array<{ key: string; value: boolean }>;\n values?: Record<string, boolean>;\n revision?: number;\n killSwitches?: string[];\n };\n\n const list = normalizeBoolMap(json);\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n\n if (Array.isArray(json.killSwitches)) {\n for (const key of json.killSwitches) {\n this.killSwitches.add(key);\n }\n }\n\n const changed = new Set<string>();\n for (const entry of list) {\n const existing = this.cache.get(this.getCacheKey(entry.key));\n if (!existing || existing.value !== entry.value || existing.revision !== revision) {\n changed.add(entry.key);\n }\n this.setCacheItem(entry.key, entry.value, 'network', revision);\n }\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'network' });\n }\n\n this.setCircuitState(false);\n void this.persistCache();\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport\n });\n return list;\n } catch {\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport,\n result: 'error'\n });\n return null;\n }\n }\n\n private revalidate(normalizedUser: FeatureFlareUser, defaultValue: boolean): Promise<Array<{ key: string; value: boolean }> | null> {\n const existing = this.inFlightRevalidate.get(this.envKey);\n if (existing) return existing;\n\n const promise = this.fetchFlagsFromNetwork(normalizedUser, defaultValue, 'network').finally(() => {\n this.inFlightRevalidate.delete(this.envKey);\n });\n\n this.inFlightRevalidate.set(this.envKey, promise);\n return promise;\n }\n\n async evaluate(\n flagKey: string,\n user: FeatureFlareUserPayload,\n defaultValue = false\n ): Promise<FeatureFlareEvaluationResult> {\n const started = monotonicNow();\n await this.ensurePersistentLoaded();\n\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n if (this.killSwitches.has(flagKey)) {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'kill_switch',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'kill_switch'\n };\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'disabled'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: false, metadata };\n }\n\n const cacheItem = this.cache.get(this.getCacheKey(flagKey));\n const cacheState = this.getCacheState(cacheItem);\n\n if (cacheItem && cacheState === 'fresh') {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent' ? 'bootstrap' : 'fresh_cache',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'cache_hit'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && cacheState === 'stale') {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'stale_cache',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'stale'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && (cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent')) {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'bootstrap',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'bootstrap'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n try {\n const networkValue = await this.fetchEvalFromNetwork(flagKey, normalizedUser, defaultValue);\n if (networkValue !== null) {\n const item = this.cache.get(this.getCacheKey(flagKey));\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'network',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'network',\n updatedAt: item?.updatedAt,\n staleAt: item?.staleAt,\n expiresAt: item?.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'network'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: networkValue, metadata };\n }\n } catch {\n // Fall through to deterministic default for outage semantics.\n }\n\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'default',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'default'\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'default'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: defaultValue, metadata };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const result = await this.evaluate(flagKey, user, defaultValue);\n return result.value;\n }\n\n async flags(user: FeatureFlareUserPayload, defaultValue = false): Promise<Array<{ key: string; value: boolean }>> {\n await this.ensurePersistentLoaded();\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n const list = await this.revalidate(normalizedUser, defaultValue);\n if (list && list.length > 0) {\n return list.map((entry) => ({\n key: entry.key,\n value: this.killSwitches.has(entry.key) ? false : entry.value\n }));\n }\n\n const cached = this.collectCachedFlags();\n if (cached.length > 0) return cached;\n return [];\n }\n\n private applyRealtimeMessage(message: RealtimeEventPayload): void {\n if (typeof message.revision === 'number' && message.revision < this.revision) {\n return;\n }\n\n if (typeof message.revision === 'number') {\n this.revision = message.revision;\n }\n\n const changed = new Set<string>();\n const now = Date.now();\n\n if (message.type === 'flag.updated') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const value = typeof message.data?.value === 'boolean' ? message.data.value : null;\n if (flagKey !== null && value !== null) {\n this.setCacheItem(flagKey, value, 'realtime', message.revision ?? this.revision, now);\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'flag.deleted') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n if (flagKey !== null) {\n this.cache.delete(this.getCacheKey(flagKey));\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'env.kill_switch.updated') {\n const started = monotonicNow();\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const enabled = typeof message.data?.enabled === 'boolean' ? message.data.enabled : true;\n if (flagKey !== null) {\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n changed.add(flagKey);\n this.emitMetric('ff_killswitch_apply_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling',\n result: enabled ? 'enabled' : 'disabled'\n });\n }\n }\n\n if (message.type === 'snapshot.invalidate' && this.lastUser) {\n void this.revalidate(this.lastUser, this.lastDefaultValue);\n }\n\n const eventLagMs = Math.max(0, Date.now() - (message.timestamp ?? Date.now()));\n this.emitMetric('ff_realtime_lag_ms', eventLagMs, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling'\n });\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'realtime' });\n void this.persistCache();\n }\n }\n\n private startPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n const tick = async () => {\n if (!this.lastUser) {\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n return;\n }\n await this.fetchFlagsFromNetwork(this.lastUser, this.lastDefaultValue, 'polling');\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n };\n\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n }\n\n private connectSse(attempt = 0): void {\n const EventSourceImpl = typeof EventSource !== 'undefined' ? EventSource : null;\n if (!EventSourceImpl || !this.sdkKey) {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.startPolling();\n return;\n }\n\n const url = new URL(this.realtimeSsePath, this.apiBaseUrl);\n url.searchParams.set('sdkKey', this.sdkKey);\n url.searchParams.set('envKey', this.envKey);\n\n this.eventSource = new EventSourceImpl(url.toString());\n\n this.eventSource.onopen = () => {\n this.emit('connectionState', { state: 'connected', transport: 'sse' });\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n };\n\n this.eventSource.onmessage = (event: MessageEvent) => {\n try {\n const payload = JSON.parse(String(event.data)) as RealtimeEventPayload;\n this.applyRealtimeMessage(payload);\n } catch {\n // Ignore malformed realtime messages.\n }\n };\n\n this.eventSource.onerror = () => {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.eventSource?.close();\n this.eventSource = null;\n this.startPolling();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const backoff = Math.min(this.backoffMs * (attempt + 1), 30000);\n this.reconnectTimer = setTimeout(() => {\n this.connectSse(attempt + 1);\n }, backoff);\n };\n }\n\n startRealtime(): void {\n this.realtimeEnabled = true;\n this.connectSse(0);\n }\n\n stopRealtime(): void {\n this.realtimeEnabled = false;\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.emit('connectionState', { state: 'offline', transport: 'none' });\n }\n\n dispose(): void {\n this.stopRealtime();\n this.listeners.update.clear();\n this.listeners.circuitOpen.clear();\n this.listeners.circuitClose.clear();\n this.listeners.connectionState.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["metadata"],"mappings":"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","file":"index.js","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareCacheSource = 'bootstrap' | 'network' | 'realtime' | 'persistent';\nexport type FeatureFlareEvaluationReason = 'fresh_cache' | 'stale_cache' | 'bootstrap' | 'default' | 'network' | 'kill_switch';\n\nexport type FeatureFlareEvaluationMetadata = {\n reason: FeatureFlareEvaluationReason;\n isStale: boolean;\n latencyMs: number;\n source: FeatureFlareCacheSource | 'default' | 'kill_switch';\n updatedAt?: number;\n staleAt?: number;\n expiresAt?: number;\n};\n\nexport type FeatureFlareEvaluationResult = {\n value: boolean;\n metadata: FeatureFlareEvaluationMetadata;\n};\n\nexport type FeatureFlareMetricName =\n | 'ff_eval_latency_ms'\n | 'ff_cache_hit_ratio'\n | 'ff_revalidate_latency_ms'\n | 'ff_realtime_lag_ms'\n | 'ff_killswitch_apply_latency_ms';\n\nexport type FeatureFlareMetricTags = Record<string, string | number | boolean | undefined>;\n\nexport type FeatureFlareErrorReport = {\n /** The flag key being evaluated when the error was observed. */\n flagKey: string;\n /** Observed error rate as a fraction from 0 to 1 (e.g. 0.05 = 5%). */\n errorRate: number;\n /** Observed p99 latency in milliseconds. */\n latencyMs?: number;\n /** ISO-8601 timestamp of the observation window end. Defaults to now. */\n observedAt?: string;\n /** Optional free-form context about the error (e.g. HTTP status, exception name). */\n context?: Record<string, string | number | boolean>;\n};\n\nexport type FeatureFlarePersistentSnapshot = {\n revision?: number;\n killSwitches?: string[];\n flags: Record<\n string,\n {\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source?: FeatureFlareCacheSource;\n revision?: number;\n }\n >;\n};\n\nexport type FeatureFlarePersistentCacheAdapter = {\n load: (envKey: string) => Promise<FeatureFlarePersistentSnapshot | null> | FeatureFlarePersistentSnapshot | null;\n save: (envKey: string, snapshot: FeatureFlarePersistentSnapshot) => Promise<void> | void;\n};\n\nexport type FeatureFlareBootstrapPayload = {\n revision?: number;\n killSwitches?: string[];\n flags?:\n | Record<string, boolean>\n | Array<{ key: string; value: boolean; revision?: number; updatedAt?: number }>;\n};\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n timeoutMs?: number;\n maxRetries?: number;\n backoffMs?: number;\n jitter?: number;\n cacheTtlMs?: number;\n staleTtlMs?: number;\n bootstrap?: FeatureFlareBootstrapPayload;\n persistentCache?: FeatureFlarePersistentCacheAdapter;\n onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n realtime?: {\n enabled?: boolean;\n pollingIntervalMs?: number;\n ssePath?: string;\n };\n};\n\ntype CacheItem = {\n envKey: string;\n flagKey: string;\n value: boolean;\n updatedAt: number;\n staleAt: number;\n expiresAt: number;\n source: FeatureFlareCacheSource;\n revision: number;\n};\n\ntype RealtimeEventPayload = {\n type: 'flag.updated' | 'flag.deleted' | 'env.kill_switch.updated' | 'snapshot.invalidate';\n timestamp?: number;\n revision?: number;\n data?: Record<string, unknown>;\n};\n\ntype FeatureFlareClientEvents = {\n update: { changedKeys: string[]; source: FeatureFlareCacheSource | 'network' };\n circuitOpen: { envKey: string; reason: string };\n circuitClose: { envKey: string };\n connectionState: { state: 'connected' | 'degraded' | 'offline'; transport: 'sse' | 'polling' | 'none' };\n};\n\nfunction getEnvKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_ENV_KEY?.trim() ||\n process.env.SHIPIT_ENV_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction monotonicNow(): number {\n if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetriableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nfunction normalizeBoolMap(\n input: { flags?: Array<{ key: string; value: boolean }>; values?: Record<string, boolean> }\n): Array<{ key: string; value: boolean }> {\n if (Array.isArray(input.flags)) {\n return input.flags\n .filter((entry): entry is { key: string; value: boolean } =>\n Boolean(entry) && typeof entry.key === 'string' && typeof entry.value === 'boolean'\n )\n .map((entry) => ({ key: entry.key, value: entry.value }));\n }\n\n const values = input.values ?? {};\n return Object.entries(values).map(([key, value]) => ({ key, value: Boolean(value) }));\n}\n\nexport class InMemoryMetricsCollector {\n private readonly buckets = new Map<string, number[]>();\n\n record = (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => {\n const key = `${metricName}:${JSON.stringify(tags ?? {})}`;\n const list = this.buckets.get(key) ?? [];\n list.push(value);\n this.buckets.set(key, list);\n };\n\n get(metricName: FeatureFlareMetricName): Array<{ tags: FeatureFlareMetricTags; values: number[] }> {\n const rows: Array<{ tags: FeatureFlareMetricTags; values: number[] }> = [];\n for (const [key, values] of this.buckets.entries()) {\n if (!key.startsWith(`${metricName}:`)) continue;\n rows.push({\n tags: JSON.parse(key.slice(metricName.length + 1)) as FeatureFlareMetricTags,\n values: [...values]\n });\n }\n return rows;\n }\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n private readonly expectedEnvKey: string | null;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly backoffMs: number;\n private readonly jitter: number;\n private readonly cacheTtlMs: number;\n private readonly staleTtlMs: number;\n private readonly persistentCache: FeatureFlarePersistentCacheAdapter | undefined;\n private readonly onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n private readonly listeners: {\n [K in keyof FeatureFlareClientEvents]: Set<(payload: FeatureFlareClientEvents[K]) => void>;\n } = {\n update: new Set(),\n circuitOpen: new Set(),\n circuitClose: new Set(),\n connectionState: new Set()\n };\n\n private readonly cache = new Map<string, CacheItem>();\n private readonly diagnostics = new Map<string, FeatureFlareEvaluationMetadata>();\n private readonly killSwitches = new Set<string>();\n\n private revision = 0;\n private circuitOpen = false;\n private persistentLoadPromise: Promise<void> | null = null;\n private readonly inFlightRevalidate = new Map<string, Promise<Array<{ key: string; value: boolean }> | null>>();\n private lastUser: FeatureFlareUser | null = null;\n private lastDefaultValue = false;\n\n private realtimeEnabled = true;\n private realtimePollingMs = 15000;\n private realtimeSsePath = '/api/v1/sdk/stream';\n private pollTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private eventSource: EventSource | null = null;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n const explicitOrEnvKey = options.envKey?.trim() || getEnvKeyFromEnv() || null;\n this.envKey = explicitOrEnvKey ?? 'production';\n this.expectedEnvKey = explicitOrEnvKey;\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n\n this.timeoutMs = Number.isFinite(options.timeoutMs) && (options.timeoutMs ?? 0) > 0 ? Number(options.timeoutMs) : 3000;\n this.maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) >= 0 ? Number(options.maxRetries) : 2;\n this.backoffMs = Number.isFinite(options.backoffMs) && (options.backoffMs ?? 0) > 0 ? Number(options.backoffMs) : 200;\n this.jitter = Number.isFinite(options.jitter) && (options.jitter ?? 0) >= 0 ? Number(options.jitter) : 0.25;\n\n this.cacheTtlMs = Number.isFinite(options.cacheTtlMs) && (options.cacheTtlMs ?? 0) > 0 ? Number(options.cacheTtlMs) : 60000;\n const configuredStaleTtlMs =\n Number.isFinite(options.staleTtlMs) && (options.staleTtlMs ?? 0) > 0 ? Number(options.staleTtlMs) : 10000;\n this.staleTtlMs = Math.min(configuredStaleTtlMs, this.cacheTtlMs);\n\n this.persistentCache = options.persistentCache;\n this.onMetric = options.onMetric;\n\n this.realtimeEnabled = options.realtime?.enabled ?? true;\n this.realtimePollingMs =\n Number.isFinite(options.realtime?.pollingIntervalMs) && (options.realtime?.pollingIntervalMs ?? 0) > 0\n ? Number(options.realtime?.pollingIntervalMs)\n : 15000;\n this.realtimeSsePath = options.realtime?.ssePath ?? '/api/v1/sdk/stream';\n\n this.applyBootstrap(options.bootstrap);\n this.persistentLoadPromise = this.loadPersistentCache();\n\n if (this.realtimeEnabled && this.sdkKey) {\n this.startRealtime();\n }\n }\n\n private getCacheKey(flagKey: string): string {\n return `${this.envKey}:${flagKey}`;\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n private emit<K extends keyof FeatureFlareClientEvents>(event: K, payload: FeatureFlareClientEvents[K]): void {\n for (const listener of this.listeners[event]) {\n listener(payload);\n }\n }\n\n on<K extends keyof FeatureFlareClientEvents>(\n event: K,\n listener: (payload: FeatureFlareClientEvents[K]) => void\n ): () => void {\n this.listeners[event].add(listener);\n return () => {\n this.listeners[event].delete(listener);\n };\n }\n\n private emitMetric(metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags): void {\n this.onMetric?.(metricName, value, tags);\n }\n\n private async ensurePersistentLoaded(): Promise<void> {\n if (!this.persistentLoadPromise) return;\n await this.persistentLoadPromise;\n }\n\n private async loadPersistentCache(): Promise<void> {\n if (!this.persistentCache) return;\n try {\n const snapshot = await this.persistentCache.load(this.envKey);\n if (!snapshot) return;\n this.revision = Math.max(this.revision, snapshot.revision ?? 0);\n for (const killSwitchKey of snapshot.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n for (const [flagKey, item] of Object.entries(snapshot.flags ?? {})) {\n const existing = this.cache.get(this.getCacheKey(flagKey));\n if (existing && existing.source === 'bootstrap') continue;\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value: Boolean(item.value),\n updatedAt: Number(item.updatedAt) || Date.now(),\n staleAt: Number(item.staleAt) || Date.now(),\n expiresAt: Number(item.expiresAt) || Date.now(),\n source: item.source ?? 'persistent',\n revision: item.revision ?? 0\n });\n }\n } catch {\n // Ignore persistent cache failures; runtime must stay non-throwing for outage semantics.\n }\n }\n\n private async persistCache(): Promise<void> {\n if (!this.persistentCache) return;\n const snapshot: FeatureFlarePersistentSnapshot = {\n revision: this.revision,\n killSwitches: [...this.killSwitches],\n flags: {}\n };\n\n for (const [key, item] of this.cache.entries()) {\n if (!key.startsWith(`${this.envKey}:`)) continue;\n snapshot.flags[item.flagKey] = {\n value: item.value,\n updatedAt: item.updatedAt,\n staleAt: item.staleAt,\n expiresAt: item.expiresAt,\n source: item.source,\n revision: item.revision\n };\n }\n\n try {\n await this.persistentCache.save(this.envKey, snapshot);\n } catch {\n // Persistent errors must not break evaluation.\n }\n }\n\n private makeCacheWindow(at = Date.now()): Pick<CacheItem, 'updatedAt' | 'staleAt' | 'expiresAt'> {\n return {\n updatedAt: at,\n staleAt: at + this.staleTtlMs,\n expiresAt: at + this.cacheTtlMs\n };\n }\n\n private setCacheItem(\n flagKey: string,\n value: boolean,\n source: FeatureFlareCacheSource,\n revision = this.revision,\n at = Date.now()\n ): void {\n this.cache.set(this.getCacheKey(flagKey), {\n envKey: this.envKey,\n flagKey,\n value,\n source,\n revision,\n ...this.makeCacheWindow(at)\n });\n }\n\n private applyBootstrap(bootstrap?: FeatureFlareBootstrapPayload): void {\n if (!bootstrap) return;\n this.revision = Math.max(this.revision, bootstrap.revision ?? 0);\n for (const killSwitchKey of bootstrap.killSwitches ?? []) {\n this.killSwitches.add(killSwitchKey);\n }\n\n const apply = (flagKey: string, value: boolean, revision?: number, updatedAt?: number) => {\n this.setCacheItem(flagKey, value, 'bootstrap', revision ?? this.revision, updatedAt ?? Date.now());\n };\n\n if (Array.isArray(bootstrap.flags)) {\n for (const item of bootstrap.flags) {\n if (!item || typeof item.key !== 'string') continue;\n apply(item.key, Boolean(item.value), item.revision, item.updatedAt);\n }\n return;\n }\n\n for (const [flagKey, value] of Object.entries(bootstrap.flags ?? {})) {\n apply(flagKey, Boolean(value));\n }\n }\n\n private getCacheState(item: CacheItem | undefined, now = Date.now()): 'fresh' | 'stale' | 'expired' | 'missing' {\n if (!item) return 'missing';\n if (now <= item.staleAt) return 'fresh';\n if (now <= item.expiresAt) return 'stale';\n return 'expired';\n }\n\n private setCircuitState(isOpen: boolean, reason = ''): void {\n if (this.circuitOpen === isOpen) return;\n this.circuitOpen = isOpen;\n if (isOpen) {\n this.emit('circuitOpen', { envKey: this.envKey, reason });\n return;\n }\n this.emit('circuitClose', { envKey: this.envKey });\n }\n\n private async fetchWithRetry(url: string, init: RequestInit, transport: 'network' | 'polling') {\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const ac = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeout =\n ac !== null\n ? setTimeout(() => {\n ac.abort();\n }, this.timeoutMs)\n : null;\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: ac?.signal\n });\n\n if (timeout) clearTimeout(timeout);\n\n if (!response.ok && isRetriableStatus(response.status) && attempt < this.maxRetries) {\n lastError = new Error(`HTTP ${response.status}`);\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n continue;\n }\n\n return response;\n } catch (error) {\n if (timeout) clearTimeout(timeout);\n lastError = error;\n if (attempt >= this.maxRetries) break;\n const jitterOffset = this.backoffMs * this.jitter * Math.random();\n await sleep(this.backoffMs * (attempt + 1) + jitterOffset);\n }\n }\n\n this.setCircuitState(true, transport);\n throw lastError;\n }\n\n private collectCachedFlags(): Array<{ key: string; value: boolean }> {\n const now = Date.now();\n const flags: Array<{ key: string; value: boolean }> = [];\n\n for (const [cacheKey, item] of this.cache.entries()) {\n if (!cacheKey.startsWith(`${this.envKey}:`)) continue;\n if (this.killSwitches.has(item.flagKey)) {\n flags.push({ key: item.flagKey, value: false });\n continue;\n }\n\n const state = this.getCacheState(item, now);\n if (state === 'missing' || state === 'expired') continue;\n flags.push({ key: item.flagKey, value: item.value });\n }\n\n return flags.sort((a, b) => a.key.localeCompare(b.key));\n }\n\n getCachedFlags(): {\n flags: Array<{ key: string; value: boolean }>;\n hasData: boolean;\n } {\n const flags = this.collectCachedFlags();\n return { flags, hasData: flags.length > 0 };\n }\n\n getFlagDiagnostics(flagKey: string): FeatureFlareEvaluationMetadata | null {\n return this.diagnostics.get(this.getCacheKey(flagKey)) ?? null;\n }\n\n setKillSwitch(flagKey: string, enabled: boolean): void {\n const started = monotonicNow();\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n const elapsed = monotonicNow() - started;\n this.emitMetric('ff_killswitch_apply_latency_ms', elapsed, {\n env: this.envKey,\n result: enabled ? 'enabled' : 'disabled'\n });\n this.emit('update', { changedKeys: [flagKey], source: 'realtime' });\n void this.persistCache();\n }\n\n private async fetchEvalFromNetwork(\n flagKey: string,\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean\n ): Promise<boolean | null> {\n const response = this.sdkKey\n ? await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/eval`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n 'network'\n )\n : await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/eval`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n },\n 'network'\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as { value?: boolean; revision?: number; killSwitch?: boolean };\n const value = typeof json.value === 'boolean' ? json.value : defaultValue;\n\n if (json.killSwitch === true) {\n this.killSwitches.add(flagKey);\n }\n\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n this.setCacheItem(flagKey, value, 'network', revision);\n this.setCircuitState(false);\n void this.persistCache();\n this.emit('update', { changedKeys: [flagKey], source: 'network' });\n return value;\n }\n\n private async fetchFlagsFromNetwork(\n normalizedUser: FeatureFlareUser,\n defaultValue: boolean,\n transport: 'network' | 'polling'\n ): Promise<Array<{ key: string; value: boolean }> | null> {\n if (!this.sdkKey) {\n return null;\n }\n\n const started = monotonicNow();\n\n try {\n const response = await this.fetchWithRetry(\n `${this.apiBaseUrl}/api/v1/sdk/flags`,\n {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n user: normalizedUser,\n defaultValue,\n expectedEnvKey: this.expectedEnvKey ?? undefined\n })\n },\n transport\n );\n\n if (!response.ok) {\n if (!isRetriableStatus(response.status)) {\n this.setCircuitState(true, `http_${response.status}`);\n }\n return null;\n }\n\n const json = (await response.json()) as {\n flags?: Array<{ key: string; value: boolean }>;\n values?: Record<string, boolean>;\n revision?: number;\n killSwitches?: string[];\n };\n\n const list = normalizeBoolMap(json);\n const revision = json.revision ?? this.revision;\n this.revision = Math.max(this.revision, revision);\n\n if (Array.isArray(json.killSwitches)) {\n for (const key of json.killSwitches) {\n this.killSwitches.add(key);\n }\n }\n\n const changed = new Set<string>();\n for (const entry of list) {\n const existing = this.cache.get(this.getCacheKey(entry.key));\n if (!existing || existing.value !== entry.value || existing.revision !== revision) {\n changed.add(entry.key);\n }\n this.setCacheItem(entry.key, entry.value, 'network', revision);\n }\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'network' });\n }\n\n this.setCircuitState(false);\n void this.persistCache();\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport\n });\n return list;\n } catch {\n this.emitMetric('ff_revalidate_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport,\n result: 'error'\n });\n return null;\n }\n }\n\n private revalidate(normalizedUser: FeatureFlareUser, defaultValue: boolean): Promise<Array<{ key: string; value: boolean }> | null> {\n const existing = this.inFlightRevalidate.get(this.envKey);\n if (existing) return existing;\n\n const promise = this.fetchFlagsFromNetwork(normalizedUser, defaultValue, 'network').finally(() => {\n this.inFlightRevalidate.delete(this.envKey);\n });\n\n this.inFlightRevalidate.set(this.envKey, promise);\n return promise;\n }\n\n async evaluate(\n flagKey: string,\n user: FeatureFlareUserPayload,\n defaultValue = false\n ): Promise<FeatureFlareEvaluationResult> {\n const started = monotonicNow();\n await this.ensurePersistentLoaded();\n\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n if (this.killSwitches.has(flagKey)) {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'kill_switch',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'kill_switch'\n };\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'disabled'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: false, metadata };\n }\n\n const cacheItem = this.cache.get(this.getCacheKey(flagKey));\n const cacheState = this.getCacheState(cacheItem);\n\n if (cacheItem && cacheState === 'fresh') {\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent' ? 'bootstrap' : 'fresh_cache',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'cache_hit'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && cacheState === 'stale') {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'stale_cache',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'stale'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n if (cacheItem && (cacheItem.source === 'bootstrap' || cacheItem.source === 'persistent')) {\n void this.revalidate(normalizedUser, defaultValue);\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'bootstrap',\n isStale: true,\n latencyMs: monotonicNow() - started,\n source: cacheItem.source,\n updatedAt: cacheItem.updatedAt,\n staleAt: cacheItem.staleAt,\n expiresAt: cacheItem.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 1, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'bootstrap'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: cacheItem.value, metadata };\n }\n\n try {\n const networkValue = await this.fetchEvalFromNetwork(flagKey, normalizedUser, defaultValue);\n if (networkValue !== null) {\n const item = this.cache.get(this.getCacheKey(flagKey));\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'network',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'network',\n updatedAt: item?.updatedAt,\n staleAt: item?.staleAt,\n expiresAt: item?.expiresAt\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'network'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: networkValue, metadata };\n }\n } catch {\n // Fall through to deterministic default for outage semantics.\n }\n\n const metadata: FeatureFlareEvaluationMetadata = {\n reason: 'default',\n isStale: false,\n latencyMs: monotonicNow() - started,\n source: 'default'\n };\n this.emitMetric('ff_cache_hit_ratio', 0, { env: this.envKey, source: metadata.reason });\n this.emitMetric('ff_eval_latency_ms', metadata.latencyMs, {\n env: this.envKey,\n source: metadata.source,\n result: 'default'\n });\n this.diagnostics.set(this.getCacheKey(flagKey), metadata);\n return { value: defaultValue, metadata };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const result = await this.evaluate(flagKey, user, defaultValue);\n return result.value;\n }\n\n async flags(user: FeatureFlareUserPayload, defaultValue = false): Promise<Array<{ key: string; value: boolean }>> {\n await this.ensurePersistentLoaded();\n const normalizedUser = this.normalizeUser(user);\n this.lastUser = normalizedUser;\n this.lastDefaultValue = defaultValue;\n\n const list = await this.revalidate(normalizedUser, defaultValue);\n if (list && list.length > 0) {\n return list.map((entry) => ({\n key: entry.key,\n value: this.killSwitches.has(entry.key) ? false : entry.value\n }));\n }\n\n const cached = this.collectCachedFlags();\n if (cached.length > 0) return cached;\n return [];\n }\n\n private applyRealtimeMessage(message: RealtimeEventPayload): void {\n if (typeof message.revision === 'number' && message.revision < this.revision) {\n return;\n }\n\n if (typeof message.revision === 'number') {\n this.revision = message.revision;\n }\n\n const changed = new Set<string>();\n const now = Date.now();\n\n if (message.type === 'flag.updated') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const value = typeof message.data?.value === 'boolean' ? message.data.value : null;\n if (flagKey !== null && value !== null) {\n this.setCacheItem(flagKey, value, 'realtime', message.revision ?? this.revision, now);\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'flag.deleted') {\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n if (flagKey !== null) {\n this.cache.delete(this.getCacheKey(flagKey));\n changed.add(flagKey);\n }\n }\n\n if (message.type === 'env.kill_switch.updated') {\n const started = monotonicNow();\n const flagKey = typeof message.data?.flagKey === 'string' ? message.data.flagKey : null;\n const enabled = typeof message.data?.enabled === 'boolean' ? message.data.enabled : true;\n if (flagKey !== null) {\n if (enabled) {\n this.killSwitches.add(flagKey);\n } else {\n this.killSwitches.delete(flagKey);\n }\n changed.add(flagKey);\n this.emitMetric('ff_killswitch_apply_latency_ms', monotonicNow() - started, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling',\n result: enabled ? 'enabled' : 'disabled'\n });\n }\n }\n\n if (message.type === 'snapshot.invalidate' && this.lastUser) {\n void this.revalidate(this.lastUser, this.lastDefaultValue);\n }\n\n const eventLagMs = Math.max(0, Date.now() - (message.timestamp ?? Date.now()));\n this.emitMetric('ff_realtime_lag_ms', eventLagMs, {\n env: this.envKey,\n transport: this.eventSource ? 'sse' : 'polling'\n });\n\n if (changed.size > 0) {\n this.emit('update', { changedKeys: [...changed], source: 'realtime' });\n void this.persistCache();\n }\n }\n\n private startPolling(): void {\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n\n const tick = async () => {\n if (!this.lastUser) {\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n return;\n }\n await this.fetchFlagsFromNetwork(this.lastUser, this.lastDefaultValue, 'polling');\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n };\n\n this.pollTimer = setTimeout(tick, this.realtimePollingMs);\n }\n\n private connectSse(attempt = 0): void {\n const EventSourceImpl = typeof EventSource !== 'undefined' ? EventSource : null;\n if (!EventSourceImpl || !this.sdkKey) {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.startPolling();\n return;\n }\n\n const url = new URL(this.realtimeSsePath, this.apiBaseUrl);\n url.searchParams.set('sdkKey', this.sdkKey);\n if (this.expectedEnvKey) {\n url.searchParams.set('expectedEnvKey', this.expectedEnvKey);\n }\n\n this.eventSource = new EventSourceImpl(url.toString());\n\n this.eventSource.onopen = () => {\n this.emit('connectionState', { state: 'connected', transport: 'sse' });\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n };\n\n this.eventSource.onmessage = (event: MessageEvent) => {\n try {\n const payload = JSON.parse(String(event.data)) as RealtimeEventPayload;\n this.applyRealtimeMessage(payload);\n } catch {\n // Ignore malformed realtime messages.\n }\n };\n\n this.eventSource.onerror = () => {\n this.emit('connectionState', { state: 'degraded', transport: 'polling' });\n this.eventSource?.close();\n this.eventSource = null;\n this.startPolling();\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n }\n const backoff = Math.min(this.backoffMs * (attempt + 1), 30000);\n this.reconnectTimer = setTimeout(() => {\n this.connectSse(attempt + 1);\n }, backoff);\n };\n }\n\n startRealtime(): void {\n this.realtimeEnabled = true;\n this.connectSse(0);\n }\n\n stopRealtime(): void {\n this.realtimeEnabled = false;\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.pollTimer) {\n clearTimeout(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.emit('connectionState', { state: 'offline', transport: 'none' });\n }\n\n /**\n * Report observed error metrics (error rate, latency) for a flag back to the FeatureFlare API.\n * The API evaluates the report against active rollback policies and may trigger an automated\n * rollback if configured thresholds are breached.\n *\n * Errors from this call are silently swallowed so that reporting never disrupts the host application.\n */\n async reportError(report: FeatureFlareErrorReport): Promise<void> {\n if (!this.sdkKey) return;\n try {\n await fetch(`${this.apiBaseUrl}/api/v1/sdk/report`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey: report.flagKey,\n errorRate: report.errorRate,\n latencyMs: report.latencyMs,\n observedAt: report.observedAt ?? new Date().toISOString(),\n envKey: this.envKey,\n context: report.context\n })\n });\n } catch {\n // Reporting failures must never surface to the caller.\n }\n }\n\n dispose(): void {\n this.stopRealtime();\n this.listeners.update.clear();\n this.listeners.circuitOpen.clear();\n this.listeners.circuitClose.clear();\n this.listeners.connectionState.clear();\n }\n}\n"]}
|