fix: removes exports of OpenFeatureClient class and makes event props readonly (#918)
<!-- Please use this template for your pull request. --> <!-- Please use the sections that you need and delete other sections --> ## This PR <!-- add the description of the PR here --> Removes OpenFeatureClient class from exports and makes event details readonly as described here: https://github.com/open-feature/js-sdk/issues/799 Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
This commit is contained in:
parent
6dd558ee61
commit
e9a25c21cb
|
|
@ -1,2 +1 @@
|
||||||
export * from './client';
|
export * from './client';
|
||||||
export * from './open-feature-client';
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,11 @@ import {
|
||||||
objectOrUndefined,
|
objectOrUndefined,
|
||||||
stringOrUndefined,
|
stringOrUndefined,
|
||||||
} from '@openfeature/core';
|
} from '@openfeature/core';
|
||||||
import { Client, OpenFeatureClient } from './client';
|
import { Client } from './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');
|
||||||
|
|
@ -26,10 +27,17 @@ type DomainRecord = {
|
||||||
|
|
||||||
const _globalThis = globalThis as OpenFeatureGlobal;
|
const _globalThis = globalThis as OpenFeatureGlobal;
|
||||||
|
|
||||||
export class OpenFeatureAPI extends OpenFeatureCommonAPI<ClientProviderStatus, Provider, Hook> implements ManageContext<Promise<void>> {
|
export class OpenFeatureAPI
|
||||||
|
extends OpenFeatureCommonAPI<ClientProviderStatus, Provider, Hook>
|
||||||
|
implements ManageContext<Promise<void>>
|
||||||
|
{
|
||||||
protected _statusEnumType: typeof ProviderStatus = ProviderStatus;
|
protected _statusEnumType: typeof ProviderStatus = ProviderStatus;
|
||||||
protected _apiEmitter: GenericEventEmitter<ProviderEvents> = new OpenFeatureEventEmitter();
|
protected _apiEmitter: GenericEventEmitter<ProviderEvents> = new OpenFeatureEventEmitter();
|
||||||
protected _defaultProvider: ProviderWrapper<Provider, ClientProviderStatus> = new ProviderWrapper(NOOP_PROVIDER, ProviderStatus.NOT_READY, this._statusEnumType);
|
protected _defaultProvider: ProviderWrapper<Provider, ClientProviderStatus> = new ProviderWrapper(
|
||||||
|
NOOP_PROVIDER,
|
||||||
|
ProviderStatus.NOT_READY,
|
||||||
|
this._statusEnumType,
|
||||||
|
);
|
||||||
protected _domainScopedProviders: Map<string, ProviderWrapper<Provider, ClientProviderStatus>> = new Map();
|
protected _domainScopedProviders: Map<string, ProviderWrapper<Provider, ClientProviderStatus>> = new Map();
|
||||||
protected _createEventEmitter = () => new OpenFeatureEventEmitter();
|
protected _createEventEmitter = () => new OpenFeatureEventEmitter();
|
||||||
|
|
||||||
|
|
@ -111,9 +119,7 @@ export class OpenFeatureAPI extends OpenFeatureCommonAPI<ClientProviderStatus, P
|
||||||
...unboundProviders,
|
...unboundProviders,
|
||||||
];
|
];
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
allDomainRecords.map((dm) =>
|
allDomainRecords.map((dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context)),
|
||||||
this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +228,7 @@ export class OpenFeatureAPI extends OpenFeatureCommonAPI<ClientProviderStatus, P
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// this should always be set according to the typings, but let's be defensive considering JS
|
// this should always be set according to the typings, but let's be defensive considering JS
|
||||||
const providerName = wrapper.provider?.metadata?.name || 'unnamed-provider';
|
const providerName = wrapper.provider?.metadata?.name || 'unnamed-provider';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (typeof wrapper.provider.onContextChange === 'function') {
|
if (typeof wrapper.provider.onContextChange === 'function') {
|
||||||
wrapper.incrementPendingContextChanges();
|
wrapper.incrementPendingContextChanges();
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import {
|
||||||
JsonObject,
|
JsonObject,
|
||||||
JsonValue,
|
JsonValue,
|
||||||
OpenFeature,
|
OpenFeature,
|
||||||
OpenFeatureClient,
|
|
||||||
Provider,
|
Provider,
|
||||||
ProviderFatalError,
|
ProviderFatalError,
|
||||||
ProviderStatus,
|
ProviderStatus,
|
||||||
ResolutionDetails,
|
ResolutionDetails,
|
||||||
StandardResolutionReasons,
|
StandardResolutionReasons,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
|
import { OpenFeatureClient } from '../src/client/open-feature-client';
|
||||||
|
|
||||||
const BOOLEAN_VALUE = true;
|
const BOOLEAN_VALUE = true;
|
||||||
const STRING_VALUE = 'val';
|
const STRING_VALUE = 'val';
|
||||||
|
|
@ -382,7 +382,7 @@ describe('OpenFeatureClient', () => {
|
||||||
// No generic information exists at runtime, but this test has some value in ensuring the generic args still exist in the typings.
|
// No generic information exists at runtime, but this test has some value in ensuring the generic args still exist in the typings.
|
||||||
const client = OpenFeature.getClient();
|
const client = OpenFeature.getClient();
|
||||||
const details: ResolutionDetails<JsonValue> = client.getObjectDetails('flag', { key: 'value' });
|
const details: ResolutionDetails<JsonValue> = client.getObjectDetails('flag', { key: 'value' });
|
||||||
|
|
||||||
expect(details).toBeDefined();
|
expect(details).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -464,45 +464,45 @@ describe('OpenFeatureClient', () => {
|
||||||
expect(details.errorCode).toEqual(ErrorCode.PROVIDER_NOT_READY);
|
expect(details.errorCode).toEqual(ErrorCode.PROVIDER_NOT_READY);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Evaluation details structure', () => {
|
describe('Evaluation details structure', () => {
|
||||||
const flagKey = 'number-details';
|
const flagKey = 'number-details';
|
||||||
const defaultValue = 1970;
|
const defaultValue = 1970;
|
||||||
let details: EvaluationDetails<number>;
|
let details: EvaluationDetails<number>;
|
||||||
|
|
||||||
describe('Normal execution', () => {
|
describe('Normal execution', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const client = OpenFeature.getClient();
|
const client = OpenFeature.getClient();
|
||||||
details = client.getNumberDetails(flagKey, defaultValue);
|
details = client.getNumberDetails(flagKey, defaultValue);
|
||||||
|
|
||||||
expect(details).toBeDefined();
|
expect(details).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.2, 1.4.3', () => {
|
describe('Requirement 1.4.2, 1.4.3', () => {
|
||||||
it('should contain flag value', () => {
|
it('should contain flag value', () => {
|
||||||
expect(details.value).toEqual(NUMBER_VALUE);
|
expect(details.value).toEqual(NUMBER_VALUE);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.4', () => {
|
describe('Requirement 1.4.4', () => {
|
||||||
it('should contain flag key', () => {
|
it('should contain flag key', () => {
|
||||||
expect(details.flagKey).toEqual(flagKey);
|
expect(details.flagKey).toEqual(flagKey);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.5', () => {
|
describe('Requirement 1.4.5', () => {
|
||||||
it('should contain flag variant', () => {
|
it('should contain flag variant', () => {
|
||||||
expect(details.variant).toEqual(NUMBER_VARIANT);
|
expect(details.variant).toEqual(NUMBER_VARIANT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.6', () => {
|
describe('Requirement 1.4.6', () => {
|
||||||
it('should contain reason', () => {
|
it('should contain reason', () => {
|
||||||
expect(details.reason).toEqual(REASON);
|
expect(details.reason).toEqual(REASON);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Abnormal execution', () => {
|
describe('Abnormal execution', () => {
|
||||||
const NON_OPEN_FEATURE_ERROR_MESSAGE = 'A null dereference or something, I dunno.';
|
const NON_OPEN_FEATURE_ERROR_MESSAGE = 'A null dereference or something, I dunno.';
|
||||||
const OPEN_FEATURE_ERROR_MESSAGE = "This ain't the flag you're looking for.";
|
const OPEN_FEATURE_ERROR_MESSAGE = "This ain't the flag you're looking for.";
|
||||||
|
|
@ -522,14 +522,14 @@ describe('OpenFeatureClient', () => {
|
||||||
} as unknown as Provider;
|
} as unknown as Provider;
|
||||||
const defaultNumberValue = 123;
|
const defaultNumberValue = 123;
|
||||||
const defaultStringValue = 'hey!';
|
const defaultStringValue = 'hey!';
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
OpenFeature.setProvider(errorProvider);
|
OpenFeature.setProvider(errorProvider);
|
||||||
client = OpenFeature.getClient();
|
client = OpenFeature.getClient();
|
||||||
nonOpenFeatureErrorDetails = client.getNumberDetails('some-flag', defaultNumberValue);
|
nonOpenFeatureErrorDetails = client.getNumberDetails('some-flag', defaultNumberValue);
|
||||||
openFeatureErrorDetails = client.getStringDetails('some-flag', defaultStringValue);
|
openFeatureErrorDetails = client.getStringDetails('some-flag', defaultStringValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.7', () => {
|
describe('Requirement 1.4.7', () => {
|
||||||
describe('OpenFeatureError', () => {
|
describe('OpenFeatureError', () => {
|
||||||
it('should contain error code', () => {
|
it('should contain error code', () => {
|
||||||
|
|
@ -537,7 +537,7 @@ describe('OpenFeatureClient', () => {
|
||||||
expect(openFeatureErrorDetails.errorCode).toEqual(ErrorCode.FLAG_NOT_FOUND); // should get code from thrown OpenFeatureError
|
expect(openFeatureErrorDetails.errorCode).toEqual(ErrorCode.FLAG_NOT_FOUND); // should get code from thrown OpenFeatureError
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Non-OpenFeatureError', () => {
|
describe('Non-OpenFeatureError', () => {
|
||||||
it('should contain error code', () => {
|
it('should contain error code', () => {
|
||||||
expect(nonOpenFeatureErrorDetails.errorCode).toBeTruthy();
|
expect(nonOpenFeatureErrorDetails.errorCode).toBeTruthy();
|
||||||
|
|
@ -545,30 +545,30 @@ describe('OpenFeatureClient', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.8', () => {
|
describe('Requirement 1.4.8', () => {
|
||||||
it('should contain error reason', () => {
|
it('should contain error reason', () => {
|
||||||
expect(nonOpenFeatureErrorDetails.reason).toEqual(StandardResolutionReasons.ERROR);
|
expect(nonOpenFeatureErrorDetails.reason).toEqual(StandardResolutionReasons.ERROR);
|
||||||
expect(openFeatureErrorDetails.reason).toEqual(StandardResolutionReasons.ERROR);
|
expect(openFeatureErrorDetails.reason).toEqual(StandardResolutionReasons.ERROR);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.9', () => {
|
describe('Requirement 1.4.9', () => {
|
||||||
it('must not throw, must return default', () => {
|
it('must not throw, must return default', () => {
|
||||||
nonOpenFeatureErrorDetails = client.getNumberDetails('some-flag', defaultNumberValue);
|
nonOpenFeatureErrorDetails = client.getNumberDetails('some-flag', defaultNumberValue);
|
||||||
|
|
||||||
expect(nonOpenFeatureErrorDetails).toBeTruthy();
|
expect(nonOpenFeatureErrorDetails).toBeTruthy();
|
||||||
expect(nonOpenFeatureErrorDetails.value).toEqual(defaultNumberValue);
|
expect(nonOpenFeatureErrorDetails.value).toEqual(defaultNumberValue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.12', () => {
|
describe('Requirement 1.4.12', () => {
|
||||||
describe('OpenFeatureError', () => {
|
describe('OpenFeatureError', () => {
|
||||||
it('should contain "error" message', () => {
|
it('should contain "error" message', () => {
|
||||||
expect(openFeatureErrorDetails.errorMessage).toEqual(OPEN_FEATURE_ERROR_MESSAGE);
|
expect(openFeatureErrorDetails.errorMessage).toEqual(OPEN_FEATURE_ERROR_MESSAGE);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Non-OpenFeatureError', () => {
|
describe('Non-OpenFeatureError', () => {
|
||||||
it('should contain "error" message', () => {
|
it('should contain "error" message', () => {
|
||||||
expect(nonOpenFeatureErrorDetails.errorMessage).toEqual(NON_OPEN_FEATURE_ERROR_MESSAGE);
|
expect(nonOpenFeatureErrorDetails.errorMessage).toEqual(NON_OPEN_FEATURE_ERROR_MESSAGE);
|
||||||
|
|
@ -576,14 +576,14 @@ describe('OpenFeatureClient', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Requirement 1.4.13, Requirement 1.4.14', () => {
|
describe('Requirement 1.4.13, Requirement 1.4.14', () => {
|
||||||
it('should return immutable `flag metadata` as defined by the provider', () => {
|
it('should return immutable `flag metadata` as defined by the provider', () => {
|
||||||
const flagMetadata = {
|
const flagMetadata = {
|
||||||
url: 'https://test.dev',
|
url: 'https://test.dev',
|
||||||
version: '1',
|
version: '1',
|
||||||
};
|
};
|
||||||
|
|
||||||
const flagMetadataProvider = {
|
const flagMetadataProvider = {
|
||||||
metadata: {
|
metadata: {
|
||||||
name: 'flag-metadata',
|
name: 'flag-metadata',
|
||||||
|
|
@ -595,14 +595,14 @@ describe('OpenFeatureClient', () => {
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
} as unknown as Provider;
|
} as unknown as Provider;
|
||||||
|
|
||||||
OpenFeature.setProvider(flagMetadataProvider);
|
OpenFeature.setProvider(flagMetadataProvider);
|
||||||
const client = OpenFeature.getClient();
|
const client = OpenFeature.getClient();
|
||||||
const response = client.getBooleanDetails('some-flag', false);
|
const response = client.getBooleanDetails('some-flag', false);
|
||||||
expect(response.flagMetadata).toBe(flagMetadata);
|
expect(response.flagMetadata).toBe(flagMetadata);
|
||||||
expect(Object.isFrozen(response.flagMetadata)).toBeTruthy();
|
expect(Object.isFrozen(response.flagMetadata)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return empty `flag metadata` because it was not set by the provider', () => {
|
it('should return empty `flag metadata` because it was not set by the provider', () => {
|
||||||
// The mock provider doesn't contain flag metadata
|
// The mock provider doesn't contain flag metadata
|
||||||
OpenFeature.setProvider(MOCK_PROVIDER);
|
OpenFeature.setProvider(MOCK_PROVIDER);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Paradigm } from '@openfeature/core';
|
import { Paradigm } from '@openfeature/core';
|
||||||
import { OpenFeature, OpenFeatureAPI, OpenFeatureClient, Provider, ProviderStatus } from '../src';
|
import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src';
|
||||||
|
import { OpenFeatureClient } from '../src/client/open-feature-client';
|
||||||
|
|
||||||
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
|
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getOpenFeatureClientToken, OpenFeatureModule, ServerProviderEvents } from '../src';
|
import { getOpenFeatureClientToken, OpenFeatureModule, ServerProviderEvents } from '../src';
|
||||||
import { OpenFeature, OpenFeatureClient } from '@openfeature/server-sdk';
|
import { Client, OpenFeature } from '@openfeature/server-sdk';
|
||||||
import { getOpenFeatureDefaultTestModule } from './fixtures';
|
import { getOpenFeatureDefaultTestModule } from './fixtures';
|
||||||
|
|
||||||
describe('OpenFeatureModule', () => {
|
describe('OpenFeatureModule', () => {
|
||||||
|
|
@ -31,19 +31,19 @@ describe('OpenFeatureModule', () => {
|
||||||
|
|
||||||
it('should return the SDKs default provider and not throw', async () => {
|
it('should return the SDKs default provider and not throw', async () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
moduleWithoutProvidersRef.get<OpenFeatureClient>(getOpenFeatureClientToken());
|
moduleWithoutProvidersRef.get<Client>(getOpenFeatureClientToken());
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the default provider', async () => {
|
it('should return the default provider', async () => {
|
||||||
const client = moduleRef.get<OpenFeatureClient>(getOpenFeatureClientToken());
|
const client = moduleRef.get<Client>(getOpenFeatureClientToken());
|
||||||
expect(client).toBeDefined();
|
expect(client).toBeDefined();
|
||||||
expect(await client.getStringValue('testStringFlag', '')).toEqual('expected-string-value-default');
|
expect(await client.getStringValue('testStringFlag', '')).toEqual('expected-string-value-default');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inject the client with the given scope', async () => {
|
it('should inject the client with the given scope', async () => {
|
||||||
const client = moduleRef.get<OpenFeatureClient>(getOpenFeatureClientToken('domainScopedClient'));
|
const client = moduleRef.get<Client>(getOpenFeatureClientToken('domainScopedClient'));
|
||||||
expect(client).toBeDefined();
|
expect(client).toBeDefined();
|
||||||
expect(await client.getStringValue('testStringFlag', '')).toEqual('expected-string-value-scoped');
|
expect(await client.getStringValue('testStringFlag', '')).toEqual('expected-string-value-scoped');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import { Controller, Get, Injectable, UseInterceptors } from '@nestjs/common';
|
import { Controller, Get, Injectable, UseInterceptors } from '@nestjs/common';
|
||||||
import { Observable, map } from 'rxjs';
|
import { Observable, map } from 'rxjs';
|
||||||
import { BooleanFeatureFlag, ObjectFeatureFlag, NumberFeatureFlag, FeatureClient, StringFeatureFlag } from '../src';
|
import { BooleanFeatureFlag, ObjectFeatureFlag, NumberFeatureFlag, FeatureClient, StringFeatureFlag } from '../src';
|
||||||
import { OpenFeatureClient, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';
|
import { Client, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';
|
||||||
import { EvaluationContextInterceptor } from '../src';
|
import { EvaluationContextInterceptor } from '../src';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpenFeatureTestService {
|
export class OpenFeatureTestService {
|
||||||
constructor(
|
constructor(
|
||||||
@FeatureClient() public defaultClient: OpenFeatureClient,
|
@FeatureClient() public defaultClient: Client,
|
||||||
@FeatureClient({ domain: 'domainScopedClient' }) public domainScopedClient: OpenFeatureClient,
|
@FeatureClient({ domain: 'domainScopedClient' }) public domainScopedClient: Client,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async serviceMethod(flag: EvaluationDetails<FlagValue>) {
|
public async serviceMethod(flag: EvaluationDetails<FlagValue>) {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
export * from './client';
|
export * from './client';
|
||||||
export * from './open-feature-client';
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
objectOrUndefined,
|
objectOrUndefined,
|
||||||
stringOrUndefined,
|
stringOrUndefined,
|
||||||
} from '@openfeature/core';
|
} from '@openfeature/core';
|
||||||
import { Client, OpenFeatureClient } from './client';
|
import { Client } from './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';
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
TransactionContextPropagator,
|
TransactionContextPropagator,
|
||||||
} from './transaction-context';
|
} from './transaction-context';
|
||||||
import { ServerProviderStatus } from '@openfeature/core';
|
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');
|
||||||
|
|
@ -28,11 +29,17 @@ const _globalThis = globalThis as OpenFeatureGlobal;
|
||||||
|
|
||||||
export class OpenFeatureAPI
|
export class OpenFeatureAPI
|
||||||
extends OpenFeatureCommonAPI<ServerProviderStatus, Provider, Hook>
|
extends OpenFeatureCommonAPI<ServerProviderStatus, Provider, Hook>
|
||||||
implements ManageContext<OpenFeatureAPI>, ManageTransactionContextPropagator<OpenFeatureCommonAPI<ServerProviderStatus, Provider>>
|
implements
|
||||||
|
ManageContext<OpenFeatureAPI>,
|
||||||
|
ManageTransactionContextPropagator<OpenFeatureCommonAPI<ServerProviderStatus, Provider>>
|
||||||
{
|
{
|
||||||
protected _statusEnumType: typeof ProviderStatus = ProviderStatus;
|
protected _statusEnumType: typeof ProviderStatus = ProviderStatus;
|
||||||
protected _apiEmitter = new OpenFeatureEventEmitter();
|
protected _apiEmitter = new OpenFeatureEventEmitter();
|
||||||
protected _defaultProvider: ProviderWrapper<Provider, ServerProviderStatus> = new ProviderWrapper(NOOP_PROVIDER, ProviderStatus.NOT_READY, this._statusEnumType);
|
protected _defaultProvider: ProviderWrapper<Provider, ServerProviderStatus> = new ProviderWrapper(
|
||||||
|
NOOP_PROVIDER,
|
||||||
|
ProviderStatus.NOT_READY,
|
||||||
|
this._statusEnumType,
|
||||||
|
);
|
||||||
protected _domainScopedProviders: Map<string, ProviderWrapper<Provider, ServerProviderStatus>> = new Map();
|
protected _domainScopedProviders: Map<string, ProviderWrapper<Provider, ServerProviderStatus>> = new Map();
|
||||||
protected _createEventEmitter = () => new OpenFeatureEventEmitter();
|
protected _createEventEmitter = () => new OpenFeatureEventEmitter();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import {
|
||||||
JsonObject,
|
JsonObject,
|
||||||
JsonValue,
|
JsonValue,
|
||||||
OpenFeature,
|
OpenFeature,
|
||||||
OpenFeatureClient,
|
|
||||||
Provider,
|
Provider,
|
||||||
ProviderFatalError,
|
ProviderFatalError,
|
||||||
ProviderStatus,
|
ProviderStatus,
|
||||||
|
|
@ -18,6 +17,7 @@ import {
|
||||||
TransactionContext,
|
TransactionContext,
|
||||||
TransactionContextPropagator,
|
TransactionContextPropagator,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
|
import { OpenFeatureClient } from '../src/client/open-feature-client';
|
||||||
|
|
||||||
const BOOLEAN_VALUE = true;
|
const BOOLEAN_VALUE = true;
|
||||||
const STRING_VALUE = 'val';
|
const STRING_VALUE = 'val';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Paradigm } from '@openfeature/core';
|
import { Paradigm } from '@openfeature/core';
|
||||||
import { OpenFeature, OpenFeatureAPI, OpenFeatureClient, Provider, ProviderStatus } from '../src';
|
import { OpenFeature, OpenFeatureAPI, Provider, ProviderStatus } from '../src';
|
||||||
|
import { OpenFeatureClient } from '../src/client/open-feature-client';
|
||||||
|
|
||||||
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
|
const mockProvider = (config?: { initialStatus?: ProviderStatus; runsOn?: Paradigm }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,24 @@ export type EventMetadata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CommonEventDetails = {
|
export type CommonEventDetails = {
|
||||||
providerName: string;
|
readonly providerName: string;
|
||||||
/**
|
/**
|
||||||
* @deprecated alias of "domain", use domain instead
|
* @deprecated alias of "domain", use domain instead
|
||||||
*/
|
*/
|
||||||
clientName?: string;
|
readonly clientName?: string;
|
||||||
readonly domain?: string;
|
readonly domain?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CommonEventProps = {
|
type CommonEventProps = {
|
||||||
message?: string;
|
readonly message?: string;
|
||||||
metadata?: EventMetadata;
|
readonly metadata?: EventMetadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReadyEvent = CommonEventProps;
|
export type ReadyEvent = CommonEventProps;
|
||||||
export type ErrorEvent = CommonEventProps;
|
export type ErrorEvent = CommonEventProps;
|
||||||
export type StaleEvent = CommonEventProps;
|
export type StaleEvent = CommonEventProps;
|
||||||
export type ReconcilingEvent = CommonEventProps & { errorCode: ErrorCode };
|
export type ReconcilingEvent = CommonEventProps & { readonly errorCode: ErrorCode };
|
||||||
export type ConfigChangeEvent = CommonEventProps & { flagsChanged?: string[] };
|
export type ConfigChangeEvent = CommonEventProps & { readonly flagsChanged?: string[] };
|
||||||
|
|
||||||
type ServerEventMap = {
|
type ServerEventMap = {
|
||||||
[ServerProviderEvents.Ready]: ReadyEvent;
|
[ServerProviderEvents.Ready]: ReadyEvent;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue