diff --git a/packages/client/README.md b/packages/client/README.md index fa86fdc17..86898970b 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -267,43 +267,52 @@ This can be a new repository or included in [the existing contrib repository](ht You’ll then need to write the provider by implementing the [Provider interface](./src/provider/provider.ts) exported by the OpenFeature SDK. ```ts -import { JsonValue, Provider, ResolutionDetails } from '@openfeature/web-sdk'; +import { + AnyProviderEvent, + EvaluationContext, + Hook, + JsonValue, + Logger, + Provider, + ProviderEventEmitter, + ProviderStatus, + ResolutionDetails +} from '@openfeature/web-sdk'; // implement the provider interface class MyProvider implements Provider { // Adds runtime validation that the provider is used with the expected SDK - public readonly runsOn = 'client'; - + public readonly runsOn = 'server'; readonly metadata = { name: 'My Provider', } as const; - // Optional provider managed hooks - hooks?: Hook[]; - + hooks?: Hook[]; resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): ResolutionDetails { // code to evaluate a boolean } - resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): ResolutionDetails { // code to evaluate a string } - resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): ResolutionDetails { // code to evaluate a number } - resolveObjectEvaluation(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): ResolutionDetails { // code to evaluate an object } + onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise { + // reconcile the provider's cached flags, if applicable + } + status?: ProviderStatus | undefined; - events?: OpenFeatureEventEmitter | undefined; + + // implement with "new OpenFeatureEventEmitter()", and use "emit()" to emit events + events?: ProviderEventEmitter | undefined; initialize?(context?: EvaluationContext | undefined): Promise { // code to initialize your provider } - onClose?(): Promise { // code to shut down your provider } diff --git a/packages/server/README.md b/packages/server/README.md index 16e460ef4..022cee3f6 100644 --- a/packages/server/README.md +++ b/packages/server/README.md @@ -271,43 +271,48 @@ This can be a new repository or included in [the existing contrib repository](ht You’ll then need to write the provider by implementing the [Provider interface](./src/provider/provider.ts) exported by the OpenFeature SDK. ```ts -import { JsonValue, Provider, ResolutionDetails } from '@openfeature/server-sdk'; +import { + AnyProviderEvent, + EvaluationContext, + Hook, + JsonValue, + Logger, + Provider, + ProviderEventEmitter, + ProviderStatus, + ResolutionDetails +} from '@openfeature/server-sdk'; // implement the provider interface class MyProvider implements Provider { // Adds runtime validation that the provider is used with the expected SDK public readonly runsOn = 'server'; - readonly metadata = { name: 'My Provider', } as const; - // Optional provider managed hooks - hooks?: Hook[]; - + hooks?: Hook[]; resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise> { // code to evaluate a boolean } - resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise> { // code to evaluate a string } - resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise> { // code to evaluate a number } - resolveObjectEvaluation(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise> { // code to evaluate an object } status?: ProviderStatus | undefined; - events?: OpenFeatureEventEmitter | undefined; + + // implement with "new OpenFeatureEventEmitter()", and use "emit()" to emit events + events?: ProviderEventEmitter | undefined; initialize?(context?: EvaluationContext | undefined): Promise { // code to initialize your provider } - onClose?(): Promise { // code to shut down your provider } diff --git a/packages/shared/src/events/generic-event-emitter.ts b/packages/shared/src/events/generic-event-emitter.ts index d221fc12e..c80837dbc 100644 --- a/packages/shared/src/events/generic-event-emitter.ts +++ b/packages/shared/src/events/generic-event-emitter.ts @@ -1,4 +1,5 @@ import { Logger, ManageLogger, SafeLogger } from '../logger'; +import { ProviderEventEmitter } from './provider-event-emitter'; import { EventContext, EventDetails, EventHandler } from './eventing'; import { AllProviderEvents, AnyProviderEvent } from './events'; @@ -7,7 +8,7 @@ import { AllProviderEvents, AnyProviderEvent } from './events'; * in the event details. */ export abstract class GenericEventEmitter = Record> - implements ManageLogger> + implements ProviderEventEmitter, ManageLogger> { protected abstract readonly eventEmitter: PlatformEventEmitter; diff --git a/packages/shared/src/events/index.ts b/packages/shared/src/events/index.ts index 3759ee4b2..3a08e8deb 100644 --- a/packages/shared/src/events/index.ts +++ b/packages/shared/src/events/index.ts @@ -1,4 +1,6 @@ +export * from './provider-event-emitter'; export * from './event-utils'; export * from './eventing'; export * from './events'; export * from './generic-event-emitter'; + diff --git a/packages/shared/src/events/provider-event-emitter.ts b/packages/shared/src/events/provider-event-emitter.ts new file mode 100644 index 000000000..71714bc4f --- /dev/null +++ b/packages/shared/src/events/provider-event-emitter.ts @@ -0,0 +1,22 @@ +import { ManageLogger } from '../logger'; +import { EventContext, EventHandler } from './eventing'; +import { AnyProviderEvent } from './events'; + +/** + * Event emitter to be optionally implemented by providers. + * Implemented by @see OpenFeatureEventEmitter. + */ +export interface ProviderEventEmitter = Record> + extends ManageLogger> +{ + // here we use E, to restrict the events a provider can manually emit (PROVIDER_CONTEXT_CHANGED is emitted by the SDK) + emit(eventType: E, context?: EventContext): void; + + addHandler(eventType: AnyProviderEvent, handler: EventHandler): void; + + removeHandler(eventType: AnyProviderEvent, handler: EventHandler): void; + + removeAllHandlers(eventType?: AnyProviderEvent): void; + + getHandlers(eventType: AnyProviderEvent): EventHandler[]; +} diff --git a/packages/shared/src/provider/provider.ts b/packages/shared/src/provider/provider.ts index 61bf19ad5..7ef3b6b02 100644 --- a/packages/shared/src/provider/provider.ts +++ b/packages/shared/src/provider/provider.ts @@ -1,5 +1,5 @@ import { EvaluationContext } from '../evaluation'; -import { AnyProviderEvent, GenericEventEmitter } from '../events'; +import { AnyProviderEvent, ProviderEventEmitter } from '../events'; import { Metadata, Paradigm } from '../types'; /** @@ -57,7 +57,7 @@ export interface CommonProvider { * An event emitter for ProviderEvents. * @see ProviderEvents */ - events?: GenericEventEmitter; + events?: ProviderEventEmitter; /** * A function used to shut down the provider.