Skip to content

Conversation

@jonathannorris
Copy link
Member

@jonathannorris jonathannorris commented Jan 2, 2026

Summary

  • Consolidates duplicate Multi-Provider code from server and web packages into @openfeature/core (shared package)
  • Uses generics (TProviderStatus, TProvider) internally to support both server and web SDKs from a single implementation

Changes

Moved to shared package (@openfeature/core):

  • BaseEvaluationStrategy and base strategy classes
  • StatusTracker for provider status management
  • Error utilities (AggregateError, constructAggregateError)
  • Common types (ProviderEntryInput, RegisteredProvider)

SDK-specific strategy exports:

  • Each SDK exports pre-configured FirstMatchStrategy, FirstSuccessfulStrategy, and ComparisonStrategy classes
  • These wrapper classes have ProviderStatus pre-bound, maintaining backward compatibility
  • Users can continue using new FirstMatchStrategy() without any changes

New tests:

  • Added unit tests for StatusTracker (event handling, status priority)
  • Added unit tests for constructAggregateError (including edge cases)

Documentation:

  • Updated Multi-Provider READMEs with clearer custom strategy examples
  • Added BaseEvaluationStrategy class structure documentation

@jonathannorris jonathannorris requested review from a team as code owners January 2, 2026 03:19
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jonathannorris, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the Multi-Provider implementation by extracting shared logic and types from the server and web SDKs into a new @openfeature/core package. This move aims to centralize common functionalities, reduce redundancy, and enhance maintainability across different OpenFeature SDKs. The changes leverage TypeScript generics to ensure a flexible and type-safe approach for handling provider statuses and evaluation strategies in both server and client environments.

Highlights

  • Code Consolidation: Duplicate Multi-Provider code from the server and web packages has been moved into the @openfeature/core shared package, reducing code duplication by approximately 275 lines.
  • Generics Implementation: The consolidated code now utilizes generics (TProviderStatus, TProvider) to support both server and web SDKs from a single, unified implementation.
  • Shared Components: Key components such as BaseEvaluationStrategy, built-in strategies (FirstMatchStrategy, FirstSuccessfulStrategy, ComparisonStrategy), StatusTracker, error utilities (AggregateError, constructAggregateError), and common types (ProviderEntryInput, RegisteredProvider) are now part of the shared core package.
  • Provider Status Enum Update: The AllProviderStatus enum has been updated to include all possible status values, specifically adding RECONCILING for web-specific status handling.
  • Strategy Constructor Changes: Evaluation strategies now require the ProviderStatus enum in their constructors to facilitate platform-specific status management.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
…types

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
@jonathannorris jonathannorris force-pushed the feat-shared-multi-provider branch from c24d7e6 to 52d8268 Compare January 2, 2026 03:20
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a well-executed refactoring that consolidates the Multi-Provider logic from the server and web packages into a shared @openfeature/core package. Using generics to support both SDKs from a single implementation is a great approach that significantly reduces code duplication and improves maintainability. The changes are logical and the test updates are thorough. My review includes a few suggestions to clean up some leftover files and remove redundant type assertions, which will help finalize this excellent refactoring.

@jonathannorris jonathannorris marked this pull request as draft January 2, 2026 03:27
- Remove redundant 'provider as Provider' casts where type is already known
- Add proper type definitions for StatusTracker enums to eliminate 'as TProviderEvents' casts
- Use variable narrowing for optional Reconciling event/status

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
These files are now obsolete as the types are imported from the shared
@openfeature/core package.

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates duplicate Multi-Provider code from the server and web packages into the @openfeature/core shared package, reducing code duplication by approximately 275 lines. The refactoring uses generics (TProviderStatus, TProvider) to support both server and web SDKs from a single implementation.

