= new Map();
- protected _clientProviders: Map (eventType: T, handler: EventHandler): void {
- [...new Map([[undefined, this._defaultProvider]]), ...this._clientProviders].forEach((keyProviderTuple) => {
- const clientName = keyProviderTuple[0];
+ [...new Map([[undefined, this._defaultProvider]]), ...this._domainScopedProviders].forEach((keyProviderTuple) => {
+ const domain = keyProviderTuple[0];
const provider = keyProviderTuple[1];
const shouldRunNow = statusMatchesEvent(eventType, keyProviderTuple[1].status);
if (shouldRunNow) {
// run immediately, we're in the matching state
try {
- handler({ clientName, providerName: provider.metadata.name });
+ handler({ domain, providerName: provider.metadata.name });
} catch (err) {
this._logger?.error('Error running event handler:', err);
}
@@ -126,8 +127,8 @@ export abstract class OpenFeatureCommonAPI }
@@ -135,40 +136,40 @@ export abstract class OpenFeatureCommonAPI ;
/**
- * Sets the provider that OpenFeature will use for flag evaluations of providers with the given name.
+ * Sets the provider that OpenFeature will use for flag evaluations on clients bound to the same domain.
* A promise is returned that resolves when the provider is ready.
- * Setting a provider supersedes the current provider used in new and existing clients with that name.
+ * Setting a provider supersedes the current provider used in new and existing clients in the same domain.
* @template P
- * @param {string} clientName The name to identify the client
+ * @param {string} domain An identifier which logically binds clients with providers
* @param {P} provider The provider responsible for flag evaluations.
* @returns {Promise | void {
- const clientName = stringOrUndefined(clientOrProvider);
- const provider = objectOrUndefined (clientOrProvider) ?? objectOrUndefined (providerOrUndefined);
+ private setAwaitableProvider(domainOrProvider?: string | P, providerOrUndefined?: P): Promise (domainOrProvider) ?? objectOrUndefined (providerOrUndefined);
if (!provider) {
this._logger.debug('No provider defined, ignoring setProvider call');
return;
}
- const oldProvider = this.getProviderForClient(clientName);
+ const oldProvider = this.getProviderForClient(domain);
const providerName = provider.metadata.name;
// ignore no-ops
@@ -201,7 +202,7 @@ export abstract class OpenFeatureCommonAPI {
// fetch the most recent event emitters, some may have been added during init
- this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
- emitter?.emit(AllProviderEvents.Ready, { clientName, providerName });
+ this.getAssociatedEventEmitters(domain).forEach((emitter) => {
+ emitter?.emit(AllProviderEvents.Ready, { clientName: domain, domain, providerName });
});
- this._events?.emit(AllProviderEvents.Ready, { clientName, providerName });
+ this._events?.emit(AllProviderEvents.Ready, { clientName: domain, domain, providerName });
})
?.catch((error) => {
- this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
- emitter?.emit(AllProviderEvents.Error, { clientName, providerName, message: error?.message });
+ this.getAssociatedEventEmitters(domain).forEach((emitter) => {
+ emitter?.emit(AllProviderEvents.Error, {
+ clientName: domain,
+ domain,
+ providerName,
+ message: error?.message,
+ });
+ });
+ this._events?.emit(AllProviderEvents.Error, {
+ clientName: domain,
+ domain,
+ providerName,
+ message: error?.message,
});
- this._events?.emit(AllProviderEvents.Error, { clientName, providerName, message: error?.message });
// rethrow after emitting error events, so that public methods can control error handling
throw error;
});
} else {
emitters.forEach((emitter) => {
- emitter?.emit(AllProviderEvents.Ready, { clientName, providerName });
+ emitter?.emit(AllProviderEvents.Ready, { clientName: domain, domain, providerName });
});
- this._events?.emit(AllProviderEvents.Ready, { clientName, providerName });
+ this._events?.emit(AllProviderEvents.Ready, { clientName: domain, domain, providerName });
}
- if (clientName) {
- this._clientProviders.set(clientName, provider);
+ if (domain) {
+ this._domainScopedProviders.set(domain, provider);
} else {
this._defaultProvider = provider;
}
- this.transferListeners(oldProvider, provider, clientName, emitters);
+ this.transferListeners(oldProvider, provider, domain, emitters);
// Do not close a provider that is bound to any client
- if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) {
+ if (![...this._domainScopedProviders.values(), this._defaultProvider].includes(oldProvider)) {
oldProvider?.onClose?.();
}
return initializationPromise;
}
- protected getProviderForClient(name?: string): P {
- if (!name) {
+ protected getProviderForClient(domain?: string): P {
+ if (!domain) {
return this._defaultProvider;
}
- return this._clientProviders.get(name) ?? this._defaultProvider;
+ return this._domainScopedProviders.get(domain) ?? this._defaultProvider;
}
- protected buildAndCacheEventEmitterForClient(name?: string): GenericEventEmitter (AllProviderEvents).forEach(
- (eventType) =>
- clientProvider.events?.addHandler(eventType, async (details) => {
- newEmitter.emit(eventType, { ...details, clientName: name, providerName: clientProvider.metadata.name });
- }),
+ this._clientEvents.set(domain, newEmitter);
+
+ const clientProvider = this.getProviderForClient(domain);
+ Object.values | undefined)[],
) {
this._clientEventHandlers
- .get(clientName)
+ .get(domain)
?.forEach((eventHandler) => oldProvider.events?.removeHandler(...eventHandler));
// iterate over the event types
@@ -315,15 +330,20 @@ export abstract class OpenFeatureCommonAPI {
// on each event type, fire the associated handlers
emitters.forEach((emitter) => {
- emitter?.emit(eventType, { ...details, clientName, providerName: newProvider.metadata.name });
+ emitter?.emit(eventType, { ...details, clientName: domain, domain, providerName: newProvider.metadata.name });
+ });
+ this._events.emit(eventType, {
+ ...details,
+ clientName: domain,
+ domain,
+ providerName: newProvider.metadata.name,
});
- this._events.emit(eventType, { ...details, clientName, providerName: newProvider.metadata.name });
};
return [eventType, handler];
});
- this._clientEventHandlers.set(clientName, newClientHandlers);
+ this._clientEventHandlers.set(domain, newClientHandlers);
newClientHandlers.forEach((eventHandler) => newProvider.events?.addHandler(...eventHandler));
}
@@ -334,7 +354,7 @@ export abstract class OpenFeatureCommonAPI {
@@ -353,7 +373,7 @@ export abstract class OpenFeatureCommonAPI