Skip to content

feat: expose js sdk identity without proxy wrappers#1377

Draft
jonathannorris wants to merge 10 commits intomainfrom
feat/client-metadata-no-proxy
Draft

feat: expose js sdk identity without proxy wrappers#1377
jonathannorris wants to merge 10 commits intomainfrom
feat/client-metadata-no-proxy

Conversation

@jonathannorris
Copy link
Copy Markdown
Member

@jonathannorris jonathannorris commented Apr 10, 2026

Summary

  • extend ClientMetadata with JS-specific identity fields: sdk, paradigm, and framework
  • set sdk / paradigm in the base web and server clients
  • keep the public getClient(...) API unchanged
  • make React, Angular, and Nest mark SDK-owned clients internally so client.metadata and hook clientMetadata expose framework identity without a Proxy

Motivation

Relates to #1375.

Today providers and hooks can access clientMetadata, but the JS SDKs do not expose enough identity to tell whether a call came from js-web vs js-server, or from react, angular, or nest.

This version avoids Proxy, keeps the existing public getClient(...) signatures in place, and treats framework identity as internal framework-owned metadata rather than a new public client-construction API.

Usage

const client = OpenFeature.getClient('my-domain', '1.2.3');

client.metadata;
// {
//   domain: 'my-domain',
//   version: '1.2.3',
//   sdk: 'js-web',
//   paradigm: 'client',
//   providerMetadata: { name: '...' }
// }
hook.before = (hookContext) => {
  hookContext.clientMetadata;
  // react-sdk:
  // {
  //   domain: 'my-domain',
  //   sdk: 'js-web',
  //   paradigm: 'client',
  //   framework: 'react',
  //   providerMetadata: { name: '...' }
  // }
};

Notes

  • framework metadata is carried on the concrete web/server client instances without a wrapper layer
  • the public getClient(...) signatures remain unchanged
  • framework SDKs set framework internally on the SDK-owned client instances they use
  • the React client prop path preserves the provided client instance and marks it locally so metadata stays aligned with provider-created clients

Related Issues

Carry framework metadata on SDK-owned clients so client metadata and hook contexts expose js sdk identity without relying on Proxy wrappers in the framework packages.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Copy link
Copy Markdown
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 introduces framework and SDK metadata to OpenFeature clients across Angular, Nest, and React. It adds a setFrameworkMetadata utility and updates the core OpenFeatureClient to include 'sdk' and 'framework' fields in its metadata. Review feedback recommends removing the manual client caching in the Angular FeatureFlagService to avoid potential stale references and simplify the code by relying on the SDK's internal client registry.

Use the current OpenFeature client for each Angular evaluation so framework metadata stays aligned with SDK lifecycle changes and test teardown.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Copy link
Copy Markdown

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 enhances JS SDK client identification by extending ClientMetadata with sdk and framework, setting sdk in base web/server clients, and enabling React/Angular/Nest wrappers to mark framework identity on the underlying SDK-owned client instances (so client.metadata and hook clientMetadata stay aligned without proxy wrappers).

Changes:

  • Extend core ClientMetadata with sdk (web/server) and framework (react/angular/nest) and add an internal helper to apply framework metadata when supported.
  • Populate metadata.sdk in the web and server OpenFeatureClient implementations; allow framework wrappers to set metadata.framework.
  • Update React/Angular/Nest integrations and tests to ensure framework metadata is visible on client.metadata and in hook contexts; Angular additionally caches framework-aware clients by domain.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/shared/src/client/client.ts Adds sdk/framework fields to ClientMetadata and introduces MetadataClient / internal FrameworkMetadataClient typing.
packages/shared/src/client/framework-metadata.ts Adds internal setFrameworkMetadata helper (duck-typed call into supported clients).
packages/shared/src/client/index.ts Re-exports the new internal helper module.
packages/web/src/client/internal/open-feature-client.ts Sets metadata.sdk = 'web' and supports updating framework via setFrameworkMetadata.
packages/web/src/client/client.ts Refactors Client to extend MetadataClient (keeps metadata in the public surface).
packages/web/test/client.spec.ts Adds coverage for metadata.sdk === 'web'.
packages/server/src/client/internal/open-feature-client.ts Sets metadata.sdk = 'server' and supports updating framework via setFrameworkMetadata.
packages/server/src/client/client.ts Refactors Client to extend MetadataClient.
packages/server/test/client.spec.ts Adds coverage for metadata.sdk === 'server'.
packages/react/src/provider/provider.tsx Applies 'react' framework metadata to the stable client used by the provider.
packages/react/test/provider.spec.tsx Ensures react framework metadata appears on client.metadata and in hook contexts; clears hooks between tests.
packages/nest/src/open-feature.module.ts Applies 'nest' framework metadata to injected clients created by module factories.
packages/nest/src/utils.ts Applies 'nest' framework metadata to clients returned from getClientForEvaluation.
packages/nest/test/open-feature.module.spec.ts Tests injected clients and hook contexts include framework: 'nest'.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.ts Adds per-domain client caching and applies 'angular' framework metadata to created clients.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.spec.ts Adds hook-context assertion for angular framework metadata; clears hooks in teardown.
packages/angular/projects/angular-sdk/src/lib/feature-flag.directive.ts Applies 'angular' framework metadata to directive-owned client instance.

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

Expose version and framework metadata through new getClient overloads while keeping domain as the optional first argument. Remove shared framework metadata helpers and keep the remaining React client-marking logic local to the provider.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Inline the remaining Angular and Nest helper wrappers now that they only forward to framework-aware getClient overloads.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Keep the legacy server getClient(domain, version, context) form parsing its third-argument context while expanding overload coverage for the supported web and server getClient signatures.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Set client metadata sdk to js-web or js-server, add paradigm as client or server, and update framework-facing tests to validate the new metadata shape across the JS SDKs.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Copy link
Copy Markdown

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 extends client metadata across the JS SDKs to expose SDK family/paradigm and framework identity, and wires that through client construction so providers/hooks can observe it (e.g., for telemetry).

Changes:

  • Extend core ClientMetadata with sdk, paradigm, and framework, plus ClientMetadataOptions.
  • Add getClient(domain?, options) overloads (web/server) and propagate framework metadata into created clients.
  • Update React/Angular/Nest integrations and tests to ensure framework identity is visible via client.metadata and hook clientMetadata.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/shared/src/client/client.ts Adds new metadata fields/types and ClientMetadataOptions/MetadataClient.
packages/web/src/open-feature.ts Adds getClient overload supporting metadata options and passes framework into client creation.
packages/web/src/client/internal/open-feature-client.ts Adds sdk/paradigm/framework to metadata and an internal setter for framework metadata.
packages/web/src/client/client.ts Switches Client to extend MetadataClient (metadata accessor via shared interface).
packages/web/test/open-feature.spec.ts Adds overload coverage tests for web getClient.
packages/web/test/client.spec.ts Asserts sdk + paradigm exposed in metadata (web).
packages/server/src/open-feature.ts Adds getClient overload supporting metadata options and updates argument parsing.
packages/server/src/client/internal/open-feature-client.ts Adds sdk/paradigm/framework to metadata and an internal setter for framework metadata.
packages/server/src/client/client.ts Switches Client to extend MetadataClient (metadata accessor via shared interface).
packages/server/test/open-feature.spec.ts Adds overload coverage tests for server getClient (domain/context/version/options combinations).
packages/server/test/client.spec.ts Asserts sdk + paradigm exposed in metadata (server).
packages/react/src/provider/provider.tsx Ensures React provider-created (or provided) clients surface framework: 'react'.
packages/react/test/provider.spec.tsx Adds expectations for React framework metadata and hook-context propagation.
packages/nest/src/open-feature.module.ts Ensures injected Nest clients are created with framework: 'nest'.
packages/nest/src/utils.ts Ensures evaluation clients are created with framework: 'nest'.
packages/nest/test/open-feature.module.spec.ts Adds expectations for Nest framework metadata and hook-context propagation.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.ts Creates clients with framework: 'angular' for evaluations.
packages/angular/projects/angular-sdk/src/lib/feature-flag.directive.ts Creates clients with framework: 'angular' for directive evaluations.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.spec.ts Adds hook-context assertion for Angular framework metadata propagation.

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