Key changes:

  • Moved evaluation strategies, status tracking, and error utilities to the shared package with generic type parameters
  • Updated AllProviderStatus enum to explicitly include all status values (including RECONCILING for web)
  • Modified strategy constructors to require ProviderStatus enum parameter for platform-specific status handling

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/shared/src/provider/provider.ts Updated AllProviderStatus enum to be explicit rather than an alias, including all status values
packages/shared/src/provider/multi-provider/types.ts Added generic type definitions for ProviderEntryInput and RegisteredProvider
packages/shared/src/provider/multi-provider/strategies/base-evaluation-strategy.ts Created generic base strategy class with type parameters for provider status and provider type
packages/shared/src/provider/multi-provider/strategies/first-match-strategy.ts Added generic implementation of first-match strategy
packages/shared/src/provider/multi-provider/strategies/first-successful-strategy.ts Added generic implementation of first-successful strategy
packages/shared/src/provider/multi-provider/strategies/comparison-strategy.ts Added generic implementation of comparison strategy with updated constructor signature
packages/shared/src/provider/multi-provider/status-tracker.ts Created generic status tracker with type parameters for events, status, and provider
packages/shared/src/provider/multi-provider/errors.ts Moved error utilities with improved null-safety in constructAggregateError
packages/shared/src/provider/index.ts Added exports for multi-provider components
packages/web/src/provider/multi-provider/multi-provider-web.ts Updated to use shared types and strategies with proper generic parameters
packages/web/src/provider/multi-provider/index.ts Removed local exports now available from shared package
packages/web/test/multi-provider-web.spec.ts Updated strategy instantiations to pass ProviderStatus enum parameter
packages/server/src/provider/multi-provider/multi-provider.ts Updated to use shared types and strategies with proper generic parameters
packages/server/src/provider/multi-provider/index.ts Removed local exports now available from shared package
packages/server/test/multi-provider.spec.ts Updated strategy instantiations to pass ProviderStatus enum parameter
(deleted files) Removed duplicate implementations of strategies, status tracker, errors, and types from both web and server packages
Comments suppressed due to low confidence (4)

packages/shared/src/provider/multi-provider/errors.ts:28

  • The .flat() call on line 28 is unnecessary. The map function returns an array of objects, each already at the top level, so there are no nested arrays to flatten. This is likely a redundant operation left from previous refactoring.
    packages/shared/src/provider/multi-provider/strategies/first-match-strategy.ts:6
  • Documentation comments describing the strategy's behavior have been removed during the refactoring. The FirstMatchStrategy class should include a JSDoc comment explaining that it returns the first result that did not indicate "flag not found", and throws an error if any provider in the course of evaluation returns or throws an error.
    packages/shared/src/provider/multi-provider/strategies/first-successful-strategy.ts:8
  • Documentation comments describing the strategy's behavior have been removed during the refactoring. The FirstSuccessfulStrategy class should include a JSDoc comment explaining that it returns the first result that did NOT result in an error, ignores errors as long as there is a successful result, and throws all errors if there is no successful result.
    packages/shared/src/provider/multi-provider/strategies/comparison-strategy.ts:11
  • Documentation comments describing the strategy's behavior have been removed during the refactoring. The ComparisonStrategy class should include a JSDoc comment explaining that it evaluates all providers in parallel and compares the results. If values agree, it returns the value; if they disagree, it returns the value from the configured "fallback provider" and executes the "onMismatch" callback if defined.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add comprehensive tests for StatusTracker event handling and status priority
- Add tests for constructAggregateError including empty array edge case
- Add tests for throwAggregateErrorFromPromiseResults
- Fix AggregateError prototype chain for proper instanceof checks

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
Keep AllProviderStatus as an alias of ClientProviderStatus instead of
creating a new enum, to maintain backward compatibility.

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
@jonathannorris jonathannorris requested a review from Copilot January 2, 2026 03:49
@jonathannorris jonathannorris changed the title refactor: Move Multi-Provider shared code to core package refactor: move Multi-Provider shared code to core package Jan 2, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ic API

- Create FirstMatchStrategy, FirstSuccessfulStrategy, ComparisonStrategy
  wrapper classes in server and web SDKs with ProviderStatus pre-bound
- Rename base strategies to BaseFirstMatchStrategy, etc. in @openfeature/core
- Update READMEs with simplified custom strategy documentation
- Users can now use strategies without passing ProviderStatus:
  new FirstMatchStrategy() instead of new FirstMatchStrategy(ProviderStatus)

Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
@jonathannorris jonathannorris force-pushed the feat-shared-multi-provider branch from 849f66a to 97eb2ea Compare January 2, 2026 05:01
Signed-off-by: Jonathan Norris <jonathan@taplytics.com>
@jonathannorris jonathannorris marked this pull request as ready for review January 2, 2026 05:10
@toddbaert
Copy link
Member

I think I found just one small issue here. You added some generic args to some of the components for building custom strats, to support the divergence in types between web/server (we do this a lot). However, I think we can make things easier for consumers by re-exporting these from server/web with the relevant generics already passed, since we know what they will have to be in those modules. I opened this PR to this branch. I hope that makes sense: #1327

Copy link
Member

@toddbaert toddbaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm approving, but please consider this.

See:
#1324 (comment)

---------

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants