UNPKG

@openfeature/angular-sdk

Version:
1 lines 56.7 kB
{"version":3,"file":"openfeature-angular-sdk.mjs","sources":["../../../projects/angular-sdk/src/lib/feature-flag.directive.ts","../../../projects/angular-sdk/src/lib/internal/is-equal.ts","../../../projects/angular-sdk/src/lib/feature-flag.service.ts","../../../projects/angular-sdk/src/lib/open-feature.module.ts","../../../projects/angular-sdk/src/public-api.ts","../../../projects/angular-sdk/src/openfeature-angular-sdk.ts"],"sourcesContent":["import {\n ChangeDetectorRef,\n Directive,\n EmbeddedViewRef,\n Input,\n OnChanges,\n OnDestroy,\n OnInit,\n TemplateRef,\n ViewContainerRef,\n inject,\n} from '@angular/core';\nimport {\n Client,\n ClientProviderEvents,\n ClientProviderStatus,\n EvaluationDetails,\n EventHandler,\n FlagValue,\n JsonValue,\n OpenFeature,\n} from '@openfeature/web-sdk';\n\nclass FeatureFlagDirectiveContext<T extends FlagValue> {\n $implicit!: T;\n evaluationDetails: EvaluationDetails<T>;\n\n constructor(details: EvaluationDetails<T>) {\n this.$implicit = details.value;\n this.evaluationDetails = details;\n }\n}\n\n@Directive({\n standalone: true,\n selector: '[featureFlag]',\n})\nexport abstract class FeatureFlagDirective<T extends FlagValue> implements OnInit, OnDestroy, OnChanges {\n protected _changeDetectorRef: ChangeDetectorRef;\n protected _viewContainerRef: ViewContainerRef;\n\n protected _featureFlagDefault: T;\n protected _featureFlagDomain: string | undefined;\n\n protected _featureFlagKey: string;\n protected _featureFlagValue?: T;\n\n protected _client: Client;\n protected _lastEvaluationResult: EvaluationDetails<T>;\n\n protected _readyHandler: EventHandler<ClientProviderEvents.Ready> | null = null;\n protected _flagChangeHandler: EventHandler<ClientProviderEvents.ConfigurationChanged> | null = null;\n protected _contextChangeHandler: EventHandler<ClientProviderEvents.Error> | null = null;\n protected _reconcilingHandler: EventHandler<ClientProviderEvents.Reconciling> | null = null;\n\n protected _updateOnContextChanged: boolean = true;\n protected _updateOnConfigurationChanged: boolean = true;\n\n protected _thenTemplateRef: TemplateRef<FeatureFlagDirectiveContext<T>> | null;\n protected _thenViewRef: EmbeddedViewRef<unknown> | null;\n\n protected _elseTemplateRef: TemplateRef<FeatureFlagDirectiveContext<T>> | null;\n protected _elseViewRef: EmbeddedViewRef<unknown> | null;\n\n protected _initializingTemplateRef: TemplateRef<FeatureFlagDirectiveContext<T>> | null;\n protected _initializingViewRef: EmbeddedViewRef<unknown> | null;\n\n protected _reconcilingTemplateRef: TemplateRef<FeatureFlagDirectiveContext<T>> | null;\n protected _reconcilingViewRef: EmbeddedViewRef<unknown> | null;\n\n protected constructor() {}\n\n set featureFlagDomain(domain: string | undefined) {\n /**\n * We have to handle the change of the domain explicitly because we need to get a new client when the domain changes.\n * This can not be done if we simply relay the onChanges method.\n */\n this._featureFlagDomain = domain;\n this.initClient();\n }\n\n ngOnInit(): void {\n this.initClient();\n }\n\n ngOnChanges(): void {\n this._flagChangeHandler?.();\n }\n\n ngOnDestroy(): void {\n if (this._client) {\n this.disposeClient(this._client);\n this._client = null;\n }\n }\n\n private initClient(): void {\n if (this._client) {\n this.disposeClient(this._client);\n }\n this._client = OpenFeature.getClient(this._featureFlagDomain);\n\n const baseHandler = () => {\n const result = this.getFlagDetails(this._featureFlagKey, this._featureFlagDefault);\n this.onFlagValue(result, this._client.providerStatus);\n };\n\n this._flagChangeHandler = () => {\n if (this._updateOnConfigurationChanged) {\n baseHandler();\n }\n };\n\n this._contextChangeHandler = () => {\n if (this._updateOnContextChanged) {\n baseHandler();\n }\n };\n\n this._readyHandler = () => baseHandler();\n this._reconcilingHandler = () => baseHandler();\n\n this._client.addHandler(ClientProviderEvents.ConfigurationChanged, this._flagChangeHandler);\n this._client.addHandler(ClientProviderEvents.ContextChanged, this._contextChangeHandler);\n this._client.addHandler(ClientProviderEvents.Ready, this._readyHandler);\n this._client.addHandler(ClientProviderEvents.Reconciling, this._reconcilingHandler);\n }\n\n private disposeClient(client: Client) {\n if (this._contextChangeHandler()) {\n client.removeHandler(ClientProviderEvents.ContextChanged, this._contextChangeHandler);\n }\n\n if (this._flagChangeHandler) {\n client.removeHandler(ClientProviderEvents.ConfigurationChanged, this._flagChangeHandler);\n }\n\n if (this._readyHandler) {\n client.removeHandler(ClientProviderEvents.Ready, this._readyHandler);\n }\n\n if (this._reconcilingHandler) {\n client.removeHandler(ClientProviderEvents.Reconciling, this._reconcilingHandler);\n }\n }\n\n protected getFlagDetails(flagKey: string, defaultValue: T): EvaluationDetails<T> {\n if (typeof defaultValue === 'boolean') {\n return this._client.getBooleanDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'number') {\n return this._client.getNumberDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'string') {\n return this._client.getStringDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else {\n return this._client.getObjectDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n }\n }\n\n protected onFlagValue(result: EvaluationDetails<T>, status: ClientProviderStatus): void {\n const shouldInitialize = this._initializingTemplateRef && status === ClientProviderStatus.NOT_READY;\n const shouldReconcile = this._reconcilingTemplateRef && status === ClientProviderStatus.RECONCILING;\n\n const context = new FeatureFlagDirectiveContext(result);\n\n const resultChanged = !deepEqual(this._lastEvaluationResult, result);\n const isValueMatch = !this._featureFlagValue || deepEqual(result.value, this._featureFlagValue);\n\n if (this._initializingViewRef && shouldInitialize && !resultChanged) {\n return;\n } else if (this._reconcilingViewRef && shouldReconcile && !resultChanged) {\n return;\n } else if (this._thenViewRef && isValueMatch && !shouldInitialize && !shouldReconcile && !resultChanged) {\n return;\n } else if (this._elseViewRef && !isValueMatch && !shouldInitialize && !shouldReconcile && !resultChanged) {\n return;\n }\n\n this._lastEvaluationResult = result;\n this._viewContainerRef.clear();\n this._initializingViewRef = null;\n this._reconcilingViewRef = null;\n this._thenViewRef = null;\n this._elseViewRef = null;\n\n if (this._initializingTemplateRef && status === ClientProviderStatus.NOT_READY) {\n this._initializingViewRef = this._viewContainerRef.createEmbeddedView(this._initializingTemplateRef, context);\n } else if (this._reconcilingTemplateRef && status === ClientProviderStatus.RECONCILING) {\n this._reconcilingViewRef = this._viewContainerRef.createEmbeddedView(this._reconcilingTemplateRef, context);\n } else if (isValueMatch) {\n this._thenViewRef = this._viewContainerRef.createEmbeddedView(this._thenTemplateRef, context);\n } else if (this._elseTemplateRef) {\n this._elseViewRef = this._viewContainerRef.createEmbeddedView(this._elseTemplateRef, context);\n }\n\n this._changeDetectorRef.markForCheck();\n }\n}\n\n/**\n * A structural directive that conditionally includes a template based on the evaluation\n * of a boolean feature flag.\n * When the flag evaluates to true, Angular renders the template provided in a `then` clause,\n * and when false, Angular renders the template provided in an optional `else` clause.\n * The default template for the `else` clause is blank.\n *\n * Usage examples:\n *\n * ```\n * <div *booleanFeatureFlag=\"'flagKey'; default: false; let value\">{{ value }}</div>\n * ```\n * ```\n * <div *booleanFeatureFlag=\"flagKey; default: false; else: elseTemplate\">Content to render when flag is true.</div>\n * <ng-template #elseTemplate>Content to render when flag is false.</ng-template>\n * ```\n *\n * @usageNotes\n *\n * You can specify templates for other statuses such as initializing and reconciling.\n *\n * ```\n * <div *booleanFeatureFlag=\"flagKey; default:true; else: elseTemplate; initializing: initializingTemplate; reconciling: reconcilingTemplate\">Content to render when flag is true.</div>\n * <ng-template #elseTemplate>Content to render when flag is false.</ng-template>\n * <ng-template #initializingTemplate>Loading...</ng-template>\n * <ng-template #reconcilingTemplate>Reconfiguring...</ng-template>\n * ```\n *\n */\n@Directive({\n standalone: true,\n selector: '[booleanFeatureFlag]',\n})\nexport class BooleanFeatureFlagDirective extends FeatureFlagDirective<boolean> implements OnChanges {\n override _changeDetectorRef = inject(ChangeDetectorRef);\n override _viewContainerRef = inject(ViewContainerRef);\n override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<boolean>>>(TemplateRef);\n\n /**\n * The key of the boolean feature flag.\n */\n @Input({ required: true }) booleanFeatureFlag: string;\n\n /**\n * The default value for the boolean feature flag.\n */\n @Input({ required: true }) booleanFeatureFlagDefault: boolean;\n\n constructor() {\n super();\n }\n\n override ngOnChanges() {\n this._featureFlagKey = this.booleanFeatureFlag;\n this._featureFlagDefault = this.booleanFeatureFlagDefault;\n this._featureFlagValue = true;\n super.ngOnChanges();\n }\n\n /**\n * The domain of the boolean feature flag.\n */\n @Input({ required: false })\n set booleanFeatureFlagDomain(domain: string | undefined) {\n super.featureFlagDomain = domain;\n }\n\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n @Input({ required: false })\n set booleanFeatureFlagUpdateOnConfigurationChanged(enabled: boolean | undefined) {\n this._updateOnConfigurationChanged = enabled ?? true;\n }\n\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which\n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n @Input({ required: false })\n set booleanFeatureFlagUpdateOnContextChanged(enabled: boolean | undefined) {\n this._updateOnContextChanged = enabled ?? true;\n }\n\n /**\n * Template to be displayed when the feature flag is false.\n */\n @Input()\n set booleanFeatureFlagElse(tpl: TemplateRef<FeatureFlagDirectiveContext<boolean>>) {\n this._elseTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the provider is not ready.\n */\n @Input()\n set booleanFeatureFlagInitializing(tpl: TemplateRef<FeatureFlagDirectiveContext<boolean>>) {\n this._initializingTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the provider is reconciling.\n */\n @Input()\n set booleanFeatureFlagReconciling(tpl: TemplateRef<FeatureFlagDirectiveContext<boolean>>) {\n this._reconcilingTemplateRef = tpl;\n }\n}\n\n/**\n * A structural directive that conditionally includes a template based on the evaluation\n * of a number feature flag.\n * When the flag matches the provided value or no expected value is given, Angular renders the template provided\n * in a `then` clause, and when it doesn't match, Angular renders the template provided\n * in an optional `else` clause.\n * The default template for the `else` clause is blank.\n *\n * Usage examples:\n *\n * ```\n * <div *numberFeatureFlag=\"'flagKey'; default: 0; let value\">{{ value }}</div>\n * ```\n * ```\n * <div *numberFeatureFlag=\"'flagKey'; value: 1; default: 0; else: elseTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * ```\n *\n * @usageNotes\n *\n * You can specify templates for other statuses such as initializing and reconciling.\n *\n * ```\n * <div *numberFeatureFlag=\"flagKey; default: 0; value: flagValue; else: elseTemplate; initializing: initializingTemplate; reconciling: reconcilingTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * <ng-template #initializingTemplate>Loading...</ng-template>\n * <ng-template #reconcilingTemplate>Reconfiguring...</ng-template>\n * ```\n *\n */\n@Directive({\n standalone: true,\n selector: '[numberFeatureFlag]',\n})\nexport class NumberFeatureFlagDirective extends FeatureFlagDirective<number> implements OnChanges {\n override _changeDetectorRef = inject(ChangeDetectorRef);\n override _viewContainerRef = inject(ViewContainerRef);\n override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<number>>>(TemplateRef);\n\n /**\n * The key of the number feature flag.\n */\n @Input({ required: true }) numberFeatureFlag: string;\n\n /**\n * The default value for the number feature flag.\n */\n @Input({ required: true }) numberFeatureFlagDefault: number;\n\n /**\n * The expected value of this number feature flag, for which the `then` template should be rendered.\n */\n @Input({ required: false }) numberFeatureFlagValue?: number;\n\n constructor() {\n super();\n }\n\n override ngOnChanges() {\n this._featureFlagKey = this.numberFeatureFlag;\n this._featureFlagDefault = this.numberFeatureFlagDefault;\n this._featureFlagValue = this.numberFeatureFlagValue;\n super.ngOnChanges();\n }\n\n /**\n * The domain of the number feature flag.\n */\n @Input({ required: false })\n set numberFeatureFlagDomain(domain: string | undefined) {\n super.featureFlagDomain = domain;\n }\n\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n @Input({ required: false })\n set numberFeatureFlagUpdateOnConfigurationChanged(enabled: boolean | undefined) {\n this._updateOnConfigurationChanged = enabled ?? true;\n }\n\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which\n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n @Input({ required: false })\n set numberFeatureFlagUpdateOnContextChanged(enabled: boolean | undefined) {\n this._updateOnContextChanged = enabled ?? true;\n }\n\n /**\n * Template to be displayed when the feature flag does not match value.\n */\n @Input()\n set numberFeatureFlagElse(tpl: TemplateRef<FeatureFlagDirectiveContext<number>>) {\n this._elseTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is not ready.\n */\n @Input()\n set numberFeatureFlagInitializing(tpl: TemplateRef<FeatureFlagDirectiveContext<number>>) {\n this._initializingTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is not ready.\n */\n @Input()\n set numberFeatureFlagReconciling(tpl: TemplateRef<FeatureFlagDirectiveContext<number>>) {\n this._reconcilingTemplateRef = tpl;\n }\n}\n\n/**\n * A structural directive that conditionally includes a template based on the evaluation\n * of a string feature flag.\n * When the flag matches the provided value or no expected value is given, Angular renders the template provided\n * in a `then` clause, and when it doesn't match, Angular renders the template provided\n * in an optional `else` clause.\n * The default template for the `else` clause is blank.\n *\n * Usage examples:\n *\n * ```\n * <div *stringFeatureFlag=\"'flagKey'; default: 'default'; let value\">{{ value }}</div>\n * ```\n * ```\n * <div *stringFeatureFlag=\"flagKey; default: 'default'; value: flagValue; else: elseTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * ```\n *\n * @usageNotes\n *\n * You can specify templates for other statuses such as initializing and reconciling.\n *\n * ```\n * <div *stringFeatureFlag=\"flagKey; default: 'default'; value: flagValue; else: elseTemplate; initializing: initializingTemplate; reconciling: reconcilingTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * <ng-template #initializingTemplate>Loading...</ng-template>\n * <ng-template #reconcilingTemplate>Reconfiguring...</ng-template>\n * ```\n *\n */\n@Directive({\n standalone: true,\n selector: '[stringFeatureFlag]',\n})\nexport class StringFeatureFlagDirective extends FeatureFlagDirective<string> implements OnChanges {\n override _changeDetectorRef = inject(ChangeDetectorRef);\n override _viewContainerRef = inject(ViewContainerRef);\n override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<string>>>(TemplateRef);\n\n /**\n * The key of the string feature flag.\n */\n @Input({ required: true }) stringFeatureFlag: string;\n\n /**\n * The default value for the string feature flag.\n */\n @Input({ required: true }) stringFeatureFlagDefault: string;\n\n /**\n * The expected value of this string feature flag, for which the `then` template should be rendered.\n */\n @Input({ required: false }) stringFeatureFlagValue?: string;\n\n constructor() {\n super();\n }\n\n override ngOnChanges() {\n this._featureFlagKey = this.stringFeatureFlag;\n this._featureFlagDefault = this.stringFeatureFlagDefault;\n this._featureFlagValue = this.stringFeatureFlagValue;\n super.ngOnChanges();\n }\n\n /**\n * The domain for the string feature flag.\n */\n @Input({ required: false })\n set stringFeatureFlagDomain(domain: string | undefined) {\n super.featureFlagDomain = domain;\n }\n\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n @Input({ required: false })\n set stringFeatureFlagUpdateOnConfigurationChanged(enabled: boolean | undefined) {\n this._updateOnConfigurationChanged = enabled ?? true;\n }\n\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which\n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n @Input({ required: false })\n set stringFeatureFlagUpdateOnContextChanged(enabled: boolean | undefined) {\n this._updateOnContextChanged = enabled ?? true;\n }\n\n /**\n * Template to be displayed when the feature flag does not match value.\n */\n @Input()\n set stringFeatureFlagElse(tpl: TemplateRef<FeatureFlagDirectiveContext<string>>) {\n this._elseTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is not ready.\n */\n @Input()\n set stringFeatureFlagInitializing(tpl: TemplateRef<FeatureFlagDirectiveContext<string>>) {\n this._initializingTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is reconciling.\n */\n @Input()\n set stringFeatureFlagReconciling(tpl: TemplateRef<FeatureFlagDirectiveContext<string>>) {\n this._reconcilingTemplateRef = tpl;\n }\n}\n\n/**\n * A structural directive that conditionally includes a template based on the evaluation\n * of an object feature flag.\n * When the flag matches the provided value or no expected value is given, Angular renders the template provided\n * in a `then` clause, and when it doesn't match, Angular renders the template provided\n * in an optional `else` clause.\n * The default template for the `else` clause is blank.\n *\n * Usage examples:\n *\n * ```\n * <div *objectFeatureFlag=\"'flagKey'; default: {}; let value\">{{ value }}</div>\n * ```\n * ```\n * <div *objectFeatureFlag=\"flagKey; default: {}; value: flagValue; else: elseTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * ```\n *\n * @usageNotes\n *\n * You can specify templates for other statuses such as initializing and reconciling.\n *\n * ```\n * <div *objectFeatureFlag=\"flagKey; default: {}; value: flagValue; else: elseTemplate; initializing: initializingTemplate; reconciling: reconcilingTemplate\">Content to render when flag matches value.</div>\n * <ng-template #elseTemplate>Content to render when flag does not match value.</ng-template>\n * <ng-template #initializingTemplate>Loading...</ng-template>\n * <ng-template #reconcilingTemplate>Reconfiguring...</ng-template>\n * ```\n *\n */\n@Directive({\n standalone: true,\n selector: '[objectFeatureFlag]',\n})\nexport class ObjectFeatureFlagDirective<T extends JsonValue> extends FeatureFlagDirective<T> implements OnChanges {\n override _changeDetectorRef = inject(ChangeDetectorRef);\n override _viewContainerRef = inject(ViewContainerRef);\n override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<T>>>(TemplateRef);\n\n /**\n * The key of the object feature flag.\n */\n @Input({ required: true }) objectFeatureFlag: string;\n\n /**\n * The default value for the object feature flag.\n */\n @Input({ required: true }) objectFeatureFlagDefault: T;\n\n /**\n * The expected value of this object feature flag, for which the `then` template should be rendered.\n */\n @Input({ required: false }) objectFeatureFlagValue?: T;\n\n constructor() {\n super();\n }\n\n override ngOnChanges() {\n this._featureFlagKey = this.objectFeatureFlag;\n this._featureFlagDefault = this.objectFeatureFlagDefault;\n this._featureFlagValue = this.objectFeatureFlagValue;\n super.ngOnChanges();\n }\n\n /**\n * The domain for the object feature flag.\n */\n @Input({ required: false })\n set objectFeatureFlagDomain(domain: string | undefined) {\n super.featureFlagDomain = domain;\n }\n\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n @Input({ required: false })\n set objectFeatureFlagUpdateOnConfigurationChanged(enabled: boolean | undefined) {\n this._updateOnConfigurationChanged = enabled ?? true;\n }\n\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which\n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n @Input({ required: false })\n set objectFeatureFlagUpdateOnContextChanged(enabled: boolean | undefined) {\n this._updateOnContextChanged = enabled ?? true;\n }\n\n /**\n * Template to be displayed when the feature flag does not match value.\n */\n @Input()\n set objectFeatureFlagElse(tpl: TemplateRef<FeatureFlagDirectiveContext<T>>) {\n this._elseTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is not ready.\n */\n @Input()\n set objectFeatureFlagInitializing(tpl: TemplateRef<FeatureFlagDirectiveContext<T>>) {\n this._initializingTemplateRef = tpl;\n }\n\n /**\n * Template to be displayed when the feature flag is reconciling.\n */\n @Input()\n set objectFeatureFlagReconciling(tpl: TemplateRef<FeatureFlagDirectiveContext<T>>) {\n this._reconcilingTemplateRef = tpl;\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction deepEqual(obj1: any, obj2: any): boolean {\n if (obj1 === obj2) {\n // If both objects are identical\n return true;\n }\n\n if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {\n // One of them is not an object or one of them is null\n return false;\n }\n\n const keys1 = Object.keys(obj1);\n const keys2 = Object.keys(obj2);\n\n if (keys1.length !== keys2.length) {\n // Different number of properties\n return false;\n }\n\n for (const key of keys1) {\n if (!keys2.includes(key)) {\n // obj2 does not have a property that obj1 has\n return false;\n }\n\n // Recursive check for each property\n if (!deepEqual(obj1[key], obj2[key])) {\n return false;\n }\n }\n\n return true;\n}\n","import { type FlagValue } from '@openfeature/web-sdk';\n\n/**\n * Deeply compare two values to determine if they are equal.\n * Supports primitives and serializable objects.\n * @param {FlagValue} value First value to compare\n * @param {FlagValue} other Second value to compare\n * @returns {boolean} True if the values are equal\n */\nexport function isEqual(value: FlagValue, other: FlagValue): boolean {\n if (value === other) {\n return true;\n }\n\n if (typeof value !== typeof other) {\n return false;\n }\n\n if (typeof value === 'object' && value !== null && other !== null) {\n const valueKeys = Object.keys(value);\n const otherKeys = Object.keys(other);\n\n if (valueKeys.length !== otherKeys.length) {\n return false;\n }\n\n for (const key of valueKeys) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (!isEqual((value as any)[key], (other as any)[key])) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n}\n","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport {\n Client,\n EvaluationDetails,\n type FlagEvaluationOptions,\n FlagValue,\n type JsonValue,\n OpenFeature,\n ProviderEvents,\n ProviderStatus,\n} from '@openfeature/web-sdk';\nimport { isEqual } from './internal/is-equal';\n\nexport type AngularFlagEvaluationOptions = {\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent updating the value when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n updateOnConfigurationChanged?: boolean;\n /**\n * Emit a new value when the OpenFeature context changes.\n * Set to false to prevent updating the value when attributes which\n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n updateOnContextChanged?: boolean;\n} & FlagEvaluationOptions;\n\n/**\n * Angular service for evaluating feature flags using OpenFeature.\n *\n * This service provides reactive methods to evaluate feature flags that automatically\n * update when flag values or evaluation context changes. All methods return Observables\n * that emit new values when the underlying flag configuration changes.\n *\n * @example\n * ```typescript\n * @Component({\n * standalone: true,\n * })\n * export class MyComponent {\n * private flagService = inject(FeatureFlagService);\n *\n * // Boolean flag evaluation\n * isEnabled$ = this.flagService.getBooleanDetails('my-flag', false);\n *\n * // Using with signals\n * isEnabledSignal = toSignal(this.isEnabled$);\n * }\n * ```\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class FeatureFlagService {\n constructor() {}\n\n /**\n * Evaluates a boolean feature flag and returns an Observable of evaluation details.\n *\n * The returned Observable will emit new values when:\n * - The provider becomes ready (if it wasn't already)\n * - The flag configuration changes (if updateOnConfigurationChanged is true)\n * - The evaluation context changes (if updateOnContextChanged is true)\n *\n * @param flagKey - The key of the feature flag to evaluate\n * @param defaultValue - The default value to return if the flag cannot be evaluated\n * @param domain - Optional domain for the OpenFeature client. If not provided, uses the global client\n * @param options - Optional evaluation options including update behavior configuration\n * @returns Observable that emits EvaluationDetails containing the boolean flag value and metadata\n *\n * @example\n * ```typescript\n * // Basic usage\n * const isFeatureEnabled$ = flagService.getBooleanDetails('feature-toggle', false);\n *\n * // With domain\n * const isDomainFeatureEnabled$ = flagService.getBooleanDetails('feature-toggle', false, 'my-domain');\n *\n * // With options to disable automatic updates\n * const isStaticFeatureEnabled$ = flagService.getBooleanDetails('feature-toggle', false, undefined, {\n * updateOnConfigurationChanged: false,\n * updateOnContextChanged: false\n * });\n * ```\n */\n public getBooleanDetails(\n flagKey: string,\n defaultValue: boolean,\n domain?: string,\n options?: AngularFlagEvaluationOptions,\n ): Observable<EvaluationDetails<boolean>> {\n return this.getFlagDetails<boolean>(flagKey, defaultValue, (client) => client.getBooleanDetails, domain, options);\n }\n\n /**\n * Evaluates a string feature flag and returns an Observable of evaluation details.\n *\n * The returned Observable will emit new values when:\n * - The provider becomes ready (if it wasn't already)\n * - The flag configuration changes (if updateOnConfigurationChanged is true)\n * - The evaluation context changes (if updateOnContextChanged is true)\n *\n * @param flagKey - The key of the feature flag to evaluate\n * @param defaultValue - The default value to return if the flag cannot be evaluated\n * @param domain - Optional domain for the OpenFeature client. If not provided, uses the global client\n * @param options - Optional evaluation options including update behavior configuration\n * @returns Observable that emits EvaluationDetails containing the string flag value and metadata\n *\n * @example\n * ```typescript\n * // Theme selection\n * const theme$ = flagService.getStringDetails('theme', 'light');\n *\n * // API endpoint selection with domain\n * const apiEndpoint$ = flagService.getStringDetails('api-endpoint', 'https://api.example.com', 'config-domain');\n * ```\n */\n public getStringDetails(\n flagKey: string,\n defaultValue: string,\n domain?: string,\n options?: AngularFlagEvaluationOptions,\n ): Observable<EvaluationDetails<string>> {\n return this.getFlagDetails<string>(flagKey, defaultValue, (client) => client.getStringDetails, domain, options);\n }\n\n /**\n * Evaluates a number feature flag and returns an Observable of evaluation details.\n *\n * The returned Observable will emit new values when:\n * - The provider becomes ready (if it wasn't already)\n * - The flag configuration changes (if updateOnConfigurationChanged is true)\n * - The evaluation context changes (if updateOnContextChanged is true)\n *\n * @param flagKey - The key of the feature flag to evaluate\n * @param defaultValue - The default value to return if the flag cannot be evaluated\n * @param domain - Optional domain for the OpenFeature client. If not provided, uses the global client\n * @param options - Optional evaluation options including update behavior configuration\n * @returns Observable that emits EvaluationDetails containing the number flag value and metadata\n *\n * @example\n * ```typescript\n * // Timeout configuration\n * const timeout$ = flagService.getNumberDetails('request-timeout', 5000);\n * ```\n */\n public getNumberDetails(\n flagKey: string,\n defaultValue: number,\n domain?: string,\n options?: AngularFlagEvaluationOptions,\n ): Observable<EvaluationDetails<number>> {\n return this.getFlagDetails<number>(flagKey, defaultValue, (client) => client.getNumberDetails, domain, options);\n }\n\n /**\n * Evaluates an object feature flag and returns an Observable of evaluation details.\n *\n * The returned Observable will emit new values when:\n * - The provider becomes ready (if it wasn't already)\n * - The flag configuration changes (if updateOnConfigurationChanged is true)\n * - The evaluation context changes (if updateOnContextChanged is true)\n *\n * @template T - The type of the JSON object, must extend JsonValue\n * @param flagKey - The key of the feature flag to evaluate\n * @param defaultValue - The default value to return if the flag cannot be evaluated\n * @param domain - Optional domain for the OpenFeature client. If not provided, uses the global client\n * @param options - Optional evaluation options including update behavior configuration\n * @returns Observable that emits EvaluationDetails containing the object flag value and metadata\n *\n * @example\n * ```typescript\n * interface FeatureConfig {\n * maxRetries: number;\n * retryDelay: number;\n * enableLogging: boolean;\n * }\n *\n * // Configuration object\n * const defaultConfig: FeatureConfig = {\n * maxRetries: 3,\n * retryDelay: 1000,\n * enableLogging: false\n * };\n *\n * const config$ = flagService.getObjectDetails<FeatureConfig>('api-config', defaultConfig);\n * ```\n */\n public getObjectDetails<T extends JsonValue = JsonValue>(\n flagKey: string,\n defaultValue: T,\n domain?: string,\n options?: AngularFlagEvaluationOptions,\n ): Observable<EvaluationDetails<T>> {\n return this.getFlagDetails<T>(flagKey, defaultValue, (client) => client.getObjectDetails, domain, options);\n }\n\n private shouldEvaluateFlag(flagKey: string, flagsChanged?: string[]): boolean {\n // if flagsChanged is missing entirely, we don't know what to re-render\n return !flagsChanged || flagsChanged.includes(flagKey);\n }\n\n private getFlagDetails<T extends FlagValue>(\n flagKey: string,\n defaultValue: T,\n resolver: (\n client: Client,\n ) => (flagKey: string, defaultValue: T, options?: FlagEvaluationOptions) => EvaluationDetails<T>,\n domain: string | undefined,\n options?: AngularFlagEvaluationOptions,\n ): Observable<EvaluationDetails<T>> {\n const client = domain ? OpenFeature.getClient(domain) : OpenFeature.getClient();\n\n return new Observable<EvaluationDetails<T>>((subscriber) => {\n let currentResult: EvaluationDetails<T> | undefined = undefined;\n\n const updateValue = () => {\n const updatedEvaluationDetails = resolver(client).call(client, flagKey, defaultValue, options);\n if (!isEqual(updatedEvaluationDetails, currentResult)) {\n currentResult = updatedEvaluationDetails;\n subscriber.next(currentResult);\n }\n };\n\n const controller = new AbortController();\n if (client.providerStatus === ProviderStatus.NOT_READY) {\n // update when the provider is ready\n client.addHandler(ProviderEvents.Ready, updateValue, { signal: controller.signal });\n }\n\n if (options?.updateOnContextChanged ?? true) {\n client.addHandler(ProviderEvents.ContextChanged, updateValue, { signal: controller.signal });\n }\n\n if (options?.updateOnConfigurationChanged ?? true) {\n client.addHandler(\n ProviderEvents.ConfigurationChanged,\n (eventDetails) => {\n /**\n * Avoid re-rendering if the value hasn't changed. We could expose a means\n * to define a custom comparison function if users require a more\n * sophisticated comparison in the future.\n */\n if (this.shouldEvaluateFlag(flagKey, eventDetails?.flagsChanged)) {\n // update when the provider configuration changes\n updateValue();\n }\n },\n { signal: controller.signal },\n );\n }\n\n // Initial evaluation\n updateValue();\n return () => {\n controller.abort();\n };\n });\n }\n}\n","import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { EvaluationContext, OpenFeature, Provider } from '@openfeature/web-sdk';\n\nexport type EvaluationContextFactory = () => EvaluationContext;\n\nexport interface OpenFeatureConfig {\n /**\n * The default provider to be used by OpenFeature.\n * If not provided, the provider can be set later using {@link OpenFeature.setProvider}\n * or {@link OpenFeature.setProviderAndWait}.\n */\n provider?: Provider;\n /**\n * A map of domain-bound providers to be registered with OpenFeature.\n * The key is the domain name, and the value is the provider instance.\n * Providers can also be registered later using {@link OpenFeature.setProvider}\n * or {@link OpenFeature.setProviderAndWait}.\n */\n domainBoundProviders?: Record<string, Provider>;\n\n /**\n * An optional evaluation context or a factory function that returns an {@link EvaluationContext}.\n * This context will be used as the context for all providers registered by the module.\n * If a factory function is provided, it will be invoked to obtain the context.\n * This allows for dynamic context generation at runtime.\n */\n context?: EvaluationContext | EvaluationContextFactory;\n}\n\nexport const OPEN_FEATURE_CONFIG_TOKEN = new InjectionToken<OpenFeatureConfig>('OPEN_FEATURE_CONFIG_TOKEN');\n\n@NgModule({\n declarations: [],\n imports: [CommonModule],\n exports: [],\n})\nexport class OpenFeatureModule {\n static forRoot(config: OpenFeatureConfig): ModuleWithProviders<OpenFeatureModule> {\n const context = typeof config.context === 'function' ? config.context() : config.context;\n OpenFeature.setProvider(config.provider, context);\n\n if (config.domainBoundProviders) {\n Object.entries(config.domainBoundProviders).map(([domain, provider]) =>\n OpenFeature.setProvider(domain, provider, context),\n );\n }\n\n return {\n ngModule: OpenFeatureModule,\n providers: [{ provide: OPEN_FEATURE_CONFIG_TOKEN, useValue: config }],\n };\n }\n}\n","/*\n * Public API Surface of angular\n */\n\nexport * from './lib/feature-flag.directive';\nexport * from './lib/feature-flag.service';\nexport * from './lib/open-feature.module';\n\n// re-export the web-sdk so consumers can access that API from the angular-sdk\nexport * from '@openfeature/web-sdk';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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