UNPKG

abmeter

Version:

ABMeter browser SDK — feature flags and A/B experiments with server-side pre-evaluated assignments

115 lines (108 loc) 3.81 kB
interface UserInput { userId?: string; email?: string; } interface User { userId: string; email?: string; } type Logger = (message: string, payload?: unknown) => void; type ErrorCallback = (error: unknown) => void; interface ConfigInput { apiKey: string; baseUrl?: string; user?: UserInput; /** Milliseconds between background flushes. */ flushInterval?: number; logger?: Logger; errorCallback?: ErrorCallback; } interface Config { apiKey: string; baseUrl: string; flushIntervalMs: number; logger: Logger; errorCallback?: ErrorCallback; } interface ExposureRecord { parameter_id: number; space_id: number; resolved_value: unknown; user_id: string; exposable_type: 'Experiment'; exposable_id: number; audience_id: number; resolved_at: string; } /** * Initialize the SDK singleton. Cache-then-network: hydrates synchronously * from localStorage when a cached map exists, then refreshes in the background * (await ready() to know the refresh settled). Throws on misconfiguration — * a bad apiKey must be loud, not error-safe. */ declare function configure(input: ConfigInput): void; /** Resolves when the background assignments refresh has settled (fetched or failed). */ declare function ready(): Promise<void>; /** * Resolved value for this user, or undefined when unknown/unconfigured. Queues * an exposure lazily — only experiment resolutions carry exposure metadata, * and repeats inside the dedup window are not re-queued. */ declare function resolveParameter(slug: string): unknown; /** The exposure record resolveParameter would submit, or null — without queueing anything. */ declare function getExposure(slug: string): ExposureRecord | null; /** * Queue an event for the configured user. * * Deliberately takes no user id, unlike the server-side SDKs: there one * process serves every user, so each call must say who it is for, while a * page has exactly the one user configure() established. An override would * only ever detach the event — results attribute events to a visitor by * matching the id their exposure was recorded under, so an event under any * other id is stored, counted, and never joined. */ declare function trackEvent(eventSlug: string, customFields?: Record<string, unknown>): void; /** Drain the queue now (e.g. on SPA route changes). */ declare function flush(): Promise<void>; /** * Drain fully and tear down timers/listeners; configure() again to restart. * force drops the queue instead of draining it. */ declare function reset(options?: { force?: boolean; }): Promise<void>; declare const VERSION = "0.2.2"; interface ExposureMetadata { exposable_type: 'Experiment'; exposable_id: number; audience_id: number; } interface Assignment { value: unknown; parameter_id: number; space_id: number; /** null for feature-flag and default resolutions — never report those as exposures. */ exposure: ExposureMetadata | null; } interface AssignmentsPayload { user: { user_id: string; email?: string | null; }; assignments: Record<string, Assignment>; } interface ErrorBody { error?: unknown; details?: { failures?: unknown[]; invalid_count?: number; }; } declare class ApiError extends Error { readonly status: number; readonly details: ErrorBody['details']; constructor(status: number, body: unknown); get retryable(): boolean; get partialFailure(): boolean; } export { ApiError, type Assignment, type AssignmentsPayload, type Config, type ConfigInput, type ErrorCallback, type ExposureMetadata, type ExposureRecord, type Logger, type User, type UserInput, VERSION, configure, flush, getExposure, ready, reset, resolveParameter, trackEvent };