Skip to content

feat(angular): generate convenience method returning flag value Observable #226

@tomflenner

Description

@tomflenner

Summary

Add an additional generated method in the Angular service that directly returns an Observable<T> of the flag value, instead of Observable<EvaluationDetails<T>>.

Today, the generator produces a method like:

/**
 * Get evaluation details for the `my-super-feature` flag.
 *
 * Feature flag.
 *
 * **Details:**
 * - Flag key: `my-super-feature`
 * - Type: `boolean`
 * - Default value: `true`
 *
 * @param domain - Optional domain for flag evaluation (scopes the flag to a specific provider).
 * @param options - Optional configuration for the flag evaluation.
 * @returns An Observable that emits EvaluationDetails whenever the flag value changes.
 */
getMySuperFeatureDetails(
  domain?: string,
  options?: AngularFlagEvaluationOptions
): Observable<EvaluationDetails<boolean>> {
  return this.flagService.getBooleanDetails(
    "my-super-feature",
    true,
    domain,
    {
      updateOnConfigurationChanged: options?.updateOnConfigurationChanged ?? true,
      updateOnContextChanged: options?.updateOnContextChanged ?? true,
    }
  );
}

Problem

In modern Angular applications (especially with Signals), consumers can be only interested in the flag value, not the full EvaluationDetails.

Typical usage looks like:

private mySuperFeatureEnabled = toSignal(
  this.featureFlagService
    .getMySuperFeatureDetails()
    .pipe(map((details) => details.value))
);

The repeated .pipe(map(details => details.value)) becomes boilerplate across the application.


Proposed Solution

Generate an additional convenience method alongside getMySuperFeatureDetails, for example:

/**
 * Get the value of the `my-super-feature` flag.
 *
 * @param domain - Optional domain for flag evaluation.
 * @param options - Optional configuration for the flag evaluation.
 * @returns An Observable that emits the flag value whenever it changes.
 */
getMySuperFeature(
  domain?: string,
  options?: AngularFlagEvaluationOptions
): Observable<boolean> {
  return this.getMySuperFeatureDetails(domain, options).pipe(
    map((details) => details.value)
  );
}

This would allow usage like:

private mySuperFeatureEnabled = toSignal(
  this.featureFlagService.getMySuperFeature()
);

Benefits

  • Reduces repetitive RxJS mapping boilerplate
  • Improves ergonomics for common use cases
  • Keeps access to EvaluationDetails when needed
  • Aligns with the existing C# generator behavior
  • Increases cross-generator consistency

Impact

  • Non-breaking change (additive feature)
  • Improves developer experience
  • Makes generated Angular API more ergonomic and modern (especially with Signals)

Notes

The naming convention should follow existing generator patterns to ensure clarity and consistency across SDKs.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions