fix: remove export of OpenFeatureClient (#794)

<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

## This PR
As discussed here
https://github.com/open-feature/js-sdk/pull/750#discussion_r1450896230,
we should not export `OpenFeatureClient` from the server and web SDK.
The type used outside the SDK should be `Client`, which is also used in
the public APIs like `OpenFeatureApi`.

The question is, if we should mark this as breaking. 
Technically it will break code that imports `OpenFeatureClient` instead
of `Client`, but as @toddbaert said code using it could also be seen as
"used wrong" while being technically fine.

I am still leaning towards marking it as breaking, to be sure we are not
breaking something that is technically fine, just because it is
unintended use. But I could also live with non-beaking.

---------

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
This commit is contained in:
Lukas Reining 2024-05-08 22:41:03 +02:00 committed by GitHub
parent 7e6c1c6e70
commit 3d197f2ea7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 39 additions and 28 deletions

View File

@ -18,13 +18,13 @@ import {
instantiateErrorByErrorCode, instantiateErrorByErrorCode,
statusMatchesEvent, statusMatchesEvent,
} from '@openfeature/core'; } from '@openfeature/core';
import { FlagEvaluationOptions } from '../evaluation'; import { FlagEvaluationOptions } from '../../evaluation';
import { ProviderEvents } from '../events'; import { ProviderEvents } from '../../events';
import { InternalEventEmitter } from '../events/internal/internal-event-emitter'; import { InternalEventEmitter } from '../../events/internal/internal-event-emitter';
import { Hook } from '../hooks'; import { Hook } from '../../hooks';
import { OpenFeature } from '../open-feature'; import { OpenFeature } from '../../open-feature';
import { Provider, ProviderStatus } from '../provider'; import { Provider, ProviderStatus } from '../../provider';
import { Client } from './client'; import { Client } from './../client';
type OpenFeatureClientOptions = { type OpenFeatureClientOptions = {
/** /**
@ -35,6 +35,11 @@ type OpenFeatureClientOptions = {
version?: string; version?: string;
}; };
/**
* This implementation of the {@link Client} is meant to only be instantiated by the SDK.
* It should not be used outside the SDK and so should not be exported.
* @internal
*/
export class OpenFeatureClient implements Client { export class OpenFeatureClient implements Client {
private _hooks: Hook[] = []; private _hooks: Hook[] = [];
private _clientLogger?: Logger; private _clientLogger?: Logger;

View File

@ -9,10 +9,10 @@ import {
stringOrUndefined, stringOrUndefined,
} from '@openfeature/core'; } from '@openfeature/core';
import { Client } from './client'; import { Client } from './client';
import { OpenFeatureClient } from './client/internal/open-feature-client';
import { OpenFeatureEventEmitter, ProviderEvents } from './events'; import { OpenFeatureEventEmitter, ProviderEvents } from './events';
import { Hook } from './hooks'; import { Hook } from './hooks';
import { NOOP_PROVIDER, Provider, ProviderStatus } from './provider'; import { NOOP_PROVIDER, Provider, ProviderStatus } from './provider';
import { OpenFeatureClient } from './client/open-feature-client';
// use a symbol as a key for the global singleton // use a symbol as a key for the global singleton
const GLOBAL_OPENFEATURE_API_KEY = Symbol.for('@openfeature/web-sdk/api'); const GLOBAL_OPENFEATURE_API_KEY = Symbol.for('@openfeature/web-sdk/api');

View File

@ -14,7 +14,7 @@ import {
ResolutionDetails, ResolutionDetails,
StandardResolutionReasons, StandardResolutionReasons,
} from '../src'; } from '../src';
import { OpenFeatureClient } from '../src/client/open-feature-client'; import { OpenFeatureClient } from '../src/client/internal/open-feature-client';
const BOOLEAN_VALUE = true; const BOOLEAN_VALUE = true;
const STRING_VALUE = 'val'; const STRING_VALUE = 'val';
@ -130,12 +130,15 @@ describe('OpenFeatureClient', () => {
resolveBooleanEvaluation(): ResolutionDetails<boolean> { resolveBooleanEvaluation(): ResolutionDetails<boolean> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
resolveStringEvaluation(): ResolutionDetails<string> { resolveStringEvaluation(): ResolutionDetails<string> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
resolveNumberEvaluation(): ResolutionDetails<number> { resolveNumberEvaluation(): ResolutionDetails<number> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
resolveObjectEvaluation<T extends JsonValue>(): ResolutionDetails<T> { resolveObjectEvaluation<T extends JsonValue>(): ResolutionDetails<T> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
@ -236,7 +239,7 @@ describe('OpenFeatureClient', () => {
numberFlag, numberFlag,
defaultNumberValue, defaultNumberValue,
{}, {},
{} {},
); );
}); });
}); });
@ -248,7 +251,7 @@ describe('OpenFeatureClient', () => {
const defaultNumberValue = 4096; const defaultNumberValue = 4096;
const value: MyRestrictedNumber = client.getNumberValue<MyRestrictedNumber>( const value: MyRestrictedNumber = client.getNumberValue<MyRestrictedNumber>(
numberFlag, numberFlag,
defaultNumberValue defaultNumberValue,
); );
expect(value).toEqual(NUMBER_VALUE); expect(value).toEqual(NUMBER_VALUE);
@ -256,7 +259,7 @@ describe('OpenFeatureClient', () => {
numberFlag, numberFlag,
defaultNumberValue, defaultNumberValue,
{}, {},
{} {},
); );
}); });
}); });
@ -333,7 +336,7 @@ describe('OpenFeatureClient', () => {
booleanFlag, booleanFlag,
defaultBooleanValue, defaultBooleanValue,
{}, {},
{} {},
); );
}); });
}); });
@ -634,4 +637,3 @@ describe('OpenFeatureClient', () => {
}); });
}); });
}); });

View File

@ -1,6 +1,6 @@
import { Paradigm } from '@openfeature/core'; import { Paradigm } from '@openfeature/core';
import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src'; import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src';
import { OpenFeatureClient } from '../src/client/open-feature-client'; import { OpenFeatureClient } from '../src/client/internal/open-feature-client';
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => { const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
return { return {

View File

@ -9,7 +9,6 @@ import {
HookContext, HookContext,
JsonValue, JsonValue,
Logger, Logger,
ManageContext,
OpenFeatureError, OpenFeatureError,
ProviderFatalError, ProviderFatalError,
ProviderNotReadyError, ProviderNotReadyError,
@ -19,13 +18,13 @@ import {
instantiateErrorByErrorCode, instantiateErrorByErrorCode,
statusMatchesEvent, statusMatchesEvent,
} from '@openfeature/core'; } from '@openfeature/core';
import { FlagEvaluationOptions } from '../evaluation'; import { FlagEvaluationOptions } from '../../evaluation';
import { ProviderEvents } from '../events'; import { ProviderEvents } from '../../events';
import { InternalEventEmitter } from '../events/internal/internal-event-emitter'; import { InternalEventEmitter } from '../../events/internal/internal-event-emitter';
import { Hook } from '../hooks'; import { Hook } from '../../hooks';
import { OpenFeature } from '../open-feature'; import { OpenFeature } from '../../open-feature';
import { Provider, ProviderStatus } from '../provider'; import { Provider, ProviderStatus } from '../../provider';
import { Client } from './client'; import { Client } from './../client';
type OpenFeatureClientOptions = { type OpenFeatureClientOptions = {
/** /**
@ -36,7 +35,12 @@ type OpenFeatureClientOptions = {
version?: string; version?: string;
}; };
export class OpenFeatureClient implements Client, ManageContext<OpenFeatureClient> { /**
* This implementation of the {@link Client} is meant to only be instantiated by the SDK.
* It should not be used outside the SDK and so should not be exported.
* @internal
*/
export class OpenFeatureClient implements Client {
private _context: EvaluationContext; private _context: EvaluationContext;
private _hooks: Hook[] = []; private _hooks: Hook[] = [];
private _clientLogger?: Logger; private _clientLogger?: Logger;

View File

@ -3,10 +3,12 @@ import {
ManageContext, ManageContext,
OpenFeatureCommonAPI, OpenFeatureCommonAPI,
ProviderWrapper, ProviderWrapper,
ServerProviderStatus,
objectOrUndefined, objectOrUndefined,
stringOrUndefined, stringOrUndefined,
} from '@openfeature/core'; } from '@openfeature/core';
import { Client } from './client'; import { Client } from './client';
import { OpenFeatureClient } from './client/internal/open-feature-client';
import { OpenFeatureEventEmitter } from './events'; import { OpenFeatureEventEmitter } from './events';
import { Hook } from './hooks'; import { Hook } from './hooks';
import { NOOP_PROVIDER, Provider, ProviderStatus } from './provider'; import { NOOP_PROVIDER, Provider, ProviderStatus } from './provider';
@ -16,8 +18,6 @@ import {
TransactionContext, TransactionContext,
TransactionContextPropagator, TransactionContextPropagator,
} from './transaction-context'; } from './transaction-context';
import { ServerProviderStatus } from '@openfeature/core';
import { OpenFeatureClient } from './client/open-feature-client';
// use a symbol as a key for the global singleton // use a symbol as a key for the global singleton
const GLOBAL_OPENFEATURE_API_KEY = Symbol.for('@openfeature/js-sdk/api'); const GLOBAL_OPENFEATURE_API_KEY = Symbol.for('@openfeature/js-sdk/api');

View File

@ -17,7 +17,7 @@ import {
TransactionContext, TransactionContext,
TransactionContextPropagator, TransactionContextPropagator,
} from '../src'; } from '../src';
import { OpenFeatureClient } from '../src/client/open-feature-client'; import { OpenFeatureClient } from '../src/client/internal/open-feature-client';
const BOOLEAN_VALUE = true; const BOOLEAN_VALUE = true;
const STRING_VALUE = 'val'; const STRING_VALUE = 'val';

View File

@ -1,6 +1,6 @@
import { Paradigm } from '@openfeature/core'; import { Paradigm } from '@openfeature/core';
import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src'; import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src';
import { OpenFeatureClient } from '../src/client/open-feature-client'; import { OpenFeatureClient } from '../src/client/internal/open-feature-client';
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => { const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
return { return {