UNPKG

@openfeature/web-sdk

Version:
536 lines (505 loc) 24.7 kB
import { BaseHook, HookHints, EvaluationDetails, JsonValue, FlagValue, CommonProvider, ClientProviderStatus, EvaluationContext, Logger, ResolutionDetails, ClientProviderEvents, GenericEventEmitter, TrackingEventDetails, EvaluationLifeCycle, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ManageContext, ProviderWrapper } from '@openfeature/core'; export * from '@openfeature/core'; export { ClientProviderEvents as ProviderEvents, ClientProviderStatus as ProviderStatus } from '@openfeature/core'; interface FlagEvaluationOptions { hooks?: BaseHook[]; hookHints?: HookHints; } interface Features { /** * Performs a flag evaluation that returns a boolean. * @param {string} flagKey The flag key uniquely identifies a particular flag * @param {boolean} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {boolean} Flag evaluation response */ getBooleanValue(flagKey: string, defaultValue: boolean, options?: FlagEvaluationOptions): boolean; /** * Performs a flag evaluation that a returns an evaluation details object. * @param {string} flagKey The flag key uniquely identifies a particular flag * @param {boolean} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {EvaluationDetails<boolean>} Flag evaluation details response */ getBooleanDetails(flagKey: string, defaultValue: boolean, options?: FlagEvaluationOptions): EvaluationDetails<boolean>; /** * Performs a flag evaluation that returns a string. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {string} T A optional generic argument constraining the string * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {T} Flag evaluation response */ getStringValue(flagKey: string, defaultValue: string, options?: FlagEvaluationOptions): string; getStringValue<T extends string = string>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): T; /** * Performs a flag evaluation that a returns an evaluation details object. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {string} T A optional generic argument constraining the string * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {EvaluationDetails<T>} Flag evaluation details response */ getStringDetails(flagKey: string, defaultValue: string, options?: FlagEvaluationOptions): EvaluationDetails<string>; getStringDetails<T extends string = string>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): EvaluationDetails<T>; /** * Performs a flag evaluation that returns a number. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {number} T A optional generic argument constraining the number * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {T} Flag evaluation response */ getNumberValue(flagKey: string, defaultValue: number, options?: FlagEvaluationOptions): number; getNumberValue<T extends number = number>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): T; /** * Performs a flag evaluation that a returns an evaluation details object. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {number} T A optional generic argument constraining the number * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {Promise<EvaluationDetails<T>>} Flag evaluation details response */ getNumberDetails(flagKey: string, defaultValue: number, options?: FlagEvaluationOptions): EvaluationDetails<number>; getNumberDetails<T extends number = number>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): EvaluationDetails<T>; /** * Performs a flag evaluation that returns an object. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {JsonValue} T A optional generic argument describing the structure * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {Promise<T>} Flag evaluation response */ getObjectValue(flagKey: string, defaultValue: JsonValue, options?: FlagEvaluationOptions): JsonValue; getObjectValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): T; /** * Performs a flag evaluation that a returns an evaluation details object. * @param {string} flagKey The flag key uniquely identifies a particular flag * @template {JsonValue} T A optional generic argument describing the structure * @param {T} defaultValue The value returned if an error occurs * @param {FlagEvaluationOptions} options Additional flag evaluation options * @returns {Promise<EvaluationDetails<T>>} Flag evaluation details response */ getObjectDetails(flagKey: string, defaultValue: JsonValue, options?: FlagEvaluationOptions): EvaluationDetails<JsonValue>; getObjectDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: FlagEvaluationOptions): EvaluationDetails<T>; } type Hook = BaseHook<FlagValue, void, void>; /** * Interface that providers must implement to resolve flag values for their particular * backend or vendor. * * Implementation for resolving all the required flag types must be defined. */ interface Provider extends CommonProvider<ClientProviderStatus> { /** * A provider hook exposes a mechanism for provider authors to register hooks * to tap into various stages of the flag evaluation lifecycle. These hooks can * be used to perform side effects and mutate the context for purposes of the * provider. Provider hooks are not configured or controlled by the application author. */ readonly hooks?: Hook[]; /** * A handler function to reconcile changes made to the static context. * Called by the SDK when the context is changed. * * Returning a promise will put the provider in the RECONCILING state and * emit the ProviderEvents.Reconciling event. * * Return void will avoid putting the provider in the RECONCILING state and * **not** emit the ProviderEvents.Reconciling event. * @param oldContext * @param newContext */ onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise<void> | void; /** * Resolve a boolean flag and its evaluation details. */ resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): ResolutionDetails<boolean>; /** * Resolve a string flag and its evaluation details. */ resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): ResolutionDetails<string>; /** * Resolve a numeric flag and its evaluation details. */ resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): ResolutionDetails<number>; /** * Resolve and parse an object flag and its evaluation details. */ resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): ResolutionDetails<T>; } /** * The No-op provider is set by default, and simply always returns the default value. */ declare class NoopFeatureProvider implements Provider { readonly metadata: { readonly name: "No-op Provider"; }; resolveBooleanEvaluation(_: string, defaultValue: boolean): ResolutionDetails<boolean>; resolveStringEvaluation(_: string, defaultValue: string): ResolutionDetails<string>; resolveNumberEvaluation(_: string, defaultValue: number): ResolutionDetails<number>; resolveObjectEvaluation<T extends JsonValue>(_: string, defaultValue: T): ResolutionDetails<T>; private noOp; } declare const NOOP_PROVIDER: NoopFeatureProvider; /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. */ declare class EventEmitter< EventTypes extends EventEmitter.ValidEventTypes = string | symbol, Context extends any = any > { static prefixed: string | boolean; /** * Return an array listing the events for which the emitter has registered * listeners. */ eventNames(): Array<EventEmitter.EventNames<EventTypes>>; /** * Return the listeners registered for a given event. */ listeners<T extends EventEmitter.EventNames<EventTypes>>( event: T ): Array<EventEmitter.EventListener<EventTypes, T>>; /** * Return the number of listeners listening to a given event. */ listenerCount(event: EventEmitter.EventNames<EventTypes>): number; /** * Calls each of the listeners registered for a given event. */ emit<T extends EventEmitter.EventNames<EventTypes>>( event: T, ...args: EventEmitter.EventArgs<EventTypes, T> ): boolean; /** * Add a listener for a given event. */ on<T extends EventEmitter.EventNames<EventTypes>>( event: T, fn: EventEmitter.EventListener<EventTypes, T>, context?: Context ): this; addListener<T extends EventEmitter.EventNames<EventTypes>>( event: T, fn: EventEmitter.EventListener<EventTypes, T>, context?: Context ): this; /** * Add a one-time listener for a given event. */ once<T extends EventEmitter.EventNames<EventTypes>>( event: T, fn: EventEmitter.EventListener<EventTypes, T>, context?: Context ): this; /** * Remove the listeners of a given event. */ removeListener<T extends EventEmitter.EventNames<EventTypes>>( event: T, fn?: EventEmitter.EventListener<EventTypes, T>, context?: Context, once?: boolean ): this; off<T extends EventEmitter.EventNames<EventTypes>>( event: T, fn?: EventEmitter.EventListener<EventTypes, T>, context?: Context, once?: boolean ): this; /** * Remove all listeners, or those of the specified event. */ removeAllListeners(event?: EventEmitter.EventNames<EventTypes>): this; } declare namespace EventEmitter { export interface ListenerFn<Args extends any[] = any[]> { (...args: Args): void; } export interface EventEmitterStatic { new < EventTypes extends ValidEventTypes = string | symbol, Context = any >(): EventEmitter<EventTypes, Context>; } /** * `object` should be in either of the following forms: * ``` * interface EventTypes { * 'event-with-parameters': any[] * 'event-with-example-handler': (...args: any[]) => void * } * ``` */ export type ValidEventTypes = string | symbol | object; export type EventNames<T extends ValidEventTypes> = T extends string | symbol ? T : keyof T; export type ArgumentMap<T extends object> = { [K in keyof T]: T[K] extends (...args: any[]) => void ? Parameters<T[K]> : T[K] extends any[] ? T[K] : any[]; }; export type EventListener< T extends ValidEventTypes, K extends EventNames<T> > = T extends string | symbol ? (...args: any[]) => void : ( ...args: ArgumentMap<Exclude<T, string | symbol>>[Extract<K, keyof T>] ) => void; export type EventArgs< T extends ValidEventTypes, K extends EventNames<T> > = Parameters<EventListener<T, K>>; export const EventEmitter: EventEmitterStatic; } /** * A subset of events that can be directly emitted by providers. */ type ProviderEmittableEvents = Exclude<ClientProviderEvents, ClientProviderEvents.ContextChanged>; /** * The OpenFeatureEventEmitter can be used by provider developers to emit * events at various parts of the provider lifecycle. * * NOTE: Ready and error events are automatically emitted by the SDK based on * the result of the initialize method. */ declare class OpenFeatureEventEmitter extends GenericEventEmitter<ProviderEmittableEvents> { protected readonly eventEmitter: EventEmitter<string | symbol, any>; constructor(); } /** * Don't export types from this file publicly. * It might cause confusion since these types are not a part of the general API, * but just for the in-memory provider. */ type Variants<T> = Record<string, T>; /** * A Feature Flag definition, containing it's specification */ type Flag = { /** * An object containing all possible flags mappings (variant -> flag value) */ variants: Variants<boolean> | Variants<string> | Variants<number> | Variants<JsonValue>; /** * The variant it will resolve to in STATIC evaluation */ defaultVariant: string; /** * Determines if flag evaluation is enabled or not for this flag. * If false, falls back to the default value provided to the client */ disabled: boolean; /** * Function used in order to evaluate a flag to a specific value given the provided context. * It should return a variant key. * If it does not return a valid variant it falls back to the default value provided to the client * @param EvaluationContext */ contextEvaluator?: (ctx: EvaluationContext) => string; }; type FlagConfiguration = Record<string, Flag>; /** * A simple OpenFeature provider intended for demos and as a test stub. */ declare class InMemoryProvider implements Provider { readonly events: OpenFeatureEventEmitter; readonly runsOn = "client"; readonly metadata: { readonly name: "in-memory"; }; private _flagConfiguration; private _context; constructor(flagConfiguration?: FlagConfiguration); /** * Overwrites the configured flags. * @param { FlagConfiguration } flagConfiguration new flag configuration */ putConfiguration(flagConfiguration: FlagConfiguration): Promise<void>; resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context?: EvaluationContext, logger?: Logger): ResolutionDetails<boolean>; resolveNumberEvaluation(flagKey: string, defaultValue: number, context?: EvaluationContext, logger?: Logger): ResolutionDetails<number>; resolveStringEvaluation(flagKey: string, defaultValue: string, context?: EvaluationContext, logger?: Logger): ResolutionDetails<string>; resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context?: EvaluationContext, logger?: Logger): ResolutionDetails<T>; private resolveAndCheckFlag; private resolveFlagWithReason; private lookupFlagValue; } interface Tracking { /** * Track a user action or application state, usually representing a business objective or outcome. * @param trackingEventName an identifier for the event * @param trackingEventDetails the details of the tracking event */ track(trackingEventName: string, trackingEventDetails?: TrackingEventDetails): void; } interface Client extends EvaluationLifeCycle<Client>, Features, ManageLogger<Client>, Eventing<ClientProviderEvents>, Tracking { readonly metadata: ClientMetadata; /** * Returns the status of the associated provider. */ readonly providerStatus: ClientProviderStatus; } declare class OpenFeatureAPI extends OpenFeatureCommonAPI<ClientProviderStatus, Provider, Hook> implements ManageContext<Promise<void>> { protected _statusEnumType: typeof ClientProviderStatus; protected _apiEmitter: GenericEventEmitter<ClientProviderEvents>; protected _defaultProvider: ProviderWrapper<Provider, ClientProviderStatus>; protected _domainScopedProviders: Map<string, ProviderWrapper<Provider, ClientProviderStatus>>; protected _createEventEmitter: () => OpenFeatureEventEmitter; private constructor(); /** * Gets a singleton instance of the OpenFeature API. * @ignore * @returns {OpenFeatureAPI} OpenFeature API */ static getInstance(): OpenFeatureAPI; private getProviderStatus; /** * Sets the default provider for flag evaluations and returns a promise that resolves when the provider is ready. * This provider will be used by domainless clients and clients associated with domains to which no provider is bound. * Setting a provider supersedes the current provider used in new and existing unbound clients. * @param {Provider} provider The provider responsible for flag evaluations. * @returns {Promise<void>} * @throws Uncaught exceptions thrown by the provider during initialization. */ setProviderAndWait(provider: Provider): Promise<void>; /** * Sets the default provider for flag evaluations and returns a promise that resolves when the provider is ready. * This provider will be used by domainless clients and clients associated with domains to which no provider is bound. * Setting a provider supersedes the current provider used in new and existing unbound clients. * @param {Provider} provider The provider responsible for flag evaluations. * @param {EvaluationContext} context The evaluation context to use for flag evaluations. * @returns {Promise<void>} * @throws Uncaught exceptions thrown by the provider during initialization. */ setProviderAndWait(provider: Provider, context: EvaluationContext): Promise<void>; /** * Sets the provider that OpenFeature will use for flag evaluations on clients bound to the same domain. * A promise is returned that resolves when the provider is ready. * Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. * @param {string} domain The name to identify the client * @param {Provider} provider The provider responsible for flag evaluations. * @returns {Promise<void>} * @throws Uncaught exceptions thrown by the provider during initialization. */ setProviderAndWait(domain: string, provider: Provider): Promise<void>; /** * Sets the provider that OpenFeature will use for flag evaluations on clients bound to the same domain. * A promise is returned that resolves when the provider is ready. * Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. * @param {string} domain The name to identify the client * @param {Provider} provider The provider responsible for flag evaluations. * @param {EvaluationContext} context The evaluation context to use for flag evaluations. * @returns {Promise<void>} * @throws Uncaught exceptions thrown by the provider during initialization. */ setProviderAndWait(domain: string, provider: Provider, context: EvaluationContext): Promise<void>; /** * Sets the default provider for flag evaluations. * This provider will be used by domainless clients and clients associated with domains to which no provider is bound. * Setting a provider supersedes the current provider used in new and existing unbound clients. * @param {Provider} provider The provider responsible for flag evaluations. * @returns {this} OpenFeature API */ setProvider(provider: Provider): this; /** * Sets the default provider and evaluation context for flag evaluations. * This provider will be used by domainless clients and clients associated with domains to which no provider is bound. * Setting a provider supersedes the current provider used in new and existing unbound clients. * @param {Provider} provider The provider responsible for flag evaluations. * @param context {EvaluationContext} The evaluation context to use for flag evaluations. * @returns {this} OpenFeature API */ setProvider(provider: Provider, context: EvaluationContext): this; /** * Sets the provider for flag evaluations of providers with the given name. * Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. * @param {string} domain The name to identify the client * @param {Provider} provider The provider responsible for flag evaluations. * @returns {this} OpenFeature API */ setProvider(domain: string, provider: Provider): this; /** * Sets the provider and evaluation context flag evaluations of providers with the given name. * Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. * @param {string} domain The name to identify the client * @param {Provider} provider The provider responsible for flag evaluations. * @param context {EvaluationContext} The evaluation context to use for flag evaluations. * @returns {this} OpenFeature API */ setProvider(domain: string, provider: Provider, context: EvaluationContext): this; /** * Sets the evaluation context globally. * This will be used by all providers that have not bound to a domain. * @param {EvaluationContext} context Evaluation context * @example * await OpenFeature.setContext({ region: "us" }); */ setContext(context: EvaluationContext): Promise<void>; /** * Sets the evaluation context for a specific provider. * This will only affect providers bound to a domain. * @param {string} domain An identifier which logically binds clients with providers * @param {EvaluationContext} context Evaluation context * @example * await OpenFeature.setContext("test", { scope: "provider" }); * OpenFeature.setProvider(new MyProvider()) // Uses the default context * OpenFeature.setProvider("test", new MyProvider()) // Uses context: { scope: "provider" } */ setContext(domain: string, context: EvaluationContext): Promise<void>; /** * Access the global evaluation context. * @returns {EvaluationContext} Evaluation context */ getContext(): EvaluationContext; /** * Access the evaluation context for a specific named client. * The global evaluation context is returned if a matching named client is not found. * @param {string} domain An identifier which logically binds clients with providers * @returns {EvaluationContext} Evaluation context */ getContext(domain?: string | undefined): EvaluationContext; /** * Resets the global evaluation context to an empty object. */ clearContext(): Promise<void>; /** * Removes the evaluation context for a specific named client. * @param {string} domain An identifier which logically binds clients with providers */ clearContext(domain: string): Promise<void>; /** * Resets the global evaluation context and removes the evaluation context for * all domains. */ clearContexts(): Promise<void>; /** * A factory function for creating new named OpenFeature clients. Clients can contain * their own state (e.g. logger, hook, context). Multiple clients can be used * to segment feature flag configuration. * * If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used. * Otherwise, the default provider is used until a provider is assigned to that name. * @param {string} domain An identifier which logically binds clients with providers * @param {string} version The version of the client (only used for metadata) * @returns {Client} OpenFeature Client */ getClient(domain?: string, version?: string): Client; /** * Clears all registered providers and resets the default provider. * @returns {Promise<void>} */ clearProviders(): Promise<void>; private runProviderContextChangeHandler; } /** * A singleton instance of the OpenFeature API. * @returns {OpenFeatureAPI} OpenFeature API */ declare const OpenFeature: OpenFeatureAPI; export { type Client, type Features, type FlagEvaluationOptions, type Hook, InMemoryProvider, NOOP_PROVIDER, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter, type Provider, type ProviderEmittableEvents, type Tracking };