@openfeature/web-sdk 0.3.11 → 0.4.1

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/dist/cjs/index.js CHANGED
@@ -467,6 +467,7 @@ __export(src_exports, {
467
467
  isObject: () => isObject,
468
468
  isString: () => isString,
469
469
  objectOrUndefined: () => objectOrUndefined,
470
+ statusMatchesEvent: () => statusMatchesEvent,
470
471
  stringOrUndefined: () => stringOrUndefined
471
472
  });
472
473
  module.exports = __toCommonJS(src_exports);
@@ -588,6 +589,15 @@ var InvalidContextError = class extends OpenFeatureError {
588
589
  }
589
590
  };
590
591
 
592
+ // ../shared/src/provider/provider.ts
593
+ var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => {
594
+ ProviderStatus2["NOT_READY"] = "NOT_READY";
595
+ ProviderStatus2["READY"] = "READY";
596
+ ProviderStatus2["ERROR"] = "ERROR";
597
+ ProviderStatus2["STALE"] = "STALE";
598
+ return ProviderStatus2;
599
+ })(ProviderStatus || {});
600
+
591
601
  // ../shared/src/events/events.ts
592
602
  var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => {
593
603
  ProviderEvents2["Ready"] = "PROVIDER_READY";
@@ -597,6 +607,20 @@ var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => {
597
607
  return ProviderEvents2;
598
608
  })(ProviderEvents || {});
599
609
 
610
+ // ../shared/src/events/event-utils.ts
611
+ var eventStatusMap = {
612
+ ["READY" /* READY */]: "PROVIDER_READY" /* Ready */,
613
+ ["ERROR" /* ERROR */]: "PROVIDER_ERROR" /* Error */,
614
+ ["STALE" /* STALE */]: "PROVIDER_STALE" /* Stale */,
615
+ ["NOT_READY" /* NOT_READY */]: void 0
616
+ };
617
+ var statusMatchesEvent = (event, status) => {
618
+ return !status && event === "PROVIDER_READY" /* Ready */ || eventStatusMap[status] === event;
619
+ };
620
+
621
+ // ../shared/src/events/open-feature-event-emitter.ts
622
+ var import_events2 = __toESM(require_events());
623
+
600
624
  // ../shared/src/logger/default-logger.ts
