@ops-ai/electron-feature-flags-toggly 1.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/main/cache.ts","../../src/sdk-identity.ts","../../src/ws-sync.ts","../../src/main/client.ts","../../src/ipc-channels.ts","../../src/main/ipc.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { mkdir, readFile, writeFile, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { EvaluatedDefinitions } from '@ops-ai/toggly-hooks-types'\n\nexport interface DiskCacheEntry {\n flags: EvaluatedDefinitions\n revision: string | null\n updatedAt: number\n}\n\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]/g, '_')\n}\n\nexport function buildCacheFilePath(\n userDataPath: string,\n appKey: string,\n environment: string,\n contextKey: string,\n): string {\n const dir = join(userDataPath, 'toggly')\n const name = `flags-${sanitizeSegment(appKey)}-${sanitizeSegment(environment)}-${sanitizeSegment(contextKey)}.json`\n return join(dir, name)\n}\n\nexport class DiskFeatureCache {\n constructor(private readonly userDataPath: string) {}\n\n private filePath(appKey: string, environment: string, contextKey: string): string {\n return buildCacheFilePath(this.userDataPath, appKey, environment, contextKey)\n }\n\n async read(\n appKey: string,\n environment: string,\n contextKey: string,\n ): Promise<DiskCacheEntry | null> {\n const path = this.filePath(appKey, environment, contextKey)\n try {\n const raw = await readFile(path, 'utf-8')\n const parsed = JSON.parse(raw) as DiskCacheEntry\n if (!parsed || typeof parsed !== 'object' || !parsed.flags || typeof parsed.flags !== 'object') {\n return null\n }\n return {\n flags: parsed.flags,\n revision: parsed.revision ?? null,\n updatedAt: typeof parsed.updatedAt === 'number' ? parsed.updatedAt : Date.now(),\n }\n } catch {\n return null\n }\n }\n\n async write(\n appKey: string,\n environment: string,\n contextKey: string,\n entry: DiskCacheEntry,\n ): Promise<void> {\n const path = this.filePath(appKey, environment, contextKey)\n await mkdir(join(this.userDataPath, 'toggly'), { recursive: true })\n await writeFile(path, JSON.stringify(entry), 'utf-8')\n }\n\n async clear(appKey: string, environment: string, contextKey: string): Promise<void> {\n const path = this.filePath(appKey, environment, contextKey)\n try {\n await unlink(path)\n } catch {\n // ignore missing file\n }\n }\n}\n","export const SDK_ID = 'electron'\nexport const SDK_VERSION = '1.0.0'\n\nexport const SDK_HEADER_ID = 'X-Toggly-Sdk'\nexport const SDK_HEADER_VERSION = 'X-Toggly-Sdk-Version'\n\nexport function sdkUserAgent(): string {\n return `toggly-${SDK_ID}/${SDK_VERSION}`\n}\n\nexport function sdkCustomHeaders(): Record<string, string> {\n return {\n [SDK_HEADER_ID]: SDK_ID,\n [SDK_HEADER_VERSION]: SDK_VERSION,\n }\n}\n\nexport function appendSdkQueryParams(params: URLSearchParams): void {\n params.set('sdk', SDK_ID)\n params.set('sdkVersion', SDK_VERSION)\n}\n\nexport function buildDefinitionFetchHeaders(\n existing: Record<string, string> = {},\n): Record<string, string> {\n return {\n ...existing,\n 'User-Agent': sdkUserAgent(),\n ...sdkCustomHeaders(),\n }\n}\n","import { appendSdkQueryParams } from './sdk-identity.js'\n\nexport const DEFINITIONS_REVISION_HEADER = 'X-Definitions-Revision'\n\nexport const WS_RECONNECT_BASE_MS = 5000\nexport const WS_RECONNECT_MAX_MS = 60000\nexport const REFRESH_DEBOUNCE_MS = 300\n\nexport interface WsSyncMessage {\n type: string\n etag?: string\n lastUpdated?: number\n unchanged?: boolean\n kid?: string\n}\n\nexport function buildWebSocketUrl(\n baseUri: string,\n appKey: string,\n cachedEtag: string | null,\n): string {\n const wsBase = baseUri\n .replace(/^https:\\/\\//, 'wss://')\n .replace(/^http:\\/\\//, 'ws://')\n .replace(/\\/$/, '')\n const params = new URLSearchParams()\n if (cachedEtag) {\n params.set('rev', cachedEtag)\n }\n appendSdkQueryParams(params)\n const query = params.toString()\n return `${wsBase}/${appKey}/ws${query ? `?${query}` : ''}`\n}\n\nexport function getNextReconnectDelayMs(attempt: number): number {\n return Math.min(WS_RECONNECT_BASE_MS * Math.pow(2, attempt), WS_RECONNECT_MAX_MS)\n}\n\nexport function shouldFetchOnSync(\n message: WsSyncMessage,\n cachedEtag: string | null,\n): boolean {\n if (message.type !== 'sync') {\n return false\n }\n if (message.unchanged === true) {\n return false\n }\n if (!cachedEtag) {\n return true\n }\n if (message.etag && message.etag !== cachedEtag) {\n return true\n }\n return false\n}\n\nexport function shouldFetchOnFlagsUpdated(\n message: WsSyncMessage,\n cachedEtag: string | null,\n): boolean {\n if (message.type !== 'flags-updated' && message.type !== 'update') {\n return false\n }\n if (!message.etag || !cachedEtag) {\n return true\n }\n return message.etag !== cachedEtag\n}\n\nexport function shouldFetchOnSigningKeyUpdated(message: WsSyncMessage): boolean {\n return message.type === 'signing-key-updated'\n}\n\nexport type FlagsUpdatedRefreshPlan =\n | { action: 'none' }\n | { action: 'refresh-jwks' }\n | { action: 'refresh-pinned'; pin: string | null }\n\nexport function planFlagsUpdatedRefresh(\n message: WsSyncMessage,\n previousRevision: string | null,\n): FlagsUpdatedRefreshPlan {\n if (shouldFetchOnSigningKeyUpdated(message)) {\n return { action: 'refresh-jwks' }\n }\n if (shouldFetchOnFlagsUpdated(message, previousRevision)) {\n return { action: 'refresh-pinned', pin: message.etag ?? null }\n }\n return { action: 'none' }\n}\n\nexport function applyFlagsUpdatedPlan(\n plan: FlagsUpdatedRefreshPlan,\n message: WsSyncMessage,\n hooks: {\n refreshJwks: () => void\n refreshPinned: (pin: string | null) => void\n cacheEtagIfPresent: (etag: string) => void\n },\n): void {\n if (plan.action === 'refresh-jwks') {\n hooks.refreshJwks()\n return\n }\n if (plan.action === 'refresh-pinned') {\n hooks.refreshPinned(plan.pin)\n return\n }\n if (message.etag) {\n hooks.cacheEtagIfPresent(message.etag)\n }\n}\n\nexport function extractDefinitionsRevision(response: Response): string | null {\n if (!response.headers?.get) {\n return null\n }\n return response.headers.get(DEFINITIONS_REVISION_HEADER) ?? response.headers.get('ETag')\n}\n\n/**\n * Append `?rev=` for a cache-proof definitions GET after `flags-updated`.\n * Never cache a WebSocket etag before HTTP confirms the revision.\n */\nexport function appendDefinitionsRevisionParam(\n url: string,\n rev: string | null | undefined,\n): string {\n if (!rev) {\n return url\n }\n try {\n const parsed = new URL(url)\n parsed.searchParams.set('rev', rev)\n return parsed.toString()\n } catch {\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}rev=${encodeURIComponent(rev)}`\n }\n}\n","import {\n appendEvaluationContext,\n evaluateEvaluatedGate,\n normalizeEntityContext,\n resolveEvaluatedDefinition,\n toBooleanDefinitions,\n type EvaluatedDefinitions,\n type Hook,\n type TogglyEntityContext,\n type EvaluationSeriesData,\n} from '@ops-ai/toggly-hooks-types'\nimport {\n InMemoryJwksCache,\n parseEvaluatedResponseBody,\n readResponseBody,\n unwrapDefsPayload,\n} from '@ops-ai/toggly-signed-defs'\nimport {\n applyLocalGate,\n buildFlagGateIndex,\n type FlagGateIndex,\n type LocalGate,\n} from '@ops-ai/toggly-local-gates'\nimport WebSocket from 'ws'\nimport { randomUUID } from 'node:crypto'\nimport { DiskFeatureCache } from './cache.js'\nimport { buildDefinitionFetchHeaders } from '../sdk-identity.js'\nimport {\n appendDefinitionsRevisionParam,\n applyFlagsUpdatedPlan,\n buildWebSocketUrl,\n extractDefinitionsRevision,\n getNextReconnectDelayMs,\n planFlagsUpdatedRefresh,\n REFRESH_DEBOUNCE_MS,\n shouldFetchOnSync,\n type WsSyncMessage,\n} from '../ws-sync.js'\nimport type {\n EntityContextInput,\n FeatureFlagsSnapshot,\n FeatureRequirement,\n SetContextInput,\n TogglyElectronConfig,\n} from '../types.js'\n\nconst DEFAULT_BASE_URI = 'https://definitions.toggly.io'\nconst DEFAULT_ENVIRONMENT = 'Production'\nconst DEFAULT_CONNECT_TIMEOUT = 5000\nconst DEFAULT_REFRESH_INTERVAL = 3 * 60 * 1000\nconst FALLBACK_REFRESH_INTERVAL = 20 * 60 * 1000\n\nclass HookExecutor {\n private hooks: Hook[] = []\n\n addHook(hook: Hook): void {\n this.hooks.push(hook)\n }\n\n async executeBeforeEvaluation(\n flagKey: string,\n defaultValue?: boolean,\n ): Promise<EvaluationSeriesData | void> {\n let data: EvaluationSeriesData | void = undefined\n for (const hook of this.hooks) {\n if (hook.beforeEvaluation) {\n data = (await hook.beforeEvaluation(flagKey, defaultValue)) ?? data\n }\n }\n return data\n }\n\n async executeAfterEvaluation(\n flagKey: string,\n data: EvaluationSeriesData | void,\n result: boolean,\n ): Promise<void> {\n for (const hook of this.hooks) {\n if (hook.afterEvaluation) {\n await hook.afterEvaluation(flagKey, data, result)\n }\n }\n }\n\n async executeBeforeIdentify(identity: string): Promise<unknown> {\n let data: unknown = undefined\n for (const hook of this.hooks) {\n if (hook.beforeIdentify) {\n data = (await hook.beforeIdentify(identity)) ?? data\n }\n }\n return data\n }\n\n async executeAfterIdentify(identity: string, data: unknown): Promise<void> {\n for (const hook of this.hooks) {\n if (hook.afterIdentify) {\n await hook.afterIdentify(identity, data as never)\n }\n }\n }\n\n async executeAfterRefresh(flags: FeatureFlagsSnapshot): Promise<void> {\n for (const hook of this.hooks) {\n if (hook.afterRefresh) {\n await hook.afterRefresh(flags)\n }\n }\n }\n}\n\nexport type FlagsUpdatedListener = (flags: FeatureFlagsSnapshot) => void\n\nexport class ElectronTogglyClient {\n private config: Required<\n Pick<\n TogglyElectronConfig,\n | 'baseURI'\n | 'environment'\n | 'connectTimeout'\n | 'featureFlagsRefreshInterval'\n | 'verifySignatures'\n | 'isDebug'\n | 'userDataPath'\n >\n > &\n TogglyElectronConfig\n\n private readonly cache: DiskFeatureCache\n private readonly hookExecutor = new HookExecutor()\n private readonly jwksCache = new InMemoryJwksCache()\n private readonly fetchImpl: typeof fetch\n private readonly listeners = new Set<FlagsUpdatedListener>()\n\n private features: EvaluatedDefinitions = {}\n private hasLoadedFlags = false\n private identity: string\n private groups: string[] = []\n private claims: Record<string, string> = {}\n private cachedDefinitionsRevision: string | null = null\n private pendingDefinitionsPin: string | null = null\n private disposed = false\n private refreshTimer: ReturnType<typeof setInterval> | null = null\n private refreshDebounceTimer: ReturnType<typeof setTimeout> | null = null\n private ws: WebSocket | null = null\n private wsConnected = false\n private wsReconnectTimer: ReturnType<typeof setTimeout> | null = null\n private wsReconnectAttempt = 0\n private lastFallbackRefresh = 0\n private localGates: LocalGate[] = []\n private localGateIndex: FlagGateIndex = new Map()\n private initPromise: Promise<FeatureFlagsSnapshot> | null = null\n\n constructor(config: TogglyElectronConfig) {\n if (!config.userDataPath) {\n throw new Error('userDataPath is required (pass app.getPath(\"userData\"))')\n }\n\n this.config = {\n baseURI: config.baseURI ?? DEFAULT_BASE_URI,\n environment: config.environment ?? DEFAULT_ENVIRONMENT,\n connectTimeout: config.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT,\n featureFlagsRefreshInterval:\n config.featureFlagsRefreshInterval ?? DEFAULT_REFRESH_INTERVAL,\n verifySignatures: config.verifySignatures ?? false,\n isDebug: config.isDebug ?? false,\n enableLiveUpdates:\n config.enableLiveUpdates ?? Boolean(config.appKey),\n ...config,\n userDataPath: config.userDataPath,\n }\n\n this.cache = new DiskFeatureCache(this.config.userDataPath)\n this.fetchImpl =\n config.fetch ??\n (typeof globalThis.fetch === 'function'\n ? globalThis.fetch.bind(globalThis)\n : (() => {\n throw new Error('fetch is not available; provide config.fetch')\n })())\n\n this.identity = config.identity ?? randomUUID()\n this.groups = config.groups ? [...config.groups] : []\n this.claims = config.claims ? { ...config.claims } : {}\n\n if (config.hooks) {\n for (const hook of config.hooks) {\n this.hookExecutor.addHook(hook)\n }\n }\n }\n\n addHook(hook: Hook): void {\n this.hookExecutor.addHook(hook)\n }\n\n onFlagsUpdated(listener: FlagsUpdatedListener): () => void {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n private notifyFlagsUpdated(): void {\n const snapshot = this.getBooleanFlags()\n for (const listener of this.listeners) {\n try {\n listener(snapshot)\n } catch (error) {\n this.reportError('Flags updated listener error', error)\n }\n }\n }\n\n private reportError(message: string, error?: unknown): void {\n this.config.onError?.(message, error)\n if (this.config.isDebug) {\n console.warn(`[Toggly] ${message}`, error)\n }\n }\n\n private get contextCacheKey(): string {\n const claims = this.claims\n return `v2:${encodeURIComponent(\n JSON.stringify([\n this.identity ?? '',\n [...this.groups].sort((a, b) => a.localeCompare(b)),\n Object.entries(claims).sort(([a], [b]) => a.localeCompare(b)),\n ]),\n )}`\n }\n\n private getBooleanFlags(): FeatureFlagsSnapshot {\n return toBooleanDefinitions(this.features)\n }\n\n private getFallbackFlags(): EvaluatedDefinitions {\n if (this.hasLoadedFlags) {\n return this.features\n }\n const defaults = this.config.flagDefaults ?? {}\n return { ...defaults }\n }\n\n private buildEvaluatedUrl(): string {\n const base = this.config.baseURI.replace(/\\/$/, '')\n const url = new URL(\n `${base}/evaluated-signed/${this.config.appKey}/${this.config.environment}`,\n )\n appendEvaluationContext(\n url,\n {\n identity: this.identity,\n groups: this.groups,\n claims: this.claims,\n },\n 'evaluated',\n )\n return url.toString()\n }\n\n private buildFetchHeaders(skipIfNoneMatch = false): Record<string, string> {\n const revision = skipIfNoneMatch ? null : this.cachedDefinitionsRevision\n return buildDefinitionFetchHeaders(\n revision ? { 'If-None-Match': revision, Accept: 'application/json' } : { Accept: 'application/json' },\n )\n }\n\n private applyRevision(response: Response): void {\n const revision = extractDefinitionsRevision(response)\n if (revision) {\n this.cachedDefinitionsRevision = revision.replace(/^\"+|\"+$/g, '')\n }\n }\n\n private async persistCache(): Promise<void> {\n if (!this.config.appKey) {\n return\n }\n try {\n await this.cache.write(\n this.config.appKey,\n this.config.environment,\n this.contextCacheKey,\n {\n flags: this.features,\n revision: this.cachedDefinitionsRevision,\n updatedAt: Date.now(),\n },\n )\n } catch (error) {\n this.reportError('Failed to write disk cache', error)\n }\n }\n\n private async loadDiskCache(): Promise<boolean> {\n if (!this.config.appKey) {\n return false\n }\n try {\n const entry = await this.cache.read(\n this.config.appKey,\n this.config.environment,\n this.contextCacheKey,\n )\n if (!entry) {\n return false\n }\n this.features = entry.flags\n this.cachedDefinitionsRevision = entry.revision\n this.hasLoadedFlags = true\n return true\n } catch (error) {\n this.reportError('Failed to read disk cache', error)\n return false\n }\n }\n\n private resolveEffectiveFlag(\n key: string,\n entityContext?: TogglyEntityContext | null,\n ): boolean {\n const resolved = resolveEvaluatedDefinition(\n this.features[key],\n entityContext,\n this.config.flagDefaults?.[key] ?? false,\n )\n return applyLocalGate(resolved, key, this.localGates, this.localGateIndex)\n }\n\n isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n const ctx = normalizeEntityContext(entityContext, kind)\n void this.runEvaluationHooks(key, () => this.resolveEffectiveFlag(key, ctx))\n return this.resolveEffectiveFlag(key, ctx)\n }\n\n isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return !this.isFeatureOn(key, entityContext, kind)\n }\n\n evaluateFeatureGate(\n keys: string[],\n requirement: FeatureRequirement | string = 'all',\n negate = false,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n const ctx = normalizeEntityContext(entityContext, kind)\n const req = requirement === 'any' ? 'any' : 'all'\n if (keys.length === 0) {\n return !negate\n }\n // Empty feature map with keys → fail closed (match evaluateStoredFeatureKeys)\n if (Object.keys(this.features).length === 0) {\n const closed = negate\n void this.runEvaluationHooks(keys[0], () => closed)\n return closed\n }\n const isEnabled = (key: string) => this.resolveEffectiveFlag(key, ctx)\n let gated: boolean\n if (req === 'any') {\n const anyOn = keys.some(isEnabled)\n gated = negate ? !anyOn : anyOn\n } else {\n const allOn = keys.every(isEnabled)\n gated = negate ? !allOn : allOn\n }\n // Keep evaluateEvaluatedGate in the hot path for parity when no local gates\n if (this.localGates.length === 0) {\n gated = evaluateEvaluatedGate(this.features, keys, req, negate, ctx)\n }\n void this.runEvaluationHooks(keys[0], () => gated)\n return gated\n }\n\n private async runEvaluationHooks(\n flagKey: string,\n evaluate: () => boolean,\n ): Promise<void> {\n try {\n const data = await this.hookExecutor.executeBeforeEvaluation(flagKey)\n const result = evaluate()\n await this.hookExecutor.executeAfterEvaluation(flagKey, data, result)\n } catch (error) {\n this.reportError('Hook execution error', error)\n }\n }\n\n getFlags(): FeatureFlagsSnapshot {\n return this.getBooleanFlags()\n }\n\n setLocalGates(gates: LocalGate[]): void {\n this.localGates = [...gates]\n this.localGateIndex = buildFlagGateIndex(this.localGates)\n }\n\n async refresh(): Promise<FeatureFlagsSnapshot> {\n if (this.disposed) {\n return this.getBooleanFlags()\n }\n\n if (!this.config.appKey) {\n this.features = { ...(this.config.flagDefaults ?? {}) }\n this.hasLoadedFlags = true\n this.notifyFlagsUpdated()\n return this.getBooleanFlags()\n }\n\n try {\n const pin = this.pendingDefinitionsPin\n this.pendingDefinitionsPin = null\n const url = appendDefinitionsRevisionParam(this.buildEvaluatedUrl(), pin)\n const headers = this.buildFetchHeaders(Boolean(pin))\n\n const controller = new AbortController()\n const timeoutId = setTimeout(\n () => controller.abort(),\n this.config.connectTimeout,\n )\n\n const response = await this.fetchImpl(url, {\n method: 'GET',\n headers,\n signal: controller.signal,\n })\n clearTimeout(timeoutId)\n\n if (response.status === 304) {\n this.applyRevision(response)\n await this.persistCache()\n return this.getBooleanFlags()\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`)\n }\n\n const bodyText = await readResponseBody(response)\n const parsed = await parseEvaluatedResponseBody(bodyText, {\n verifySignatures: this.config.verifySignatures,\n baseURI: this.config.baseURI,\n allowedKeyIds: this.config.allowedKeyIds,\n maxSignatureAgeSeconds: this.config.maxSignatureAgeSeconds ?? undefined,\n headers,\n fetchImpl: this.fetchImpl,\n getJwks: this.config.verifySignatures\n ? () =>\n this.jwksCache.get({\n verifySignatures: true,\n baseURI: this.config.baseURI,\n allowedKeyIds: this.config.allowedKeyIds,\n maxSignatureAgeSeconds:\n this.config.maxSignatureAgeSeconds ?? undefined,\n headers,\n fetchImpl: this.fetchImpl,\n })\n : undefined,\n })\n\n const defs = (\n this.config.verifySignatures\n ? (parsed as EvaluatedDefinitions)\n : (unwrapDefsPayload(parsed) as EvaluatedDefinitions)\n ) ?? {}\n\n this.features = defs\n this.hasLoadedFlags = true\n this.applyRevision(response)\n await this.persistCache()\n await this.hookExecutor.executeAfterRefresh(this.getBooleanFlags())\n this.notifyFlagsUpdated()\n return this.getBooleanFlags()\n } catch (error) {\n this.reportError('Failed to refresh feature flags', error)\n if (!this.hasLoadedFlags) {\n const loaded = await this.loadDiskCache()\n if (!loaded) {\n this.features = this.getFallbackFlags()\n this.hasLoadedFlags = true\n }\n }\n this.notifyFlagsUpdated()\n return this.getBooleanFlags()\n }\n }\n\n async init(): Promise<FeatureFlagsSnapshot> {\n if (this.initPromise) {\n return this.initPromise\n }\n this.initPromise = this.doInit()\n return this.initPromise\n }\n\n private async doInit(): Promise<FeatureFlagsSnapshot> {\n await this.loadDiskCache()\n const flags = await this.refresh()\n this.startRefreshInterval()\n if (this.config.enableLiveUpdates && this.config.appKey) {\n this.startWebSocket()\n }\n return flags\n }\n\n async setContext(input: SetContextInput): Promise<FeatureFlagsSnapshot> {\n if (input.identity !== undefined) {\n const data = await this.hookExecutor.executeBeforeIdentify(input.identity)\n this.identity = input.identity\n await this.hookExecutor.executeAfterIdentify(input.identity, data)\n }\n if (input.groups !== undefined) {\n this.groups = [...input.groups]\n }\n if (input.claims !== undefined) {\n this.claims = { ...input.claims }\n }\n this.hasLoadedFlags = false\n this.cachedDefinitionsRevision = null\n return this.refresh()\n }\n\n async clearContext(): Promise<FeatureFlagsSnapshot> {\n this.identity = randomUUID()\n this.groups = []\n this.claims = {}\n this.hasLoadedFlags = false\n this.cachedDefinitionsRevision = null\n return this.refresh()\n }\n\n private startRefreshInterval(): void {\n this.stopRefreshInterval()\n const interval = () =>\n this.wsConnected\n ? FALLBACK_REFRESH_INTERVAL\n : this.config.featureFlagsRefreshInterval\n\n this.refreshTimer = setInterval(() => {\n if (this.wsConnected) {\n const elapsed = Date.now() - this.lastFallbackRefresh\n if (elapsed < FALLBACK_REFRESH_INTERVAL) {\n return\n }\n }\n this.lastFallbackRefresh = Date.now()\n void this.refresh()\n }, Math.min(interval(), this.config.featureFlagsRefreshInterval))\n }\n\n private stopRefreshInterval(): void {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n\n private scheduleDebouncedRefresh(forceJwksRefresh = false): void {\n if (this.refreshDebounceTimer) {\n clearTimeout(this.refreshDebounceTimer)\n }\n this.refreshDebounceTimer = setTimeout(() => {\n this.refreshDebounceTimer = null\n if (forceJwksRefresh && this.config.verifySignatures) {\n this.cachedDefinitionsRevision = null\n this.jwksCache.clear()\n }\n void this.refresh()\n }, REFRESH_DEBOUNCE_MS)\n }\n\n private handleWsMessage(raw: WebSocket.RawData): void {\n try {\n const message = JSON.parse(String(raw)) as WsSyncMessage\n if (message.type === 'ping') {\n return\n }\n if (shouldFetchOnSync(message, this.cachedDefinitionsRevision)) {\n this.scheduleDebouncedRefresh()\n return\n }\n if (message.type === 'sync' && message.etag) {\n this.cachedDefinitionsRevision = message.etag\n return\n }\n const plan = planFlagsUpdatedRefresh(message, this.cachedDefinitionsRevision)\n applyFlagsUpdatedPlan(plan, message, {\n refreshJwks: () => this.scheduleDebouncedRefresh(true),\n refreshPinned: (pin) => {\n this.pendingDefinitionsPin = pin\n this.cachedDefinitionsRevision = null\n this.scheduleDebouncedRefresh()\n },\n cacheEtagIfPresent: (etag) => {\n this.cachedDefinitionsRevision = etag\n },\n })\n } catch (error) {\n this.reportError('Failed to parse WebSocket message', error)\n }\n }\n\n startWebSocket(): void {\n if (this.disposed || !this.config.appKey || !this.config.enableLiveUpdates) {\n return\n }\n this.stopWebSocket(false)\n\n const url = buildWebSocketUrl(\n this.config.baseURI,\n this.config.appKey,\n this.cachedDefinitionsRevision,\n )\n\n try {\n const ws = new WebSocket(url)\n this.ws = ws\n\n ws.on('open', () => {\n this.wsConnected = true\n this.wsReconnectAttempt = 0\n this.lastFallbackRefresh = Date.now()\n if (this.config.isDebug) {\n console.log('[Toggly] WebSocket connected')\n }\n })\n\n ws.on('message', (data) => this.handleWsMessage(data))\n\n ws.on('close', () => {\n this.wsConnected = false\n this.ws = null\n this.scheduleReconnect()\n })\n\n ws.on('error', (error) => {\n this.reportError('WebSocket error', error)\n })\n } catch (error) {\n this.reportError('Failed to start WebSocket', error)\n this.scheduleReconnect()\n }\n }\n\n private scheduleReconnect(): void {\n if (this.disposed || !this.config.enableLiveUpdates) {\n return\n }\n if (this.wsReconnectTimer) {\n return\n }\n const delay = getNextReconnectDelayMs(this.wsReconnectAttempt)\n this.wsReconnectAttempt += 1\n this.wsReconnectTimer = setTimeout(() => {\n this.wsReconnectTimer = null\n this.startWebSocket()\n }, delay)\n }\n\n stopWebSocket(clearReconnect = true): void {\n if (this.wsReconnectTimer && clearReconnect) {\n clearTimeout(this.wsReconnectTimer)\n this.wsReconnectTimer = null\n }\n if (this.ws) {\n try {\n this.ws.removeAllListeners()\n this.ws.close()\n } catch {\n // ignore\n }\n this.ws = null\n }\n this.wsConnected = false\n }\n\n close(): void {\n this.disposed = true\n this.stopRefreshInterval()\n if (this.refreshDebounceTimer) {\n clearTimeout(this.refreshDebounceTimer)\n this.refreshDebounceTimer = null\n }\n this.stopWebSocket(true)\n this.listeners.clear()\n this.initPromise = null\n }\n}\n\nlet singleton: ElectronTogglyClient | null = null\n\nexport async function initToggly(\n config: TogglyElectronConfig,\n): Promise<FeatureFlagsSnapshot> {\n if (singleton) {\n singleton.close()\n }\n singleton = new ElectronTogglyClient(config)\n return singleton.init()\n}\n\nexport function getToggly(): ElectronTogglyClient | null {\n return singleton\n}\n\nexport function isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n return singleton?.isFeatureOn(key, entityContext, kind) ?? false\n}\n\nexport function isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n return singleton?.isFeatureOff(key, entityContext, kind) ?? true\n}\n\nexport function evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n if (!singleton) {\n return negate ?? false\n }\n return singleton.evaluateFeatureGate(\n keys,\n requirement,\n negate,\n entityContext,\n kind,\n )\n}\n\nexport async function setContext(\n input: SetContextInput,\n): Promise<FeatureFlagsSnapshot> {\n if (!singleton) {\n throw new Error('Toggly is not initialized. Call initToggly first.')\n }\n return singleton.setContext(input)\n}\n\nexport async function clearContext(): Promise<FeatureFlagsSnapshot> {\n if (!singleton) {\n throw new Error('Toggly is not initialized. Call initToggly first.')\n }\n return singleton.clearContext()\n}\n\nexport function addHook(hook: Hook): void {\n singleton?.addHook(hook)\n}\n\nexport function closeToggly(): void {\n singleton?.close()\n singleton = null\n}\n\n/** Test helper — reset singleton without requiring prior init. */\nexport function __resetTogglyForTests(): void {\n singleton?.close()\n singleton = null\n}\n","/** Internal channel names — not part of the public renderer API. */\nexport const IPC_PREFIX = 'toggly:' as const\n\nexport const IPC_CHANNELS = {\n isFeatureOn: `${IPC_PREFIX}isFeatureOn`,\n isFeatureOff: `${IPC_PREFIX}isFeatureOff`,\n evaluateFeatureGate: `${IPC_PREFIX}evaluateFeatureGate`,\n getFlags: `${IPC_PREFIX}getFlags`,\n setContext: `${IPC_PREFIX}setContext`,\n clearContext: `${IPC_PREFIX}clearContext`,\n flagsUpdated: `${IPC_PREFIX}flags-updated`,\n} as const\n\nexport type IpcChannelName = (typeof IPC_CHANNELS)[keyof typeof IPC_CHANNELS]\n","import type { BrowserWindow } from 'electron'\nimport { IPC_CHANNELS } from '../ipc-channels.js'\nimport {\n clearContext,\n evaluateFeatureGate,\n getToggly,\n isFeatureOff,\n isFeatureOn,\n setContext,\n type ElectronTogglyClient,\n} from './client.js'\nimport type { EntityContextInput, FeatureRequirement, SetContextInput } from '../types.js'\n\nexport type IpcMainLike = {\n on: (\n channel: string,\n listener: (event: { returnValue: unknown }, ...args: unknown[]) => void,\n ) => void\n handle: (\n channel: string,\n listener: (event: unknown, ...args: unknown[]) => unknown | Promise<unknown>,\n ) => void\n removeHandler?: (channel: string) => void\n removeAllListeners?: (channel: string) => void\n}\n\nexport type WebContentsLike = {\n send: (channel: string, ...args: unknown[]) => void\n isDestroyed?: () => boolean\n}\n\nexport type BrowserWindowLike = {\n webContents: WebContentsLike\n isDestroyed?: () => boolean\n}\n\n/**\n * Register main-process handlers and fan out flag updates to renderer windows.\n * Call after `initToggly`.\n */\nexport function registerTogglyIpc(\n ipcMain: IpcMainLike,\n getWindows: () => Array<BrowserWindow | BrowserWindowLike> = () => [],\n): () => void {\n const client = getToggly()\n if (!client) {\n throw new Error('Toggly is not initialized. Call initToggly before registerTogglyIpc.')\n }\n\n ipcMain.on(IPC_CHANNELS.isFeatureOn, (event, key, entityContext, kind) => {\n event.returnValue = isFeatureOn(\n String(key),\n entityContext as EntityContextInput,\n kind as string | undefined,\n )\n })\n\n ipcMain.on(IPC_CHANNELS.isFeatureOff, (event, key, entityContext, kind) => {\n event.returnValue = isFeatureOff(\n String(key),\n entityContext as EntityContextInput,\n kind as string | undefined,\n )\n })\n\n ipcMain.on(\n IPC_CHANNELS.evaluateFeatureGate,\n (event, keys, requirement, negate, entityContext, kind) => {\n event.returnValue = evaluateFeatureGate(\n (keys as string[]) ?? [],\n requirement as FeatureRequirement | string | undefined,\n Boolean(negate),\n entityContext as EntityContextInput,\n kind as string | undefined,\n )\n },\n )\n\n ipcMain.handle(IPC_CHANNELS.getFlags, () => {\n return getToggly()?.getFlags() ?? {}\n })\n\n ipcMain.handle(IPC_CHANNELS.setContext, (_event, context) => {\n return setContext((context as SetContextInput) ?? {})\n })\n\n ipcMain.handle(IPC_CHANNELS.clearContext, () => {\n return clearContext()\n })\n\n const unsubscribe = client.onFlagsUpdated((flags) => {\n for (const win of getWindows()) {\n try {\n if (win.isDestroyed?.()) {\n continue\n }\n if (win.webContents.isDestroyed?.()) {\n continue\n }\n win.webContents.send(IPC_CHANNELS.flagsUpdated, flags)\n } catch {\n // window may have closed\n }\n }\n })\n\n return () => {\n unsubscribe()\n ipcMain.removeAllListeners?.(IPC_CHANNELS.isFeatureOn)\n ipcMain.removeAllListeners?.(IPC_CHANNELS.isFeatureOff)\n ipcMain.removeAllListeners?.(IPC_CHANNELS.evaluateFeatureGate)\n ipcMain.removeHandler?.(IPC_CHANNELS.getFlags)\n ipcMain.removeHandler?.(IPC_CHANNELS.setContext)\n ipcMain.removeHandler?.(IPC_CHANNELS.clearContext)\n }\n}\n\nexport type { ElectronTogglyClient }\n"]}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var electron = require('electron');
4
+
5
+ // src/preload/index.ts
6
+
7
+ // src/ipc-channels.ts
8
+ var IPC_PREFIX = "toggly:";
9
+ var IPC_CHANNELS = {
10
+ isFeatureOn: `${IPC_PREFIX}isFeatureOn`,
11
+ isFeatureOff: `${IPC_PREFIX}isFeatureOff`,
12
+ evaluateFeatureGate: `${IPC_PREFIX}evaluateFeatureGate`,
13
+ getFlags: `${IPC_PREFIX}getFlags`,
14
+ setContext: `${IPC_PREFIX}setContext`,
15
+ clearContext: `${IPC_PREFIX}clearContext`,
16
+ flagsUpdated: `${IPC_PREFIX}flags-updated`
17
+ };
18
+
19
+ // src/preload/index.ts
20
+ function exposeToggly() {
21
+ const api = {
22
+ isFeatureOn(key, entityContext, kind) {
23
+ return electron.ipcRenderer.sendSync(
24
+ IPC_CHANNELS.isFeatureOn,
25
+ key,
26
+ entityContext ?? null,
27
+ kind
28
+ );
29
+ },
30
+ isFeatureOff(key, entityContext, kind) {
31
+ return electron.ipcRenderer.sendSync(
32
+ IPC_CHANNELS.isFeatureOff,
33
+ key,
34
+ entityContext ?? null,
35
+ kind
36
+ );
37
+ },
38
+ evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
39
+ return electron.ipcRenderer.sendSync(
40
+ IPC_CHANNELS.evaluateFeatureGate,
41
+ keys,
42
+ requirement ?? "all",
43
+ negate ?? false,
44
+ entityContext ?? null,
45
+ kind
46
+ );
47
+ },
48
+ getFlags() {
49
+ return electron.ipcRenderer.invoke(IPC_CHANNELS.getFlags);
50
+ },
51
+ setContext(context) {
52
+ return electron.ipcRenderer.invoke(IPC_CHANNELS.setContext, context);
53
+ },
54
+ clearContext() {
55
+ return electron.ipcRenderer.invoke(IPC_CHANNELS.clearContext);
56
+ },
57
+ onFlagsUpdated(callback) {
58
+ const listener = (_event, flags) => {
59
+ callback(flags);
60
+ };
61
+ electron.ipcRenderer.on(IPC_CHANNELS.flagsUpdated, listener);
62
+ return () => {
63
+ electron.ipcRenderer.removeListener(IPC_CHANNELS.flagsUpdated, listener);
64
+ };
65
+ }
66
+ };
67
+ electron.contextBridge.exposeInMainWorld("toggly", Object.freeze(api));
68
+ }
69
+
70
+ exports.exposeToggly = exposeToggly;
71
+ //# sourceMappingURL=index.cjs.map
72
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ipc-channels.ts","../../src/preload/index.ts"],"names":["ipcRenderer","contextBridge"],"mappings":";;;;;;;AACO,IAAM,UAAA,GAAa,SAAA;AAEnB,IAAM,YAAA,GAAe;AAAA,EAC1B,WAAA,EAAa,GAAG,UAAU,CAAA,WAAA,CAAA;AAAA,EAC1B,YAAA,EAAc,GAAG,UAAU,CAAA,YAAA,CAAA;AAAA,EAC3B,mBAAA,EAAqB,GAAG,UAAU,CAAA,mBAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,UAAU,CAAA,QAAA,CAAA;AAAA,EACvB,UAAA,EAAY,GAAG,UAAU,CAAA,UAAA,CAAA;AAAA,EACzB,YAAA,EAAc,GAAG,UAAU,CAAA,YAAA,CAAA;AAAA,EAC3B,YAAA,EAAc,GAAG,UAAU,CAAA,aAAA;AAC7B,CAAA;;;ACHO,SAAS,YAAA,GAAqB;AACnC,EAAA,MAAM,GAAA,GAAoB;AAAA,IACxB,WAAA,CACE,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,MAAA,OAAOA,oBAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,WAAA;AAAA,QACb,GAAA;AAAA,QACA,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,YAAA,CACE,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,MAAA,OAAOA,oBAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,YAAA;AAAA,QACb,GAAA;AAAA,QACA,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,mBAAA,CACE,IAAA,EACA,WAAA,EACA,MAAA,EACA,eACA,IAAA,EACS;AACT,MAAA,OAAOA,oBAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,mBAAA;AAAA,QACb,IAAA;AAAA,QACA,WAAA,IAAe,KAAA;AAAA,QACf,MAAA,IAAU,KAAA;AAAA,QACV,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,QAAA,GAA0C;AACxC,MAAA,OAAOA,oBAAA,CAAY,MAAA,CAAO,YAAA,CAAa,QAAQ,CAAA;AAAA,IACjD,CAAA;AAAA,IAEA,WAAW,OAAA,EAAyD;AAClE,MAAA,OAAOA,oBAAA,CAAY,MAAA,CAAO,YAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAAA,IAC5D,CAAA;AAAA,IAEA,YAAA,GAA8C;AAC5C,MAAA,OAAOA,oBAAA,CAAY,MAAA,CAAO,YAAA,CAAa,YAAY,CAAA;AAAA,IACrD,CAAA;AAAA,IAEA,eAAe,QAAA,EAA6D;AAC1E,MAAA,MAAM,QAAA,GAAW,CAAC,MAAA,EAAiB,KAAA,KAAgC;AACjE,QAAA,QAAA,CAAS,KAAK,CAAA;AAAA,MAChB,CAAA;AACA,MAAAA,oBAAA,CAAY,EAAA,CAAG,YAAA,CAAa,YAAA,EAAc,QAAQ,CAAA;AAClD,MAAA,OAAO,MAAM;AACX,QAAAA,oBAAA,CAAY,cAAA,CAAe,YAAA,CAAa,YAAA,EAAc,QAAQ,CAAA;AAAA,MAChE,CAAA;AAAA,IACF;AAAA,GACF;AAEA,EAAAC,sBAAA,CAAc,iBAAA,CAAkB,QAAA,EAAU,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAC9D","file":"index.cjs","sourcesContent":["/** Internal channel names — not part of the public renderer API. */\nexport const IPC_PREFIX = 'toggly:' as const\n\nexport const IPC_CHANNELS = {\n isFeatureOn: `${IPC_PREFIX}isFeatureOn`,\n isFeatureOff: `${IPC_PREFIX}isFeatureOff`,\n evaluateFeatureGate: `${IPC_PREFIX}evaluateFeatureGate`,\n getFlags: `${IPC_PREFIX}getFlags`,\n setContext: `${IPC_PREFIX}setContext`,\n clearContext: `${IPC_PREFIX}clearContext`,\n flagsUpdated: `${IPC_PREFIX}flags-updated`,\n} as const\n\nexport type IpcChannelName = (typeof IPC_CHANNELS)[keyof typeof IPC_CHANNELS]\n","import { contextBridge, ipcRenderer } from 'electron'\nimport { IPC_CHANNELS } from '../ipc-channels.js'\nimport type { EntityContextInput, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput, TogglyBridge } from '../types.js'\n\n/**\n * Expose the Flutter-like `window.toggly` API to the renderer via contextBridge.\n * Call from your preload script with contextIsolation enabled.\n */\nexport function exposeToggly(): void {\n const api: TogglyBridge = {\n isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.isFeatureOn,\n key,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.isFeatureOff,\n key,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.evaluateFeatureGate,\n keys,\n requirement ?? 'all',\n negate ?? false,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n getFlags(): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.getFlags) as Promise<FeatureFlagsSnapshot>\n },\n\n setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.setContext, context) as Promise<FeatureFlagsSnapshot>\n },\n\n clearContext(): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.clearContext) as Promise<FeatureFlagsSnapshot>\n },\n\n onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void {\n const listener = (_event: unknown, flags: FeatureFlagsSnapshot) => {\n callback(flags)\n }\n ipcRenderer.on(IPC_CHANNELS.flagsUpdated, listener)\n return () => {\n ipcRenderer.removeListener(IPC_CHANNELS.flagsUpdated, listener)\n }\n },\n }\n\n contextBridge.exposeInMainWorld('toggly', Object.freeze(api))\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Expose the Flutter-like `window.toggly` API to the renderer via contextBridge.
3
+ * Call from your preload script with contextIsolation enabled.
4
+ */
5
+ declare function exposeToggly(): void;
6
+
7
+ export { exposeToggly };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Expose the Flutter-like `window.toggly` API to the renderer via contextBridge.
3
+ * Call from your preload script with contextIsolation enabled.
4
+ */
5
+ declare function exposeToggly(): void;
6
+
7
+ export { exposeToggly };
@@ -0,0 +1,70 @@
1
+ import { contextBridge, ipcRenderer } from 'electron';
2
+
3
+ // src/preload/index.ts
4
+
5
+ // src/ipc-channels.ts
6
+ var IPC_PREFIX = "toggly:";
7
+ var IPC_CHANNELS = {
8
+ isFeatureOn: `${IPC_PREFIX}isFeatureOn`,
9
+ isFeatureOff: `${IPC_PREFIX}isFeatureOff`,
10
+ evaluateFeatureGate: `${IPC_PREFIX}evaluateFeatureGate`,
11
+ getFlags: `${IPC_PREFIX}getFlags`,
12
+ setContext: `${IPC_PREFIX}setContext`,
13
+ clearContext: `${IPC_PREFIX}clearContext`,
14
+ flagsUpdated: `${IPC_PREFIX}flags-updated`
15
+ };
16
+
17
+ // src/preload/index.ts
18
+ function exposeToggly() {
19
+ const api = {
20
+ isFeatureOn(key, entityContext, kind) {
21
+ return ipcRenderer.sendSync(
22
+ IPC_CHANNELS.isFeatureOn,
23
+ key,
24
+ entityContext ?? null,
25
+ kind
26
+ );
27
+ },
28
+ isFeatureOff(key, entityContext, kind) {
29
+ return ipcRenderer.sendSync(
30
+ IPC_CHANNELS.isFeatureOff,
31
+ key,
32
+ entityContext ?? null,
33
+ kind
34
+ );
35
+ },
36
+ evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
37
+ return ipcRenderer.sendSync(
38
+ IPC_CHANNELS.evaluateFeatureGate,
39
+ keys,
40
+ requirement ?? "all",
41
+ negate ?? false,
42
+ entityContext ?? null,
43
+ kind
44
+ );
45
+ },
46
+ getFlags() {
47
+ return ipcRenderer.invoke(IPC_CHANNELS.getFlags);
48
+ },
49
+ setContext(context) {
50
+ return ipcRenderer.invoke(IPC_CHANNELS.setContext, context);
51
+ },
52
+ clearContext() {
53
+ return ipcRenderer.invoke(IPC_CHANNELS.clearContext);
54
+ },
55
+ onFlagsUpdated(callback) {
56
+ const listener = (_event, flags) => {
57
+ callback(flags);
58
+ };
59
+ ipcRenderer.on(IPC_CHANNELS.flagsUpdated, listener);
60
+ return () => {
61
+ ipcRenderer.removeListener(IPC_CHANNELS.flagsUpdated, listener);
62
+ };
63
+ }
64
+ };
65
+ contextBridge.exposeInMainWorld("toggly", Object.freeze(api));
66
+ }
67
+
68
+ export { exposeToggly };
69
+ //# sourceMappingURL=index.js.map
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ipc-channels.ts","../../src/preload/index.ts"],"names":[],"mappings":";;;;;AACO,IAAM,UAAA,GAAa,SAAA;AAEnB,IAAM,YAAA,GAAe;AAAA,EAC1B,WAAA,EAAa,GAAG,UAAU,CAAA,WAAA,CAAA;AAAA,EAC1B,YAAA,EAAc,GAAG,UAAU,CAAA,YAAA,CAAA;AAAA,EAC3B,mBAAA,EAAqB,GAAG,UAAU,CAAA,mBAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,UAAU,CAAA,QAAA,CAAA;AAAA,EACvB,UAAA,EAAY,GAAG,UAAU,CAAA,UAAA,CAAA;AAAA,EACzB,YAAA,EAAc,GAAG,UAAU,CAAA,YAAA,CAAA;AAAA,EAC3B,YAAA,EAAc,GAAG,UAAU,CAAA,aAAA;AAC7B,CAAA;;;ACHO,SAAS,YAAA,GAAqB;AACnC,EAAA,MAAM,GAAA,GAAoB;AAAA,IACxB,WAAA,CACE,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,MAAA,OAAO,WAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,WAAA;AAAA,QACb,GAAA;AAAA,QACA,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,YAAA,CACE,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,MAAA,OAAO,WAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,YAAA;AAAA,QACb,GAAA;AAAA,QACA,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,mBAAA,CACE,IAAA,EACA,WAAA,EACA,MAAA,EACA,eACA,IAAA,EACS;AACT,MAAA,OAAO,WAAA,CAAY,QAAA;AAAA,QACjB,YAAA,CAAa,mBAAA;AAAA,QACb,IAAA;AAAA,QACA,WAAA,IAAe,KAAA;AAAA,QACf,MAAA,IAAU,KAAA;AAAA,QACV,aAAA,IAAiB,IAAA;AAAA,QACjB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,QAAA,GAA0C;AACxC,MAAA,OAAO,WAAA,CAAY,MAAA,CAAO,YAAA,CAAa,QAAQ,CAAA;AAAA,IACjD,CAAA;AAAA,IAEA,WAAW,OAAA,EAAyD;AAClE,MAAA,OAAO,WAAA,CAAY,MAAA,CAAO,YAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAAA,IAC5D,CAAA;AAAA,IAEA,YAAA,GAA8C;AAC5C,MAAA,OAAO,WAAA,CAAY,MAAA,CAAO,YAAA,CAAa,YAAY,CAAA;AAAA,IACrD,CAAA;AAAA,IAEA,eAAe,QAAA,EAA6D;AAC1E,MAAA,MAAM,QAAA,GAAW,CAAC,MAAA,EAAiB,KAAA,KAAgC;AACjE,QAAA,QAAA,CAAS,KAAK,CAAA;AAAA,MAChB,CAAA;AACA,MAAA,WAAA,CAAY,EAAA,CAAG,YAAA,CAAa,YAAA,EAAc,QAAQ,CAAA;AAClD,MAAA,OAAO,MAAM;AACX,QAAA,WAAA,CAAY,cAAA,CAAe,YAAA,CAAa,YAAA,EAAc,QAAQ,CAAA;AAAA,MAChE,CAAA;AAAA,IACF;AAAA,GACF;AAEA,EAAA,aAAA,CAAc,iBAAA,CAAkB,QAAA,EAAU,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAC9D","file":"index.js","sourcesContent":["/** Internal channel names — not part of the public renderer API. */\nexport const IPC_PREFIX = 'toggly:' as const\n\nexport const IPC_CHANNELS = {\n isFeatureOn: `${IPC_PREFIX}isFeatureOn`,\n isFeatureOff: `${IPC_PREFIX}isFeatureOff`,\n evaluateFeatureGate: `${IPC_PREFIX}evaluateFeatureGate`,\n getFlags: `${IPC_PREFIX}getFlags`,\n setContext: `${IPC_PREFIX}setContext`,\n clearContext: `${IPC_PREFIX}clearContext`,\n flagsUpdated: `${IPC_PREFIX}flags-updated`,\n} as const\n\nexport type IpcChannelName = (typeof IPC_CHANNELS)[keyof typeof IPC_CHANNELS]\n","import { contextBridge, ipcRenderer } from 'electron'\nimport { IPC_CHANNELS } from '../ipc-channels.js'\nimport type { EntityContextInput, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput, TogglyBridge } from '../types.js'\n\n/**\n * Expose the Flutter-like `window.toggly` API to the renderer via contextBridge.\n * Call from your preload script with contextIsolation enabled.\n */\nexport function exposeToggly(): void {\n const api: TogglyBridge = {\n isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.isFeatureOn,\n key,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.isFeatureOff,\n key,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n ): boolean {\n return ipcRenderer.sendSync(\n IPC_CHANNELS.evaluateFeatureGate,\n keys,\n requirement ?? 'all',\n negate ?? false,\n entityContext ?? null,\n kind,\n ) as boolean\n },\n\n getFlags(): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.getFlags) as Promise<FeatureFlagsSnapshot>\n },\n\n setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.setContext, context) as Promise<FeatureFlagsSnapshot>\n },\n\n clearContext(): Promise<FeatureFlagsSnapshot> {\n return ipcRenderer.invoke(IPC_CHANNELS.clearContext) as Promise<FeatureFlagsSnapshot>\n },\n\n onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void {\n const listener = (_event: unknown, flags: FeatureFlagsSnapshot) => {\n callback(flags)\n }\n ipcRenderer.on(IPC_CHANNELS.flagsUpdated, listener)\n return () => {\n ipcRenderer.removeListener(IPC_CHANNELS.flagsUpdated, listener)\n }\n },\n }\n\n contextBridge.exposeInMainWorld('toggly', Object.freeze(api))\n}\n"]}
@@ -0,0 +1,146 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ // src/react/Feature.tsx
7
+
8
+ // src/renderer/index.ts
9
+ function tryBridge() {
10
+ if (typeof window === "undefined" || !window.toggly) {
11
+ return null;
12
+ }
13
+ return window.toggly;
14
+ }
15
+ function isFeatureOn(key, entityContext, kind) {
16
+ const bridge = tryBridge();
17
+ if (!bridge) {
18
+ return false;
19
+ }
20
+ return bridge.isFeatureOn(key, entityContext, kind);
21
+ }
22
+ function evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
23
+ const bridge = tryBridge();
24
+ if (!bridge) {
25
+ return negate ?? false;
26
+ }
27
+ return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind);
28
+ }
29
+ function onFlagsUpdated(callback) {
30
+ const bridge = tryBridge();
31
+ if (!bridge) {
32
+ return () => void 0;
33
+ }
34
+ return bridge.onFlagsUpdated(callback);
35
+ }
36
+ function Feature({
37
+ featureKey,
38
+ featureKeys = [],
39
+ requirement = "all",
40
+ negate = false,
41
+ context,
42
+ contextKind,
43
+ children,
44
+ loading = null
45
+ }) {
46
+ const gate = react.useMemo(() => {
47
+ if (featureKey) {
48
+ return [featureKey, ...featureKeys];
49
+ }
50
+ return [...featureKeys];
51
+ }, [featureKey, featureKeys]);
52
+ const [shouldShow, setShouldShow] = react.useState(null);
53
+ react.useEffect(() => {
54
+ const evaluate = () => {
55
+ if (gate.length === 0) {
56
+ setShouldShow(!negate);
57
+ return;
58
+ }
59
+ try {
60
+ setShouldShow(
61
+ evaluateFeatureGate(gate, requirement, negate, context, contextKind)
62
+ );
63
+ } catch {
64
+ setShouldShow(false);
65
+ }
66
+ };
67
+ evaluate();
68
+ return onFlagsUpdated(() => evaluate());
69
+ }, [gate.join(","), requirement, negate, context, contextKind]);
70
+ if (shouldShow === null) {
71
+ return loading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loading }) : null;
72
+ }
73
+ return shouldShow ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : null;
74
+ }
75
+ function useFeatureFlag(featureKey, options = {}) {
76
+ const { negate = false, defaultValue = false, context, contextKind } = options;
77
+ return useFeatureGate(featureKey ? [featureKey] : [], {
78
+ requirement: "all",
79
+ negate,
80
+ defaultValue,
81
+ context,
82
+ contextKind
83
+ });
84
+ }
85
+ function useFeatureGate(featureKeys, options = {}) {
86
+ const {
87
+ requirement = "all",
88
+ negate = false,
89
+ defaultValue = false,
90
+ context,
91
+ contextKind
92
+ } = options;
93
+ const keysKey = react.useMemo(() => featureKeys.join("\0"), [featureKeys]);
94
+ const stableKeys = react.useMemo(() => [...featureKeys], [keysKey]);
95
+ const evaluate = react.useCallback(() => {
96
+ if (stableKeys.length === 0) {
97
+ return !negate;
98
+ }
99
+ try {
100
+ return evaluateFeatureGate(
101
+ stableKeys,
102
+ requirement,
103
+ negate,
104
+ context,
105
+ contextKind
106
+ );
107
+ } catch {
108
+ return defaultValue;
109
+ }
110
+ }, [stableKeys, keysKey, requirement, negate, defaultValue, context, contextKind]);
111
+ const [isEnabled, setIsEnabled] = react.useState(() => {
112
+ try {
113
+ return evaluate();
114
+ } catch {
115
+ return defaultValue;
116
+ }
117
+ });
118
+ const refresh = react.useCallback(() => {
119
+ setIsEnabled(evaluate());
120
+ }, [evaluate]);
121
+ react.useEffect(() => {
122
+ refresh();
123
+ return onFlagsUpdated(() => {
124
+ refresh();
125
+ });
126
+ }, [refresh]);
127
+ return { isEnabled, refresh };
128
+ }
129
+ function readFeatureFlag(featureKey, options = {}) {
130
+ const { negate = false, defaultValue = false, context, contextKind } = options;
131
+ try {
132
+ if (negate) {
133
+ return !isFeatureOn(featureKey, context, contextKind);
134
+ }
135
+ return isFeatureOn(featureKey, context, contextKind);
136
+ } catch {
137
+ return defaultValue;
138
+ }
139
+ }
140
+
141
+ exports.Feature = Feature;
142
+ exports.readFeatureFlag = readFeatureFlag;
143
+ exports.useFeatureFlag = useFeatureFlag;
144
+ exports.useFeatureGate = useFeatureGate;
145
+ //# sourceMappingURL=index.cjs.map
146
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/renderer/index.ts","../../src/react/Feature.tsx","../../src/react/useFeatureFlag.ts"],"names":["useMemo","useState","useEffect","jsx","Fragment","useCallback"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n EntityContextInput,\n FeatureFlagsSnapshot,\n FeatureRequirement,\n SetContextInput,\n TogglyBridge,\n} from '../types.js'\n\nfunction tryBridge(): TogglyBridge | null {\n if (typeof window === 'undefined' || !window.toggly) {\n return null\n }\n return window.toggly\n}\n\nexport function isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return false\n }\n return bridge.isFeatureOn(key, entityContext, kind)\n}\n\nexport function isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return true\n }\n return bridge.isFeatureOff(key, entityContext, kind)\n}\n\nexport function evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return negate ?? false\n }\n return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind)\n}\n\nexport function getFlags(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.getFlags()\n}\n\nexport function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.setContext(context)\n}\n\nexport function clearContext(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.clearContext()\n}\n\nexport function onFlagsUpdated(\n callback: (flags: FeatureFlagsSnapshot) => void,\n): () => void {\n const bridge = tryBridge()\n if (!bridge) {\n return () => undefined\n }\n return bridge.onFlagsUpdated(callback)\n}\n\nexport type { TogglyBridge, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput }\n","import React, { useEffect, useMemo, useState, type ReactNode } from 'react'\nimport { evaluateFeatureGate, onFlagsUpdated } from '../renderer/index.js'\nimport type { EntityContextInput, FeatureRequirement } from '../types.js'\n\nexport interface FeatureProps {\n featureKey?: string\n featureKeys?: string[]\n requirement?: FeatureRequirement | string\n negate?: boolean\n context?: EntityContextInput\n contextKind?: string\n children?: ReactNode\n /** Content while evaluating (optional). */\n loading?: ReactNode\n}\n\n/**\n * Conditionally render children based on feature flags (Flutter-like DX).\n */\nexport function Feature({\n featureKey,\n featureKeys = [],\n requirement = 'all',\n negate = false,\n context,\n contextKind,\n children,\n loading = null,\n}: FeatureProps): React.ReactElement | null {\n const gate = useMemo(() => {\n if (featureKey) {\n return [featureKey, ...featureKeys]\n }\n return [...featureKeys]\n }, [featureKey, featureKeys])\n\n const [shouldShow, setShouldShow] = useState<boolean | null>(null)\n\n useEffect(() => {\n const evaluate = () => {\n if (gate.length === 0) {\n setShouldShow(!negate)\n return\n }\n try {\n setShouldShow(\n evaluateFeatureGate(gate, requirement, negate, context, contextKind),\n )\n } catch {\n setShouldShow(false)\n }\n }\n\n evaluate()\n return onFlagsUpdated(() => evaluate())\n }, [gate.join(','), requirement, negate, context, contextKind])\n\n if (shouldShow === null) {\n return loading ? <>{loading}</> : null\n }\n\n return shouldShow ? <>{children}</> : null\n}\n\nexport default Feature\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport {\n evaluateFeatureGate,\n isFeatureOn,\n onFlagsUpdated,\n} from '../renderer/index.js'\nimport type { EntityContextInput, FeatureRequirement } from '../types.js'\n\nexport interface UseFeatureFlagOptions {\n defaultValue?: boolean\n negate?: boolean\n context?: EntityContextInput\n contextKind?: string\n}\n\nexport interface UseFeatureFlagResult {\n isEnabled: boolean\n refresh: () => void\n}\n\nexport interface UseFeatureGateOptions extends UseFeatureFlagOptions {\n requirement?: FeatureRequirement | string\n}\n\nexport function useFeatureFlag(\n featureKey: string,\n options: UseFeatureFlagOptions = {},\n): UseFeatureFlagResult {\n const { negate = false, defaultValue = false, context, contextKind } = options\n return useFeatureGate(featureKey ? [featureKey] : [], {\n requirement: 'all',\n negate,\n defaultValue,\n context,\n contextKind,\n })\n}\n\nexport function useFeatureGate(\n featureKeys: string[],\n options: UseFeatureGateOptions = {},\n): UseFeatureFlagResult {\n const {\n requirement = 'all',\n negate = false,\n defaultValue = false,\n context,\n contextKind,\n } = options\n const keysKey = useMemo(() => featureKeys.join('\\0'), [featureKeys])\n const stableKeys = useMemo(() => [...featureKeys], [keysKey])\n\n const evaluate = useCallback((): boolean => {\n if (stableKeys.length === 0) {\n return !negate\n }\n try {\n return evaluateFeatureGate(\n stableKeys,\n requirement,\n negate,\n context,\n contextKind,\n )\n } catch {\n return defaultValue\n }\n }, [stableKeys, keysKey, requirement, negate, defaultValue, context, contextKind])\n\n const [isEnabled, setIsEnabled] = useState<boolean>(() => {\n try {\n return evaluate()\n } catch {\n return defaultValue\n }\n })\n\n const refresh = useCallback(() => {\n setIsEnabled(evaluate())\n }, [evaluate])\n\n useEffect(() => {\n refresh()\n return onFlagsUpdated(() => {\n refresh()\n })\n }, [refresh])\n\n return { isEnabled, refresh }\n}\n\n/** Sync helper for non-hook callers. */\nexport function readFeatureFlag(\n featureKey: string,\n options: UseFeatureFlagOptions = {},\n): boolean {\n const { negate = false, defaultValue = false, context, contextKind } = options\n try {\n if (negate) {\n return !isFeatureOn(featureKey, context, contextKind)\n }\n return isFeatureOn(featureKey, context, contextKind)\n } catch {\n return defaultValue\n }\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { F as FeatureRequirement, E as EntityContextInput } from '../types-BbMSwQVV.cjs';
3
+ import '@ops-ai/toggly-hooks-types';
4
+
5
+ interface FeatureProps {
6
+ featureKey?: string;
7
+ featureKeys?: string[];
8
+ requirement?: FeatureRequirement | string;
9
+ negate?: boolean;
10
+ context?: EntityContextInput;
11
+ contextKind?: string;
12
+ children?: ReactNode;
13
+ /** Content while evaluating (optional). */
14
+ loading?: ReactNode;
15
+ }
16
+ /**
17
+ * Conditionally render children based on feature flags (Flutter-like DX).
18
+ */
19
+ declare function Feature({ featureKey, featureKeys, requirement, negate, context, contextKind, children, loading, }: FeatureProps): React.ReactElement | null;
20
+
21
+ interface UseFeatureFlagOptions {
22
+ defaultValue?: boolean;
23
+ negate?: boolean;
24
+ context?: EntityContextInput;
25
+ contextKind?: string;
26
+ }
27
+ interface UseFeatureFlagResult {
28
+ isEnabled: boolean;
29
+ refresh: () => void;
30
+ }
31
+ interface UseFeatureGateOptions extends UseFeatureFlagOptions {
32
+ requirement?: FeatureRequirement | string;
33
+ }
34
+ declare function useFeatureFlag(featureKey: string, options?: UseFeatureFlagOptions): UseFeatureFlagResult;
35
+ declare function useFeatureGate(featureKeys: string[], options?: UseFeatureGateOptions): UseFeatureFlagResult;
36
+ /** Sync helper for non-hook callers. */
37
+ declare function readFeatureFlag(featureKey: string, options?: UseFeatureFlagOptions): boolean;
38
+
39
+ export { Feature, type FeatureProps, type UseFeatureFlagOptions, type UseFeatureFlagResult, type UseFeatureGateOptions, readFeatureFlag, useFeatureFlag, useFeatureGate };
@@ -0,0 +1,39 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { F as FeatureRequirement, E as EntityContextInput } from '../types-BbMSwQVV.js';
3
+ import '@ops-ai/toggly-hooks-types';
4
+
5
+ interface FeatureProps {
6
+ featureKey?: string;
7
+ featureKeys?: string[];
8
+ requirement?: FeatureRequirement | string;
9
+ negate?: boolean;
10
+ context?: EntityContextInput;
11
+ contextKind?: string;
12
+ children?: ReactNode;
13
+ /** Content while evaluating (optional). */
14
+ loading?: ReactNode;
15
+ }
16
+ /**
17
+ * Conditionally render children based on feature flags (Flutter-like DX).
18
+ */
19
+ declare function Feature({ featureKey, featureKeys, requirement, negate, context, contextKind, children, loading, }: FeatureProps): React.ReactElement | null;
20
+
21
+ interface UseFeatureFlagOptions {
22
+ defaultValue?: boolean;
23
+ negate?: boolean;
24
+ context?: EntityContextInput;
25
+ contextKind?: string;
26
+ }
27
+ interface UseFeatureFlagResult {
28
+ isEnabled: boolean;
29
+ refresh: () => void;
30
+ }
31
+ interface UseFeatureGateOptions extends UseFeatureFlagOptions {
32
+ requirement?: FeatureRequirement | string;
33
+ }
34
+ declare function useFeatureFlag(featureKey: string, options?: UseFeatureFlagOptions): UseFeatureFlagResult;
35
+ declare function useFeatureGate(featureKeys: string[], options?: UseFeatureGateOptions): UseFeatureFlagResult;
36
+ /** Sync helper for non-hook callers. */
37
+ declare function readFeatureFlag(featureKey: string, options?: UseFeatureFlagOptions): boolean;
38
+
39
+ export { Feature, type FeatureProps, type UseFeatureFlagOptions, type UseFeatureFlagResult, type UseFeatureGateOptions, readFeatureFlag, useFeatureFlag, useFeatureGate };