Drop the unused server-side framework metadata mutator and clarify why the React provider casts before calling the internal client helper.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Remove the public client metadata options overloads and restore the original getClient signatures. Framework SDKs now mark SDK-owned client instances locally so framework metadata still flows into client and hook metadata without a public API change.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
@jonathannorris
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown
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 introduces framework-specific metadata (Angular, Nest, and React) to OpenFeature clients by updating the core ClientMetadata interface and implementing a setFrameworkMetadata method in the web and server SDKs. While the implementation successfully surfaces SDK family, paradigm, and framework information in hook contexts, there is significant code duplication of internal utility types and helper functions within the Angular and Nest packages. It is recommended to consolidate these helpers into shared utility files within their respective packages to adhere to DRY principles and improve maintainability.

Move Angular and Nest framework-marking casts into package-local helpers, clarify the server internal mutator comment, and inline the now-unneeded private client factory helpers in web and server.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
Copy link
Copy Markdown

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 extends the JS SDK client metadata model so providers/hooks can identify the SDK family (js-web/js-server), runtime paradigm (client/server), and (when applicable) the framework (react/angular/nest) without using proxy wrappers, while keeping the existing OpenFeature.getClient(...) public API unchanged.

Changes:

  • Extend ClientMetadata with sdk, paradigm, and framework, and introduce a MetadataClient interface for shared typing.
  • Populate sdk/paradigm in the concrete web/server client implementations and add an internal setFrameworkMetadata mutator used by framework SDKs.
  • Update React/Angular/Nest wrappers and add tests to ensure framework identity is surfaced via client.metadata and hook contexts.

Reviewed changes

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

Show a summary per file
File Description
packages/shared/src/client/client.ts Adds JS identity fields to ClientMetadata and introduces MetadataClient.
packages/web/src/client/internal/open-feature-client.ts Populates web client metadata (sdk, paradigm, framework) and adds internal setFrameworkMetadata.
packages/web/src/client/client.ts Switches the web Client interface to include metadata via MetadataClient.
packages/web/test/open-feature.spec.ts Adds coverage for web getClient overload forms and expected metadata.
packages/web/test/client.spec.ts Verifies web client exposes sdk and paradigm in metadata.
packages/server/src/client/internal/open-feature-client.ts Populates server client metadata (sdk, paradigm, framework) and adds internal setFrameworkMetadata.
packages/server/src/client/client.ts Switches the server Client interface to include metadata via MetadataClient.
packages/server/test/open-feature.spec.ts Adds coverage for server getClient overload forms, context behavior, and expected metadata.
packages/server/test/client.spec.ts Verifies server client exposes sdk and paradigm in metadata.
packages/react/src/provider/provider.tsx Marks SDK-owned clients as React-backed via internal framework metadata setter without wrappers.
packages/react/test/provider.spec.tsx Adds assertions that React metadata is present on clients and hook contexts; clears hooks between tests.
packages/nest/src/framework-metadata.ts Adds helper to mark SDK-owned server clients as Nest-backed while preserving identity.
packages/nest/src/utils.ts Ensures getClientForEvaluation returns a Nest-marked client.
packages/nest/src/open-feature.module.ts Ensures injected clients are marked as Nest-backed.
packages/nest/test/open-feature.module.spec.ts Adds tests for Nest framework metadata on injected clients and hook contexts.
packages/angular/projects/angular-sdk/src/lib/framework-metadata.ts Adds helper to mark SDK-owned web clients as Angular-backed while preserving identity.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.ts Marks the service’s client as Angular-backed for evaluations.
packages/angular/projects/angular-sdk/src/lib/feature-flag.directive.ts Marks directive-created clients as Angular-backed.
packages/angular/projects/angular-sdk/src/lib/feature-flag.service.spec.ts Adds test ensuring Angular metadata is present in hook contexts and clears hooks after tests.

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

Restore Angular's previous empty-string domain behavior so unbound clients continue to resolve through the default OpenFeature client path.

Signed-off-by: Jonathan Norris <jonathan.norris@dynatrace.com>
* @returns {Client} the same client instance
*/
export function setAngularFrameworkMetadata(client: Client): Client {
(client as FrameworkMetadataClient).setFrameworkMetadata?.('angular');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I'm particularly a fan of relying on type-casts to enable this

const stableClient = React.useMemo(() => client || OpenFeature.getClient(domain), [client, domain]);
const stableClient = React.useMemo(() => {
if (client) {
return setReactFrameworkMetadata(client);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This mutates a user-provided client that might also be used elsewhere, this seems problematic?

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