601
625
  var DefaultLogger = class {
602
626
  error(...args) {
@@ -651,13 +675,12 @@ var SafeLogger = class {
651
675
  };
652
676
 
653
677
  // ../shared/src/events/open-feature-event-emitter.ts
654
- var import_events = __toESM(require_events());
655
678
  var GenericEventEmitter = class {
656
679
  constructor(globalLogger) {
657
680
  this.globalLogger = globalLogger;
658
681
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
659
682
  this._handlers = /* @__PURE__ */ new WeakMap();
660
- this.eventEmitter = new import_events.default({ captureRejections: true });
683
+ this.eventEmitter = new import_events2.default({ captureRejections: true });
661
684
  this.eventEmitter.on("error", (err) => {
662
685
  var _a;
663
686
  (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
@@ -667,8 +690,8 @@ var GenericEventEmitter = class {
667
690
  this.eventEmitter.emit(eventType, context);
668
691
  }
669
692
  addHandler(eventType, handler) {
670
- const asyncHandler = (context) => __async(this, null, function* () {
671
- yield handler(context);
693
+ const asyncHandler = (details) => __async(this, null, function* () {
694
+ yield handler(details);
672
695
  });
673
696
  this._handlers.set(handler, asyncHandler);
674
697
  this.eventEmitter.on(eventType, asyncHandler);
@@ -704,14 +727,6 @@ var OpenFeatureEventEmitter = class extends GenericEventEmitter {
704
727
  var InternalEventEmitter = class extends GenericEventEmitter {
705
728
  };
706
729
 
707
- // ../shared/src/provider/provider.ts
708
- var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => {
709
- ProviderStatus2["NOT_READY"] = "NOT_READY";
710
- ProviderStatus2["READY"] = "READY";
711
- ProviderStatus2["ERROR"] = "ERROR";
712
- return ProviderStatus2;
713
- })(ProviderStatus || {});
714
-
715
730
  // ../shared/src/transaction-context/no-op-transaction-context-propagator.ts
716
731
  var NoopTransactionContextPropagator = class {
717
732
  getTransactionContext() {
@@ -744,7 +759,7 @@ function isDefined(input) {
744
759
 
745
760
  // ../shared/src/open-feature.ts
746
761
  var OpenFeatureCommonAPI = class {
747
- constructor() {
762
+ constructor(category) {
748
763
  this._hooks = [];
749
764
  this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
750
765
  this._context = {};
@@ -753,6 +768,7 @@ var OpenFeatureCommonAPI = class {
753
768
  this._clientEventHandlers = /* @__PURE__ */ new Map();
754
769
  this._clientProviders = /* @__PURE__ */ new Map();
755
770
  this._clientEvents = /* @__PURE__ */ new Map();
771
+ this._runsOn = category;
756
772
  }
757
773
  addHooks(...hooks) {
758
774
  this._hooks = [...this._hooks, ...hooks];
@@ -779,11 +795,24 @@ var OpenFeatureCommonAPI = class {
779
795
  /**
780
796
  * Adds a handler for the given provider event type.
781
797
  * The handlers are called in the order they have been added.
782
- * When changing the provider, the currently attached handlers will listen to the events of the new provider.
798
+ * API (global) events run for all providers.
783
799
  * @param {ProviderEvents} eventType The provider event type to listen to
784
800
  * @param {EventHandler} handler The handler to run on occurrence of the event type
785
801
  */
786
802
  addHandler(eventType, handler) {
803
+ [.../* @__PURE__ */ new Map([[void 0, this._defaultProvider]]), ...this._clientProviders].forEach((keyProviderTuple) => {
804
+ var _a;
805
+ const clientName = keyProviderTuple[0];
806
+ const provider = keyProviderTuple[1];
807
+ const shouldRunNow = statusMatchesEvent(eventType, keyProviderTuple[1].status);
808
+ if (shouldRunNow) {
809
+ try {
810
+ handler({ clientName, providerName: provider.metadata.name });
811
+ } catch (err) {
812
+ (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
813
+ }
814
+ }
815
+ });
787
816
  this._events.addHandler(eventType, handler);
788
817
  }
789
818
  /**
@@ -802,43 +831,66 @@ var OpenFeatureCommonAPI = class {
802
831
  getHandlers(eventType) {
803
832
  return this._events.getHandlers(eventType);
804
833
  }
834
+ setProviderAndWait(clientOrProvider, providerOrUndefined) {
835
+ return __async(this, null, function* () {
836
+ yield this.setAwaitableProvider(clientOrProvider, providerOrUndefined);
837
+ });
838
+ }
805
839
  setProvider(clientOrProvider, providerOrUndefined) {
806
- var _a, _b, _c, _d, _e, _f, _g;
840
+ const maybePromise = this.setAwaitableProvider(clientOrProvider, providerOrUndefined);
841
+ if (maybePromise) {
842
+ maybePromise.catch(() => {
843
+ });
844
+ }
845
+ return this;
846
+ }
847
+ setAwaitableProvider(clientOrProvider, providerOrUndefined) {
848
+ var _a, _b, _c, _d, _e, _f;
807
849
  const clientName = stringOrUndefined(clientOrProvider);
808
850
  const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined);
809
851
  if (!provider) {
810
- return this;
852
+ this._logger.debug("No provider defined, ignoring setProvider call");
853
+ return;
811
854
  }
812
855
  const oldProvider = this.getProviderForClient(clientName);
856
+ const providerName = provider.metadata.name;
813
857
  if (oldProvider === provider) {
814
- return this;
858
+ this._logger.debug("Provider is already set, ignoring setProvider call");
859
+ return;
860
+ }
861
+ if (!provider.runsOn) {
862
+ this._logger.debug(`Provider '${provider.metadata.name}' has not defined its intended use.`);
863
+ } else if (provider.runsOn !== this._runsOn) {
864
+ throw new GeneralError(`Provider '${provider.metadata.name}' is intended for use on the ${provider.runsOn}.`);
815
865
  }
816
866
  const emitters = this.getAssociatedEventEmitters(clientName);
817
867
  if (typeof provider.initialize === "function" && provider.status === void 0) {
818
868
  const activeLogger = this._logger || console;
819
869
  activeLogger.warn(
820
- `Provider ${(_b = provider == null ? void 0 : provider.metadata) == null ? void 0 : _b.name} implements 'initialize' but not 'status'. Please implement 'status'.`
870
+ `Provider ${providerName} implements 'initialize' but not 'status'. Please implement 'status'.`
821
871
  );
822
872
  }
873
+ let initializationPromise = void 0;
823
874
  if ((provider == null ? void 0 : provider.status) === "NOT_READY" /* NOT_READY */ && typeof provider.initialize === "function") {
824
- (_e = (_d = (_c = provider.initialize) == null ? void 0 : _c.call(provider, this._context)) == null ? void 0 : _d.then(() => {
875
+ initializationPromise = (_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => {
825
876
  var _a2;
826
877
  this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
827
- emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName });
878
+ emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
828
879
  });
829
- (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName });
830
- })) == null ? void 0 : _e.catch((error) => {
880
+ (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
881
+ })) == null ? void 0 : _d.catch((error) => {
831
882
  var _a2;
832
883
  this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
833
- emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message });
884
+ emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message });
834
885
  });
835
- (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message });
886
+ (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message });
887
+ throw error;
836
888
  });
837
889
  } else {
838
890
  emitters.forEach((emitter) => {
839
- emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName });
891
+ emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
840
892
  });
841
- (_f = this._events) == null ? void 0 : _f.emit("PROVIDER_READY" /* Ready */, { clientName });
893
+ (_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
842
894
  }
843
895
  if (clientName) {
844
896
  this._clientProviders.set(clientName, provider);
@@ -847,9 +899,9 @@ var OpenFeatureCommonAPI = class {
847
899
  }
848
900
  this.transferListeners(oldProvider, provider, clientName, emitters);
849
901
  if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) {
850
- (_g = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _g.call(oldProvider);
902
+ (_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider);
851
903
  }
852
- return this;
904
+ return initializationPromise;
853
905
  }
854
906
  getProviderForClient(name) {
855
907
  var _a;
@@ -870,7 +922,7 @@ var OpenFeatureCommonAPI = class {
870
922
  (eventType) => {
871
923
  var _a;
872
924
  return (_a = clientProvider.events) == null ? void 0 : _a.addHandler(eventType, (details) => __async(this, null, function* () {
873
- newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name }));
925
+ newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name, providerName: clientProvider.metadata.name }));
874
926
  }));
875
927
  }
876
928
  );
@@ -899,9 +951,9 @@ var OpenFeatureCommonAPI = class {
899
951
  const newClientHandlers = Object.values(ProviderEvents).map((eventType) => {
900
952
  const handler = (details) => __async(this, null, function* () {
901
953
  emitters.forEach((emitter) => {
902
- emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName }));
954
+ emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name }));
903
955
  });
904
- this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName }));
956
+ this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name }));
905
957
  });
906
958
  return [eventType, handler];
907
959
  });
@@ -1000,7 +1052,7 @@ var _globalThis = globalThis;
1000
1052
  var OpenFeatureAPI = class extends OpenFeatureCommonAPI {
1001
1053
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1002
1054
  constructor() {
1003
- super();
1055
+ super("client");
1004
1056
  this._defaultProvider = NOOP_PROVIDER;
1005
1057
  }
1006
1058
  /**
@@ -1083,7 +1135,7 @@ var OpenFeatureClient = class {
1083
1135
  const providerReady = !this._provider.status || this._provider.status === "READY" /* READY */;
1084
1136
  if (eventType === "PROVIDER_READY" /* Ready */ && providerReady) {
1085
1137
  try {
1086
- handler({ clientName: this.metadata.name });
1138
+ handler({ clientName: this.metadata.name, providerName: this._provider.metadata.name });
1087
1139
  } catch (err) {
1088
1140
  (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
1089
1141
  }