### Install Dependencies and Run Tests Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Install all project dependencies using npm ci and run the test suite to ensure your environment is correctly set up. This is a prerequisite for starting development. ```bash npm install npm test ``` -------------------------------- ### Install with yarn Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Install the OpenFeature Web SDK using yarn. Note that yarn requires manual installation of the @openfeature/core peer-dependency. ```sh # yarn requires manual installation of the @openfeature/core peer-dependency yarn add @openfeature/web-sdk @openfeature/core ``` -------------------------------- ### Install Server SDK with yarn Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Install the OpenFeature Server SDK using yarn. Note that yarn requires manual installation of the @openfeature/core peer-dependency. ```sh # yarn requires manual installation of the @openfeature/core peer-dependency yarn add @openfeature/server-sdk @openfeature/core ``` -------------------------------- ### Install OpenFeature React SDK with yarn Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Install the OpenFeature React SDK using yarn. Note that yarn requires manual installation of peer dependencies. ```sh # yarn requires manual installation of the peer dependencies (see below) yarn add @openfeature/react-sdk @openfeature/web-sdk @openfeature/core ``` -------------------------------- ### Install OpenFeature React SDK with npm Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Install the OpenFeature React SDK using npm. Ensure you also install the web SDK and core SDK. ```sh npm install --save @openfeature/react-sdk ``` -------------------------------- ### Install with npm Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Install the OpenFeature Web SDK using npm. This is the standard package manager for Node.js and browser projects. ```sh npm install --save @openfeature/web-sdk ``` -------------------------------- ### Install Server SDK with npm Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Install the OpenFeature Server SDK using npm. Ensure you are using Node.js version 18 or higher. ```sh npm install --save @openfeature/server-sdk ``` -------------------------------- ### Initialize Multi-Provider Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Set up the Multi-Provider to manage multiple underlying providers. This example demonstrates initializing it with two providers and then evaluating a flag. ```typescript import { MultiProvider } from '@openfeature/web-sdk'; const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); await OpenFeature.setProviderAndWait(multiProvider); const client = OpenFeature.getClient(); console.log(client.getBooleanDetails('my-flag', false)); ``` -------------------------------- ### Install OpenFeature NestJS SDK with yarn Source: https://github.com/open-feature/js-sdk/blob/main/packages/nest/README.md Install the OpenFeature NestJS SDK using yarn. Note that yarn requires manual installation of peer dependencies. ```bash yarn add @openfeature/nestjs-sdk @openfeature/server-sdk @openfeature/core ``` -------------------------------- ### Initialize Multi-Provider and Set as Default Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Initialize the Multi-Provider with an array of providers and set it as the default provider for the OpenFeature SDK. This example demonstrates basic setup and flag evaluation. ```typescript import { MultiProvider } from '@openfeature/server-sdk'; import { OpenFeature } from '@openfeature/server-sdk'; const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); await OpenFeature.setProviderAndWait(multiProvider); const client = OpenFeature.getClient(); console.log('Evaluating flag'); console.log(await client.getBooleanDetails('my-flag', false)); ``` -------------------------------- ### Migration Example with Multi-Provider Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Demonstrates using `MultiProvider` for gradual migration between flag providers. The new provider is consulted first, falling back to the old provider if necessary. ```typescript import { OpenFeature, MultiProvider, FirstMatchStrategy } from '@openfeature/server-sdk'; // During migration, serve some flags from the new provider and fallback to the old one const newProvider = new NewFlagProvider(); const oldProvider = new OldFlagProvider(); const multiProvider = new MultiProvider( [{ provider: newProvider }, { provider: oldProvider }], // New provider is consulted first new FirstMatchStrategy(), ); await OpenFeature.setProviderAndWait(multiProvider); ``` -------------------------------- ### Initialize and Use OpenFeature Server SDK Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md This example demonstrates how to register a feature flag provider, create a client, and evaluate a boolean feature flag. Ensure your provider is correctly implemented and registered. ```ts import { OpenFeature } from '@openfeature/server-sdk'; // Register your feature flag provider try { await OpenFeature.setProviderAndWait(new YourProviderOfChoice()); } catch (error) { console.error('Failed to initialize provider:', error); } // create a new client const client = OpenFeature.getClient(); // Evaluate your feature flag const v2Enabled = await client.getBooleanValue('v2_enabled', false); if (v2Enabled) { console.log('v2 is enabled'); } ``` -------------------------------- ### Comparison Example with Multi-Provider Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Illustrates using `MultiProvider` with a `ComparisonStrategy` to validate flag results from multiple providers. Mismatches are logged to the console. ```typescript import { OpenFeature, MultiProvider, ComparisonStrategy } from '@openfeature/server-sdk'; // Compare results from two providers for validation const providerA = new ProviderA(); const providerB = new ProviderB(); const multiProvider = new MultiProvider( [{ provider: providerA }, { provider: providerB }], new ComparisonStrategy(providerA, (resolutions) => { console.warn('Mismatch detected', resolutions); }), ); await OpenFeature.setProviderAndWait(multiProvider); ``` -------------------------------- ### Install OpenFeature Angular SDK with npm Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Use npm to install the OpenFeature Angular SDK. This command adds the SDK to your project's dependencies. ```sh npm install --save @openfeature/angular-sdk ``` -------------------------------- ### Install OpenFeature NestJS SDK with npm Source: https://github.com/open-feature/js-sdk/blob/main/packages/nest/README.md Install the OpenFeature NestJS SDK using npm. Ensure Node.js version 20+ and NestJS version 8+ are met. ```bash npm install --save @openfeature/nestjs-sdk ``` -------------------------------- ### Install OpenFeature Angular SDK with yarn Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Use yarn to install the OpenFeature Angular SDK and its peer dependencies. Manual installation of peer dependencies is required for yarn. ```sh # yarn requires manual installation of the peer dependencies (see below) yarn add @openfeature/angular-sdk @openfeature/web-sdk @openfeature/core ``` -------------------------------- ### OpenFeatureProvider Context Provider Example Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Demonstrates how to use the OpenFeatureProvider context provider with a TypedInMemoryProvider. This sets up the OpenFeature client for all child components. ```tsx import { EvaluationContext, OpenFeatureProvider, useFlag, OpenFeature, TypedInMemoryProvider, } from '@openfeature/react-sdk'; const flagConfig = { 'new-message': { disabled: false, variants: { on: true, off: false, }, defaultVariant: 'on', contextEvaluator: (context: EvaluationContext) => { if (context.silly) { return 'on'; } return 'off'; }, }, } as const; // Instantiate and set our provider (be sure this only happens once)! // Note: there's no need to await its initialization, the React SDK handles re-rendering and suspense for you! OpenFeature.setProvider(new TypedInMemoryProvider(flagConfig)); // Enclose your content in the configured provider function App() { return ( ); } ``` -------------------------------- ### Implement a Custom Mock Provider Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Create a custom testing provider by implementing Partial. This example shows a mock provider that resolves boolean evaluations. ```typescript class MyTestProvider implements Partial { // implement the relevant resolver resolveBooleanEvaluation(): ResolutionDetails { return { value: true, variant: 'my-variant', reason: 'MY_REASON', }; } } ``` -------------------------------- ### Implement a Custom OpenFeature Provider Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Example of a custom provider implementing the Provider interface. This includes methods for evaluating different flag types and lifecycle management. ```typescript import { AnyProviderEvent, EvaluationContext, Hook, JsonValue, Logger, Provider, ProviderEventEmitter, ResolutionDetails, } from '@openfeature/web-sdk'; // implement the provider interface class MyProvider implements Provider { // Adds runtime validation that the provider is used with the expected SDK public readonly runsOn = 'client'; readonly metadata = { name: 'My Provider', } as const; // Optional provider managed hooks hooks?: Hook[]; resolveBooleanEvaluation( flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger, ): ResolutionDetails { // code to evaluate a boolean } resolveStringEvaluation( flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger, ): ResolutionDetails { // code to evaluate a string } resolveNumberEvaluation( flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger, ): ResolutionDetails { // code to evaluate a number } resolveObjectEvaluation( flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger, ): ResolutionDetails { // code to evaluate an object } onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise { // reconcile the provider's cached flags, if applicable } // implement with "new OpenFeatureEventEmitter()", and use "emit()" to emit events events?: ProviderEventEmitter | undefined; initialize?(context?: EvaluationContext | undefined): Promise { // code to initialize your provider } onClose?(): Promise { // code to shut down your provider } } ``` -------------------------------- ### Implement OpenFeature Provider Interface Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Example of a custom provider implementing the `Provider` interface. This includes methods for evaluating different flag types and lifecycle management. ```typescript import { AnyProviderEvent, EvaluationContext, Hook, JsonValue, Logger, Provider, ProviderEventEmitter, ResolutionDetails, } from '@openfeature/server-sdk'; // implement the provider interface class MyProvider implements Provider { // Adds runtime validation that the provider is used with the expected SDK public readonly runsOn = 'server'; readonly metadata = { name: 'My Provider', } as const; // Optional provider managed hooks hooks?: Hook[]; resolveBooleanEvaluation( flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger, ): Promise> { // code to evaluate a boolean } resolveStringEvaluation( flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger, ): Promise> { // code to evaluate a string } resolveNumberEvaluation( flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger, ): Promise> { // code to evaluate a number } resolveObjectEvaluation( flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger, ): Promise> { // code to evaluate an object } // implement with "new OpenFeatureEventEmitter()", and use "emit()" to emit events events?: ProviderEventEmitter | undefined; initialize?(context?: EvaluationContext | undefined): Promise { // code to initialize your provider } onClose?(): Promise { // code to shut down your provider } } ``` -------------------------------- ### Implement OpenFeature Hook Interface Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Example of a custom hook implementing the `Hook` interface. This hook demonstrates the `after` method, which runs after flag values are resolved. ```typescript import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/server-sdk'; export class MyHook implements Hook { after(hookContext: HookContext, evaluationDetails: EvaluationDetails) { // code that runs after flag values are successfully resolved from the provider } } ``` -------------------------------- ### Set Initial Evaluation Context with Static Object Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Configure the OpenFeature Angular SDK with a static evaluation context object during application setup. This context is applied when the SDK is provided. ```typescript import { ApplicationConfig } from '@angular/core'; import { provideOpenFeature } from '@openfeature/angular-sdk'; const initialContext = { user: { id: 'user123', role: 'admin', }, }; export const appConfig: ApplicationConfig = { providers: [ provideOpenFeature({ provider: yourFeatureProvider, context: initialContext, }), ], }; ``` -------------------------------- ### UseFlag Hook for Boolean Evaluation Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Example of using the useFlag hook to evaluate a boolean flag. It takes the flag key and a default value. ```tsx function Page() { // Use the "query-style" flag evaluation hook, specifying a flag-key and a default value. const { value: showNewMessage } = useFlag('new-message', true); return (
{showNewMessage ?

Welcome to this OpenFeature-enabled React app!

:

Welcome to this React app.

}
); } ``` -------------------------------- ### Express Middleware for Transaction Context Propagation Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md This example demonstrates how to use an Express middleware to propagate request-specific data like user ID and IP address into the OpenFeature transaction context. The `AsyncLocalStorageTransactionContextPropagator` ensures this context is available for all flag evaluations within the request's call chain. ```typescript import express, { Request, Response, NextFunction } from 'express'; import { OpenFeature, AsyncLocalStorageTransactionContextPropagator } from '@openfeature/server-sdk'; OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator()); /** * This example is based on an express middleware. */ const app = express(); app.use((req: Request, res: Response, next: NextFunction) => { const ip = req.headers['x-forwarded-for']; OpenFeature.setTransactionContext({ targetingKey: req.user.id, ipAddress: ip }, () => { // The transaction context is used in any flag evaluation throughout the whole call chain of next next(); }); }); ``` -------------------------------- ### Shutting Down OpenFeature SDK Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md This example demonstrates how to properly close the OpenFeature API to clean up all registered providers. This function should be called only when the application is shutting down. ```typescript import { OpenFeature } from '@openfeature/server-sdk'; await OpenFeature.close(); ``` -------------------------------- ### Implement a Custom OpenFeature Hook Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Example of a custom hook implementing the Hook interface. This hook provides a method to execute code after flag values are resolved. ```typescript import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/web-sdk'; export class MyHook implements Hook { after(hookContext: HookContext, evaluationDetails: EvaluationDetails) { // code that runs after flag values are successfully resolved from the provider } } ``` -------------------------------- ### Custom Tracking Strategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Implement a custom tracking strategy to control which providers receive tracking calls. This example shows how to selectively track based on provider name or event type. ```typescript import { FirstMatchStrategy, StrategyPerProviderContext } from '@openfeature/server-sdk'; class CustomTrackingStrategy extends FirstMatchStrategy { override shouldTrackWithThisProvider( strategyContext: StrategyPerProviderContext, context: EvaluationContext, trackingEventName: string, trackingEventDetails: TrackingEventDetails, ): boolean { // Only track with the primary provider if (strategyContext.providerName === 'primary-provider') { return true; } // Skip tracking for analytics events on backup providers if (trackingEventName.startsWith('analytics.')) { return false; } return super.shouldTrackWithThisProvider(strategyContext, context, trackingEventName, trackingEventDetails); } } ``` -------------------------------- ### FeatureFlagService with Observables Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Access feature flags programmatically using `FeatureFlagService`. All methods return Observables that emit new values upon configuration or context changes. This example demonstrates fetching boolean, string, number, and object flags. ```typescript import { Component, inject } from '@angular/core'; import { AsyncPipe } from '@angular/common'; import { FeatureFlagService } from '@openfeature/angular-sdk'; @Component({ selector: 'my-component', standalone: true, imports: [AsyncPipe], template:ധ്യ
Feature is enabled! Reason: {{ (isFeatureEnabled$ | async)?.reason }}
Theme: {{ (currentTheme$ | async)?.value }}
Max items: {{ (maxItems$ | async)?.value }}
ധ്യ, }) export class MyComponent { private flagService = inject(FeatureFlagService); // Boolean flag isFeatureEnabled$ = this.flagService.getBooleanDetails('my-feature', false); // String flag currentTheme$ = this.flagService.getStringDetails('theme', 'light'); // Number flag maxItems$ = this.flagService.getNumberDetails('max-items', 10); // Object flag with type safety config$ = this.flagService.getObjectDetails<{ timeout: number }>('api-config', { timeout: 5000 }); } ``` -------------------------------- ### Registering Providers with Domains Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Demonstrates how to register providers, including a default provider and domain-specific providers, and how to obtain clients bound to these providers. ```typescript import { OpenFeature, TypedInMemoryProvider } from '@openfeature/server-sdk'; const myFlags = { v2_enabled: { variants: { on: true, off: false, }, disabled: false, defaultVariant: 'on', }, } as const; OpenFeature.setProvider(new TypedInMemoryProvider(myFlags)); OpenFeature.setProvider('my-domain', new TypedInMemoryProvider(someOtherFlags)); const clientWithDefault = OpenFeature.getClient(); const domainScopedClient = OpenFeature.getClient('my-domain'); ``` -------------------------------- ### Initialize and Use OpenFeature Web SDK Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md This snippet shows how to register a feature flag provider and create a client to evaluate boolean flags. Ensure your provider is correctly implemented and handles potential initialization errors. ```ts import { OpenFeature } from '@openfeature/web-sdk'; // Register your feature flag provider try { await OpenFeature.setProviderAndWait(new YourProviderOfChoice()); } catch (error) { console.error('Failed to initialize provider:', error); } // create a new client const client = OpenFeature.getClient(); // Evaluate your feature flag const v2Enabled = client.getBooleanValue('v2_enabled', false); if (v2Enabled) { console.log('v2 is enabled'); } ``` -------------------------------- ### Initialize Multi-Provider and Track Events Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Demonstrates how to initialize the Multi-Provider with multiple providers and send a tracking event. Tracking events are sent to all providers by default. ```typescript import { OpenFeature } from '@openfeature/server-sdk'; import { MultiProvider } from '@openfeature/server-sdk'; const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); await OpenFeature.setProviderAndWait(multiProvider); const client = OpenFeature.getClient(); // Tracked events will be sent to all providers by default client.track('purchase', { targetingKey: 'user123' }, { value: 99.99, currency: 'USD' }); ``` -------------------------------- ### Run End-to-End Tests (Web) Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Execute the end-to-end tests for the web client implementation. Ensure your development environment is set up correctly before running. ```bash npm run e2e-web ``` -------------------------------- ### Boolean Feature Flag Directive Example Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Use the `*booleanFeatureFlag` directive for conditional rendering based on a boolean feature flag. The content is shown when the flag is enabled. ```html
This is shown when the feature flag is enabled.
``` -------------------------------- ### Navigate to Repository Directory Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Change your current directory to the cloned js-sdk repository. This is necessary to run subsequent commands within the project context. ```bash cd openfeature-js-sdk ``` -------------------------------- ### Stage, Commit, and Push Changes Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Stage all your changes, commit them with a signoff, and push the new branch to your fork. This prepares your work for a pull request. ```bash git add --all git commit --signoff git push fork feat/NAME_OF_FEATURE ``` -------------------------------- ### Registering Providers with Domains Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Demonstrates how to register a default provider and domain-specific providers using the OpenFeature SDK. This allows for logical separation and management of clients. ```typescript import { OpenFeature, TypedInMemoryProvider } from '@openfeature/web-sdk'; const myFlags = { v2_enabled: { variants: { on: true, off: false, }, disabled: false, defaultVariant: 'on', }, } as const; // Registering the default provider OpenFeature.setProvider(new TypedInMemoryProvider(myFlags)); // Registering a provider to a domain OpenFeature.setProvider('my-domain', new TypedInMemoryProvider(someOtherFlags)); // A Client bound to the default provider const clientWithDefault = OpenFeature.getClient(); // A Client bound to the TypedInMemoryProvider provider const domainScopedClient = OpenFeature.getClient('my-domain'); ``` -------------------------------- ### Test Declarative FeatureFlag Components Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Use flagValueMap with OpenFeatureTestProvider to test declarative FeatureFlag components. This example shows setting values for 'new-feature' and 'theme' flags. ```tsx // testing declarative FeatureFlag components ``` -------------------------------- ### Initialize Multi-Provider with FirstSuccessfulStrategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/src/provider/multi-provider/README.md Configure the Multi-Provider to use the FirstSuccessfulStrategy, which returns the first successful result and skips any provider that returns an error. ```typescript import { MultiProvider, FirstSuccessfulStrategy } from '@openfeature/web-sdk'; const multiProvider = new MultiProvider( [{ provider: new ProviderA() }, { provider: new ProviderB() }], new FirstSuccessfulStrategy(), ); ``` -------------------------------- ### Clone the js-sdk Repository Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Clone the official js-sdk repository to your local machine. This is the first step in setting up your development environment for contributions. ```bash git clone https://github.com/open-feature/js-sdk.git openfeature-js-sdk ``` -------------------------------- ### Basic Multi-Provider Tracking Usage Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/src/provider/multi-provider/README.md Demonstrates how to initialize a `MultiProvider` with multiple providers and use the `track` method to send events to all configured providers. Events are sent to all providers by default. ```typescript import { MultiProvider } from '@openfeature/web-sdk'; import { OpenFeature } from '@openfeature/web-sdk'; const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); await OpenFeature.setProviderAndWait(multiProvider); const client = OpenFeature.getClient(); // Tracked events will be sent to all providers by default client.track('user-conversion', { value: 99.99, currency: 'USD', conversionType: 'purchase', }); client.track('page-view', { page: '/checkout', source: 'direct', }); ``` -------------------------------- ### Initialize Multi-Provider with ComparisonStrategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Initialize the Multi-Provider with the 'ComparisonStrategy'. This strategy evaluates providers in parallel and uses a fallback provider if values do not agree. It accepts a fallback provider and an optional mismatch callback. ```typescript import { MultiProvider, ComparisonStrategy } from '@openfeature/server-sdk'; const providerA = new ProviderA(); const multiProvider = new MultiProvider( [{ provider: providerA }, { provider: new ProviderB() }], new ComparisonStrategy(providerA, (details) => { console.log('Mismatch detected', details); }), ); ``` -------------------------------- ### Run End-to-End Tests (Server) Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Execute the end-to-end tests for the server-side implementation. Ensure your development environment is set up correctly before running. ```bash npm run e2e-server ``` -------------------------------- ### Initialize Multi-Provider with Default Strategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/src/provider/multi-provider/README.md Initialize the Multi-Provider with an array of providers. The default strategy evaluates providers sequentially and returns the first successful result, skipping FLAG_NOT_FOUND errors. ```typescript import { MultiProvider } from '@openfeature/web-sdk'; import { OpenFeature } from '@openfeature/web-sdk'; const multiProvider = new MultiProvider([{ provider: new ProviderA() }, { provider: new ProviderB() }]); await OpenFeature.setProviderAndWait(multiProvider); const client = OpenFeature.getClient(); console.log('Evaluating flag'); console.log(client.getBooleanDetails('my-flag', false)); ``` -------------------------------- ### OpenFeatureProvider with Client Instance Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Configures the `OpenFeatureProvider` by passing a pre-configured `Client` instance directly. This allows for more explicit control over the client used by the provider. ```tsx const client = OpenFeature.getClient('my-domain'); function App() { return ( ); } ``` -------------------------------- ### Initialize Multi-Provider with FirstSuccessfulStrategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Initialize the Multi-Provider with a custom strategy, 'FirstSuccessfulStrategy', to alter the default evaluation behavior. This strategy skips providers that return an error. ```typescript import { MultiProvider, FirstSuccessfulStrategy } from '@openfeature/server-sdk'; const multiProvider = new MultiProvider( [{ provider: new ProviderA() }, { provider: new ProviderB() }], new FirstSuccessfulStrategy(), ); ``` -------------------------------- ### Bootstrap Application with Standalone Configuration Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Bootstrap your Angular application using the `appConfig` that includes the `provideOpenFeature()` configuration. ```typescript import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { appConfig } from './app/app.config'; bootstrapApplication(AppComponent, appConfig); ``` -------------------------------- ### Simulate Provider Startup Delay Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Introduce an artificial delay (in milliseconds) to the provider startup using delayMs. This is useful for testing suspense boundaries or loaders affected by feature flag availability. ```tsx // delay the provider start by 1000ms and then return `true` for all evaluations of `'my-boolean-flag'` ``` -------------------------------- ### Initialize Multi-Provider with ComparisonStrategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/src/provider/multi-provider/README.md Utilize the ComparisonStrategy for scenarios where providers should return identical results. It evaluates all providers and uses a fallback provider if values differ, with an optional callback for mismatch notifications. ```typescript import { MultiProvider, ComparisonStrategy } from '@openfeature/web-sdk'; const providerA = new ProviderA(); const multiProvider = new MultiProvider( [{ provider: providerA }, { provider: new ProviderB() }], new ComparisonStrategy(providerA, (details) => { console.log('Mismatch detected', details); }), ); ``` -------------------------------- ### Handling Provider Events Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Shows how to subscribe to provider events like Ready and Error at both the global OpenFeature API level and for specific clients. ```typescript import { OpenFeature, ProviderEvents } from '@openfeature/server-sdk'; OpenFeature.addHandler(ProviderEvents.Ready, (eventDetails) => { console.log(`Ready event from: ${eventDetails?.providerName}:`, eventDetails); }); const client = OpenFeature.getClient(); client.addHandler(ProviderEvents.Error, (eventDetails) => { console.log(`Error event from: ${eventDetails?.providerName}:`, eventDetails); }); ``` -------------------------------- ### Handling Provider Events Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Illustrates how to subscribe to OpenFeature provider events, such as readiness and errors, using both the global OpenFeature API and specific client instances. This enables reacting to state changes. ```typescript import { OpenFeature, ProviderEvents } from '@openfeature/web-sdk'; // OpenFeature API OpenFeature.addHandler(ProviderEvents.Ready, (eventDetails) => { console.log(`Ready event from: ${eventDetails?.providerName}:`, eventDetails); }); // Specific client const client = OpenFeature.getClient(); client.addHandler(ProviderEvents.Error, (eventDetails) => { console.log(`Error event from: ${eventDetails?.providerName}:`, eventDetails); }); ``` -------------------------------- ### Add Fork as Remote Origin Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Configure your local repository to point to your personal fork on GitHub. This allows you to push your changes to your fork. ```bash git remote add fork https://github.com/YOUR_GITHUB_USERNAME/js-sdk.git ``` -------------------------------- ### Custom Logging Configuration Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Illustrates how to override the default console logging behavior by providing a custom logger implementation globally or per client. ```typescript import type { Logger } from '@openfeature/server-sdk'; const logger: Logger = console; OpenFeature.setLogger(logger); const client = OpenFeature.getClient(); client.setLogger(logger); ``` -------------------------------- ### Configure Multi-Provider with First Match Strategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Set up a Multi-Provider to use multiple underlying providers. The `FirstMatchStrategy` ensures that the first provider to successfully return a flag value is used, short-circuiting on errors. ```typescript import { OpenFeature, MultiProvider, FirstMatchStrategy } from '@openfeature/server-sdk'; // Create providers const primaryProvider = new YourPrimaryProvider(); const backupProvider = new YourBackupProvider(); // Create multi-provider with a strategy const multiProvider = new MultiProvider( [{ provider: primaryProvider }, { provider: backupProvider }], new FirstMatchStrategy(), ); // Register the multi-provider await OpenFeature.setProviderAndWait(multiProvider); // Use as normal const client = OpenFeature.getClient(); const value = await client.getBooleanValue('my-flag', false); ``` -------------------------------- ### Register Provider Asynchronously Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Use `setProviderAndWait` to register a provider and ensure it's ready before proceeding. Handles potential initialization errors. ```typescript try { await OpenFeature.setProviderAndWait(new MyProvider()); } catch (error) { console.error('Failed to initialize provider:', error); } ``` -------------------------------- ### Register Provider Awaitably Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Use `setProviderAndWait` to register a provider and ensure it's ready before proceeding. This is useful for ensuring flag data is available immediately after initialization. ```typescript await OpenFeature.setProviderAndWait(new MyProvider()); ``` -------------------------------- ### Register Hooks Globally, Client-wide, and Per-Evaluation Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Demonstrates how to add hooks at different scopes: globally for all evaluations, on a specific client, or for a single flag evaluation. ```typescript import { OpenFeature } from '@openfeature/web-sdk'; // add a hook globally, to run on all evaluations OpenFeature.addHooks(new ExampleGlobalHook()); // add a hook on this client, to run on all evaluations made by this client const client = OpenFeature.getClient(); client.addHooks(new ExampleClientHook()); // add a hook for this evaluation only const boolValue = client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] }); ``` -------------------------------- ### OpenFeatureProvider with Domain Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Configures the `OpenFeatureProvider` to use a specific domain, allowing flags within that domain to be associated with a particular client or provider. This is an alternative to passing a pre-configured `Client` instance. ```tsx // Flags within this domain will use the client/provider associated with `my-domain`, function App() { return ( ); } ``` -------------------------------- ### Configure OpenFeatureProvider with a Domain Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Use the `domain` parameter on `OpenFeatureProvider` to scope a client to a particular provider and context when using multiple providers. ```tsx ``` -------------------------------- ### Setting Context for Domain-Scoped Clients Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Shows how to set evaluation context for domain-scoped clients, either during provider registration or by updating context after registration. This allows for personalized flag evaluations. ```typescript OpenFeature.setProvider('my-domain', new NewCachedProvider(), { targetingKey: localStorage.getItem('targetingKey') }); ``` ```typescript await OpenFeature.setContext('my-domain', { targetingKey: localStorage.getItem('targetingKey') }); ``` -------------------------------- ### Customizing Tracking with CustomTrackingStrategy Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/src/provider/multi-provider/README.md Illustrates how to customize tracking behavior by extending `FirstMatchStrategy` and overriding the `shouldTrackWithThisProvider` method. This allows selective tracking based on provider name or event type. ```typescript import { FirstMatchStrategy, StrategyPerProviderContext } from '@openfeature/web-sdk'; class CustomTrackingStrategy extends FirstMatchStrategy { // Override tracking behavior override shouldTrackWithThisProvider( strategyContext: StrategyPerProviderContext, context: EvaluationContext, trackingEventName: string, trackingEventDetails: TrackingEventDetails, ): boolean { // Only track with the primary provider if (strategyContext.providerName === 'primary-provider') { return true; } // Skip tracking for analytics events on backup providers if (trackingEventName.startsWith('analytics.')) { return false; } return super.shouldTrackWithThisProvider(strategyContext, context, trackingEventName, trackingEventDetails); } } ``` -------------------------------- ### Set Provider with Initial Context Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Register a new provider with initial context data. This context will be used for flag evaluations. ```typescript await OpenFeature.setProvider(new MyProvider(), { origin: document.location.host }); ``` -------------------------------- ### Create a New Feature Branch Source: https://github.com/open-feature/js-sdk/blob/main/CONTRIBUTING.md Create a new branch for your feature or bugfix. Use a descriptive name following the 'feat/NAME_OF_FEATURE' or 'fix/NAME_OF_BUG' convention. ```bash git checkout -b feat/NAME_OF_FEATURE ``` -------------------------------- ### Setting Evaluation Context Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Demonstrates how to set evaluation context at global, client, and invocation levels for dynamic flag targeting. ```typescript OpenFeature.setContext({ region: 'us-east-1' }); const client = OpenFeature.getClient(); client.setContext({ version: process.env.APP_VERSION }); const requestContext = { targetingKey: req.session.id, email: req.session.email, product: req.productId, }; const boolValue = await client.getBooleanValue('some-flag', false, requestContext); ``` -------------------------------- ### Tracking User Actions with OpenFeature Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md This snippet shows how to associate user actions with feature flag evaluations for experimentation. After a flag is evaluated, the `client.track` function can be called to record specific events, linking user behavior to feature flag usage. ```typescript // flag is evaluated await client.getBooleanValue('new-feature', false); // new feature is used and track function is called recording the usage useNewFeature(); client.track('new-feature-used'); ``` -------------------------------- ### Custom Evaluation Strategy Implementation Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/src/provider/multi-provider/README.md Shows how to create a custom evaluation strategy by extending the BaseEvaluationStrategy. This allows for custom logic in provider evaluation and result determination. ```typescript import { FirstMatchStrategy } from '@openfeature/server-sdk'; class MyCustomStrategy extends FirstMatchStrategy { // Override methods as needed override shouldEvaluateThisProvider( strategyContext: StrategyPerProviderContext, evalContext: EvaluationContext, ): boolean { // Custom logic here return super.shouldEvaluateThisProvider(strategyContext, evalContext); } } ``` -------------------------------- ### Registering Hooks Globally, Per Client, and Per Invocation Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Shows how to register custom hooks at different scopes: globally for all evaluations, on a specific client, or for a single flag evaluation. ```typescript import { OpenFeature } from '@openfeature/server-sdk'; OpenFeature.addHooks(new ExampleGlobalHook()); const client = OpenFeature.getClient(); client.addHooks(new ExampleClientHook()); const boolValue = await client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] }); ``` -------------------------------- ### FeatureFlagService Usage with Observables Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Demonstrates how to use the FeatureFlagService to fetch feature flag details (boolean, string, number, object) and subscribe to their changes using Observables and the AsyncPipe. ```APIDOC ## FeatureFlagService The `FeatureFlagService` provides programmatic access to feature flags through reactive patterns. All methods return Observables that automatically emit new values when flag configurations or evaluation context changes. ### Method Signature `getBooleanDetails(flagKey: string, defaultValue: boolean, options?: FlagOptions): Observable>` `getStringDetails(flagKey: string, defaultValue: string, options?: FlagOptions): Observable>` `getNumberDetails(flagKey: string, defaultValue: number, options?: FlagOptions): Observable>` `getObjectDetails(flagKey: string, defaultValue: T, options?: FlagOptions): Observable>` ### Parameters - **flagKey** (string) - Required - The key of the feature flag. - **defaultValue** (boolean | string | number | object) - Required - The default value to return if the flag is not found or an error occurs. - **options** (FlagOptions) - Optional - Options to configure flag evaluation behavior, such as `updateOnConfigurationChanged` and `updateOnContextChanged`. ### Request Example ```typescript import { Component, inject } from '@angular/core'; import { AsyncPipe } from '@angular/common'; import { FeatureFlagService } from '@openfeature/angular-sdk'; @Component({ selector: 'my-component', standalone: true, imports: [AsyncPipe], template: `
Feature is enabled! Reason: {{ (isFeatureEnabled$ | async)?.reason }}
Theme: {{ (currentTheme$ | async)?.value }}
Max items: {{ (maxItems$ | async)?.value }}
`, }) export class MyComponent { private flagService = inject(FeatureFlagService); // Boolean flag isFeatureEnabled$ = this.flagService.getBooleanDetails('my-feature', false); // String flag currentTheme$ = this.flagService.getStringDetails('theme', 'light'); // Number flag maxItems$ = this.flagService.getNumberDetails('max-items', 10); // Object flag with type safety config$ = this.flagService.getObjectDetails<{ timeout: number }>('api-config', { timeout: 5000 }); } ``` ### Response - **value** (any) - The evaluated value of the feature flag. - **reason** (string) - The reason for the flag evaluation (e.g., `"TARGETING_MATCH"`, `"DEFAULT"`, `"ERROR"`). - **flagMetadata** (object) - Metadata associated with the flag evaluation. ``` -------------------------------- ### Tracking Feature Flag Usage Source: https://github.com/open-feature/js-sdk/blob/main/packages/web/README.md Demonstrates how to associate user actions with feature flag evaluations using the `track` function. This is useful for experimentation and understanding user engagement with new features. ```typescript // flag is evaluated client.getBooleanValue('new-feature', false); // new feature is used and track function is called recording the usage useNewFeature(); client.track('new-feature-used'); ``` -------------------------------- ### Set Initial Evaluation Context with Factory Function Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Configure the OpenFeature Angular SDK with a factory function that returns an evaluation context. This allows for dynamic context loading, such as from local storage, when the SDK is provided. ```typescript import { ApplicationConfig } from '@angular/core'; import { provideOpenFeature, EvaluationContext } from '@openfeature/angular-sdk'; const contextFactory = (): EvaluationContext => loadContextFromLocalStorage(); export const appConfig: ApplicationConfig = { providers: [ provideOpenFeature({ provider: yourFeatureProvider, context: contextFactory, }), ], }; ``` -------------------------------- ### Register Provider Synchronously Source: https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md Use `setProvider` for synchronous provider registration. This method registers the provider without waiting for it to be ready, which might be suitable in certain application flows. ```typescript OpenFeature.setProvider(new MyProvider()); ``` -------------------------------- ### Track User Actions with Feature Flags Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Use the `useTrack` hook to associate user actions with feature flag evaluations for robust experimentation. Call the `track` function with an event name and optional details within your component. ```tsx function MyComponent() { // get a tracking function for this . const { track } = useTrack(); // call the tracking event // can be done in render, useEffect, or in handlers, depending on your use case track(eventName, trackingDetails); return <>...; } ``` -------------------------------- ### FeatureFlagService Usage with Angular Signals Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Shows how to convert Observables returned by FeatureFlagService into Angular Signals using `toSignal` for reactive programming with Signals. ```APIDOC ## FeatureFlagService with Signals You can convert any Observable from the service to an Angular Signal using `toSignal()`: ### Method Signature `toSignal(observable: Observable, options?: ToSignalOptions): Signal` ### Parameters - **observable** (Observable) - Required - The Observable to convert. - **options** (ToSignalOptions) - Optional - Options for `toSignal`. ### Request Example ```typescript import { Component, inject } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { FeatureFlagService } from '@openfeature/angular-sdk'; @Component({ selector: 'my-component', standalone: true, template: `
Feature is enabled! Reason: {{ isFeatureEnabled()?.reason }}
Theme: {{ currentTheme()?.value }}
`, }) export class MyComponent { private flagService = inject(FeatureFlagService); // Convert Observables to Signals isFeatureEnabled = toSignal(this.flagService.getBooleanDetails('my-feature', false)); currentTheme = toSignal(this.flagService.getStringDetails('theme', 'light')); } ``` ### Response - **Signal>** - A Signal that holds the latest evaluated flag details. ``` -------------------------------- ### FeatureFlag Component Usage Source: https://github.com/open-feature/js-sdk/blob/main/packages/react/README.md Demonstrates various ways to use the `FeatureFlag` component for conditional rendering based on flag values, including basic usage, matching specific values, boolean flags with fallbacks, custom predicates, and function children for accessing flag details. ```tsx import { FeatureFlag } from '@openfeature/react-sdk'; function App() { return ( {/* Basic usage - renders children when flag is truthy */} {/* Match specific values */} {/* Boolean flag with fallback */} }> {/* Custom predicate function for complex matching */} !!expected && actual.value.includes(expected)} > {/* Function as children for accessing flag details */} {( { value, reason } ) => ( value is {value}, reason is {reason?.toString()} )} ); } ``` -------------------------------- ### Standalone Configuration for Angular Apps Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Configure OpenFeature for standalone Angular applications by providing `provideOpenFeature()` in the `providers` array of your `ApplicationConfig`. This is the recommended approach. ```typescript import { ApplicationConfig } from '@angular/core'; import { provideOpenFeature } from '@openfeature/angular-sdk'; export const appConfig: ApplicationConfig = { providers: [ provideOpenFeature({ provider: yourFeatureProvider, // domainBoundProviders are optional, mostly needed if more than one provider is used in the application. domainBoundProviders: { domain1: new YourOpenFeatureProvider(), domain2: new YourOtherOpenFeatureProvider(), }, }), ], }; ``` -------------------------------- ### NgModule Configuration for OpenFeature (Deprecated) Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Configure OpenFeature for NgModule-based applications by importing `OpenFeatureModule` and calling `forRoot()`. This method is deprecated in favor of standalone configuration. ```typescript import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { OpenFeatureModule } from '@openfeature/angular-sdk'; @NgModule({ declarations: [ // Other components ], imports: [ CommonModule, OpenFeatureModule.forRoot({ provider: yourFeatureProvider, // domainBoundProviders are optional, mostly needed if more than one provider is used in the application. domainBoundProviders: { domain1: new YourOpenFeatureProvider(), domain2: new YourOtherOpenFeatureProvider(), }, }), ], }) export class AppModule {} ``` -------------------------------- ### Feature Flag Directives Source: https://github.com/open-feature/js-sdk/blob/main/packages/angular/projects/angular-sdk/README.md Illustrates how to use structural directives like `*stringFeatureFlag` to conditionally render templates based on feature flag values and evaluation details. ```APIDOC ## Feature Flag Directives The `*stringFeatureFlag` directive can be used for conditional rendering based on flag values. ### Directive Usage `*stringFeatureFlag="''; value: ''; default: ''; else: ; let ; let details = evaluationDetails" ### Parameters - **flagKey** (string) - Required - The key of the feature flag. - **value** (any) - Optional - The expected value of the flag for the template to be rendered. - **default** (any) - Optional - The default value to use if the flag is not evaluated or an error occurs. - **else** (TemplateRef) - Optional - A reference to an ng-template to render if the condition is not met. - **let ** - Optional - Binds the flag's evaluated value to a template variable. - **let details = evaluationDetails** - Optional - Binds the full evaluation details object to a template variable. ### Request Example ```html
It was a match! The theme color is {{ value }} because of {{ details.reason }}
It was no match! The theme color is {{ value }} because of {{ details.reason }} ``` When the expected flag value is omitted, the template will always be rendered. ```html
The theme color is {{ value }}.
``` ```