@openfeature/web-sdk 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -6
- package/dist/cjs/index.js +237 -202
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/index.js +237 -201
- package/dist/esm/index.js.map +4 -4
- package/dist/types.d.ts +85 -57
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -206,41 +206,6 @@ var require_eventemitter3 = __commonJS({
|
|
|
206
206
|
}
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
// src/client/open-feature-client.ts
|
|
210
|
-
import {
|
|
211
|
-
ErrorCode as ErrorCode2,
|
|
212
|
-
ProviderFatalError,
|
|
213
|
-
ProviderNotReadyError,
|
|
214
|
-
SafeLogger,
|
|
215
|
-
StandardResolutionReasons as StandardResolutionReasons2,
|
|
216
|
-
statusMatchesEvent
|
|
217
|
-
} from "@openfeature/core";
|
|
218
|
-
|
|
219
|
-
// src/open-feature.ts
|
|
220
|
-
import {
|
|
221
|
-
OpenFeatureCommonAPI,
|
|
222
|
-
ProviderWrapper,
|
|
223
|
-
objectOrUndefined,
|
|
224
|
-
stringOrUndefined
|
|
225
|
-
} from "@openfeature/core";
|
|
226
|
-
|
|
227
|
-
// src/events/open-feature-event-emitter.ts
|
|
228
|
-
import { GenericEventEmitter } from "@openfeature/core";
|
|
229
|
-
|
|
230
|
-
// ../../node_modules/eventemitter3/index.mjs
|
|
231
|
-
var import_index = __toESM(require_eventemitter3(), 1);
|
|
232
|
-
|
|
233
|
-
// src/events/open-feature-event-emitter.ts
|
|
234
|
-
var OpenFeatureEventEmitter = class extends GenericEventEmitter {
|
|
235
|
-
eventEmitter = new import_index.default();
|
|
236
|
-
constructor() {
|
|
237
|
-
super();
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
// src/events/events.ts
|
|
242
|
-
import { ClientProviderEvents } from "@openfeature/core";
|
|
243
|
-
|
|
244
209
|
// src/provider/provider.ts
|
|
245
210
|
import { ClientProviderStatus } from "@openfeature/core";
|
|
246
211
|
|
|
@@ -280,6 +245,23 @@ import {
|
|
|
280
245
|
TypeMismatchError
|
|
281
246
|
} from "@openfeature/core";
|
|
282
247
|
|
|
248
|
+
// src/events/open-feature-event-emitter.ts
|
|
249
|
+
import { GenericEventEmitter } from "@openfeature/core";
|
|
250
|
+
|
|
251
|
+
// ../../node_modules/eventemitter3/index.mjs
|
|
252
|
+
var import_index = __toESM(require_eventemitter3(), 1);
|
|
253
|
+
|
|
254
|
+
// src/events/open-feature-event-emitter.ts
|
|
255
|
+
var OpenFeatureEventEmitter = class extends GenericEventEmitter {
|
|
256
|
+
eventEmitter = new import_index.default();
|
|
257
|
+
constructor() {
|
|
258
|
+
super();
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// src/events/events.ts
|
|
263
|
+
import { ClientProviderEvents } from "@openfeature/core";
|
|
264
|
+
|
|
283
265
|
// src/provider/in-memory-provider/variant-not-found-error.ts
|
|
284
266
|
import { ErrorCode, OpenFeatureError } from "@openfeature/core";
|
|
285
267
|
var VariantNotFoundError = class _VariantNotFoundError extends OpenFeatureError {
|
|
@@ -387,172 +369,23 @@ var InMemoryProvider = class {
|
|
|
387
369
|
};
|
|
388
370
|
|
|
389
371
|
// src/open-feature.ts
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
_domainScopedProviders = /* @__PURE__ */ new Map();
|
|
397
|
-
_createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
398
|
-
constructor() {
|
|
399
|
-
super("client");
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Gets a singleton instance of the OpenFeature API.
|
|
403
|
-
* @ignore
|
|
404
|
-
* @returns {OpenFeatureAPI} OpenFeature API
|
|
405
|
-
*/
|
|
406
|
-
static getInstance() {
|
|
407
|
-
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
|
|
408
|
-
if (globalApi) {
|
|
409
|
-
return globalApi;
|
|
410
|
-
}
|
|
411
|
-
const instance = new _OpenFeatureAPI();
|
|
412
|
-
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
|
|
413
|
-
return instance;
|
|
414
|
-
}
|
|
415
|
-
getProviderStatus(domain) {
|
|
416
|
-
if (!domain) {
|
|
417
|
-
return this._defaultProvider.status;
|
|
418
|
-
}
|
|
419
|
-
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status;
|
|
420
|
-
}
|
|
421
|
-
async setContext(domainOrContext, contextOrUndefined) {
|
|
422
|
-
const domain = stringOrUndefined(domainOrContext);
|
|
423
|
-
const context = objectOrUndefined(domainOrContext) ?? objectOrUndefined(contextOrUndefined) ?? {};
|
|
424
|
-
if (domain) {
|
|
425
|
-
const wrapper = this._domainScopedProviders.get(domain);
|
|
426
|
-
if (wrapper) {
|
|
427
|
-
const oldContext = this.getContext(domain);
|
|
428
|
-
this._domainScopedContext.set(domain, context);
|
|
429
|
-
await this.runProviderContextChangeHandler(domain, wrapper, oldContext, context);
|
|
430
|
-
} else {
|
|
431
|
-
this._domainScopedContext.set(domain, context);
|
|
432
|
-
}
|
|
433
|
-
} else {
|
|
434
|
-
const oldContext = this._context;
|
|
435
|
-
this._context = context;
|
|
436
|
-
const unboundProviders = Array.from(this._domainScopedProviders.entries()).filter(([domain2]) => !this._domainScopedContext.has(domain2)).reduce((acc, [domain2, wrapper]) => {
|
|
437
|
-
acc.push({ domain: domain2, wrapper });
|
|
438
|
-
return acc;
|
|
439
|
-
}, []);
|
|
440
|
-
const allDomainRecords = [
|
|
441
|
-
// add in the default (no domain)
|
|
442
|
-
{ domain: void 0, wrapper: this._defaultProvider },
|
|
443
|
-
...unboundProviders
|
|
444
|
-
];
|
|
445
|
-
await Promise.all(
|
|
446
|
-
allDomainRecords.map(
|
|
447
|
-
(dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context)
|
|
448
|
-
)
|
|
449
|
-
);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
getContext(domainOrUndefined) {
|
|
453
|
-
const domain = stringOrUndefined(domainOrUndefined);
|
|
454
|
-
if (domain) {
|
|
455
|
-
const context = this._domainScopedContext.get(domain);
|
|
456
|
-
if (context) {
|
|
457
|
-
return context;
|
|
458
|
-
} else {
|
|
459
|
-
this._logger.debug(`Unable to find context for '${domain}'.`);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
return this._context;
|
|
463
|
-
}
|
|
464
|
-
async clearContext(domainOrUndefined) {
|
|
465
|
-
const domain = stringOrUndefined(domainOrUndefined);
|
|
466
|
-
if (domain) {
|
|
467
|
-
const wrapper = this._domainScopedProviders.get(domain);
|
|
468
|
-
if (wrapper) {
|
|
469
|
-
const oldContext = this.getContext(domain);
|
|
470
|
-
this._domainScopedContext.delete(domain);
|
|
471
|
-
const newContext = this.getContext();
|
|
472
|
-
await this.runProviderContextChangeHandler(domain, wrapper, oldContext, newContext);
|
|
473
|
-
} else {
|
|
474
|
-
this._domainScopedContext.delete(domain);
|
|
475
|
-
}
|
|
476
|
-
} else {
|
|
477
|
-
return this.setContext({});
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* Resets the global evaluation context and removes the evaluation context for
|
|
482
|
-
* all domains.
|
|
483
|
-
*/
|
|
484
|
-
async clearContexts() {
|
|
485
|
-
await this.clearContext();
|
|
486
|
-
await Promise.allSettled(Array.from(this._domainScopedProviders.keys()).map((domain) => this.clearContext(domain)));
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* A factory function for creating new named OpenFeature clients. Clients can contain
|
|
490
|
-
* their own state (e.g. logger, hook, context). Multiple clients can be used
|
|
491
|
-
* to segment feature flag configuration.
|
|
492
|
-
*
|
|
493
|
-
* If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used.
|
|
494
|
-
* Otherwise, the default provider is used until a provider is assigned to that name.
|
|
495
|
-
* @param {string} domain An identifier which logically binds clients with providers
|
|
496
|
-
* @param {string} version The version of the client (only used for metadata)
|
|
497
|
-
* @returns {Client} OpenFeature Client
|
|
498
|
-
*/
|
|
499
|
-
getClient(domain, version) {
|
|
500
|
-
return new OpenFeatureClient(
|
|
501
|
-
// functions are passed here to make sure that these values are always up to date,
|
|
502
|
-
// and so we don't have to make these public properties on the API class.
|
|
503
|
-
() => this.getProviderForClient(domain),
|
|
504
|
-
() => this.getProviderStatus(domain),
|
|
505
|
-
() => this.buildAndCacheEventEmitterForClient(domain),
|
|
506
|
-
() => this._logger,
|
|
507
|
-
{ domain, version }
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Clears all registered providers and resets the default provider.
|
|
512
|
-
* @returns {Promise<void>}
|
|
513
|
-
*/
|
|
514
|
-
async clearProviders() {
|
|
515
|
-
await super.clearProvidersAndSetDefault(NOOP_PROVIDER);
|
|
516
|
-
this._domainScopedContext.clear();
|
|
517
|
-
}
|
|
518
|
-
async runProviderContextChangeHandler(domain, wrapper, oldContext, newContext) {
|
|
519
|
-
const providerName = wrapper.provider?.metadata?.name || "unnamed-provider";
|
|
520
|
-
try {
|
|
521
|
-
if (typeof wrapper.provider.onContextChange === "function") {
|
|
522
|
-
wrapper.incrementPendingContextChanges();
|
|
523
|
-
wrapper.status = this._statusEnumType.RECONCILING;
|
|
524
|
-
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
525
|
-
emitter?.emit(ClientProviderEvents.Reconciling, { domain, providerName });
|
|
526
|
-
});
|
|
527
|
-
this._apiEmitter?.emit(ClientProviderEvents.Reconciling, { domain, providerName });
|
|
528
|
-
await wrapper.provider.onContextChange(oldContext, newContext);
|
|
529
|
-
wrapper.decrementPendingContextChanges();
|
|
530
|
-
}
|
|
531
|
-
wrapper.status = this._statusEnumType.READY;
|
|
532
|
-
if (wrapper.allContextChangesSettled) {
|
|
533
|
-
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
534
|
-
emitter?.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
|
|
535
|
-
});
|
|
536
|
-
this._apiEmitter?.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
|
|
537
|
-
}
|
|
538
|
-
} catch (err) {
|
|
539
|
-
wrapper.decrementPendingContextChanges();
|
|
540
|
-
wrapper.status = this._statusEnumType.ERROR;
|
|
541
|
-
if (wrapper.allContextChangesSettled) {
|
|
542
|
-
const error = err;
|
|
543
|
-
const message = `Error running ${providerName}'s context change handler: ${error?.message}`;
|
|
544
|
-
this._logger?.error(`${message}`, err);
|
|
545
|
-
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
546
|
-
emitter?.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
|
|
547
|
-
});
|
|
548
|
-
this._apiEmitter?.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
var OpenFeature = OpenFeatureAPI.getInstance();
|
|
372
|
+
import {
|
|
373
|
+
OpenFeatureCommonAPI,
|
|
374
|
+
ProviderWrapper,
|
|
375
|
+
objectOrUndefined,
|
|
376
|
+
stringOrUndefined
|
|
377
|
+
} from "@openfeature/core";
|
|
554
378
|
|
|
555
|
-
// src/client/open-feature-client.ts
|
|
379
|
+
// src/client/internal/open-feature-client.ts
|
|
380
|
+
import {
|
|
381
|
+
ErrorCode as ErrorCode2,
|
|
382
|
+
ProviderFatalError,
|
|
383
|
+
ProviderNotReadyError,
|
|
384
|
+
SafeLogger,
|
|
385
|
+
StandardResolutionReasons as StandardResolutionReasons2,
|
|
386
|
+
instantiateErrorByErrorCode,
|
|
387
|
+
statusMatchesEvent
|
|
388
|
+
} from "@openfeature/core";
|
|
556
389
|
var OpenFeatureClient = class {
|
|
557
390
|
constructor(providerAccessor, providerStatusAccessor, emitterAccessor, globalLogger, options) {
|
|
558
391
|
this.providerAccessor = providerAccessor;
|
|
@@ -682,6 +515,9 @@ var OpenFeatureClient = class {
|
|
|
682
515
|
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
|
|
683
516
|
flagKey
|
|
684
517
|
};
|
|
518
|
+
if (evaluationDetails.errorCode) {
|
|
519
|
+
throw instantiateErrorByErrorCode(evaluationDetails.errorCode);
|
|
520
|
+
}
|
|
685
521
|
this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
|
|
686
522
|
return evaluationDetails;
|
|
687
523
|
} catch (err) {
|
|
@@ -746,6 +582,207 @@ var OpenFeatureClient = class {
|
|
|
746
582
|
}
|
|
747
583
|
};
|
|
748
584
|
|
|
585
|
+
// src/open-feature.ts
|
|
586
|
+
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api");
|
|
587
|
+
var _globalThis = globalThis;
|
|
588
|
+
var OpenFeatureAPI = class _OpenFeatureAPI extends OpenFeatureCommonAPI {
|
|
589
|
+
_statusEnumType = ClientProviderStatus;
|
|
590
|
+
_apiEmitter = new OpenFeatureEventEmitter();
|
|
591
|
+
_defaultProvider = new ProviderWrapper(
|
|
592
|
+
NOOP_PROVIDER,
|
|
593
|
+
ClientProviderStatus.NOT_READY,
|
|
594
|
+
this._statusEnumType
|
|
595
|
+
);
|
|
596
|
+
_domainScopedProviders = /* @__PURE__ */ new Map();
|
|
597
|
+
_createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
598
|
+
constructor() {
|
|
599
|
+
super("client");
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Gets a singleton instance of the OpenFeature API.
|
|
603
|
+
* @ignore
|
|
604
|
+
* @returns {OpenFeatureAPI} OpenFeature API
|
|
605
|
+
*/
|
|
606
|
+
static getInstance() {
|
|
607
|
+
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
|
|
608
|
+
if (globalApi) {
|
|
609
|
+
return globalApi;
|
|
610
|
+
}
|
|
611
|
+
const instance = new _OpenFeatureAPI();
|
|
612
|
+
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
|
|
613
|
+
return instance;
|
|
614
|
+
}
|
|
615
|
+
getProviderStatus(domain) {
|
|
616
|
+
if (!domain) {
|
|
617
|
+
return this._defaultProvider.status;
|
|
618
|
+
}
|
|
619
|
+
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status;
|
|
620
|
+
}
|
|
621
|
+
async setProviderAndWait(clientOrProvider, providerContextOrUndefined, contextOrUndefined) {
|
|
622
|
+
const domain = stringOrUndefined(clientOrProvider);
|
|
623
|
+
const provider = domain ? objectOrUndefined(providerContextOrUndefined) : objectOrUndefined(clientOrProvider);
|
|
624
|
+
const context = domain ? objectOrUndefined(contextOrUndefined) : objectOrUndefined(providerContextOrUndefined);
|
|
625
|
+
if (context) {
|
|
626
|
+
if (domain) {
|
|
627
|
+
this._domainScopedContext.set(domain, context);
|
|
628
|
+
} else {
|
|
629
|
+
this._context = context;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
await this.setAwaitableProvider(domain, provider);
|
|
633
|
+
}
|
|
634
|
+
setProvider(domainOrProvider, providerContextOrUndefined, contextOrUndefined) {
|
|
635
|
+
const domain = stringOrUndefined(domainOrProvider);
|
|
636
|
+
const provider = domain ? objectOrUndefined(providerContextOrUndefined) : objectOrUndefined(domainOrProvider);
|
|
637
|
+
const context = domain ? objectOrUndefined(contextOrUndefined) : objectOrUndefined(providerContextOrUndefined);
|
|
638
|
+
if (context) {
|
|
639
|
+
if (domain) {
|
|
640
|
+
this._domainScopedContext.set(domain, context);
|
|
641
|
+
} else {
|
|
642
|
+
this._context = context;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const maybePromise = this.setAwaitableProvider(domain, provider);
|
|
646
|
+
Promise.resolve(maybePromise).catch((err) => {
|
|
647
|
+
this._logger.error("Error during provider initialization:", err);
|
|
648
|
+
});
|
|
649
|
+
return this;
|
|
650
|
+
}
|
|
651
|
+
async setContext(domainOrContext, contextOrUndefined) {
|
|
652
|
+
const domain = stringOrUndefined(domainOrContext);
|
|
653
|
+
const context = objectOrUndefined(domainOrContext) ?? objectOrUndefined(contextOrUndefined) ?? {};
|
|
654
|
+
if (domain) {
|
|
655
|
+
const wrapper = this._domainScopedProviders.get(domain);
|
|
656
|
+
if (wrapper) {
|
|
657
|
+
const oldContext = this.getContext(domain);
|
|
658
|
+
this._domainScopedContext.set(domain, context);
|
|
659
|
+
await this.runProviderContextChangeHandler(domain, wrapper, oldContext, context);
|
|
660
|
+
} else {
|
|
661
|
+
this._domainScopedContext.set(domain, context);
|
|
662
|
+
}
|
|
663
|
+
} else {
|
|
664
|
+
const oldContext = this._context;
|
|
665
|
+
this._context = context;
|
|
666
|
+
const unboundProviders = Array.from(this._domainScopedProviders.entries()).filter(([domain2]) => !this._domainScopedContext.has(domain2)).reduce((acc, [domain2, wrapper]) => {
|
|
667
|
+
acc.push({ domain: domain2, wrapper });
|
|
668
|
+
return acc;
|
|
669
|
+
}, []);
|
|
670
|
+
const allDomainRecords = [
|
|
671
|
+
// add in the default (no domain)
|
|
672
|
+
{ domain: void 0, wrapper: this._defaultProvider },
|
|
673
|
+
...unboundProviders
|
|
674
|
+
];
|
|
675
|
+
await Promise.all(
|
|
676
|
+
allDomainRecords.map((dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context))
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
getContext(domainOrUndefined) {
|
|
681
|
+
const domain = stringOrUndefined(domainOrUndefined);
|
|
682
|
+
if (domain) {
|
|
683
|
+
const context = this._domainScopedContext.get(domain);
|
|
684
|
+
if (context) {
|
|
685
|
+
return context;
|
|
686
|
+
} else {
|
|
687
|
+
this._logger.debug(`Unable to find context for '${domain}'.`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return this._context;
|
|
691
|
+
}
|
|
692
|
+
async clearContext(domainOrUndefined) {
|
|
693
|
+
const domain = stringOrUndefined(domainOrUndefined);
|
|
694
|
+
if (domain) {
|
|
695
|
+
const wrapper = this._domainScopedProviders.get(domain);
|
|
696
|
+
if (wrapper) {
|
|
697
|
+
const oldContext = this.getContext(domain);
|
|
698
|
+
this._domainScopedContext.delete(domain);
|
|
699
|
+
const newContext = this.getContext();
|
|
700
|
+
await this.runProviderContextChangeHandler(domain, wrapper, oldContext, newContext);
|
|
701
|
+
} else {
|
|
702
|
+
this._domainScopedContext.delete(domain);
|
|
703
|
+
}
|
|
704
|
+
} else {
|
|
705
|
+
return this.setContext({});
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Resets the global evaluation context and removes the evaluation context for
|
|
710
|
+
* all domains.
|
|
711
|
+
*/
|
|
712
|
+
async clearContexts() {
|
|
713
|
+
await this.clearContext();
|
|
714
|
+
await Promise.allSettled(Array.from(this._domainScopedProviders.keys()).map((domain) => this.clearContext(domain)));
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* A factory function for creating new named OpenFeature clients. Clients can contain
|
|
718
|
+
* their own state (e.g. logger, hook, context). Multiple clients can be used
|
|
719
|
+
* to segment feature flag configuration.
|
|
720
|
+
*
|
|
721
|
+
* If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used.
|
|
722
|
+
* Otherwise, the default provider is used until a provider is assigned to that name.
|
|
723
|
+
* @param {string} domain An identifier which logically binds clients with providers
|
|
724
|
+
* @param {string} version The version of the client (only used for metadata)
|
|
725
|
+
* @returns {Client} OpenFeature Client
|
|
726
|
+
*/
|
|
727
|
+
getClient(domain, version) {
|
|
728
|
+
return new OpenFeatureClient(
|
|
729
|
+
// functions are passed here to make sure that these values are always up to date,
|
|
730
|
+
// and so we don't have to make these public properties on the API class.
|
|
731
|
+
() => this.getProviderForClient(domain),
|
|
732
|
+
() => this.getProviderStatus(domain),
|
|
733
|
+
() => this.buildAndCacheEventEmitterForClient(domain),
|
|
734
|
+
() => this._logger,
|
|
735
|
+
{ domain, version }
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Clears all registered providers and resets the default provider.
|
|
740
|
+
* @returns {Promise<void>}
|
|
741
|
+
*/
|
|
742
|
+
async clearProviders() {
|
|
743
|
+
await super.clearProvidersAndSetDefault(NOOP_PROVIDER);
|
|
744
|
+
this._domainScopedContext.clear();
|
|
745
|
+
}
|
|
746
|
+
async runProviderContextChangeHandler(domain, wrapper, oldContext, newContext) {
|
|
747
|
+
const providerName = wrapper.provider?.metadata?.name || "unnamed-provider";
|
|
748
|
+
try {
|
|
749
|
+
if (typeof wrapper.provider.onContextChange === "function") {
|
|
750
|
+
const maybePromise = wrapper.provider.onContextChange(oldContext, newContext);
|
|
751
|
+
if (typeof maybePromise?.then === "function") {
|
|
752
|
+
wrapper.incrementPendingContextChanges();
|
|
753
|
+
wrapper.status = this._statusEnumType.RECONCILING;
|
|
754
|
+
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
755
|
+
emitter?.emit(ClientProviderEvents.Reconciling, { domain, providerName });
|
|
756
|
+
});
|
|
757
|
+
this._apiEmitter?.emit(ClientProviderEvents.Reconciling, { domain, providerName });
|
|
758
|
+
await maybePromise;
|
|
759
|
+
wrapper.decrementPendingContextChanges();
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
wrapper.status = this._statusEnumType.READY;
|
|
763
|
+
if (wrapper.allContextChangesSettled) {
|
|
764
|
+
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
765
|
+
emitter?.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
|
|
766
|
+
});
|
|
767
|
+
this._apiEmitter?.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
|
|
768
|
+
}
|
|
769
|
+
} catch (err) {
|
|
770
|
+
wrapper.decrementPendingContextChanges();
|
|
771
|
+
wrapper.status = this._statusEnumType.ERROR;
|
|
772
|
+
if (wrapper.allContextChangesSettled) {
|
|
773
|
+
const error = err;
|
|
774
|
+
const message = `Error running ${providerName}'s context change handler: ${error?.message}`;
|
|
775
|
+
this._logger?.error(`${message}`, err);
|
|
776
|
+
this.getAssociatedEventEmitters(domain).forEach((emitter) => {
|
|
777
|
+
emitter?.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
|
|
778
|
+
});
|
|
779
|
+
this._apiEmitter?.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
var OpenFeature = OpenFeatureAPI.getInstance();
|
|
785
|
+
|
|
749
786
|
// src/index.ts
|
|
750
787
|
export * from "@openfeature/core";
|
|
751
788
|
export {
|
|
@@ -753,7 +790,6 @@ export {
|
|
|
753
790
|
NOOP_PROVIDER,
|
|
754
791
|
OpenFeature,
|
|
755
792
|
OpenFeatureAPI,
|
|
756
|
-
OpenFeatureClient,
|
|
757
793
|
OpenFeatureEventEmitter,
|
|
758
794
|
ClientProviderEvents as ProviderEvents,
|
|
759
795
|
ClientProviderStatus as ProviderStatus
|